一 JAVA語言中主要通過流來完成IO操作。
流:計算機的輸入輸出之間流動的數據序列,也是類的對象。java中的流方式就像是建立在數據交換源和目的之間的一條通信路徑。
數據源:計算機中的數據源是指可以提供數據的地方,包括鍵盤,磁盤文件,網絡接口等。
輸入流:從程序外部傳向程序的流。輸入流只能從中讀數據。
輸出流: 從程序傳到外部的流。輸出流只能向其寫入數據。
所謂的輸入和輸出是以程序為中心的,數據流向程序即輸入流,數據從程序中流出即輸出流。
二 字節流
字節流是以字節為傳輸單位的數據讀寫形式,用於直接讀取二進制數據,如圖像和聲音文件等。
InputStream和OutputStream分別為面向字節的輸入流類的父類和輸出流類的父類。InputStream和OutputStream都是抽象類。
FileInputStream和FileOutputStream是文件流類,他們是InputStream和OutputStream的子類。
FileInputStream類的一般用法是:先創建一個FileInputStream對象關聯到要讀取的文件,然后調用read方法讀取字節數據到程序中,再進行其他處理。因為read方法是按字節的讀入的,所以漢字被讀入時會出現亂碼。
FileOutputStream類的一般用法是:先創建一個FileOutputStream對象關聯到要寫入的文件,然后調用write方法將字節數據寫到程序中。如果進行寫操作的文件不存在,則自動創建該文件,但是如果文件所在的路徑也不存在,則運行時會報錯。
例如 FileOutputStream fos = new FileOutputStream("D:\\test.txt");是不會報錯的,
FileOutputStream fos = new FileOutputStream("D:\\tmp\\test.txt");如果之前在D盤中沒有tmp這個文件夾,那么此時運行這條語句會報錯。
代碼如下

1 package 文件操作_FileInputStream和FileOutputStream; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 8 public class FileDemo { 9 public static void main(String[] args) { 10 try { 11 FileInputStream fis = new FileInputStream("D:\\test.txt"); 12 int ch = fis.read(); 13 while (ch != -1) { 14 System.out.print((char) ch); 15 ch = fis.read(); 16 } 17 // byte[] buffer = new byte[8]; 18 // fis.read(buffer); 19 // for (int i = 0; i < buffer.length; i++) { 20 // System.out.print((char) buffer[i]); 21 // } 22 FileOutputStream fos = new FileOutputStream("D:\\test1.txt"); 23 byte[] b = {'a', 'c', 'd', 'e', 'x'}; 24 fos.write(b); 25 fis.close(); 26 fos.close(); 27 } catch (FileNotFoundException e) { 28 // TODO Auto-generated catch block 29 e.printStackTrace(); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 } 34 35 36 }
緩存流 BufferedInputStream 和 BufferedOutputStream
使用緩存流可以提高大文件的讀寫效率。例如從文件讀入數據時,每次從輸入流中讀取較大的數據量存入內存緩沖區,具體的讀操作針對該緩沖區進行;執行緩沖輸出時,每次將輸出流中的數據寫入到內存緩沖區,知道緩沖區寫滿,才將數據寫入到最終的介質中。
使用緩存流的缺點:當計算機突然關閉時,可能會丟失數據。通過清空緩沖區的數據可以減少這種情況的發生,使用flush()方法即可。
代碼如下

1 package 文件操作_BufferedInputStream; 2 3 import java.io.BufferedInputStream; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 8 public class BufferDemo { 9 public static void main(String[] args) { 10 try { 11 FileInputStream fis = new FileInputStream("D:\\test.txt"); 12 BufferedInputStream bis = new BufferedInputStream(fis); //默認的輸入緩沖區是2048B 13 int ch = bis.read(); 14 while (ch != -1) { 15 System.out.print((char)ch); 16 ch = bis.read(); 17 } 18 19 } catch (FileNotFoundException e) { 20 // TODO Auto-generated catch block 21 e.printStackTrace(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 } 26 27 }
三 字符流
Reader 和 Writer類是所有字符流的父類。一次讀取或是寫入兩個字節,16位,即一個Unicode字符,因此可以使用字符流直接讀寫漢字內容。
BufferedReader 和 BufferedWriter類的用法示例

1 package 文件操作_字符流_BufferedReader和BufferedWriter; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.FileNotFoundException; 6 import java.io.FileReader; 7 import java.io.FileWriter; 8 import java.io.IOException; 9 10 public class BufferedDemo { 11 public static void main(String[] args) { 12 try { 13 FileReader fr = new FileReader("D:\\test.txt"); 14 BufferedReader br = new BufferedReader(fr); 15 FileWriter fw = new FileWriter("D:\\test1.txt"); 16 BufferedWriter bw = new BufferedWriter(fw); 17 String str = br.readLine(); 18 while (str != null) { 19 bw.write(str); 20 bw.newLine(); 21 str = br.readLine(); 22 } 23 br.close(); 24 bw.close(); 25 } catch (FileNotFoundException e) { 26 // TODO Auto-generated catch block 27 e.printStackTrace(); 28 } catch (IOException e) { 29 e.printStackTrace(); 30 } 31 } 32 33 }
四 File文件類
File aa = new File(aaName); 這里的aa可以指向文件,也可以指向文件夾
在進行文件的操作時,若操作的對象是文件,那么在進行文件的創建,刪除,復制之前,
(1)需要判斷文件是否存在,
(2)以及File所指向的對象是一個文件還是一個文件夾(目錄)
(3)該文件所在的文件夾是否存在,file.getParentFile().exists()
(4)若文件所在的文件夾不存在,需要建立其父文件夾,若未建立成功,返回false
if (!file.getParentFile().mkdirs()) return false;
在對文件夾(目錄)進行操作時,
(1)首先判斷 dirName 是不是以文件分隔符 File.separator結尾,如果不是,
則 dirName += File.separator;
(2)需要判斷 File dir = new File(dirName) 中的dir是不是存在以及指向的是不是一個文件夾 dir.exists() dir.isDirctory();
(3) 在對文件夾進行復制,刪除等操作時,一般會用到遞歸,因為文件夾里面有時候會存在子文件夾。
程序示例1 刪除指定目錄下的文件

1 package 輸入輸出流_刪除指定目錄下的文件; 2 3 import java.io.File; 4 5 //delete()方法可以刪除文件和文件夾,當成功刪除文件或文件夾后,返回true 否則返回false 6 //在使用delete()方法時,如果此路徑名表示一個文件夾(目錄),則此目錄必須為空才能刪除 7 //(若要刪除文件夾,需要先刪除文件夾中的文件和文件夾,才能刪除該文件夾) 8 public class FileDemo_05 { 9 10 public static boolean deleteFilesOrDir (String fileName) {//判斷將指定文件或文件夾刪除是否成功 11 File file = new File(fileName); 12 if (!file.exists()) { //指定的文件或文件夾不存在,返回false 13 System.out.println("文件刪除失敗,因為文件" + fileName + "不存在"); 14 return false; 15 } else { //指定的文件或是文件夾存在 16 if (file.isFile()) { //若file 是文件 17 return FileDemo_05.deleteFiles(fileName); 18 } else { //若file是文件夾 19 return FileDemo_05.deleteDir(fileName); 20 } 21 } 22 23 } 24 25 public static boolean deleteFiles(String fileName) { //判斷刪除指定文件是否成功 26 File file = new File(fileName); 27 if ( file.exists() && file.isFile() ) { 28 if (file.delete()) { 29 System.out.println("文件" + fileName + "刪除成功!"); 30 return true; 31 } else { 32 System.out.println("文件" + fileName + "刪除失敗!"); 33 return false; 34 } 35 } else { 36 System.out.println("文件刪除失敗 : " + fileName + "文件不存在!"); 37 return false; 38 } 39 40 } 41 42 public static boolean deleteDir(String dir) { //判斷刪除指定文件夾以及文件夾下的文件是否成功 43 if (!dir.endsWith(File.separator)) { 44 dir += File.separator; 45 } 46 File dirFile = new File(dir); 47 if (!dirFile.exists() || !dirFile.isDirectory()) { 48 System.out.println("文件夾刪除失敗!" + dir + "文件夾不存在"); 49 return false; 50 } 51 boolean flag = true; 52 File[] files = dirFile.listFiles(); 53 for (int i = 0; i < files.length; i++) { 54 if (files[i].isFile()) { //刪除文件 55 flag = FileDemo_05.deleteFiles(files[i].getAbsolutePath()); 56 if (!flag) { 57 break; 58 } 59 } else if (files[i].isDirectory()) { //刪除子文件夾,此處為遞歸 60 flag = FileDemo_05.deleteDir(files[i].getAbsolutePath()); 61 if (!flag) { 62 break; 63 } 64 } 65 } 66 if (!flag) { 67 System.out.println("刪除文件夾失敗"); 68 } 69 if (dirFile.delete()) { 70 System.out.println("文件夾" + dir + "刪除成功!"); 71 return true; 72 } else { 73 return false; 74 } 75 } 76 77 78 79 }
程序示例2 移動指定目錄下的文件,該程序用到了 程序示例1

1 package 輸入輸出流_移動指定目錄下的文件; 2 3 import java.io.File; 4 5 public class FileDemo_06 { 6 //英東某個指定的文件,但移動成功后不會覆蓋已存在的文件 7 public static boolean moveA_File(String sourceFileName, String targetFileName) { 8 return FileDemo_06.moveA_File(sourceFileName, targetFileName, false); 9 } 10 11 //移動某個指定的文件,但移動成功后可以根據isOverlay的值來決定是否覆蓋已存在的目標文件 12 public static boolean moveA_File(String sourceFileName, String targetFileName, 13 boolean isOverlay) { 14 File sourceFile = new File(sourceFileName); 15 if (!sourceFile.exists()) { 16 System.out.println("文件" + sourceFileName + "不存在,移動失敗"); 17 return false; 18 } else if (!sourceFile.isFile()) { 19 System.out.println(sourceFileName + "不是文件,移動失敗"); 20 return false; 21 } 22 File targetFile = new File(targetFileName); 23 if (targetFile.exists()) { 24 if (isOverlay) { 25 System.out.println("目標文件已經存在,准備刪除它"); 26 if (!FileDemo_05.deleteFilesOrDir(targetFileName)) { 27 System.out.println("文件移動失敗,文件" + targetFileName + "刪除失敗"); 28 return false; 29 } 30 } else { 31 System.out.println("文件移動失敗,因為文件" + targetFileName + "已經存在"); 32 return false; 33 } 34 } else { 35 if (!targetFile.getParentFile().exists()) { 36 System.out.println("文件" + targetFile + "所在的目錄不存在,正在創建"); 37 if (!targetFile.getParentFile().mkdirs()) { 38 System.out.println("移動文件失敗,因為創建文件坐在的文件夾失敗"); 39 return false; 40 } 41 } 42 } 43 44 //移動源文件至目標文件 45 if (sourceFile.renameTo(targetFile)) { 46 System.out.println("移動源文件" + sourceFileName + "到" + targetFileName 47 + "成功" ); 48 return true; 49 } else { 50 System.out.println("移動源文件" + sourceFileName + "到" + targetFileName 51 + "失敗" ); 52 return false; 53 } 54 55 56 } 57 58 public static boolean moveDir(String sourceDirName, String targetDirName) { 59 //默認為不覆蓋目標文件 60 return FileDemo_06.moveDir(sourceDirName, targetDirName, false); 61 } 62 63 //移動某個指定的目錄,但移動成功后可以根據isOverlay的值來決定是否覆蓋當前已存在的目標目錄 64 public static boolean moveDir(String sourceDirName, String targetDirName, 65 boolean isOverlay) { 66 //判斷原目錄是否存在 67 File sourceDir = new File(sourceDirName); 68 if (!sourceDir.exists()) { 69 System.out.println("源目錄" + sourceDirName + "不存在,移動目錄失敗"); 70 return false; 71 } else if (!sourceDir.isDirectory()) { 72 System.out.println("移動目錄失敗," + sourceDirName + "不是目錄"); 73 return false; 74 } 75 //如果目標文件名不是以文件分割符結尾,自動添加文件分隔符 76 if (!targetDirName.endsWith(File.separator)) { 77 targetDirName += File.separator; 78 } 79 File targetDir = new File(targetDirName); 80 //如果目標文件夾存在 81 if (targetDir.exists()) { 82 if (isOverlay) { 83 //允許刪除則刪除已存在的目標目錄 84 System.out.println("該目錄已經存在,准備刪除它"); 85 if (!FileDemo_05.deleteFilesOrDir(targetDirName)) { 86 System.out.println("移動目錄失敗,因為目標目錄已經存在。 刪除目錄" + 87 targetDirName + "失敗!" ); 88 } 89 } else { 90 System.out.println("移動目錄失敗:該目錄" + targetDirName + "已存在!"); 91 return false; 92 } 93 } else { 94 //創建目標目錄 95 System.out.println("該目錄不存在,正在創建"); 96 if (!targetDir.mkdirs()) { 97 System.out.println("移動目錄失敗: 創建目標目錄失敗"); 98 return false; 99 } 100 } 101 boolean flag = true; 102 //移動原目錄下的文件和子目錄到目標目錄下 103 File[] files = sourceDir.listFiles(); 104 for (int i = 0; i < files.length; i++) { 105 //移動子文件 106 if (files[i].isFile()) { 107 flag = FileDemo_06.moveA_File(files[i].getAbsolutePath(), 108 targetDirName + files[i].getName(), isOverlay); 109 if (!flag) { 110 break; 111 } 112 } else if (files[i].isDirectory()) { //移動子目錄 113 flag = FileDemo_06.moveDir(files[i].getAbsolutePath(), 114 targetDirName + files[i].getName(), isOverlay); 115 if (!flag) { 116 break; 117 } 118 119 } 120 } 121 122 if (!flag) { 123 System.out.println("目錄" + sourceDirName + "移動到" + targetDirName + "失敗"); 124 return false; 125 } 126 //刪除原目錄 127 if (FileDemo_05.deleteDir(sourceDirName)) { 128 System.out.println("目錄" + sourceDirName + "移動到" + targetDirName + "成功"); 129 return true; 130 } else { 131 System.out.println("目錄" + sourceDirName + "移動到" + targetDirName + "失敗"); 132 return false; 133 } 134 } 135 136 137 public static void main(String[] args) { 138 //移動文件,如果目標文件存在,則替換 139 System.out.println("調用moveA_File方法的結果如下"); 140 String sourceFileName = "D:\\aa\\temp\\key.txt"; 141 String targetFileName = "D:\\bbb\\ddd\\"; 142 FileDemo_06.moveA_File(sourceFileName, targetFileName); 143 //移動目錄,如果目標目錄存在,則不覆蓋 144 System.out.println("\n調用moveDir方法的結果如下"); 145 String sourceDir = "D:\\aa"; 146 String targetDir = "C:\\mm"; 147 FileDemo_06.moveDir(sourceDir, targetDir,false); 148 } 149 150 151 }