File類File類概述和構造方法
檔案和資料夾都存放在磁碟的某個路徑下,java.io.File類是檔案和目錄(資料夾)路徑名的抽象表示,主要用於檔案和目錄(資料夾)的建立、查詢、刪除等操作。
操作檔案和目錄之前需要先使用File類的構造方法來建立File物件File類的構造方法
public File(String pathName) 透過給定的路徑字串轉換為抽象的路徑建立新的File例項public File(String parent,String child) 從父路徑名字字串和子路徑字串建立新的File例項public File(File parent,String child) 從父抽象路徑和子路徑名字字串建立新的File例項在使用File表示檔案或者目錄時,無論檔案或者目錄是否真實存在,都可以使用檔案和目錄來建立File物件。
macOS的目錄結構和Linux一樣都是單根結構,即使用/表示根目錄Windows使用磁碟的碟符表示根目錄,例如C盤
File類常用方法File類獲取檔案、目錄資訊常用方法
public String getAbsolutePath() 獲取file物件的絕對路徑字串public String getPath() 獲取file物件的構造路徑,也就是構造方法中傳的路徑public String getName() 返回File物件表示的檔案或者目錄名稱public long length() 返回由File表示檔案的位元組大小,但是不能獲取資料夾的大小絕對路徑就是從磁碟的根路徑開始的目錄,Windows下是以碟符開始的完整路徑,而Linux/macOS下是以/開始的完整路徑相對路徑是相對當前路徑開始的路徑
File類獲取檔案資訊常用方法測試用例
File類獲取資料夾資訊常用方法測試用例
/** * 獲取資料夾的資訊 */ @Test public void testGetFilePathInfo(){ //以檔案建立File物件 File javaCore=new File("java-core"); //獲取java-core所在的絕對路徑 String absolutePath=javaCore.getAbsolutePath(); log.info("獲取java-core所在的絕對路徑{}",absolutePath); //獲取java-core的構造路徑 String constructPath=javaCore.getPath(); log.info("獲取java-core的構造路徑{}",constructPath); String fileName =javaCore.getName(); log.info("java-core表示的檔名{}",fileName); //File物件的length()方法只能獲取檔案大小,不能獲取資料夾大小 long fileSize=javaCore.length(); //因此輸出結果是0 log.info("javaCore資料夾的大小是{}",fileSize); }
程式執行結果
File類判斷檔案、目錄方法,這些方法的返回值都是布林型別,只會對真實存在的路徑、資料夾有效,如果不存在直接返回false
public boolean exists() 檔案或者目錄是否存在public boolean isDirectory() 當前file物件是否是目錄public boolean isFile() 當前file物件是否是檔案檔案、資料夾常用判斷方法測試用例
public boolean createNewFile() throws IOException 當檔案不存在時,建立一個空檔案,如果檔案存在不會覆蓋public boolean delete() 刪除File表示的檔案或者目錄,刪除資料夾時不能刪除非空資料夾使用File物件完成檔案的建立和刪除測試用例
/** * 使用File物件完成檔案的建立和刪除測試用例 */ @Test public void testFileCreateDelete() { //在Document目錄下建立一個test.txt目錄 String fileName = "test.txt"; File file = new File("/Users/liuguanglei/Documents", fileName); log.info("test.txt檔案是否存在{}", file.exists()); try { //檔案或者目錄不存在時建立一個空檔案 file.createNewFile(); log.info("test.txt檔案是否存在{}", file.exists()); } catch (IOException e) { e.printStackTrace(); } boolean delete = file.delete(); log.info(fileName + "是否刪除成功{}", delete); }
程式執行結果
public boolean mkdir() 建立目錄,目錄層級只能是一級public boolean mkdirs() 建立多級目錄/** * 資料夾的建立 */ @Test public void testMkDirs(){ String directoryName = "file"; File newDirectory = new File("/Users/liuguanglei/Documents", directoryName); if (!newDirectory.exists()) { //在Documents目錄下建立file目錄 newDirectory.mkdir(); } boolean fileDirectoryDeleteFlag = newDirectory.delete(); log.info(directoryName + "是否刪除成功{}", fileDirectoryDeleteFlag); String multiLevelDirectoryName = "parent/child"; File multiLevelDirectoryFile = new File("/Users/liuguanglei/Documents/", multiLevelDirectoryName); boolean mkdirs = multiLevelDirectoryFile.mkdirs(); log.info(multiLevelDirectoryName + "多級目錄是否建立成功?{}", mkdirs); }
程式執行結果
使用File類遍歷子檔案和子資料夾
public String[] list() 獲取File物件指定目錄的子目錄或者子檔案public File[] listFiles() 獲取File物件指定目錄的子目錄路徑或者子檔案的File物件list()和listFiles()方法只能訪問一級子目錄,如果想要訪問多級,需要使用遞迴演算法實現。
list()和listFiles()方法如果獲取的File指定的目錄或者檔案不存在或者沒有訪問許可權,會引發空指標異常。因此在遍歷子檔案或者子目錄之前需要使用非空判斷。
/** * 定義一個遞迴方法 */ void recursionMethodV1(){ //方法內部呼叫自己 recursionMethodV1(); } /** * 遞迴方法沒有出棧就會在程式執行後導致棧記憶體溢位 */ @Test public void testRecursionStackOverflowErrorV1(){ recursionMethodV1(); }
程式執行結果
不正確的使用遞迴,會導致程式棧記憶體溢位(程式開闢的棧記憶體操過了JVM的最大棧記憶體)錯誤。因此在使用遞迴時,遞迴一定要有出口(結束)。
而且棧的出口不能太晚,否則也會造成程式棧記憶體溢位錯誤
static int count=0; void recursionMethodV2(){ count++; //統計執行次數 log.info("count = {}",count); //方法內部呼叫自己 recursionMethodV2(); } /** * 遞迴方法出棧太晚就會在程式執行後導致棧記憶體溢位 */ @Test public void testRecursionStackOverflowErrorV2(){ recursionMethodV2(); }
程式執行結果
程式執行結果
當方法執行到7001次後棧溢位,因此如果要出棧必須在呼叫7000次之前出棧,具體的呼叫次數導致棧溢位錯誤和機器效能有關係。
遞迴演算法在日常開發中也比較常用
遞迴的應用:使用遞迴計算n的累加求和
/** * 遞迴求累加和 * 1的累加和是1 * 2的累加和是1+2 * 3的累加和是1+2+3 * 4的累加和是1+2+3+4 * 5的累加和是1+2+3+4+5 * * 規律 n的累加和等於n+(n-1)的累加和 */ int recursionSum(int n){ //遞迴的出口 為了不出現棧記憶體溢位錯誤 //n等於1 if(n==1){ //直接返回1 return 1; } //遞迴的規律 即什麼時候開始遞迴計算 return n+recursionSum(n-1); }
n的累加求和測試用例
/** * n的累加求和測試用例 */ @Test public void testRecursionSum(){ int n=5; int result=recursionSum(n); log.info("{}的累加和的結果是{}",n,result); }
程式執行結果
遞迴的應用:實現n的階乘,即所有小於或者等於該數的正整數的積
例如 5的階乘就是1*2*3*4*5=120
/** * 實現n的階乘 * @param n * @return */ public long recursionFactorial(long n){ //n等於1 直接返回1 if(n==1){ return 1; } //遞迴計算n的階乘 return n*recursionFactorial(n-1); }
n的階乘測試用例
/** * n的階乘測試用例 */ @Test public void testRecursionFactorial(){ long n=5; long result=recursionFactorial(n); log.info("{}的階乘的結果是{}",n,result); }
程式執行結果
遞迴的應用:使用遞迴實現查詢指定字尾的檔案
/** * 使用遞迴查詢指定目錄的指定字尾的檔案 * @param path * @param suffix */ void recursionFileSearch(String path,String suffix){ //建立File物件 File currentFile=new File(path); //獲取當前目錄的所有子資料夾和子檔案的File物件 File[] files=currentFile.listFiles(); for (File file : files) { if(file.isFile()&&file.getName().endsWith(suffix)){ log.info(file); } // 如果是目錄,則遞迴呼叫 else if(file.isDirectory()){ recursionFileSearch(file.getAbsolutePath(),suffix); } } }
遞迴查詢自動檔案字尾測試用例
遞迴的應用:統計資料夾大小
long allSize = 0; /** * 統計指定目錄的檔案大小 單位是位元組 * * @param path * @return */ public long staticFileSize(String path) { File currentFile = new File(path); if (currentFile.isFile()) { return currentFile.length(); } File[] files = currentFile.listFiles(); for (File file : files) { if (file.isFile()) { allSize += file.length(); } if (file.isDirectory()) { staticFileSize(file.getAbsolutePath()); } } return allSize; } @Test public void testStaticFileSize() { String path = "/Users/liuguanglei/Documents/book"; long size = staticFileSize(path); log.info("size ={} ", size); }
程式執行結果
/** * 刪除非空資料夾 */ public void deleteFolder(String path) { File currentFile = new File(path); if (currentFile.isFile()) { currentFile.delete(); return; } File[] files = currentFile.listFiles(); for (File file : files) { if (file.isFile()) { file.delete(); } else if (file.isDirectory()) { //刪除檔案 deleteFolder(file.getAbsolutePath()); //刪除資料夾 file.delete(); } } //刪除目錄 if(currentFile.isDirectory()){ currentFile.delete(); } } @Test public void testDeleteFolder() { String path = "/Users/liuguanglei/Documents/java"; deleteFolder(path); }
刪除之前的資料夾目錄
程式執行結果
IO流IO概述I(Input)O(Output) 表示輸入輸出,因為程式執行時會被載入到記憶體中,輸入表示從其他儲存裝置(例如磁碟)讀取資料到記憶體中,而輸出表示從記憶體寫資料到其他儲存裝置(例如磁碟)中IO流的分類按照流向分為輸入流和輸出流輸入流分為位元組輸入流和字元輸入流,其中位元組輸入流是以位元組為基本單位讀資料,而字元輸入流是以字元為基本單位讀資料輸出流也分為位元組輸出流和字元輸出流,其中位元組輸出流以位元組為基本單位寫資料,而字元輸出流以字元為基本單位寫輸出。
IO流的分類按照型別分為位元組流和字元流,位元組流以位元組為單位進行讀寫資料,位元組流可以操作文字檔案和二進位制檔案,例如圖片,音訊,影片,字元流以字元為單位進行讀寫資料,只能操作文字檔案。
編碼說明IDEA預設的編碼是UTF-8有些Windows系統預設的編碼是ANSI,有些是UTF-8簡體中文下ANSI編碼就是GBK編碼一箇中文在UTF-8編碼下佔據3個位元組,而一箇中文在GBK編碼下佔據2個位元組。編碼就是字元對應的二進位制儲存編號,例如字元A在計算機內部儲存的編號是65
位元組流位元組輸出流 java.io.OutputStream,該類是一個抽象類,表示所有位元組輸出流的頂級父類,表示以位元組為單位寫資料,常用子類有java.io.FileOutputStream使用File物件建立FileOutputStream物件
如果File指定的目錄不存在,則會觸發java.io.FileNotFoundException異常如果File指定的檔案不存在,則會建立一個空檔案如果File指定的檔案存在,則會清空檔案內容
/** * FileOutputStream構造器測試用例 * 使用File引數建立FileOutputStream物件 */ @Test public void testOutputStreamConstructor(){ //如果檔案不存在會建立空檔案 ,如果目錄不存在 則會觸發java.io.FileNotFoundException異常 try { OutputStream sourceOutputStream=new FileOutputStream(new File("/Users/liuguanglei/Documents/test/source.txt")); //如果檔案存在,清空檔案內容 // OutputStream targetOutputStream=new FileOutputStream(new File("/Users/liuguanglei/Documents/test/target.txt")); } catch (FileNotFoundException e) { e.printStackTrace(); } }
建立OutputStream物件後,就可以使用該物件的write()方法寫資料到指定的檔案中。其中寫資料的方式可以傳單個位元組、位元組陣列,或者是指定範圍的位元組陣列三種方式寫入資料。寫完資料後需要呼叫OutputStream的close()方法關閉資源。
/** * OutputStream可以透過write()方法寫資料 * @see OutputStream#write(int) * @see OutputStream#write(byte[]) * @see OutputStream#write(byte[], int, int); */ @Test public void testOutputStreamWriteData(){ OutputStream sourceOutputStream = null; try { sourceOutputStream=new FileOutputStream(new File("/Users/liuguanglei/Documents/test/source.txt")); String str="跟光磊學Java開發"; byte[] bytes = str.getBytes(); //將跟光磊學Java開發寫入到source.txt檔案中 sourceOutputStream.write(bytes); //寫一個位元組到source.txt中 //檔案儲存的97,編輯器以字元的方式解析,開啟的是字元a sourceOutputStream.write(97); byte[]data=new byte[]{98,99,100,101,102,103}; //將指定位元組陣列長度的內容寫入到source.txt //這裡寫入的是bcd sourceOutputStream.write(data,0,3); } catch (IOException e) { e.printStackTrace(); } finally { try { //關閉流 sourceOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行效果
由於傳遞File物件的FileOutputStream構造方法 預設會清空已經存在的檔案資料。如果想要拼接寫入的資料,可以使用FileOutputStream(File, boolean)構造方法,如果boolean引數的值是true,在寫入資料時不會情況原有的資料,會拼接新寫入的資料
/** * 使用FileOutputStream(File, boolean) 構造方法實現寫資料時拼接原有檔案的資料 * @see FileOutputStream#FileOutputStream(File, boolean) */ @Test public void testOutputStreamWriteAppendData(){ OutputStream sourceOutputStream = null; try { sourceOutputStream=new FileOutputStream(new File("/Users/liuguanglei/Documents/test/source.txt"),true); String str="跟光磊學前端開發"; byte[] bytes = str.getBytes(); //將跟光磊學Java開發寫入到source.txt檔案中 sourceOutputStream.write(bytes); } catch (IOException e) { e.printStackTrace(); } finally { try { //關閉流 sourceOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
OutputStream在寫資料時預設是不會換行的,但是不同的作業系統換行是不一樣的
Windows 10的換行是\r \nmacOS11的換行是\n可以使用System.getProperty("os.name")方法獲取當前系統,然後分別處理 /** * 換行寫資料 * * @see */ @Test public void testOutputStreamNewLineWriteData() { OutputStream sourceOutputStream = null; try { sourceOutputStream = new FileOutputStream(new File("/Users/liuguanglei/Documents/test/target.txt"), false); //由於不同作業系統的換行處理不同,需要分別處理 //獲取當前作業系統名稱 String osName = System.getProperty("os.name"); if (osName.equals("Mac OS X")) { //將跟光磊學Java開發寫入到source.txt檔案中 sourceOutputStream.write("跟光磊學Java開發\n".getBytes()); sourceOutputStream.write("跟光磊學大前端開發\n".getBytes()); sourceOutputStream.write("跟光磊學大資料開發\n".getBytes()); } else if (osName.equals("Windows 10")) { //將跟光磊學Java開發寫入到source.txt檔案中 sourceOutputStream.write("跟光磊學Java開發\r\n".getBytes()); sourceOutputStream.write("跟光磊學大前端開發\n\n".getBytes()); sourceOutputStream.write("跟光磊學大資料開發\n\n".getBytes()); } } catch (IOException e) { e.printStackTrace(); } finally { try { //關閉流 sourceOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
位元組輸入流 java.io.InputStream,該類是一個抽象類,表示位元組輸入流的所有超類,用於將儲存裝置的資料讀入到記憶體中,常用子類有java.io.FileInputStream首先準備一個測試檔案test.txt該檔案內容包含了26個字母和13個數字
使用File物件建立FileInputStream物件,File物件指定路徑的檔案必須存在,如果不存在會引發FileNotFoundException異常
/** * FileInputStream物件的建立 * 必須傳入一個檔案路徑。如果檔案不存在會引發FileNotFoundException異常 * * @see FileInputStream#FileInputStream(File) */ @Test public void testFileInputStreamConstructor() { try { //透過File建立FileInputStream物件 關聯/Users/liuguanglei/Documents/test/test.txt檔案 //檔案不存在會引發FileNotFoundException異常 InputStream inputStream = new FileInputStream(new File("/Users/liuguanglei/Documents/test/test.txt")); } catch (FileNotFoundException e) { e.printStackTrace(); } }
FileInputStream在讀取檔案時,可以一次讀取一個位元組
/** * FileInputStream讀取資料 * * @see FileInputStream#read() 每次讀取一個位元組,讀到檔案末尾返回-1 */ @Test public void testFileInputStreamReadOneByteData() { InputStream inputStream = null; try { inputStream = new FileInputStream(new File("/Users/liuguanglei/Documents/test/test.txt")); //迴圈讀取 int value = 0; //讀取一個位元組資料賦值給value 然後拿value的值和-1進行迴圈比較 while ((value = inputStream.read()) != -1) { //將讀取的內容轉換為字元輸出 log.info((char)value); } } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
FileInputStream讀取檔案時也可以一次性讀取指定長度的位元組陣列
/ /** * FileInputStream讀取資料 * * @see FileInputStream#read(byte[]) 從輸入流讀取一些位元組,儲存到位元組陣列中,返回的是讀取到的字元個數 */ @Test public void testFileInputStreamReadByteArray() { InputStream inputStream = null; try { inputStream = new FileInputStream(new File("/Users/liuguanglei/Documents/test/test.txt")); //一般來說檔案大小大於8192位元組,寫8192,小於8192位元組任意寫 //每次讀取3個位元組儲存到data位元組陣列中 byte[] data = new byte[2]; int byteLength = 0; while ((byteLength = inputStream.read(data)) != -1) { log.info("讀取的檔案內容是{}", new String(data,0,byteLength)); } } catch (IOException e) { e.printStackTrace(); } finally { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
FileInputStream和FileOutputStream不僅能操作文字檔案,還可以操作二進位制檔案,例如圖片、音訊、影片等等。
使用FileInputStream和FileOutputStream實現圖片複製
第一個版本是每次複製一個位元組
/** * 使用位元組流實現圖片檔案的複製,一次複製1個位元組 * */ @Test public void testImageCopyV1() { //源圖片檔案 File sourceImageFile = new File("/Users/liuguanglei/Documents/test/james_gosling.jpg"); //目標圖片檔案 File targetImageFile = new File("/Users/liuguanglei/Documents/test/james_gosling_v1.jpg"); //基於位元組的輸入流 FileInputStream fileInputStream = null; //基於位元組的輸出流 FileOutputStream fileOutputStream = null; try { //建立輸入輸出流物件 fileInputStream = new FileInputStream(sourceImageFile); fileOutputStream = new FileOutputStream(targetImageFile); //迴圈讀取james_gosling.jpg檔案的輸入流 int length = 0; while ((length = fileInputStream.read()) != -1) { //將讀取到的james_gosling.jpg寫入到james_gosling_v1.jpg檔案中,每次寫一個位元組 fileOutputStream.write(length); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
第二個版本是每次複製8個位元組
/** * 使用位元組流實現圖片檔案的複製,一次複製8個位元組 * */ @Test public void testImageCopyV2() { File sourceImageFile = new File("/Users/liuguanglei/Documents/test/james_gosling.jpg"); File targetImageFile = new File("/Users/liuguanglei/Documents/test/james_gosling_v2.jpg"); FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(sourceImageFile); fileOutputStream = new FileOutputStream(targetImageFile); int length = 0; byte[] buffer=new byte[8192]; //每次讀取八個位元組 while ((length = fileInputStream.read(buffer)) != -1) { //按照讀取檔案返回的長度寫入,因為檔案內容可能最後不足8個位元組 fileOutputStream.write(buffer,0,length); } } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
字元流字元輸入流 java.io.Reader,該類是一個抽象類,是所有字元輸入流的父類,用於讀取字元到記憶體中,常用子類有java.io.FileReaderFileReader提供了基於File物件和字串路徑兩種方式建立物件,指定路徑的檔案不存在會引發FileNotFoundException
/** * FileReader構造方法 * @see FileReader#FileReader(File) * @see FileReader#FileReader(String) */ @Test public void testFileReaderConstructor(){ try { Reader readerByFile = new FileReader(new File("/Users/liuguanglei/Documents/test/chinese.txt")); Reader readerByPath = new FileReader("/Users/liuguanglei/Documents/test/chinese.txt"); } catch (FileNotFoundException e) { e.printStackTrace(); } }
Reader提供了read()方法用於讀取文字檔案,每次讀取一個位元組
首先準備測試檔案chinese.txt
/** * 讀取單個字元 * * @see FileReader#read() 讀取單個字元並返回,讀到檔案末尾返回-1 */ @Test public void testFileReaderChar() { Reader reader=null; try { reader = new FileReader(new File("/Users/liuguanglei/Documents/test/chinese.txt")); int value = 0; while ((value = reader.read()) != -1) { log.info((char) value); } } catch (IOException e) { e.printStackTrace(); }finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
Reader提供了read(char[]) 方法用於讀取文字檔案,每次讀取指定的位元組陣列,讀取結束返回-1
/** * @see FileReader#read(char[]) 從輸入流讀取一些字元,儲存到字元陣列中,讀取結束返回-1 */ @Test public void testFileReaderCharArray(){ Reader reader=null; try { reader = new FileReader(new File("/Users/liuguanglei/Documents/test/chinese.txt")); //每次讀取3個字元儲存到buf字元陣列中 char[]buf=new char[3]; int length =0; while((length=reader.read(buf))!=-1){ log.info(new String(buf,0,length)); } } catch (IOException e) { e.printStackTrace(); }finally { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
字元輸出流 java.io.Writer,該類是一個抽象類,是所有字元輸出流的父類,用於寫字元資料到其他檔案,常用子類有java.io.FileWriter首先準備測試檔案file_write.txt
FileWriter和FileOutputStream一樣,也提供了基於File和字串路徑兩種方式來建立物件如果指定的目錄不存在會引發java.io.FileNotFoundException異常如果指定的路徑檔案不存在會建立空檔案如果指定的檔案存在預設會清空檔案內容,再寫檔案,FileWriter#FileWriter(File, boolean) 構造方法的布林值如果是true則不會清空檔案原有內容
/** * FileWriter物件的建立 * @see FileWriter#FileWriter(File, boolean) */ @Test public void testFileWriterConstructor(){ Writer writer=null; try { //基於File建立FileWrite物件,預設追加寫檔案,即不會覆蓋檔案原有內容 writer=new FileWriter(new File("/Users/liuguanglei/Documents/test/file_write.txt"),true); } catch (IOException e) { e.printStackTrace(); }finally { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } }
而FileWriter在寫資料時,可以寫入字串、字元陣列或者指定長度的字串、字元陣列
/** * 使用Writer寫資料 * 關閉流寫資料到檔案 * * @see FileWriter#write(String) * @see FileWriter#write(char[]) * @see FileWriter#write(char[], int off, int len) * @see FileWriter#write(String, int off, int len) * @see FileWriter#write(int) */ @Test public void testFileWrite() { Writer writer = null; try { //基於File建立FileWrite物件,預設追加寫檔案,即不會覆蓋檔案原有內容 writer = new FileWriter(new File("/Users/liuguanglei/Documents/test/file_write.txt"), true); //寫入字串 writer.write("hello world"); //寫入字元陣列 char[] charArray = new char[]{'你', '好', '世', '界'}; writer.write(charArray); String str = "跟光磊學Java,"; writer.write(str, 0, str.length() - 1); //寫入一箇中字元 int zhong = '中'; writer.write(zhong); } catch (IOException e) { e.printStackTrace(); } finally { try { //必須要關閉流 writer.close(); } catch (IOException e) { e.printStackTrace(); } } }
程式執行結果
當多次執行testFileWrite()方法時,可以拼接資料寫入到file_write.txt檔案中,而不會清空上次寫入的資料
在使用FileWrite物件的write()方法寫資料時,由於記憶體快取區的原因,如果不關閉輸出流或者重新整理緩衝區,那麼無法寫入到字元檔案中。
close()關閉流flush() 重新整理緩衝區關閉流後流不能再使用,如果使用系統會提示流已經關閉,而重新整理緩衝區後流物件依然可以使用。