黑馬程序員——淺談java中的I/O流操作(二)

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS開發</a>、<a href="http://edu.csdn.net"target="blank">.Net培訓</a>、期待與您交流! ----------------------

一、概述

1File類:文件和目錄路徑名的抽象表現形式

2、特點:

        1)用來將文件或文件夾封裝成對象

        2)方便於對文件與文件夾的屬性信息進行操作

        3File類的實例是不可變的;也就是說,一旦創建,File 對象表示的抽象路徑名將永不改變

        4File對象可以作爲參數傳遞給流的構造函數

 

二、File對象創建

方式一:      

             File f =new File("a.txt");

        將a.txt封裝成File對象。可以將已有的和未出現的文件或者文件夾封裝成對象。

 方式二:

            File f2=newFile("c:\\abc","b.txt");

        將文件所在目錄路徑和文件一起傳入,指定文件路徑。

 方式三:

            File d=new File("c:\\abc");

             File f3=new File(d,"c.txt");

        將文件目錄路徑封裝成對象。再創建文件對象。降低了文件於父目錄的關聯性。

小知識:

        File.separator表示目錄分隔符,可以跨平臺使用。相當於路徑中的“\”(雙斜槓\\windows中表示表示轉義後的分隔符,但是在linux系統中就不是)。

 

三、File類的常見方法

1、創建

        booleancreateNewFile();

        //在指定位置創建文件,如果該文件已經存在,則不創建,返回false。和輸出流不一樣,輸出流對象一建立就創建文件。而且文件已經存在,會覆蓋。

        boolean mkdir();//創建文件夾,只能創建一級文件夾

例:

        File dir=new File("abc");

        dir.mkdir();//創建abc這個文件夾

        boolean mkdirs();//創建多級文件夾

2、刪除

        boolean delete();

        //刪除文件或目錄。文件存在,返回true;文件不存在或者正在被執行,返回false    

        void deleteOnExit();//在程序退出時刪除指定文件

3、判斷

        boolean canExecute();//是否是可執行文件

        boolean exists();//文件是否存在

        boolean isFile();//是否是文件

        boolean isDirectory();//是否是文件夾

        boolean isHidden();//是否是隱藏文件

        boolean isAbsolute();//文件是否是絕對路徑

記住:在判斷文件對象是否是文件或者目錄時,必須要判斷該文件對象封裝的內容是否存在。通過exists判斷。

4、獲取信息

        String getName();//獲取文件名

        String getPath();

        //獲取文件的相對路徑(即創建的對象傳入的參數是什麼就獲取到什麼)

        String getParent();

        //獲取文件父目錄。返回的是絕對路徑中的父目錄。如果獲取的是相對路徑,返回null。如果相對路徑中有上一層目錄,那麼該目錄就是返回結果。

        String getAbsolutePath();//獲取文件的絕對路徑      

        long lastModified();//返回文件最後一次被修改的時間

        long length();//返回文件長度

5、列出文件及文件過濾

        static File[] listRoots();//列出可用的文件系統根目錄,即系統盤符

        String[] list();

        //列出當前目錄下所有文件,包括隱藏。調用list方法的file對象必須是封裝了一個目錄。該目錄還必須存在。

        String[]list(FilenameFilter filter);

        //返回一個字符串數組,獲取目錄中滿足指定過濾器的文件或目錄。

        //FilenameFilter:文件名過濾器,是一個接口,其中包含一個方法,accept(Filedir,String name),返回的是boolean型,對不符合條件的文件過濾掉。

        File[] listFiles();//返回一個抽象路徑名數組,獲取當前文件夾下的所有文件和文件夾

        File[] ListFiles(FilenameFilterfilter);//返回抽象路徑名數組,獲取目錄中滿足指定過濾器的文件或目錄。

/*
練習:用String[] list(FilenameFilter filter)方法獲取一個目錄下所有的.java文件,其他文件不要。
思路:1、FilenameFilter是一個過濾器接口,用匿名內部類傳入filter對象
	  2、複寫FilenameFilter接口的accept(File file,String name)方法,並判斷name是否是java文件
	  3、遍歷String類型數組
*/

import java.io.*;
class  GetJavaFile
{
	public static void main(String[] args) 
	{
		File file=new File("E:\\Java Study\\Practice\\day07");
		getJavaFile(file);
	}
	//獲取一個目錄下所有的.java文件方法
	public static void getJavaFile(File dir)
	{
		//傳入FilenameFilter匿名內部類子類對象,並複寫accept方法
		String[] javaFile=dir.list(new FilenameFilter()
		{
			public boolean accept(File dir,String name)
			{
				return name.endsWith(".java");//判斷文件名是否是以.java結尾
			}
		});

		System.out.println("len:"+javaFile.length);
		//遍歷數組
		for (String s : javaFile )
		{
			System.out.println(s);
		}
	}
}


四、遞歸

1、定義

       當函數內每一次循環還可以調用本功能來實現,也就是函數自身調用自身。這種表現形式,或者編程手法,稱爲遞歸。

2、遞歸注意事項

        a、限定條件。是來結束循環調用,否則是死循環。

        b、注意遞歸的次數,儘量避免內存溢出。因爲每次調用自身的時候都會先執行下一次調用自己的方法,所以會不斷在棧內存中開闢新空間,次數過多,會導致內存溢出。

示例一

/*
需求:列出指定目錄下文件或文件夾,包含子目錄,即列出指定目錄下所有內容(帶層次的)。

分析,因爲目錄中還有目錄,只有使用同一個列出目錄功能的函數完成即可,在列出過程中出現的還是目錄的話,還可以再調用本功能,這就是利用遞歸原理。

*/
import java.io.*;
class  RecursionDemo
{
	public static void main(String[] args) 
	{
		//關聯指定路徑
		File dir=new File("e:\\Java Study\\Practice");
		
        //列出關聯路徑中所有的.java文件
		allFileList(dir,0);
	}

	//列出指定目錄下的所以內容
	public static void allFileList(File dir,int level)
	{
		//有層次的輸出
		System.out.println(getLevel(level)+dir);
		level++;
		File[] fileArr=dir.listFiles();//獲取本目錄下的所以文件和目錄的抽象路徑
		
        //遍歷
		for (File file : fileArr)
		{
			if(file.isDirectory())
			{
				//如果目錄下還是目錄,則繼續調用本函數
				allFileList(file,level);
			}
			else
				System.out.println(getLevel(level)+file);//顯示(列出)文件
		}	
	}

	//帶層次的列表
	public static String getLevel(int level)
	{
		StringBuilder sb=new StringBuilder();
		sb.append("|--");
		//每多一級目錄,就多輸出指定字符
		for (int x=level;x>0 ; x--)
		{
			//sb.append("|--");
			sb.insert(0,"|  ");
		}
		return sb.toString();
	}
}

示例二

/*
刪除一個帶內容的目錄。
刪除原理:
在windows中,刪除目錄從裏面往外面刪除的。
既然是從裏往外刪除。就需要用到遞歸。

*/
import java.io.*;
class RemoveDir 
{
	public static void main(String[] args) 
	{
		//指定目錄
		File dir=new File("e:\\1");
		//刪除目錄
        removeDir(dir);

	}

	//刪除傳入目錄
	public static void removeDir(File dir)
	{
		File[] files=dir.listFiles();//列出目錄下的所以文件和文件夾
		//遍歷
        for (File file : files )
		{
			//如果還是目錄且非隱藏
			if(!file.isHidden()&&file.isDirectory())
				removeDir(file);//繼續刪除目錄裏的內容
			else
				System.out.println(file.toString()+":-file-:"+file.delete());//刪除文件
		}
		System.out.println(dir+":::dir:::"+dir.delete());//刪除目錄
	}
}

示例三

/*
練習:
將一個指定目錄下的java文件的絕對路徑,存儲到一個文本文件中。建立一個java文件列表的文件。
思路:
     1、對指定的目錄進行遞歸。
     2、獲取遞歸過程所有的java文件的路徑。
     3、將這些路徑存儲到集合中。
     4、將集合中的數據寫入到一個文件中。
*/
import java.util.*;
import java.io.*;

class  JavaFileList
{
	public static void main(String[] args) 
	{
		//指定目錄
		File dir=new File("e:/Java Study/Practice");
		
		//定義一個List集合,用於存儲.java文件的File對象
		List<File> list =new ArrayList<File>();
		
		//調用獲取文件路徑方法
		fileToList(dir,list);
		
		//指定寫入文件
		File file=new File(dir,"javafilelist.txt");
		//調用寫入文件方法
        writeToFile(list,file);
	
	}
	//獲取指定文件夾內的所有java文件的絕對路徑,並存入集合中
	public static void fileToList(File dir,List<File> list)
	{
		File[] files=dir.listFiles();//列出dir路徑下的所以文件和目錄,
		//遍歷
		for (File file : files)
		{
			//如果是目錄,則繼續獲取
			if(file.isDirectory())
			{
				list.add(file.getAbsoluteFile());//把父目錄路徑也存入
				fileToList(file,list);
			}
			//將是.java文件的絕對路徑存入
			else if(file.getName().endsWith(".java"))
				list.add(file);
		}
	}

	//將集合中元素寫入到一個文本文件中
	public static void writeToFile(List<File> list,File file)
	{
		
		BufferedWriter bw=null;
			
		try
		{	//使用字符流緩衝區對象關聯寫入的文件
			bw=new BufferedWriter(new FileWriter(file));
			for (File file0 : list )
			{
				bw.write(file0.getAbsolutePath());//寫入
				bw.newLine();//換行
				bw.flush();//刷新
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("寫入文件失敗");
		}
		finally
		{
			try
			{
				if(bw!=null)
					bw.close();//關流
			}
			catch (IOException e)
			{
				throw new RuntimeException("流資源關閉失敗");
			}
		}
	}
}
 
 

  Properties

一、概述

1PropertiesHashtable的子類,它具備Map集合的特點。而且它裏面還有存儲的鍵值對,都是字符串,無泛型定義。是集合中和IO技術想結合的集合容器。

2、特點:

        1)可用於鍵值對形式的配置文件

        2)在加載時,需要數據有固定的格式,常用的是:鍵=

 

二、特有方法

1、設置

        Object setProperty(String key,String value);

        //設置鍵和值,調用Hashtable的方法put

2、獲取

        String getProperty(String key);

        //指定key搜索value

        Set<String> stringPropertyName();

        //返回屬性列表的鍵集,存入Set集合

3、加載流和存入流

        void load(InputStream ism);

        //從輸入字節流中讀取屬性列表(鍵和元素對)。又稱將流中的數據加載進集合。

        void load(Readerreader);

        //從輸入字符流中讀取屬性列表(鍵和元素對)。又稱將流中的數據加載進集合。

        voidlist(PrintStream out);//將屬性列表輸出到指定的輸出流

        void store(OutputStreamout,String comments);

        //對應load(InputStream )將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。

        void store(Writerwriter, String comments);

        //對應load(Reader)將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。

示例

//演示,如何將流中的數據存儲到集合中。
	//想要將info.txt中鍵值數據存到集合中進行操作。
	/*
		1,用一個流和info.txt文件關聯。
		2,讀取一行數據,將該行數據用"="進行切割。
		3,等號左邊作爲鍵,右邊作爲值。存入到Properties集合中即可。

	*/
		//將文件數據存儲進Properties集合方法
	public static void method()throws IOException
	{
		//使用字符讀取緩衝流關聯文件
		BufferedReader bufr = new BufferedReader(new FileReader("info.txt"));

		String line = null;
		//定義Properties集合
		Properties prop = new Properties();

		   	while((line=bufr.readLine())!=null)
		{
			String[] arr = line.split("=");//將一行數據以“=”號進行分割
			//將=左邊作爲鍵存入,將=右邊作爲值存入
			prop.setProperty(arr[0],arr[1]);
		}

		bufr.close();//關流

		System.out.println(prop);
	}

練習:

/*
練習:用於記錄應用程序運行次數。如果使用次數已到,那麼給出註冊提示。
	
分析:
很容易想到的是:計數器。可是該計數器定義在程序中,隨着該應用程序的退出,該計數器也在內存中消失了。
所以要建立一個配置文件,用於記錄該軟件的使用次數。該配置文件使用鍵值對的形式。鍵值對數據是map集合。數據是以文件形式存儲。使用io技術。那麼map+io——>Properties。

思路:1、用讀取流關聯文本信息文件。如果存在則讀取,如果不存在,則創建
	  2、每次運行,將文件數據存入集合中,讀取值,判斷次數,如果小於等於5次,則次數增加1次,如果大於則輸出提示信息。
	  3、將值小於等於5次的信息數據存入文件中
*/
import java.util.*;
import java.io.*;

class  RunCount
{
	public static void main(String[] args)throws IOException 
	{
		int count=runCount();
		if(count>5)//如果程序被使用了超過5次,則終止使用,並提示
		{
			System.out.println("次數到了,交錢!!!!!");
			return ;
		}
		else
			System.out.println("程序第"+count+"次Run!");
	}
	//獲取程序運行的次數
	public static int runCount()throws IOException
	{
		Properties ps=new Properties();//創建集合對象

		File file=new File("info.ini");//將文件進行封裝
		if(!file.exists())//判斷是否存在
			file.createNewFile();
		FileReader fr=new FileReader(file);//將文件於讀取流進行關聯
		
		ps.load(fr);//加載流中的文件數據到集合中

		int count=0;//定義計數器
		String value=ps.getProperty("time");//獲取次數值
		
		if(value!=null)//如過值不等於null,則將其賦值給count
		{
			count=Integer.parseInt(value);
		}
		count++;//每啓動一次自增
		ps.setProperty("time",count+"");//將次數記錄住集合

		FileWriter fw=new FileWriter(file);
		ps.store(fw,"");//將集合中的數據存入硬盤文件中
		
		fr.close();//關流
		fw.close();

		return count;//返回程序啓動的次數
	}
}

 

打印流

一、概述

        1、打印流包括:PrintStreamPrintWriter

        2、該流提供了打印方法,可將各種類型的數據都原樣打印。

 

二、字節打印流:PrintStream

構造方法中可接收的參數類型:

        1File對象。File

        2、字符串路徑:String

        3、字符輸出流:OutputStream

 

三、字符串打印流:PrintWriter

構造方法中可接受的參數類型

        1File對象:File

        2、字符串路徑:String

        3、字節輸出流:OutputStream

        4、字符輸出流:Writer

示例

import java.io.*;

class  PrintStreamDemo
{
	public static void main(String[] args) throws IOException
	{
		//鍵盤錄入
		BufferedReader bufr = 
			new BufferedReader(new InputStreamReader(System.in));

		//打印流關聯文件,自動刷新
		PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);

		String line = null;

		while((line=bufr.readLine())!=null)
		{
			if("over".equals(line))//結束字符
				break;
			out.println(line.toUpperCase());
			//out.flush();
		}
		
		//關流
		out.close();
		bufr.close();

	}	
}

 

序列流

一、概述

1SequenceInputStream對多個流進行合併。也被稱爲合併流。

2、常用構造函數

        SequenceInputStream(Enumeration<?extends FileInputStream> e)

 

二、常見合併多個流文件步驟

        1、創建集合,並將流對象添加進集合

        2、創建Enumeration對象,將集合元素加入。

        3、創建SequenceInputStream對象,合併流對象

        4、創建寫入流對象,FileOutputStream關聯寫入文件

        5、利用SequenceInputStream對象和FileOutputStream對象讀數據進行反覆讀寫操作。

示例:

/*
SequenceInputStream
合併流
需求:將三個文本文件中的數據合併到一個文本文件中
思路:1、創建一個Vector集合,將三個文本文件字節流添加到集合中
	  2、創建Enumeration對象,創建SequnceInputStream對象關聯Enumeration
	  3、輸出流關聯新文本文件
	  4、反覆讀寫操作
*/
import java.util.*;
import java.io.*;

class  SequenceInputStreamDemo
{
	public static void main(String[] args)throws IOException
	{
		Vector<InputStream> ve=new Vector<InputStream>();//創建vector集合,並添加相關流對象
		ve.add(new FileInputStream("1.txt"));
		ve.add(new FileInputStream("2.txt"));
		ve.add(new FileInputStream("3.txt"));

		Enumeration<InputStream> en=ve.elements();//創建枚舉對象
		SequenceInputStream sis=new SequenceInputStream(en);//合併流

		FileOutputStream fos=new FileOutputStream("4.txt");//關聯寫入文件
		
		//反覆讀寫操作
		byte[] buf=new byte[1024];
		int len=0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}
		
		//關流
		fos.close();
		sis.close();
	}
}

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS開發</a>、<a href="http://edu.csdn.net"target="blank">.Net培訓</a>、期待與您交流! ----------------------


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章