從14年10月份開始工作,到今天做Android已經兩年半了。可是到現在也沒搞清楚java的I/O機制,痛定思痛,覺得好好整理一下。古人云“格物致知”,今天就好好格一格I/O機制吧!
“流”是一連串流動的字符,同時也說明了數據傳輸的一種狀態:“均勻與連續”。java使用“流”進行數據傳輸。而傳輸的雙方一般是“你的程序”和“設備(手機)”。
根據流的方向,可以分為輸入流和輸出流。流的輸入(Input)和輸出(Output)是以應用程序為參考中心的。輸入流就是從設備流入到應用程序,也即常說的讀(Read);輸出流就是從應用程序流到設備,也即我們常說的寫(Write)。
原理圖如下: 
注:輸入流命名規則是包含Input或Reader,如InputStream、BufferedReader;輸出流命名規則是包含Output或Writer,如OutputStream、BufferedWriter。
數據傳輸的基本單位是字節(bytes),但1個字節是8位,表示范圍是0-255。面對諸多漢字,1個字節很明顯是不足的。所以生成了一種新的單位:字符,而字符和字節之間的映射關系就是Unicode。在java中1個字符等于2個字節。根據流的數據類型,可分為字節流和和字符流。
1. 讀寫單位:字節流處理的基本單元是字節;字符流處理的基本單元是Unicode碼,2個字節 2. 處理對象:字節流能處理所有類型的數據(圖片,視頻,音頻等),字符流只能處理字符型數據(字符串,純文本文檔) 3. 是否緩存:字符流傳輸之前要先經過Unicode轉換成字節流,批量轉換后的字節流存儲到緩存當中(提示效率),然后再進行讀寫。字節流則不用緩存(字節流本身是不使用字節流的,但是如果想提升效率,可以自定義緩存區)。
注:字節流一般命名規則是以Stream結尾,如InputStream或OutputStream;字符流一般命名規則是以Reader或Writer結尾。如BufferedReader、BufferedWriter。
根據流是否直接與數據源相連,可以劃分為節點流和處理流。節點流是可以直接從/向數據源(設備,硬盤,內存等)讀/寫數據;處理流是對一個已存在的流的連接、封裝和處理。
注:處理流命名規則是包含buffered,如BufferedInputStream、BufferedReader。
 根據操作的數據類型,分為字節流和字符流;根據數據的流向,又分為輸入流和輸出流;根據功能,分為節點流和處理流。
字節流處理的抽象基類是InputStream和OutputStream。InputStream是字節輸入流,OutputStream是字節輸出流。
字符流處理的抽象基類是Reader和Writer。Reader是字符輸入流,Writer是字符輸出流。
介紹的差不多了,接下來就是實戰演示了。 1.從本地讀取圖片 1. 讀取說明數據流是從設備到應用,因此使用輸入流,那就是InputStream或Reader 2. 操作的數據對象是圖片,使用字節流的話效率較高(不用經由Unicode轉換) 3. 所以排除Reader,選擇InputStream
public void readImg(ImageView iv) { File file = new File("/sdcard/temp.jpg"); if (file.exists()) { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(file); byte[] img = new byte[(int) file.length()];// 根據文件長度創建字節數組 fileInputStream.read(img); // 將圖片字節信息寫入到字節數組 Bitmap bitmap = BitmapFactory.decodeByteArray(img,0,img.length); iv.setImageBitmap(bitmap); // 顯示圖片 } catch (FileNotFoundException e) { e.PRintStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }2.保存圖片到本地 1. 保存到本地說明數據流是從應用到設備,因此使用輸出流,所以選擇OutputStream或Writer 2. 由于操作的數據對象是圖片,使用字節流的話效率較高(不用經由Unicode轉換) 3. 所以排除Writer,選擇OutputStream
public void saveImg() { InputStream inputStream = null; FileOutputStream fileOutputStream = null; try { URL url = new URL("https://ss0.baidu.com/94o3dSag_xI4khGko9WTAnF6hhy/image/h%3D360/sign=e572f27e9058d109dbe3afb4e158ccd0/b7fd5266d0160924933e331bd60735fae6cd3492.jpg"); URLConnection urlConnect = url.openConnection(); urlConnect.setConnectTimeout(5000); inputStream = urlConnect.getInputStream(); File tempFile = new File("/sdcard/temp.jpg");// 保存到臨時文件中 if(tempFile.isDirectory()){ tempFile.delete(); } if (!tempFile.exists()) { tempFile.createNewFile(); } fileOutputStream = new FileOutputStream(tempFile);// 創建輸出流,參數tempFile為寫入的目標 byte[] buffer = new byte[1024]; int length = -1; while ((length = inputStream.read(buffer)) != -1) { // 讀取字節,先存儲到緩存區 fileOutputStream.write(buffer, 0, length); // 從緩存區提取數據,可以提升效率 } inputStream.close(); fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }3.從本地讀取純文檔 1. 由于是讀取,說明數據流是從設備流到應用,因此使用輸入流,所以選擇InputStream或Reader 2. 操作的數據對象是純文檔,需要使用字符流(純文檔需要經由Unicode轉碼) 3. 所以排除InputStream,選擇Reader
public String readWold() { try { FileReader fileReader = new FileReader("/sdcard/test.txt"); BufferedReader bufferedReader = new BufferedReader(fileReader); String line = null; StringBuilder builder = new StringBuilder(); while ((line = bufferedReader.readLine()) != null) { builder.append(line + "/n"); } bufferedReader.close(); return builder.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; }4.寫入到本地純文檔 1.寫入說明數據流是從應用到設備,因此使用輸出流,所以選擇OutputStream或Writer 2. 操作的數據對象是純文檔,需要使用字符流(純文檔或字符串需要經由Unicode轉碼) 3. 所以排除OutputStream,選擇Writer
public void saveWord() { try { File file = new File("/sdcard/test.txt"); if (file.isDirectory()){ file.delete(); } if (!file.exists()){ file.createNewFile(); } FileWriter fileWriter = new FileWriter(file); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); bufferedWriter.write("Hi,I am Chaos!"); bufferedWriter.newLine(); bufferedWriter.write("I am come from China!"); bufferedWriter.newLine(); bufferedWriter.flush(); bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } }字節流和字符流 http://www.jianshu.com/p/4edb6b99204e Java中的字節流、緩沖流 http://blog.csdn.net/sinat_34669892/article/details/52738643 java 下載網絡上的圖片并保存到本地目錄 http://takeme.iteye.com/blog/1683380 IO結構圖源于百度圖片
新聞熱點
疑難解答