Java之IO操作总结
所謂IO,也就是Input與Output的縮寫。在java中,IO涉及的范圍比較大,這里主要討論針對文件內容的讀寫
其他知識點將放置后續章節
對于文件內容的操作主要分為兩大類
分別是:
- 字符流
- 字節流
其中,字符流有兩個抽象類:Writer Reader
其對應子類FileWriter和FileReader可實現文件的讀寫操作
BufferedWriter和BufferedReader能夠提供緩沖區功能,用以提高效率
同樣,字節流也有兩個抽象類:InputStream OutputStream
其對應子類有FileInputStream和FileOutputStream實現文件讀寫
BufferedInputStream和BufferedOutputStream提供緩沖區功能
概念:
字符流處理的單元為2個字節的Unicode字符,分別操作字符、字符數組或字符串,而字節流處理單元為1個字節, 操作字節和字節數組。所以字符流是由Java虛擬機將字節轉化為2個字節的Unicode字符為單位的字符而成的,所以它對多國語言支持性比較好!如果是 音頻文件、圖片、歌曲,就用字節流好點,如果是關系到中文(文本)的,用字符流好點.
字節流可用于任何類型的對象,包括二進制對象,而字符流只能處理字符或者字符串; 2. 字節流提供了處理任何類型的IO操作的功能,但它不能直接處理Unicode字符,而字符流就可以。
轉換:
在從字節流轉化為字符流時,實際上就是byte[]轉化為String時,
public String(byte bytes[], String charsetName)
有一個關鍵的參數字符集編碼,通常我們都省略了,那系統就用操作系統的lang
而在字符流轉化為字節流時,實際上是String轉化為byte[]時,
byte[] String.getBytes(String charsetName)
也是一樣的道理
參考鏈接
字節流與字符流的區別 - hintcnuie - ITeye技術網站
俺當初學IO的時候犯了不少迷糊,網上有些代碼也無法通過編譯,甚至風格都很大不同,所以新手請注意:
1.本文代碼較長,不該省略的都沒省略,主要是因為作為一個新手需要養成良好的代碼編寫習慣
2.本文在linux下編譯,類似于File.pathSeparator和File.separator這種表示方法是出于跨平臺性和健壯性考慮
3.代碼中有些操作有多種執行方式,我采用了方式1…方式2…的表述,只需輕輕解開注釋便可編譯
4.代碼中并沒有在主方法上拋出異常,而是分別捕捉,造成代碼過長,如果僅是測試,或者不想有好的編程習慣,那你就隨便拋吧……
5.功能類似的地方就沒有重復寫注釋了,如果新手看不懂下面的代碼,那肯定是上面的沒有理解清楚
字符流
實例1:字符流的寫入
import java.io.File;import java.io.FileWriter;import java.io.IOException;public class Demo {public static void main(String[] args ) {//創建要操作的文件路徑和名稱//其中,File.separator表示系統相關的分隔符,Linux下為:/ Windows下為:\\String path = File.separator + "home" + File.separator + "siu" + File.separator + "work" + File.separator + "demo.txt";//由于IO操作會拋出異常,因此在try語句塊的外部定義FileWriter的引用FileWriter w = null;try {//以path為路徑創建一個新的FileWriter對象//如果需要追加數據,而不是覆蓋,則使用FileWriter(path,true)構造方法w = new FileWriter(path);//將字符串寫入到流中,\r\n表示換行想有好的w.write("Nerxious is a good boy\r\n");//如果想馬上看到寫入效果,則需要調用w.flush()方法w.flush();} catch (IOException e) {e.printStackTrace();} finally {//如果前面發生異常,那么是無法產生w對象的 //因此要做出判斷,以免發生空指針異常if(w != null) {try {//關閉流資源,需要再次捕捉異常w.close();} catch (IOException e) {e.printStackTrace();}}}}}實例2:字符流的讀取
import java.io.File;import java.io.FileReader;import java.io.IOException;public class Demo2 {public static void main(String[] args ) {String path = File.separator + "home" + File.separator + "siu" + File.separator + "work" + File.separator + "demo.txt";FileReader r = null;try {r = new FileReader(path);//方式一:讀取單個字符的方式//每讀取一次,向下移動一個字符單位int temp1 = r.read();System.out.println((char)temp1);int temp2 = r.read();System.out.println((char)temp2);//方式二:循環讀取//read()方法讀到文件末尾會返回-1/*while (true) {int temp = r.read();if (temp == -1) {break;}System.out.print((char)temp);}*///方式三:循環讀取的簡化操作//單個字符讀取,當temp不等于-1的時候打印字符/*int temp = 0;while ((temp = r.read()) != -1) {System.out.print((char)temp);}*///方式四:讀入到字符數組/*char[] buf = new char[1024];int temp = r.read(buf);//將數組轉化為字符串打印,后面參數的意思是//如果字符數組未滿,轉化成字符串打印后尾部也許會出現其他字符//因此,讀取的字符有多少個,就轉化多少為字符串System.out.println(new String(buf,0,temp));*///方式五:讀入到字符數組的優化//由于有時候文件太大,無法確定需要定義的數組大小//因此一般定義數組長度為1024,采用循環的方式讀入/*char[] buf = new char[1024];int temp = 0;while((temp = r.read(buf)) != -1) {System.out.print(new String(buf,0,temp));}*/} catch (IOException e) {e.printStackTrace();} finally {if(r != null) {try {r.close();} catch (IOException e) {e.printStackTrace();}}}}}實例3:文本文件的復制
import java.io.File;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class Demo {public static void main(String[] args ) {String doc = File.separator + "home" + File.separator + "siu" + File.separator + "work" + File.separator + "demo.txt";String copy = File.separator + "home" + File.separator + "siu" + File.separator + "life" + File.separator + "lrc.txt";FileReader r = null;FileWriter w = null;try {r = new FileReader(doc);w = new FileWriter(copy);//方式一:單個字符寫入int temp = 0;while((temp = r.read()) != -1) {w.write(temp);}//方式二:字符數組方式寫入/*char[] buf = new char[1024];int temp = 0;while ((temp = r.read(buf)) != -1) {w.write(new String(buf,0,temp));}*/} catch (IOException e) {e.printStackTrace();} finally {//分別判斷是否空指針引用,然后關閉流if(r != null) {try {r.close();} catch (IOException e) {e.printStackTrace();}}if(w != null) {try {w.close();} catch (IOException e) {e.printStackTrace();}}}}}實例4:利用字符流的緩沖區來進行文本文件的復制
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class Demo {public static void main(String[] args ) {String doc = File.separator + "home" + File.separator + "siu" + File.separator + "work" + File.separator + "demo.txt";String copy = File.separator + "home" + File.separator + "siu" + File.separator + "life" + File.separator + "lrc.txt";FileReader r = null;FileWriter w = null;//創建緩沖區的引用BufferedReader br = null;BufferedWriter bw = null;try {r = new FileReader(doc);w = new FileWriter(copy);//創建緩沖區對象//將需要提高效率的FileReader和FileWriter對象放入其構造函數內//當然,也可以使用匿名對象的方式 br = new BufferedReader(new FileReader(doc));br = new BufferedReader(r);bw = new BufferedWriter(w);String line = null;//讀取行,直到返回null//readLine()方法只返回換行符之前的數據while((line = br.readLine()) != null) {//使用BufferWriter對象的寫入方法bw.write(line);//寫完文件內容之后換行//newLine()方法依據平臺而定//windows下的換行是\r\n//Linux下則是\nbw.newLine();} } catch (IOException e) {e.printStackTrace();} finally {//此處不再需要捕捉FileReader和FileWriter對象的異常//關閉緩沖區就是關閉緩沖區中的流對象if(br != null) {try {r.close();} catch (IOException e) {e.printStackTrace();}}if(bw != null) {try {bw.close();} catch (IOException e) {e.printStackTrace();}}}}}字節流
實例5:字節流的寫入
import java.io.File;import java.io.FileOutputStream;import java.io.IOException;public class Demo {public static void main(String[] args ) {String path = File.separator + "home" + File.separator + "siu" +File.separator + "work" + File.separator + "demo.txt";FileOutputStream o = null;try {o = new FileOutputStream(path);String str = "Nerxious is a good boy\r\n";byte[] buf = str.getBytes();//也可以直接使用o.write("String".getBytes());//因為字符串就是一個對象,能直接調用方法o.write(buf);} catch (IOException e) {e.printStackTrace();} finally {if(o != null) {try {o.close();} catch (IOException e) {e.printStackTrace();}}}}}實例6:字節流的讀取
import java.io.File;import java.io.FileInputStream;import java.io.IOException;public class Demo {public static void main(String[] args ) {String path = File.separator + "home" + File.separator + "siu" +File.separator + "work" + File.separator + "demo.txt";FileInputStream i = null;try {i = new FileInputStream(path);//方式一:單個字符讀取//需要注意的是,此處我用英文文本測試效果良好//但中文就悲劇了,不過下面兩個方法效果良好int ch = 0;while((ch=i.read()) != -1){System.out.print((char)ch);}//方式二:數組循環讀取/*byte[] buf = new byte[1024];int len = 0;while((len = i.read(buf)) != -1) {System.out.println(new String(buf,0,len));}*///方式三:標準大小的數組讀取/*//定一個一個剛好大小的數組//available()方法返回文件的字節數//但是,如果文件過大,內存溢出,那就悲劇了//所以,親們要慎用!!!上面那個方法就不錯byte[] buf = new byte[i.available()];i.read(buf);//因為數組大小剛好,所以轉換為字符串時無需在構造函數中設置起始點System.out.println(new String(buf));*/} catch (IOException e) {e.printStackTrace();} finally {if(i != null) {try {i.close();} catch (IOException e) {e.printStackTrace();}}}}}實例7:二進制文件的復制
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class Demo {public static void main(String[] args ) {String bin = File.separator + "home" + File.separator + "siu" +File.separator + "work" + File.separator + "一個人生活.mp3";String copy = File.separator + "home" + File.separator + "siu" +File.separator + "life" + File.separator + "一個人生活.mp3";FileInputStream i = null;FileOutputStream o = null;try {i = new FileInputStream(bin);o = new FileOutputStream(copy);//循環的方式讀入寫出文件,從而完成復制byte[] buf = new byte[1024];int temp = 0;while((temp = i.read(buf)) != -1) {o.write(buf, 0, temp);}} catch (IOException e) {e.printStackTrace();} finally {if(i != null) {try {i.close();} catch (IOException e) {e.printStackTrace();}}if(o != null) {try {o.close();} catch (IOException e) {e.printStackTrace();}}}}}實例8:利用字節流的緩沖區進行二進制文件的復制
import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class Demo {public static void main(String[] args ) {String bin = File.separator + "home" + File.separator + "siu" +File.separator + "work" + File.separator + "一個人生活.mp3";String copy = File.separator + "home" + File.separator + "siu" +File.separator + "life" + File.separator + "一個人生活.mp3";FileInputStream i = null;FileOutputStream o = null;BufferedInputStream bi = null;BufferedOutputStream bo = null;try {i = new FileInputStream(bin);o = new FileOutputStream(copy);bi = new BufferedInputStream(i);bo = new BufferedOutputStream(o);byte[] buf = new byte[1024];int temp = 0;while((temp = bi.read(buf)) != -1) {bo.write(buf,0,temp);}} catch (IOException e) {e.printStackTrace();} finally {if(bi != null) {try {i.close();} catch (IOException e) {e.printStackTrace();}}if(bo != null) {try {o.close();} catch (IOException e) {e.printStackTrace();}}}}}初學者在學會使用字符流和字節流之后未免會產生疑問:什么時候該使用字符流,什么時候又該使用字節流呢?
其實仔細想想就應該知道,所謂字符流,肯定是用于操作類似文本文件或者帶有字符文件的場合比較多
而字節流則是操作那些無法直接獲取文本信息的二進制文件,比如圖片,mp3,視頻文件等
說白了在硬盤上都是以字節存儲的,只不過字符流在操作文本上面更方便一點而已
此外,為什么要利用緩沖區呢?
我們知道,像迅雷等下載軟件都有個緩存的功能,硬盤本身也有緩沖區
試想一下,如果一有數據,不論大小就開始讀寫,勢必會給硬盤造成很大負擔,它會感覺很不爽
人不也一樣,一頓飯不讓你一次吃完,每分鐘喂一勺,你怎么想?
因此,采用緩沖區能夠在讀寫大文件的時候有效提高效率
最后解決的一個問題是字節流和字符流的轉化,使用的是InputStreamReader和OutputStreamWriter,它們本身屬于的是reader和writer字符流,我們之所以會用到這些轉化流是因為系統有時候只給我們提供了字節流,為了方便操作,要用到字符流。比如說System.in標準輸入流就是字節流。你想從那里得到用戶在鍵盤上的輸入,只能是以轉換流將它轉換為Reader以方便自己的程序讀取輸入。再比如說Socket里的getInputStream()很明顯只給你提供字節流,你要想讀取字符,就得給他套個InputStreamReader()用來讀取。
package com.zaojiahua.iodemo;import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter;public class Test {public static void main(String[] args) throws IOException {//字節流和字符流的相互轉化FileInputStream fileInputStream = new FileInputStream("input.txt");//inputSreamReader本來就是reader對象,創建的時候需要傳入一個InputStream對象,將字節流轉化為字符流BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream));//將字符流轉化為字節流OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("output.txt"));BufferedWriter writer = new BufferedWriter(outputStreamWriter);//實現拷貝文件的操作String buf;while((buf = reader.readLine()) != null){writer.write(buf);writer.newLine();System.out.println(buf);}//關閉流reader.close();writer.close();} }參考鏈接
java中的IO操作總結(一) - Nerxious - 博客園
java中的IO操作|皂莢花
Java之美[從菜鳥到高手演變]之Java中的IO - 智慧演繹,無處不在 - 博客頻道 - CSDN.NET
總結
以上是生活随笔為你收集整理的Java之IO操作总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用C与C++混合编程封装UDP协议
- 下一篇: java美元兑换,(Java实现) 美元