我計划在接下來的幾篇文章中快速回顧一下Java,主要是一些基礎的JDK相關的內容。
工作后,使用的技術隨着項目的變化而變化,時而C#,時而Java,當然還有其他一些零碎的技術。總體而言,C#的使用時間要更長一些,其次是Java。我本身對語言沒有什么傾向性,能干活的語言,就是好語言。而且從面向對象的角度來看,我覺得C#和Java對我來說,沒什么區別。
這篇文章主要回顧Java中和I/O操作相關的內容,I/O也是編程語言的一個基礎特性,Java中的I/O分為兩種類型,一種是順序讀取,一種是隨機讀取。
我們先來看順序讀取,有兩種方式可以進行順序讀取,一種是InputStream/OutputStream,它是針對字節進行操作的輸入輸出流;另外一種是Reader/Writer,它是針對字符進行操作的輸入輸出流。
下面我們畫出InputStream的結構
- FileInputStream:操作文件,經常和BufferedInputStream一起使用
- PipedInputStream:可用於線程間通信
- ObjectInputStream:可用於對象序列化
- ByteArrayInputStream:用於處理字節數組的輸入
- LineNumberInputStream:可輸出當前行數,並且可以在程序中進行修改
下面是OutputStream的結構
- PrintStream:提供了類似print和println的接口去輸出數據
下面我們來看如何使用Stream的方式來操作輸入輸出
- 使用InputStream讀取文件
使用FileInputStream讀取文件信息
1 public static byte[] readFileByFileInputStream(File file) throws IOException 2 { 3 ByteArrayOutputStream output = new ByteArrayOutputStream(); 4 FileInputStream fis = null; 5 try 6 { 7 fis = new FileInputStream(file); 8 byte[] buffer = new byte[1024]; 9 int bytesRead = 0; 10 while((bytesRead = fis.read(buffer, 0, buffer.length)) != -1) 11 { 12 output.write(buffer, 0, bytesRead); 13 } 14 } 15 catch(Exception ex) 16 { 17 System.out.println("Error occurs during reading " + file.getAbsoluteFile()); 18 } 19 finally 20 { 21 if (fis !=null) fis.close(); 22 if (output !=null) output.close(); 23 } 24 return output.toByteArray(); 25 }
使用BufferedInputStream讀取文件
1 public static byte[] readFileByBufferedInputStream(File file) throws Exception 2 { 3 FileInputStream fis = null; 4 BufferedInputStream bis = null; 5 ByteArrayOutputStream output = new ByteArrayOutputStream(); 6 try 7 { 8 fis = new FileInputStream(file); 9 bis = new BufferedInputStream(fis); 10 byte[] buffer = new byte[1024]; 11 int bytesRead = 0; 12 while((bytesRead = bis.read(buffer, 0, buffer.length)) != -1) 13 { 14 output.write(buffer, 0, bytesRead); 15 } 16 } 17 catch(Exception ex) 18 { 19 System.out.println("Error occurs during reading " + file.getAbsoluteFile()); 20 } 21 finally 22 { 23 if (fis != null) fis.close(); 24 if (bis != null) bis.close(); 25 if (output != null) output.close(); 26 } 27 return output.toByteArray(); 28 }
- 使用OutputStream復制文件
使用FileOutputStream復制文件
1 public static void copyFileByFileOutputStream(File file) throws IOException 2 { 3 FileInputStream fis = null; 4 FileOutputStream fos = null; 5 try 6 { 7 fis = new FileInputStream(file); 8 fos = new FileOutputStream(file.getName() + ".bak"); 9 byte[] buffer = new byte[1024]; 10 int bytesRead = 0; 11 while((bytesRead = fis.read(buffer,0,buffer.length)) != -1) 12 { 13 fos.write(buffer, 0, bytesRead); 14 } 15 fos.flush(); 16 } 17 catch(Exception ex) 18 { 19 System.out.println("Error occurs during copying " + file.getAbsoluteFile()); 20 } 21 finally 22 { 23 if (fis != null) fis.close(); 24 if (fos != null) fos.close(); 25 } 26 }
使用BufferedOutputStream復制文件
1 public static void copyFilebyBufferedOutputStream(File file)throws IOException 2 { 3 FileInputStream fis = null; 4 BufferedInputStream bis = null; 5 FileOutputStream fos = null; 6 BufferedOutputStream bos = null; 7 try 8 { 9 fis = new FileInputStream(file); 10 bis = new BufferedInputStream(fis); 11 fos = new FileOutputStream(file.getName() + ".bak"); 12 bos = new BufferedOutputStream(fos); 13 byte[] buffer = new byte[1024]; 14 int bytesRead = 0; 15 while((bytesRead = bis.read(buffer, 0, buffer.length)) != -1) 16 { 17 bos.write(buffer, 0, bytesRead); 18 } 19 bos.flush(); 20 } 21 catch(Exception ex) 22 { 23 System.out.println("Error occurs during copying " + file.getAbsoluteFile()); 24 } 25 finally 26 { 27 if (fis != null) fis.close(); 28 if (bis != null) bis.close(); 29 if (fos != null) fos.close(); 30 if (bos != null) bos.close(); 31 } 32 }
這里的代碼對異常的處理非常不完整,稍后我們會給出完整嚴謹的代碼。
下面我們來看Reader的結構
這里的Reader基本上和InputStream能夠對應上。
Writer的結構如下
下面我們來看一些使用Reader或者Writer的例子
- 使用Reader讀取文件內容
使用BufferedReader讀取文件內容
1 public static String readFile(String file)throws IOException 2 { 3 BufferedReader br = null; 4 StringBuffer sb = new StringBuffer(); 5 try 6 { 7 br = new BufferedReader(new FileReader(file)); 8 String line = null; 9 10 while((line = br.readLine()) != null) 11 { 12 sb.append(line); 13 } 14 } 15 catch(Exception ex) 16 { 17 System.out.println("Error occurs during reading " + file); 18 } 19 finally 20 { 21 if (br != null) br.close(); 22 } 23 return sb.toString(); 24 }
- 使用Writer復制文件
使用BufferedWriter復制文件
1 public static void copyFile(String file) throws IOException 2 { 3 BufferedReader br = null; 4 BufferedWriter bw = null; 5 try 6 { 7 br = new BufferedReader(new FileReader(file)); 8 bw = new BufferedWriter(new FileWriter(file + ".bak")); 9 String line = null; 10 while((line = br.readLine())!= null) 11 { 12 bw.write(line); 13 } 14 } 15 catch(Exception ex) 16 { 17 System.out.println("Error occurs during copying " + file); 18 } 19 finally 20 { 21 if (br != null) br.close(); 22 if (bw != null) bw.close(); 23 } 24 }
下面我們來看如何對文件進行隨機訪問,Java中主要使用RandomAccessFile來對文件進行隨機操作。
- 創建一個大小固定的文件
創建大小固定的文件
1 public static void createFile(String file, int size) throws IOException 2 { 3 File temp = new File(file); 4 RandomAccessFile raf = new RandomAccessFile(temp, "rw"); 5 raf.setLength(size); 6 raf.close(); 7 }
- 向文件中隨機寫入數據
向文件中隨機插入數據
1 public static void writeFile(String file, byte[] content, int startPos, int contentLength) throws IOException 2 { 3 RandomAccessFile raf = new RandomAccessFile(new File(file), "rw"); 4 raf.seek(startPos); 5 raf.write(content, 0, contentLength); 6 raf.close(); 7 }
接下里,我們來看一些其他的常用操作
- 移動文件
移動文件
1 public static boolean moveFile(String sourceFile, String destFile) 2 { 3 File source = new File(sourceFile); 4 if (!source.exists()) throw new RuntimeException("source file does not exist."); 5 File dest = new File(destFile); 6 if (!(new File(dest.getPath()).exists())) new File(dest.getParent()).mkdirs(); 7 return source.renameTo(dest); 8 }
- 復制文件
復制文件
1 public static void copyFile(String sourceFile, String destFile) throws IOException 2 { 3 File source = new File(sourceFile); 4 if (!source.exists()) throw new RuntimeException("File does not exist."); 5 if (!source.isFile()) throw new RuntimeException("It is not file."); 6 if (!source.canRead()) throw new RuntimeException("File cound not be read."); 7 File dest = new File(destFile); 8 if (dest.exists()) 9 { 10 if (dest.isDirectory()) throw new RuntimeException("Destination is a folder."); 11 else 12 { 13 dest.delete(); 14 } 15 } 16 else 17 { 18 File parentFolder = new File(dest.getParent()); 19 if (!parentFolder.exists()) parentFolder.mkdirs(); 20 if (!parentFolder.canWrite()) throw new RuntimeException("Destination can not be written."); 21 } 22 FileInputStream fis = null; 23 FileOutputStream fos = null; 24 try 25 { 26 fis = new FileInputStream(source); 27 fos = new FileOutputStream(dest); 28 byte[] buffer = new byte[1024]; 29 int bytesRead = 0; 30 while((bytesRead = fis.read(buffer, 0, buffer.length)) != -1) 31 { 32 fos.write(buffer, 0, bytesRead); 33 } 34 fos.flush(); 35 } 36 catch(IOException ex) 37 { 38 System.out.println("Error occurs during copying " + sourceFile); 39 } 40 finally 41 { 42 if (fis != null) fis.close(); 43 if (fos != null) fos.close(); 44 } 45 }
- 復制文件夾
復制文件夾
1 public static void copyDir(String sourceDir, String destDir) throws IOException 2 { 3 4 File source = new File(sourceDir); 5 if (!source.exists()) throw new RuntimeException("Source does not exist."); 6 if (!source.canRead()) throw new RuntimeException("Source could not be read."); 7 File dest = new File(destDir); 8 if (!dest.exists()) dest.mkdirs(); 9 10 File[] arrFiles = source.listFiles(); 11 for(int i = 0; i < arrFiles.length; i++) 12 { 13 if (arrFiles[i].isFile()) 14 { 15 BufferedReader reader = new BufferedReader(new FileReader(arrFiles[i])); 16 BufferedWriter writer = new BufferedWriter(new FileWriter(destDir + "/" + arrFiles[i].getName())); 17 String line = null; 18 while((line = reader.readLine()) != null) writer.write(line); 19 writer.flush(); 20 reader.close(); 21 writer.close(); 22 } 23 else 24 { 25 copyDir(sourceDir + "/" + arrFiles[i].getName(), destDir + "/" + arrFiles[i].getName()); 26 } 27 } 28 }
- 刪除文件夾
刪除文件夾
1 public static void del(String filePath) 2 { 3 File file = new File(filePath); 4 if (file == null || !file.exists()) return; 5 if (file.isFile()) 6 { 7 file.delete(); 8 } 9 else 10 { 11 File[] arrFiles = file.listFiles(); 12 if (arrFiles.length > 0) 13 { 14 for(int i = 0; i < arrFiles.length; i++) 15 { 16 del(arrFiles[i].getAbsolutePath()); 17 } 18 } 19 file.delete(); 20 } 21 }
- 獲取文件夾大小
獲取文件夾大小
1 public static long getFolderSize(String dir) 2 { 3 long size = 0; 4 File file = new File(dir); 5 if (!file.exists()) throw new RuntimeException("dir does not exist."); 6 if (file.isFile()) return file.length(); 7 else 8 { 9 String[] arrFileName = file.list(); 10 for (int i = 0; i < arrFileName.length; i++) 11 { 12 size += getFolderSize(dir + "/" + arrFileName[i]); 13 } 14 } 15 16 return size; 17 }
- 將大文件切分為多個小文件
將大文件切分成多個小文件
1 public static void splitFile(String filePath, long unit) throws IOException 2 { 3 File file = new File(filePath); 4 if (!file.exists()) throw new RuntimeException("file does not exist."); 5 long size = file.length(); 6 if (unit >= size) return; 7 int count = size % unit == 0 ? (int)(size/unit) : (int)(size/unit) + 1; 8 String newFile = null; 9 FileOutputStream fos = null; 10 FileInputStream fis =null; 11 byte[] buffer = new byte[(int)unit]; 12 fis = new FileInputStream(file); 13 long startPos = 0; 14 String countFile = filePath + "_Count"; 15 PrintWriter writer = new PrintWriter(new FileWriter( new File(countFile))); 16 writer.println(filePath + "\t" + size); 17 for (int i = 1; i <= count; i++) 18 { 19 newFile = filePath + "_" + i; 20 startPos = (i - 1) * unit; 21 System.out.println("Creating " + newFile); 22 fos = new FileOutputStream(new File(newFile)); 23 int bytesRead = fis.read(buffer, 0, buffer.length); 24 if (bytesRead != -1) 25 { 26 fos.write(buffer, 0, bytesRead); 27 writer.println(newFile + "\t" + startPos + "\t" + bytesRead); 28 } 29 fos.flush(); 30 fos.close(); 31 System.out.println("StartPos:" + i*unit + "; EndPos:" + (i*unit + bytesRead)); 32 } 33 writer.flush(); 34 writer.close(); 35 fis.close(); 36 }
- 將多個小文件合並為一個大文件
將多個小文件合並成一個大文件
1 public static void linkFiles(String countFile) throws IOException 2 { 3 File file = new File(countFile); 4 if (!file.exists()) throw new RuntimeException("Count file does not exist."); 5 BufferedReader reader = new BufferedReader(new FileReader(file)); 6 String line = reader.readLine(); 7 String newFile = line.split("\t")[0]; 8 long size = Long.parseLong(line.split("\t")[1]); 9 RandomAccessFile raf = new RandomAccessFile(newFile, "rw"); 10 raf.setLength(size); 11 FileInputStream fis = null; 12 byte[] buffer = null; 13 14 while((line = reader.readLine()) != null) 15 { 16 String[] arrInfo = line.split("\t"); 17 fis = new FileInputStream(new File(arrInfo[0])); 18 buffer = new byte[Integer.parseInt(arrInfo[2])]; 19 long startPos = Long.parseLong(arrInfo[1]); 20 fis.read(buffer, 0, Integer.parseInt(arrInfo[2])); 21 raf.seek(startPos); 22 raf.write(buffer, 0, Integer.parseInt(arrInfo[2])); 23 fis.close(); 24 } 25 raf.close(); 26 }
- 執行外部命令
執行外部命令
1 public static void execExternalCommand(String command, String argument) 2 { 3 Process process = null; 4 try 5 { 6 process = Runtime.getRuntime().exec(command + " " + argument); 7 InputStream is = process.getInputStream(); 8 BufferedReader br = new BufferedReader(new InputStreamReader(is)); 9 String line = null; 10 while((line = br.readLine()) != null) 11 { 12 System.out.println(line); 13 } 14 } 15 catch(Exception ex) 16 { 17 System.err.println(ex.getMessage()); 18 } 19 finally 20 { 21 if (process != null) process.destroy(); 22 } 23 }