黑馬程序員_【總結】_IO知識梳理2

IO知識梳理2


---------- android培訓 java培訓、期待與您交流! ---------- 

---------------------------------------------------------------------------------------------------------------------------------------------

1、File 重點方法
listRoots():列出 系統的盤符。
String list()     :列出該盤符下所有的文件夾、文件 保過隱藏部分。
list(FilenameFilter filter): 文件過濾,選出指定文件
File listFiles()  :比list()更常用,因爲被封裝爲對象,所以可以獲取其名字和長度
2、遞歸   函數自身調用自身。
這種表現形式,或者說編程手法,稱爲【遞歸。【函數自身調用自身。】】
3、遞歸注意事項:
1、限定條件。
2、要注意遞歸的次數,儘量避免內存溢出。
4、Properties  是 hashtable  的子類
也就是說它具備 map 集合的特點,而且他裏面存儲的【鍵值對】 都是字符串
5、打印流 : 可以直接操作輸入流和文件。
PrintStream
PrintWriter
該流提供了打印方法,可以將各種數據類型的數據都原樣打印。
6、合併--分割
SequenceInputStream(en)    en爲枚舉值
1、 SequenceInputStream 是合併流,參數接收一個枚舉值
2、那麼集合中,誰有枚舉呢: Vector 
把流都裝入到Vector 形成一個結合
3、 SequenceInputStream 接收枚舉, 形成合並流。
4、 創建一個輸入流,並關聯文件。
-------------------------------------------------------
【1】
常用方法:
1、創建
boolean createNewFile();  在指定位置常見文件,
如果該文件已經存在,則不創建,返回false,
同輸出流不一樣,輸出流建立文件,如果存在,則直接覆蓋。
boolean mkdir():創建文件夾(只能是一級目錄)
boolean mkdirs():創建多級文件夾(D:\\e\\aa\\ee\\dd)
2、刪除
boolean delete(); 指定刪除
void deleteonExit();  退出時,刪除
3、判斷
exists() 判斷文件或目錄【是否存在】。
isDirectory() 是否是目錄
isFile() 是否是文件
isHidden() 是否是隱藏文件 (Java是不能使用隱藏文件的)
isAbsolute()  是否是絕對路徑(E:\\2\\213\2.txt)
4、查找
String getName();  獲取名稱
getPath() :獲取路徑
getParent(): 獲取路徑  沒有明確指定負目錄,返回的是空
getAbsolutePath() 獲取絕對路徑。
long lastModifide() :返回最後修改的時間。[last,modifai]
long length()  :  文件大小。
---------
【重點的部分】
listRoots():列出 系統的盤符。
String list()     :列出該盤符下所有的文件夾、文件 保過隱藏部分。
list(FilenameFilter filter): 文件過濾,選出指定文件

File listFiles()  :比list()更常用,因爲被封裝爲對象,所以可以獲取其名字和長度
-----------------------------------
endsWith(".java") 篩選
renameTo(File dest) 
分隔符:File.separator      可以跨平臺使用。
因爲E:\\   跨平臺性不強
【2】
遞歸 概念
函數自身調用自身。
這種表現形式,或者說編程手法,稱爲【遞歸。【函數自身調用自身。】】


遞歸注意:
1、限定條件。
2、要注意遞歸的次數,儘量避免內存溢出。


遞歸中不要建立集合,因爲會自己調用自己會不斷創建集合。
class $3FileDemo {
	public static void main(String[] args) {
		File dir = new File("E:\\yunyao\\edjava\\");
		//showDir(dir);
		//toBin(6);
		int sum = getSum(8000);
		sop(sum);
	}
	//遞歸運算示例2:
	public static int getSum(int n){
		//計算1234一次相加的和
		if(n == 1){
			return 1;
		}
		return n+getSum(n-1);
	}
	//遞歸運算示例:
	public static void toBin(int num){
		if(num>0){
			toBin(num /2 );
			//num = num /2 ;
			sop(num%2);
		}
	}
	public static void showDir(File dir){
		sop("-----------------------------------");
		sop(dir);
		sop("--------");
		File [] files = dir.listFiles();
		for(int i = 0; i<files.length; i++){
			if(files[i].isDirectory())
				showDir(files[i]);//【再次調用本功能】函數自身調用自身。
			else
				sop(files[i]+"::"+files[i].length());
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}
//最簡單的遞歸:  a 調用b b調用c   c打印完後,打印b  然後打印a    
// 有這麼一個規律:先進後出。(棧的規律也)
class Test{
	void showA(){
	showB();
	sop(A);
	}
	void showB(){
		showC();
		sop(B);
	}
	void showC(){
		sop(C);
	}
}
【3】
Properties
Properties  是 hashtable  的子類
也就是說它具備 map 集合的特點,而且他裏面存儲的【鍵值對】 都是字符串

是集合中的 和 IO 技術相結合的容器

該對象的特點: 可以用於鍵值對象的配置文件
(因爲配置文件都是存放與電腦,和集合是在內存中。Properties  誕生)

需求。 在指定目錄下編寫一個配置文件,然後把該文件中傳入到Propertise中。
class $8Properties{
	public static void main(String[] args) throws IOException{
		File f = new File("E:\\bbc.txt");
		method_1(f);		
		method_2(f);//
		method_3(f);//
	}
	//修改某一個數值
	public static void method_3(File file)throws IOException{
		Properties prop = new Properties();
		FileInputStream fis = new FileInputStream(file);
		prop.load(fis);
		//當需要修改值時,發現setProperty方法只能修改集合中的值,而文件
		//	中並沒有修改。查看API 發現store()方法和 load 方法對應:
		prop.setProperty("laopo","9");
		FileOutputStream fos = new FileOutputStream(file);//同樣一個流
		prop.store(fos,"update");//同樣傳入流,後面是註釋標題:
		prop.list(System.out);//列出Properties 建議用該方法。
		fis.close();
		fos.close();
	}
	//[method_1 終極進化模式。]
	public static void method_2(File file)throws IOException{
		Properties prop = new Properties();
		FileInputStream fis = new FileInputStream(file);
		prop.load(fis);//將集合中數據成對加載Properties 集合中。
		//System.out.println(prop);
		prop.list(System.out);//列出Properties 建議用該方法。
	}
	public static void method_1(File file)throws IOException{
		BufferedReader bufr = new BufferedReader(new FileReader(file));
		String line = null;
		Properties prop = new Properties();
		int index=0;
		while((line=bufr.readLine())!=null){
			if(line.contains("=")){   //只對鍵值對進行分割				 
				String [] str = line.split("=");
				prop.setProperty(str[0],str[1]);
			}
		}
		//查看是否成功將數據插入到Properties
		Set<String> set =prop.stringPropertyNames();
		for(String s : set ){
			System.out.println(s+"::"+prop.getProperty(s));
		}
	}
}
練習案例:
需求:
用於記錄應用程序運行次數。
如果使用次數已到,那麼給出註冊提示。

通常會想到:計數器
但是該計數器定義在程序中,隨着程序的運行而存在於內中,並進行自增
隨着應用程序的退出,該計數器也會在內存中消失。

下一次在啓動該程序,又會重新開始從0計數。
這樣就達不到要求。

可以創建一個 Properties 集合,設定一個計數器鍵值對。
打開某一個應用程序時,建立一個相對應的計數器集合。初始值爲1
再次打開判斷是否有該程序的計數器,沒有,新建,有,值自增。
當這個值達到某個數值時,提示次數已滿。 

1、接收文本目錄,創建一個BufferedReader 關聯文件
2、創建Pro 集合,根據文件名寫入鍵值對。
3、主函數可以用一個循環,運行一次,調用一次計數。
4、輸出次數。
public class IO3 {
	public static void main(String[] args) throws IOException{			
		Properties prop = new Properties();//1、創建集合
		File file = new File("E:\\cout.ini");//2、把文件封裝爲對象
		if(!file.exists()){  //3、判斷文件是否存在
			file.createNewFile();  //3-1、如果沒有該文件則創建一個。
		}
		FileInputStream fis = new FileInputStream(file); //4、建立讀取流並關聯文件
		prop.load(fis);        //5、載入。鍵值對數據。
		int count = 0;
		String value = prop.getProperty("Sum"); //6/獲取  key  對應的值  value
		System.out.println("模擬啓動");
		if(value!=null){	// 7、判斷有沒有該  key 
			count = Integer.parseInt(value);  //7-1、如果有則把 value 值轉換爲int
			if(count>=5){
				System.out.println("軟件使用次數到期。交錢吧。");
				return ;
			}
		}
		count++;    //  8、自增一次。
		prop.setProperty("Sum",count+"");  // 9、 更新數據/一定要通過 count+"" 進行轉換
		FileOutputStream fos = new FileOutputStream(file);  //10、建立輸入流並關聯文件
		prop.store(fos,"update");//11、更新到硬盤文件
		fis.close();//12、管理兩個緩衝區。
		fos.close();
	}
}
【4】
打印流 : 可以直接操作輸入流和文件。
PrintStream
PrintWriter
該流提供了打印方法,可以將各種數據類型的數據都原樣打印。

字節打印流
PrintStream
構造函數可以接收的參數類型:
1、file對象
2、字符串路徑 
3、字節輸出流 OutputStream
字符打印流
PrintWriter
構造函數可以接收的參數類型:
1、file對象
2、字符串路徑 
3、字節輸出流 OutputStream
4、字符輸出流  Writer
【5】 合併--分割
對多個流進行合併
SequenceInputStream(en)    en爲枚舉值
1、 SequenceInputStream 是合併流,參數接收一個枚舉值
2、那麼集合中,誰有枚舉呢: Vector 
把流都裝入到Vector 形成一個結合
3、 SequenceInputStream 接收枚舉, 形成合並流。
4、 創建一個輸入流,並關聯文件。
//  Vector Enumeration elements  SequenceInputStream
實現兩個功能:
1、分割
1、創建讀取流並關聯文件,聲明讀寫流
源,電腦,視頻文件: FileInputStream
2、創建一個byte 類型數組,大小爲需求每個文件的大小
3、通過循環方式,new出讀寫流,並裝入數據。
4、關閉所有流。
2、合併   
老方法:
1、因爲合併流 SequenceInputStream  的參數必須是枚舉,所以需要用到Vector
2、創建 Vector 新增被分割的文件。
3、枚舉 Enumeration en  = v.elements
4、創建 SequenceInputStream 接收en
5、創建讀寫流 FileOutputStream 並管理文件位置。
6、記住 一個字節數組來存儲,利用循環。
7、關閉所有流

方法2:
因爲vector 方法效率很低,所以使用 ArrayList  來處理
因爲 ArrayList 只有迭代沒有枚舉 所以,使用迭代 建立 枚舉內部來來返回 轉型。
注意,Enumeration 必須重載兩個方法,hashCodeElements nextElement   
剩餘步驟一致
//  Vector Enumeration SequenceInputStream hasMoreElements nextElement
class $93Test1 {
	public static void main(String[] args) throws Exception{
		File f = new File("E:\\Test\\mp4");
		spiltFile_1();                  //  切割
		Thread.sleep(2000);
		toSequenceInputStream_2(f);     //  合併
		//toSequenceInputStream_1(f);   //	 低效率合併--摒棄。
		Thread.sleep(3000);//延遲幾秒再進行刪除
		DeleteFile(f);                  //  刪除
	}
	//【2】  發現分割出問題了,刪除錯誤分割文件
	public static void DeleteFile(File dir)throws Exception	{
			try{
				File [] files = dir.listFiles();// 把接收到的路徑對象 裝入數組中
				for(File file : files){  // 遞歸 判斷內部是否還包含文件夾
					if(file.isDirectory()){						
						DeleteFile(file);
					}
					System.out.println("Dele:"+file.delete());//  刪除文件
				}
				System.out.println("OVER");
				//System.out.println("OVER\nDele:"+dir.delete());// 刪除文件夾
			}
			catch (IOException e){
				throw new RuntimeException();
			}				
	}
	//【1】 分割
	public static void spiltFile_1(){
		FileInputStream fis =null;
		FileOutputStream fos = null;
		try{
			fis = new FileInputStream("E:\\207.mp4");//讀寫流 關聯文件
			int len = 0;
			int count = 1;
			byte [] by = new byte[1024*1024*10];// 設置 10M
			while((len = fis.read(by))!=-1){
				fos = new FileOutputStream("E:\\Test\\mp4\\"+(count++)+".part");//創建一個寫入流 並關聯文件
				fos.write(by,0,len);//寫入
				fos.close();//關閉該流        //循環後,count++   這個時候關聯新的文件。
			}
			System.out.println("Spilt is Over!");
		}
		catch (IOException e){
			throw new RuntimeException();
		}
		finally{
			try{
				if(fis!=null)//切記關閉流
					fis.close();
			}
			catch (IOException e){
				throw new RuntimeException();
			}
		}			
	}
	//【3】 合併
	public static void toSequenceInputStream_2(File dir) throws IOException{
		SequenceInputStream sis =null;
		FileOutputStream fos =null;
		BufferedOutputStream bufi=null;
		try{
			ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();//  用該集合取代 低效的 vector 
			for(int i = 1; i<= 14 ; i++){
				al.add(new FileInputStream("E:\\Test\\mp4\\"+i+".part")); // 遍歷新增 被分割的文件。
			}
			final Iterator<FileInputStream> it = al.iterator(); //  因爲 ArrayList 沒有枚舉,只有迭代, 那麼我們中轉一下。 記住是 final 修飾

			Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){  //  枚舉  通過內部類  通過 轉換 使枚舉 返回 迭代值
						public boolean hasMoreElements(){  // 切記覆蓋該方法  boolean 類型
								return it.hasNext();
						}
						public FileInputStream nextElement(){ // 切記覆蓋該方法  FileInputStrean 類型
								return it.next();
						}
			};
			sis = new SequenceInputStream(en);// SequenceInputStream  接收枚舉
			//fos = new FileOutputStream("E:\\Test\\mp4\\2222.mp4");
			bufi =new BufferedOutputStream(new FileOutputStream("E:\\Test\\mp4\\2222.mp4")); //  爲了效率
			int len = 0;
			byte [] by = new byte[1024];// 別忘了字節數組
			while((len = sis.read(by))!=-1){  //  讀的是數組
				bufi.write(by,0,len);//fos.write(by,0,len); //  寫入
				//bufi.flush();//fos.flush();                  // 刷新,其實可以不寫。 因爲接着就關閉了,自動刷新了。
			}
			System.out.println("Sequence is Over!");
		}
		catch (IOException e){
			throw new RuntimeException();
		}
		finally{
			try{
				if(bufi!=null) //切記關閉流
					bufi.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException();
			}
			finally{
				try{
					if(sis!=null)//切記關閉流
						sis.close();
				}
				catch (IOException e)
				{
					throw new RuntimeException();
				}
			}
		}
	}
	// 使用 Vector  --  但是效率不好。 
	public static void toSequenceInputStream_1(File dir) throws IOException
	{
//		1、因爲合併流 SequenceInputStream  的參數必須是枚舉,所以需要用到Vector
//		2、創建 Vector 新增被分割的文件。
//		3、枚舉 Enumeration en  = v.elements
//		4、創建 SequenceInputStream 接收en
//		5、創建讀寫流 FileOutputStream 並管理文件位置。
//		6、記住 一個字節數組來存儲,利用循環。
//		7、關閉所有流
		File [] files = dir.listFiles();
		Vector<FileInputStream> v = new Vector<FileInputStream>();
		for(int i = 1 ;i<files.length-1 ; i++){
			v.add(new FileInputStream("E:\\Test\\mp4\\"+i+".part"));
		}
		Enumeration<FileInputStream> en = v.elements();
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream("E:\\Test\\mp4\\008.mp4");
		int len = 0;
		byte [] by = new byte [1024];
		while((len = sis.read(by))!=-1){
			fos.write(by,0,len);
			fos.flush();
		}
		System.out.println("Sequence is Over!");
		fos.close();
		sis.close();
		
	}
}
//end
1、分割,讀取文件的時候,
byte [] by = new byte[1024*1024*10]; 設置 10m  來設定 每一個分割文件的大小
2、合併,遍歷 新增所有分割文件 到集合中  
sis = new SequenceInputStream(en) 接收集合轉化的  枚舉值  進行文件的合併。
3、刪除文件時,注意判斷 是否爲文件夾  利用   遞歸    完成。



---------------------------------------------------------------------------------------------------------------------------------------------
---------- android培訓、 java培訓、期待與您交流!----------


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