android 文件 IO,固然也是 Java IO。廖廖幾百字,來講清楚文件 IO 究竟是什麼。經過對一些基本概念的理解以及 Java IO 中其餘的一些必要性知識的理解,來透徹的理解 Java IO.java
字節:代碼裏表示就是 byteandroid
字符:代碼裏單獨表示就是 char,byte 不能表示一個字符。dom
字符編碼:字符要用多少個字節表示,以包括如何表示。就是傳說中的 utf-8,ansi,utf-16be,gbk 等異步
文件編碼:也就是文件存儲時採用何種字符編碼。存儲時採用何種編碼,那讀取時也必須採用相應的編碼。不然在碰到非英文字符的時候,就會碰到不懷好意的亂碼問題。函數
理解了上面的概念,也就是理解了,爲何 Java 的 IO 會區分字節流與字符流了。學習
能夠這麼說,最基本的字節流分別是 讀 - FileInputStream(FileWriter) ,寫 - FileOutputStream (FileReader)。這兩個類能夠理解是真正與 「文件 - File」 發生關係的。這兩個類中包含了更底層的 IO 處理,例如調用 IoBridge.open(),IoBridge.read(),IoBrige.write()以及IoBridge.closeAndSignalBlockedThreads()等橋接方法調用。而這些底層的類又是經過更底層的 Posix 類,再經過 JNI 調用到 C 層實現(C 層並無用 C語言的fread()等函數,而是直接調用的系統調用 read()),最後實現文件的讀與寫等文件相關的操做。因此流是對底層IO相關的系統調用的一個細節封裝。編碼
Java中定義了流的概念,輸入流或者輸出流,且不可逆不可任意跳轉,從源碼上來看都是出於設計上的考量。參考 RandomAccessFile 的實現,其之因此可以隨機訪問文件,其實就是經過調用了 Libcore.os.lseek() 來實現。固然,普通的流也有調用到 Libcore.os.lseek(),就是 skip()方法,而沒有像 RandomAccessFile 同樣提供了上層的 seek() 方法。spa
爲了你們使用上的方便,如讀一個 int 須要分紅 4 個字節去讀,而且作一次計算,Java中提供了 DataInputStream/DataOutputStream,其就是裝飾了一下,底層的文件 IO 操做均是由 FileInputStream/FileOutStream 來實現的。線程
public final int readInt() throws IOException { 387 // b/30268192 388 // Android-changed: Use read(byte[], int, int) instead of read(). 389 readFully(readBuffer, 0, 4);//讀 4 個字節 390 return Memory.peekInt(readBuffer, 0, ByteOrder.BIG_ENDIAN);//將 4 個字節轉換成 Int 值 391 } /** * 分大小端轉成 Int **/ public static int peekInt(byte[] src, int offset, ByteOrder order) { 46 if (order == ByteOrder.BIG_ENDIAN) { 47 return (((src[offset++] & 0xff) << 24) | 48 ((src[offset++] & 0xff) << 16) | 49 ((src[offset++] & 0xff) << 8) | 50 ((src[offset ] & 0xff) << 0)); 51 } else { 52 return (((src[offset++] & 0xff) << 0) | 53 ((src[offset++] & 0xff) << 8) | 54 ((src[offset++] & 0xff) << 16) | 55 ((src[offset ] & 0xff) << 24)); 56 } 57 }
BufferedInputStream/BufferedOutputStream 就更簡單了,就是在 IO 前先將數據存入或者寫出到byte[] buffer 中,外加一個 count 計數器記錄下寫入與寫出的字節個數。而真正與文件發生 IO 的仍是 FileInputStream/FileOutputStream設計
BufferedWriter/BufferedReader 是相似的,只不過它的 buf 是 char[] ,而不是 byte[]。同時,它也用了一個 pos 做爲下標計數器。
管道流,單獨放在最後講,並非由於它有多麼的高大上,由於慚愧的是,我在實際編碼當中歷來沒有用到過。但這兩個類所涉及的設計思想很是值得咱們學習。
做用:用於兩個不一樣的線程之間進行通訊
文件IO:這兩個類是沒有文件 IO 的。寫入讀出都是在同一個 byte[] buffer 內
封裝:PipedOutputStream 封裝了 PIpedInputStream,PipedInputStream 封裝了 byte[] buffer
buffer:這是一個循環 buffer ,分別用了 in 表示下一個要寫的位置,out 表示下一個要讀的位置。讀的最大範圍爲 [out,int) 左閉右開區間,寫的最大範圍爲 [in,out)
in 爲 -1 表示空 buffer,讀線程阻塞等待
in == empty 表示 buffer 滿,寫線程阻塞等待
但須要注意的是,無論是讀待仍是寫等待,最多隻會等 3 秒鐘,且是每隔一次一秒的。
Java 中還有一些其餘相關的流,如 PrintStream/PrintWriter ,其也就是多了一些封裝幫助咱們更方便更快捷的完成代碼編寫,從而摒棄一些複雜的運算,專心處理業務邏輯便可。
Java IO 的知識點還不少,上面都是一些最基礎的東西,但掌握了上面這些比較基礎的東西,那其餘複雜的東西也就容易掌握了。
Java 還有一類 IO 稱爲 NIO,其主要目的是爲了超大文件,複用IO的異步讀寫。NIO 的三要素爲 Channel,Buffer,Selector。先知道有這麼幾個東西吧。