2017java檔案操作(讀寫操作)
java的讀寫操作是學java開發的必經之路,下面就來總結下java的讀寫操作。
從上圖可以開出,java的讀寫操作(輸入輸出)可以用“流”這個概念來表示,總體而言,java的讀寫操作又分為兩種:字元流和位元組流。
什麼是流?
流是一個抽象的概念。當Java程式需要從資料來源讀取資料時,會開啟一個到資料來源的流。資料來源可以是檔案,記憶體或者網路等。同樣,當程式需要輸出資料到目的地時也一樣會開啟一個流,資料目的地也可以是檔案、記憶體或者網路等。流的建立是為了更方便地處理資料的輸入輸出。
那麼位元組流和字元流又有什麼區別呢?
1.位元組流也稱為原始資料,需要使用者讀入後進行相應的編碼轉換。而字元流的實現是基於自動轉換的,讀取資料時會把資料按照JVM的預設編碼自動轉換成字元。
2.字元流處理的單元為2個位元組的Unicode字元,分別操作字元、字元陣列或字串,而位元組流處理單元為1個位元組,操作位元組和位元組陣列。
所以字元流是由Java虛擬機器將位元組轉化為2個位元組的Unicode字元為單位的字元而成的。
3.位元組流可用於任何型別的物件,包括二進位制物件,而字元流只能處理字元或者字串,位元組流提供了處理任何型別的IO操作的功能,但它不能直接處理Unicode字元,而字元流就可以;
基於以上的區別,那麼什麼情況下用字元流,什麼情況下用位元組流呢?
如果是音訊檔案、圖片、歌曲,就用位元組流好點;如果是中文(文字)的,用字元流更好;
說了這麼多,位元組流和字元流處理檔案到底怎麼用呢?
稍安勿躁,讓我們先來看看在java中,輸入輸出操作的步驟是什麼?
1 使用File類開啟一個檔案
通過位元組流或字元流的子類,指定輸出的位置,注,
3 進行讀/寫操作
4 關閉輸入/輸出
IO操作屬於資源操作,一定要記得關閉
位元組流:
1.按照位元組流的方式從檔案中讀取資料。
package ioInJava.characterStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException;import java.io.InputStream; public class CharIo { public static void main(String[] args) { // 第一種方式讀檔案,因為方法throws了異常,所以在這要捕獲異常 try { CharIo.readFromFileByByte(); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("找不到檔案啊"); } catch (IOException e) { e.printStackTrace(); System.out.println("讀不成功啊!"); } System.out.println("==========================="); // 第二種方式讀檔案 try { CharIo.readFromFileByteTwo(); } catch (IOException e) { e.printStackTrace(); System.out.println("還是讀不成功啊!"); } } /** * 第一種方法讀檔案 * 通過字元流讀取檔案中的資料 * @throws IOException */ public static void readFromFileByByte() throws IOException{ File file = new File("abc.txt"); // 如果檔案不存在則建立檔案 if (!file.exists()) { file.createNewFile(); } InputStream inputStream = new FileInputStream(file); // 這裡定義了陣列的長度是1024個位元組,如果檔案超出這位元組,就會溢位,結果就是讀不到1024位元組以後的東西 byte[] bs = new byte[1024]; // 這裡len獲得的是檔案中內容的長度 int len = inputStream.read(bs); inputStream.close(); System.out.println(new String(bs)); } /** * 第二種方法讀檔案 * 通過字元流讀取檔案中的資料 * @throws IOException */ public static void readFromFileByteTwo() throws IOException{ // 注意這裡的不同,File.separator是分隔符,這裡指明絕對路徑,即D盤根目錄下的abc.txt檔案 File file = new File("d:" + File.separator+"abc.txt"); // 如果檔案不存在則建立檔案 if (!file.exists()) { file.createNewFile(); } InputStream inputStream = new FileInputStream(file); // 這裡也有不同,可以根據檔案的大小來宣告byte陣列的大小,確保能把檔案讀完 byte[] bs = new byte[(int)file.length()]; // read()方法每次只能讀一個byte的內容 inputStream.read(bs); inputStream.close(); System.out.println(new String(bs)); } }
2.按照位元組流的方式向檔案中寫入資料。
package ioInJava.byteStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; /** * 不要被那麼多的try和catch嚇到奧,那只是因為不想在main上throws * @author wsg */ public class WriteToFile { public static void main(String[] args) { File file = new File("D:"+File.separator+"write.doc"); OutputStream outputStream = null; if (!file.exists()) { try { // 如果檔案找不到,就new一個 file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { // 定義輸出流,寫入檔案的流 outputStream = new FileOutputStream(file); } catch (FileNotFoundException e) { e.printStackTrace(); } // 定義將要寫入檔案的資料 String string = "Hell Java, Hello World, 你好,世界!"; // 把string轉換成byte型的,並存放在陣列中 byte[] bs = string.getBytes(); try { // 寫入bs中的資料到file中 outputStream.write(bs); } catch (IOException e) { e.printStackTrace(); } try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } // =================到此,檔案的寫入已經完成了! // 如果想在檔案後面追加內容的話,用下面的方法 OutputStream outToFileEnd = null; try { outToFileEnd = new FileOutputStream(file,true); } catch (FileNotFoundException e) { e.printStackTrace(); }finally {// 這裡利用了finally總會被執行的特性,索性把後面的程式碼都寫在finally中 String string2 = "Here I come!!"; byte[] bs2 = string2.getBytes(); try { outToFileEnd.write(bs2); } catch (IOException e) { e.printStackTrace(); }finally { try { outToFileEnd.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
=====================================================注意!!==================================================
1.初學者一般很容易搞混,或者弄不清inputstream和outpustream到底哪個是讀資料,哪個是寫資料,這裡要說明的是,“讀和寫”是相對於程式本身而言的,主要記清楚一點即可,那就是凡是需要提供給程式處理的資料就是輸入資料,當然就是inputstream,這裡的in是要in到程式裡面去,那麼資料從哪裡來呢,自然是從外界(網路,記憶體或者檔案),那麼針對檔案而言,inputstream就是讀檔案了。反之,凡是程式已經處理過的資料,當然要流出程式啦,那就是out咯,所以outputstream就是輸出的,那麼從程式中流出,只能到外界(網路、記憶體或者檔案),針對檔案而言,就是寫操作啦!(同樣的道理可以針對字元流的操作)
【簡言之,針對程式而言,in是入,out是出;這對檔案而言,in是讀,out是寫!】
2.inputstream和OutputStream都是抽象類,不能例項化,使用時必須例項化一個子類(其中FileInputStream和FileOutputStream使用最多)物件來進行相關操作。
3.InputStream inputStream = new FileInputStream(fileName);當使用這個命令時,系統會提示有異常丟擲,因為我們上面定義的檔案程式認為是有可能存在,有可能不存在的,所以在eclipse中,給出了兩個解決辦法,一個是直接丟擲異常宣告,由系統自己解決;另一個是用try,catch結構處理異常!
===============================================================================================================
3.按照字元流的方式向檔案中寫入資料。
package ioInJava.characterStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Writer; public class CharIo { public static void main(String[] args) throws IOException { // 定義一個d盤根目錄下的test文件,File.separator是分隔符 // 下面這句程式碼,就算原本沒有這個檔案,也會在對應的目錄建立一個檔案 File file = new File("D:" + File.separator + "test.docx"); // 下面這也會丟擲異常,這次我們為了程式碼結構清晰起見,直接throw給main吧 Writer writer = new FileWriter(file); String string = "今天是教師節!"; writer.write(string); // 在這一定要記得關閉流 writer.close(); } }
但是,上面的程式碼有一個問題,比如,載定義一個string2,再次呼叫writer.write(string2)方法的時候,會發現test檔案中的內容會被string2的內容覆蓋,要想實現內容追加到檔案尾部,程式碼如下,其實就是小小的修改,利用它的一個方法!
package ioInJava.characterStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Writer; public class CharIo { public static void main(String[] args) throws IOException { // 定義一個d盤根目錄下的test文件,File.separator是分隔符 // 下面這句程式碼,就算原本沒有這個檔案,也會在對應的目錄建立一個檔案 File file = new File("D:" + File.separator + "test.docx"); // 下面這也會丟擲異常,這次我們為了程式碼結構清晰起見,直接throw給main吧 // 這裡改變了writer的型別,變成了追加型 Writer writer = new FileWriter(file, true); String string = "今天是教師節!"; writer.write(string); String string2 = "祝願所有的老師教師節快樂!"; writer.write(string2);; // 在這一定要記得關閉流 writer.close(); } }
4.按照字元流的方式從檔案中讀取資料。
package ioInJava.characterStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; public class ReadFromFile { public static void main(String[] args) throws IOException { File file = new File("d:" + File.separator + "test.docx"); Reader reader = new FileReader(file); char[] cs= new char[1024]; // 上面定義了一個大小為1024的char型陣列,如果檔案內容過大,程式就會報錯,而不是隻讀到1024的大小 reader.read(cs, 0, (int)file.length()); System.out.println(cs); reader.close(); } }
上面的程式碼只能讀取內容不超過1024字元的內容,這顯然不是我們想要的,如何讀取一個任意大小的檔案呢!那麼最簡單的方法就是加大陣列的空間大小了,可以用file.length獲取檔案的大小,從而定義陣列的大小!char[] cs= new char[(int)file.length()];
當然,這不是最好的辦法,請看下面的程式碼:
package ioInJava.characterStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.io.Writer; public class ReadFromFile { public static void main(String[] args) throws IOException { try { // 宣告一個可變長的stringBuffer物件 StringBuffer sb = new StringBuffer(""); /* * 讀取完整檔案 */ Reader reader = new FileReader("d:" + File.separator + "test.docx"); // 這裡我們用到了字元操作的BufferedReader類 BufferedReader bufferedReader = new BufferedReader(reader); String string = null; // 按行讀取,結束的判斷是是否為null,按位元組或者字元讀取時結束的標誌是-1 while ((string = bufferedReader.readLine()) != null) { // 這裡我們用到了StringBuffer的append方法,這個比string的“+”要高效 sb.append(string + "/n"); System.out.println(string); } // 注意這兩個關閉的順序 bufferedReader.close(); reader.close(); /* * 完整寫入檔案 */ Writer writer = new FileWriter("d:" + File.separator + "test2.docx"); BufferedWriter bw = new BufferedWriter(writer); // 注意這裡呼叫了toString方法 bw.write(sb.toString()); // 注意這兩個關閉的順序 bw.close(); writer.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
上面的程式碼我們順利實現了從test檔案中讀取全文,並將其寫入test2檔案中!!
摘自:https://www.cnblogs.com/wsg25/p/7499227.html