java基礎---------IO字符流及綜合練習題


第一部分:字符流

字符流=字節流+編碼表。

字符流是相對字節流來說的,由於一箇中文字符佔據了兩個字節,因此用字節流讀中文字符時,不如字符流處理中文效果好,因此在遇到文本情況時,能用字符流的最好用字符流。
1、編碼表:

由字符及其對應的數值組成的一張表:

這裏通過String類的構造函數及方法,來講述編碼表:


String (byte [] bytes,String charseName):通過制定的字符集解碼字節數組
byte [] getBytes(String charseName):使用指定的字符集合把字符串編碼爲字節數組。

String s="你好";
byte [] bys1=s.getBytes("GBK");
byte [] bys2=s.getBytes();
byte [] bys3=s.getBytes("UTF-8");
System.out.println(Arrays.toString(bys))//打印數組


String s1=new String(bys1);
String s2=new String(by2."GBK");
String s3=new String(by3,"UTF-8");
System.out.println(s1);


由於我們使用的是默認的簡體中文系統,因此默認使用的是GBK編碼表。當我們默認,或者指定將一串中文字符串轉爲byte數組時,我們看到的是兩個byte值的負數表示一個漢字字符。當我們指定用UTF-8編碼表時,我們看到的就會是三個byte值的負數表示一個漢字字符。


2、轉換流:
(1)、轉換輸出流的構造方法:

OutputStreamWriter(OutputStream out)//參數爲字節流
OutputStreamWriter(OutputStream out,String charsetName)//參數爲字節流加上指定編碼表

import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.IOException;


class OutputStreamWriter{
	public static void main(String [] args)throws IOException {
		OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("a.txt"));
		OutputStreamWriter osw1=new OutputStreamWriter(new FileOutputStream("a.txt"),"UTF-8");//這裏由於是UTF-8的編碼,因此文本打開的時候,也需要選擇UTF-8.
		osw.write("黑馬");
		osw1.write("北京");
		osw.close();
		osw1.close();
	}
}


(2)、轉換輸入流的構造方法:
InputStreamReader(InputStream in)//參數爲字節流
InputStreamReader(InputStream in,String charsetName)//參數爲字節流和編碼表


import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.IOException;


class InputStreamReaderDemo{
	public static void main(String [] args)throws IOException{
		//這裏也可以採用參數爲字節流加上指定編碼表。  
		InputStreamReader isr=InputStreamReader(new FileInputStream("b.txt"));
		int ch=0;
		while((ch=isr.read())!=-1){
			System.out.println((char)ch);
		}
		isr.close();
	}
}



(3)、OutputStreamWriter的常用方法方法:
1、public void write(int c)//寫一個字符
2、public void write(char [] cbuf)//寫一個字符數組
3、public void write(char[] cbuf,int off,int len)//寫一個字符數組的一部分
4、public void write(String str)//寫一個字符串
5、public void write(String str,int off,int len)//寫一個字符串的一部分

import java.io.IOException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;


class Demo{
	public static void main(String [] args)throws IOException{
		OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("c.txt"));
		osw.write('中');//write(int c);
		osw.write("中國");//write(String str);
		osw.flush();//刷新。一個字符等於兩個字節。
		char [] chs={'a','b','c'};
		osw.write(chs);
		osw.close();
	}
}


close()和flush()區別
close():關閉流對象,但是先刷新一次緩衝區。關閉之後,流對象不可以繼續再使用了。
flush():僅僅刷新緩衝區,刷新之後,流對象還可以繼續使用。


(4)、InputStreamReader的常用方法:
int read():一次讀取一個字符
int read(char [] chs):一次讀取一個字符數組


import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileInputStream;
class InputStreamReaderDemo{
	public static void main(String [] args)throws IOException{
		InputStreamReader isr=new InputStreamReader(new FileInputStream("d.txt"));
		int len=0;//一次讀取一個字節
		while((len=isr.read())!=-1){
			System.out.print(char(len));
		}
		isr.close();
	}<span style="white-space:pre">	</span>//一次讀取一個數組
		/*InputStreamReader isr1=new InputStreamReader(new FileInputStream("e.txt"));
		char [] chs=new char[1024];
		int le=0;
		while((le=isr1.read(chs))!=-1){
			System.out.print(new String(chs,0,le));
		}
		isr.close();*/
}




3、字符流讀寫案例:
(1)、一次讀取一個字符複製

import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
class CopyDemo{
	public static void main(String [] args)throws IOException{
		InputStreamReader isr=new InputStreamReader(new FileInputStream("f.txt"));
		OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("g.txt"));
		int ch=0;
		//一次讀一個字符,直到返回爲-1
		while((ch=isr.read())!=-1){
			osw.write(ch);
		}
			//關閉轉換流
			osw.close();
			isr.close();
	}
}




(2)、一次讀取一個字符數組複製
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
class CopyDemo1{
	public static void main(String [] args)throws IOException{
		OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("h.txt");
		InputStreamReader isr=new InputStreamReader(new FileInputStream("i.txt");
		//定義一個字符數組的長度
		char[] chs=new char[1024];
		int len=0;
		//一次讀一個字符數組的長度,直到長度爲-1
		while((len=isr.read(chs))!=-1){
			osw.write(chs,0,len);
		}
		//關閉轉換流
		isr.close();
		osw.close();
	}
}


4、轉換流的簡化形式

由於我們使用本地編碼表,不使用制定編碼,又由於轉換流名字較長,因此就有了轉換流的子類
OutputStreamWriter=FileOutputStream+編碼表
FileWriter = FileOutStream+編碼表


InputStreamReader= FileInputStream+編碼表
FileReader =FileInputStream + 編碼表


一次讀取一個字符

import java.io.IOException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class CopyDemo3{
	public static void main(String [] args)throws IOException{
		FileReader fr=new FileReader("j.txt");
		FileWriter fw=new FileWriter("k.txt");
		int ch=0;
		while((ch=fr.read())!=-1){
			fw.write(ch);
		}
		fr.close();
		fw.close();
	}
}



一次讀取一個字符數組
import java.io.IOException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
class CopyDemo4{
	public static void main(String [] args)throws IOException{
		FileReader fr=new FileReader("l.txt");
		FileWriter fw=new FileWriter("m.txt");
		char [] chs = new char[1024];
		int len=0;
		while((len=fr.read(chs))!=-1){
			fw.write(chs,0,len);
			fw.flush();
		}
		fr.close();
		fw.close();
	}
}


5、高級字符緩衝流

BufferedWriter(Writer out)

字符緩衝輸出流構造函數.其參數爲字符轉換流。字符轉換流構造函數的的參數爲字節流。
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
class BufferedWriterDemo{
	public static void main(String [] args)throws IOException{
		BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("n.txt")));
		//上面的可以簡化爲:BufferedWriter bw=new BufferedWriter(new FileWriter("n.txt"));
		bw.write("北京黑馬");
		bw.close();		
	}
}



BufferedReader(Reader in)
字符緩衝輸入流
一次讀取一個字符
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
class BufferedReaderDemo{
	public static void main(String [] args)throws IOException{
		BufferedReader br=new BufferedReader(new FileReader("o.txt"));
		int ch=0;
		while((ch=br.read())!=-1){
			System.out.print(char(ch));
		}
		br.close();
	}
}




一次讀取一個字符數組
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
class BufferedReaderDemo{
	public static void main(String [] args)throws IOException{
		BufferedReader br=new BufferedReader(new FileReader("o.txt"));
		char [] chs =new char[1024];
		int len=0;
		while((len=br.read(chs))!=-1){
			System.out.print(new String(chs,0,len));
		}
		br.close();
	}
}




用緩衝流複製文件:
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.bufferedWriter;
import java.io.FileWriter;
//一次讀取一個字符數組複製文件
class BufferedCopyDemo{
	public static void main(String [] args)throws Exception{
		BufferedReader br=new BufferedReader(new FileReader("p.txt"));
		bufferedWriter bw=new BufferedWriter(new FileWriter("q.txt"));
		char [] chs=new char[1024];
		int len=0;
		while((len=br.read(chs))!=-1){
			bw.write(chs,0,len);
		}
		bw.close();
		br.close();
	}
}


一次讀取一個字符複製文件

import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.bufferedWriter;
import java.io.FileWriter;


class BufferedCopyDemo{
	public static void main(String [] args)throws Exception{
		BufferedReader br=new BufferedReader(new FileReader("p.txt"));
		bufferedWriter bw=new BufferedWriter(new FileWriter("q.txt"));
		int ch=0;
		while((ch=br.read())!=-1){
			bw.write(ch);
		}
		bw.close();
		br.close();
	}
}



6、字符緩衝流的特殊方法:
BufferedWriter:  public void newLine():根據系統來決定換行符
BufferedReader: public String readLine():一次讀取一行.包含了改行的字符串內容,不包含終止符。如果讀不到,返回null。


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
class BufferedSpecialDemo{
	public static void main(String [] args){
		BufferedWriter bw =new BufferedWriter(new FileWriter("r.txt"));		
		 for(int x=0;x<10;x++){
			bw.write("黑馬"+x);
			//起到換行效果
			bw.write("\r\n");
			//也起到換行效果
			bw.newLine();
		}
		
			bw.close();
	}
	public static void read() throws IOException{
		BufferedReader br=new BufferedReader(new FileReader("s.txt"));
			String line=null;
			while( (line=br.readLine()!=null){
				System.out.println(line);	
			}
			br.close();
			
		
	}
}




特殊功能複製文件:一次讀一行
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.FileReader;
class ReaderLineCopy{
	public static void main(String [] args) throws IOException{
		BufferedReader br=new BufferedReader(new FileReader("t.txt"));
		BufferedWriter bw = new BufferedWriter(new FileWriter("u.txt"));
		String line=null;
		while((line=br.readLine())!=null){//一次讀取一行
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		bw.close();
		br.close();
		
	}
}


第二部分:練習題:


1、將ArrayList集合中的字符串數據存儲到文本文件


分析:首先我們應該考慮到將數據存儲到文本,這個數據是從哪裏來的?毫無疑問,數據是從ArrayList集合中遍歷得到的,那麼我們遍歷得到的數據,該如何存儲到文本文件呢?方式有很多有字節流,也有字符流,這裏由於是文本文件,因此我們選擇的是字符流。在遍歷集合的過程中,將獲得的每一個集合元素,寫到文本中。


import java.io.IOException;
import java.util.ArrayList;
import java.io.FileWriter;
import java.io.BufferedWriter;
class ArrayListDemo{
	public static void main(String [] args)throws IOException{
		//創建一個ArrayList集合
		ArrayList<String> list= new ArrayList<String>();
		//創建一個字符緩衝流
		BufferedWriter bw=new BufferedWriter(new FileWriter("v.txt"));
		//爲集合添加數據
		list.add("hello");
		list.add("heima");
		list.add("beijing");
		//遍歷集合
		for(String s:list){
		//將遍歷獲得的集合元素,寫到文本中
			bw.write(s);
			bw.newLine();
			bw.flush();
		}
		//關閉字符緩衝流
		bw.close();
	}
}



2、從文本文件中讀取數據(每一行爲一個字符串數據)到集合中,並遍歷集合


分析:數據是我們從文本文件中獲得的,這就要用到字符流或者字節流,這裏我們選擇了字符緩衝流來讀取文件數據,由於要求每一行爲一個字符串,因此我們選擇的是字符緩衝流中的readLine().在我們每讀一行時,通過集合的add方法,將改行的數據添加到集合。然後遍歷該集合,就能得到答案。


import java.io.IOException;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.FileReader;
class ReadText{
	public static void main(String [] args)throws IOException{
		//創建字符緩衝流
		BufferedReader br=new BufferedReader(new FileReader("w.txt"));
		//創建集合
		ArrayList<String> list=new ArrayList<String>();
		//定義一個String類型的變量
		String line=null;
		//調用字符緩衝流的特有方法readLine()來讀取數據
		while((line=br.readLine())!=null){
		//添加數據到集合
			list.add(line);
		}
		//關閉字符緩衝流
		br.close();
		//遍歷集合
		for(String s:list){
			System.out.println(s);
		}
	}
}



3、複製單級文件夾


第一步:複製單級文件夾的時,首先先不考慮裏面的文件,而是考慮需要複製到的盤符裏是否有該文件夾,如果有,則不用創建,如果沒有,則要另外創建。
第二步:將需要複製的文件夾中的文件一一遍歷出來,由於是單級目錄,所以文件夾下都是文件,所以遍歷出來一個,就可以通過複製方法,將其複製到目標文件夾一個。
第三步:但是在複製之前,就是雖然目標文件夾我們在第一步就已經創建或者已經有了,但是我們知道在使用複製功能時,需要傳遞的是如同d:\\t.txt;e:\\y.txt這樣的文件路徑名,但是我們的目標文件地只有文件夾,還沒有文件名的全路徑,因此需要通過File的另一個構造函數:FIle file =new File(File file,String name);這裏面的參數前者是文件夾的路徑,後者是文件的文件名,因此這個封裝的就是文件全路徑名。這個時候就可以賦值了。這裏面的name可以再第二步的時候,通過getName()方法,從需要複製的文件身上得到。


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; 
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputSteram;
class CopyFolder{
	public static void main(String [] args)throws IOException{
		File src=new File("d:\\x");//封裝源文件夾目錄
		File dest=new File("e:\\y");//封裝目的地文件夾目錄
		if(!dest.exists()){//如果目標文件夾不存在,就創建一個
			dest.mkdir();
		}
		File [] fileArray=src.listFiles();//將源文件的每個對象封裝成一個對象
		for(File file:fileArray){//得到每一個對象
			String name=file.getName();//獲得每個對象的名字
			File newFile=new File(dest,name);//創建目的地文件夾目錄對象
			copy(file,newFile);//複製到目的地文件夾
		}
				
	}<span style="white-space:pre">	</span>//將複製方法封裝成獨立的方法
		public static void copy(File file, File newFile)throws IOException{
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(newFile));
		byte [] bys=new byte[1024];
		int len=0;
		while((len=bis.read(bys))!=-1){
			bos.write(bys,0,len);
		}
		bis.close();
		bos.close();
	}
}



4、複製單級文件夾中指定文件並修改文件後綴名


分析:這裏在複製的過程中,同上面一題的步驟相同,都是先封裝文件源目錄,和文件目的地目錄。如果文件目的地文件夾沒有就創建。


第二步是將源文件中需要複製的文件轉爲File[],這一步是通過文件過濾器來實現的。在上面那題複製文件夾時,我們不需要通過文件過濾器來選擇需要複製哪些文件,而是直接一窩端。文件過濾器可以將不需要複製的文件排除在外。這樣需要複製的文件就轉爲File [];


第三步,遍歷需要複製的文件數組,然後一個一個地複製到目標文件夾。


第四步,雖然複製到了目標文件夾,但是文件名沒有改,這時就可以再次將目標文件夾轉爲File[] 數組,遍歷獲得剛剛複製過來的文件。


第五步,再次遍歷這個File[]數組,裏面的每個剛剛複製過來的文件都是File類型,因此調用getName()可以得到該文件的名稱,獲取的這個名稱僅僅是個字符串,而不是這個文件本身,該文件的名稱是個字符串類型,因此可以通過字符串的替換功能,將需要改名後的名字替換先前的名字,現在這個字符串被替換成了我們需要的名字,但是如何才能把這個字符串重新賦給文件呢?這個時候可以通過File的構造函數File(File dir,String name);參數的前者是路徑,後者是文件名,這樣就相當建了一個新的File對象,新的文件名和複製過來後的路徑組合成了新的文件,然後再將舊的我們在這一步開始就遍歷獲得的那個文件名,也就是從源文件地複製過來的文件,更名爲新的File對象即可。


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;


class ModificationDemo{
	public static void main(String [] args)throws IOException{
		//封裝源文件夾目錄
		File srcFile=new File("e:\\heima");
		//封裝目的文件夾目錄
		File destFile =new File("d:\\chuanzhi");
		if(!destFile.exists()){
			//如果沒有文件夾,將會建一個文件夾。但是destFile從始至終指向的都是d:\chuanzhi這個文件夾。儘管沒有這個文件夾,但是依然指向的是這個地方。這裏只是創建了這個文件夾而已。
			destFile.mkdir();
		}


		//將需要複製的文件過濾出來,通過文件過濾器
		File [] fileArray=srcFile.listFiles(new FilenameFilter(){
		public boolean accept(File dir,String name){
			return new File(dir,name).isFile()&&name.endsWith(".jpg");
		}
		});


		//將需要複製的文件遍歷
		for(File file:fileArray){
			String name=file.getName();
			File newFile=new File(destFile,name);
			copy(file,newFile);
		}
		


		File[] destFileArray=destFile.listFiles();
		for(File dest:destFileArray){
			String name=dest.getName();
			String newName=name.replace(".jpg",".jpeg");
			File newFile =new File(destFile,newName);
			dest.renameTo(newFile);
			
		}
	}


		//封裝的複製方法
	public static void copy(File file, File newFile)throws IOException{
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(newFile));
		byte [] bys=new byte[1024];
		int len=0;
		while((len=bis.read(bys))!=-1){
			bos.write(bys,0,len);
		}
		bis.close();
		bos.close();
	}
}


5、複製多層文件夾


分析:複製多層文件夾,可以建兩個方法,一個方法時複製文件,一個方法時複製文件夾
在複製文件夾時,首先要封裝該文件夾,封裝後,通過該File的對象,來調用isDirectory()判斷,這個對象是文件還是文件夾。(1)如果是文件的話,就將目的地目錄和通過該文件對象調用的getName()作爲參數,來創建一個新File。這個新File就是目標文件所要複製到的地方。(2)如果對象是文件夾的話,通過文件夾對象來調用方法,獲得其名稱,然後和目標文件夾拼接成新的目的地文件夾。然後創建。這時再將對象轉成File類型的數組,通過遍歷該對象,就可以獲取對象文件夾下的內容,然後重複調用isDirectory()判斷是文件還是文件夾。

import java.io.BufferedOutputStream;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;


class CopyFolderDemo{
	public static void main(String [] args) throws IOException{
		File srcFolder=new File("d:\\資料\\day03");
		File destFolder=new File("e:\\");
		copyFolder(srcFolder,destFolder);




	}//複製文件夾的方法
	public static void copyFolder(File srcFolder,File destFolder) throws IOException{
		//判斷對象是不是文件夾
		if(srcFolder.isDirectory()){
			//如果是文件夾,就通過File的構造方法,將目的地和源文件夾名作爲參數,構造新的文件夾。
			File newdestFolder=new File(destFolder,srcFolder.getName());
			//在目的地創建該新的文件夾
			newdestFolder.mkdir();
			//將源文件夾對象的內容作爲對象,存入一個File類型的數組。
			File[] fileArray=srcFolder.listFiles();
			//遍歷該數組,得到的是該源文件夾內容的對象
			for( File file:fileArray){
			//重複複製文件夾,判斷其是文件夾還是文件。
				copyFolder(file,newdestFolder);
			}
		}else{//如果是文件對象,就通過File的帶參構造方法,在目的文件夾中創建對象。其參數分別爲目的地文件夾路徑,源文件名稱。
			File newFile=new File(destFolder,srcFolder.getName());
			//複製該源文件
			copy(srcFolder,newFile);
		}
	}
		
		//複製文件的方法
	public static void copy(File file, File newFile)throws IOException{
		BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(newFile));
		byte [] bys=new byte[1024];
		int len=0;
		while((len=bis.read(bys))!=-1){
			bos.write(bys,0,len);
		}
		bis.close();
		bos.close();
	}
}




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