Java粗淺認識-I/O(一)
阿新 • • 發佈:2018-12-20
I/O
IO到底是什麼?I/O是(Input和Output)輸入輸出,在作業系統層面,Input就是從輸入裝置(磁碟驅動器、網路和終端)讀取資料到記憶體中,
Output就是從記憶體中把資料輸出到輸出裝置中(磁碟驅動器、網路和終端),而這些輸入輸出裝置都是在Linux系統當中,所有的輸入、輸出裝置都被抽象化為檔案,二檔案就是一個n個位元組的序列,檔案又被分類為普通檔案(二進位制和文字),目錄,套接字(用於網路通訊)。
Unix系統上支援的I/O模型
同步IO,非同步IO
同步IO,阻塞式IO、非阻塞式IO、IO複用、訊號驅動IO,都是同步IO,不同之處在於,應用系統呼叫核心進行資料訪問時的兩個階段中的第一個階段等待資料是否阻塞,第二個階段都是阻塞式的,從核心把資料返回給應用程式
非同步IO,則是在兩個階段都不會阻塞當前程序或執行緒
Java中的IO發展
java1.0中就存在阻塞式IO,就是常見的基於Stream、File、RandomAccessFile、Writers和Readers的IO處理,
java1.4中引入了NIO,主要解決,第一階級等待資料是否阻塞的問題,IO複用式的IO操作,引入了新的處理的物件,如Channel、Selecotr、Buffer緩衝區
java1.7中引入了NIO2,引入了非同步IO(這裡需要注意,真正在現在unix作業系統上,是不支援非同步IO,只有Windows作業系統才實現了真正意義上的非同步IO),
引入新的類;新的檔案系統抽象,如:Path、Files工具類等
接下來,針對上面的內容,一一寫程式碼舉例:
阻塞式I/O
/** * 基於java 流檔案複製,這裡面涉及到的異常處理,資源回收,位運算等,後面會一一講解 * * @param sourceFileName * @param targetFileName */ public static void copyFile(String sourceFileName, String targetFileName) { File sourceFile = new File(sourceFileName); File targetFile = new File(targetFileName); if (!sourceFile.exists()) { System.out.println("檔案" + sourceFileName + "不存在。"); return; } if (!targetFile.exists()) { try { if (!targetFile.createNewFile()) { System.out.println("檔案" + targetFileName + "建立失敗。"); return; } } catch (IOException e) { System.out.println("檔案" + targetFileName + "建立失敗。"); e.printStackTrace(); } } InputStream inputStream = null; OutputStream outputStream = null; try { inputStream = new FileInputStream(sourceFile); outputStream = new FileOutputStream(targetFile); byte[] buffer = new byte[1 << 10]; int len; while ((len = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void fileCopyWithBuffer(String sourceFileName, String targetFileName) { File sourceFile = new File(sourceFileName); File targetFile = new File(targetFileName); if (!sourceFile.exists()) { System.out.println("檔案" + sourceFileName + "不存在。"); return; } if (!targetFile.exists()) { try { if (!targetFile.createNewFile()) { System.out.println("檔案" + targetFileName + "建立失敗。"); return; } } catch (IOException e) { System.out.println("檔案" + targetFileName + "建立失敗。"); e.printStackTrace(); } } InputStream inputStream; OutputStream outputStream; BufferedInputStream bufferedInputStream = null; BufferedOutputStream bufferedOutputStream = null; try { inputStream = new FileInputStream(sourceFile); outputStream = new FileOutputStream(targetFile); bufferedInputStream = new BufferedInputStream(inputStream); bufferedOutputStream = new BufferedOutputStream(outputStream); byte[] buffer = new byte[1 << 10]; int len; while ((len = bufferedInputStream.read(buffer)) != -1) { bufferedOutputStream.write(buffer, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //這裡資源關閉,沒有顯示關閉inputStream和outputStream,那是因為,buffered**的關閉操作,會關閉底層的內嵌的stream if (bufferedOutputStream != null) { try { bufferedOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedInputStream != null) { try { bufferedInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 這裡涉及到一個亂碼問題 * * @param sourceFileName * @param targetFileName */ public static void copyFileWithCharacterStream(String sourceFileName, String targetFileName) { File sourceFile = new File(sourceFileName); File targetFile = new File(targetFileName); if (!sourceFile.exists()) { System.out.println("檔案" + sourceFileName + "不存在。"); return; } if (!targetFile.exists()) { try { if (!targetFile.createNewFile()) { System.out.println("檔案" + targetFileName + "建立失敗。"); return; } } catch (IOException e) { System.out.println("檔案" + targetFileName + "建立失敗。"); e.printStackTrace(); } } Reader reader = null; Writer writer = null; try { reader = new FileReader(sourceFile); writer = new FileWriter(targetFile); char[] chars = new char[1 << 10]; int len; while ((len = reader.read(chars)) != -1) { writer.write(chars, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 這裡有字元亂碼問題 * * @param sourceFileName * @param targetFileName */ public static void copyFileWithBuffedCharacterStream(String sourceFileName, String targetFileName) { File sourceFile = new File(sourceFileName); File targetFile = new File(targetFileName); if (!sourceFile.exists()) { System.out.println("檔案" + sourceFileName + "不存在。"); return; } if (!targetFile.exists()) { try { if (!targetFile.createNewFile()) { System.out.println("檔案" + targetFileName + "建立失敗。"); return; } } catch (IOException e) { System.out.println("檔案" + targetFileName + "建立失敗。"); e.printStackTrace(); } } Reader reader; Writer writer; BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { reader = new FileReader(sourceFile); writer = new FileWriter(targetFile); bufferedReader = new BufferedReader(reader); bufferedWriter = new BufferedWriter(writer); String line; while ((line = bufferedReader.readLine()) != null) { bufferedWriter.write(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 文字檔案編解碼過程,文字檔案(有自己的字符集)->StreamDecoder做解碼(傳入進去的字符集) * ->StreamEncoder做編碼(自己的字符集) * 沒有解碼時用的字符集不相容檔案的字符集,則會產生亂碼 * * @param sourceFileName * @param targetFileName */ public static void copyFileWithInputCharset(String sourceFileName, String targetFileName) { File sourceFile = new File(sourceFileName); File targetFile = new File(targetFileName); if (!sourceFile.exists()) { System.out.println("檔案" + sourceFileName + "不存在。"); return; } if (!targetFile.exists()) { try { if (!targetFile.createNewFile()) { System.out.println("檔案" + targetFileName + "建立失敗。"); return; } } catch (IOException e) { System.out.println("檔案" + targetFileName + "建立失敗。"); e.printStackTrace(); } } InputStream inputStream; OutputStream outputStream; InputStreamReader inputStreamReader; OutputStreamWriter outputStreamWriter; BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { inputStream = new FileInputStream(sourceFile); outputStream = new FileOutputStream(targetFile); //系統的字符集編碼GBK,底層通過StreamDecoder,做的流解碼 inputStreamReader = new InputStreamReader(inputStream, "utf-8"); //StreamEncoder,做流編碼 outputStreamWriter = new OutputStreamWriter(outputStream, "utf-8"); bufferedReader = new BufferedReader(inputStreamReader); bufferedWriter = new BufferedWriter(outputStreamWriter); String line; while ((line = bufferedReader.readLine()) != null) { bufferedWriter.write(line); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedWriter != null) { try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } } public static void copyFileWithRandomAccessFile(String sourceFileName, String targetFileName) { File sourceFile = new File(sourceFileName); File targetFile = new File(targetFileName); if (!sourceFile.exists()) { System.out.println("檔案" + sourceFileName + "不存在。"); return; } if (!targetFile.exists()) { try { if (!targetFile.createNewFile()) { System.out.println("檔案" + targetFileName + "建立失敗。"); return; } } catch (IOException e) { System.out.println("檔案" + targetFileName + "建立失敗。"); e.printStackTrace(); } } RandomAccessFile reader = null; RandomAccessFile writer = null; try { reader = new RandomAccessFile(sourceFile, "r"); writer = new RandomAccessFile(targetFile, "rw"); byte[] buffer = new byte[1 << 10]; int len; //第一次的時候是零 System.out.println("reader所在位置:"+reader.getFilePointer()); System.out.println("writer所在位置:"+writer.getFilePointer()); //這裡是可以調整當前位置 reader.seek(0); writer.seek(0); while ((len = reader.read(buffer)) != -1) { writer.write(buffer, 0, len); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if(writer!=null){ try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } if(reader!=null){ try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
阻塞式I/O在java中的檔案操作使用到此結束。