IO就是輸入流輸出流的意思。之內存爲基準,分爲輸入input
和輸出output
,即流向內存是輸入流,流出內存的輸出流。java
上方的表格是頂級父類數組
一切文件數據(文本、圖片、視頻等)在存儲時,都是以二進制數字的形式保存,都一個一個的字節,那麼傳輸時同樣如此。app
因此,字節流能夠傳輸任意文件數據。在操做流的時候,咱們要時刻明確,不管使用什麼樣的流對象,底層傳輸的始終爲二進制數據。優化
java.io.InputStream ``抽象類
是表示字節輸入流的全部類的超類,能夠讀取字節信息到內存中。編碼
它定義了字節輸入流的基本共性功能方法。操作系統
public abstract int read()
: 從輸入流讀取數據的下一個字節。public int read(byte[] b)
: 從輸入流中讀取一些字節數,並將它們存儲到字節數組 b中 。public void close()
:關閉此輸入流並釋放與此流相關聯的任何系統資源。java.io.FileInputStream
類是文件輸入流,繼承InputStream抽象類。publicclass FileInputStream extends InputStream
3d
做用是把硬盤文件中的數據,讀取到內存中使用。code
讀取數據的原理(硬盤->內存):Java程序-->JVM-->操做系統-->調用本地方法-->讀取文件內容視頻
Constructor | Description |
---|---|
FileInputStream(File file) * |
經過打開與實際文件的鏈接建立一個 FileInputStream ,該文件由文件系統中的 File 對象 file 命名。 |
FileInputStream(String name) |
經過打開與實際文件的鏈接來建立一個 FileInputStream ,該文件由文件系統中的路徑名 name 命名。 |
FileInputStream(FileDescriptor fdObj) |
建立 FileInputStream 經過使用文件描述符 fdObj ,其表示在文件系統中的現有鏈接到一個實際的文件。 |
當你建立一個流對象時,必須傳入一個文件路徑。該路徑下,若是沒有該文件,會拋出FileNotFoundException
。對象
方法 | 描述 |
---|---|
int read() | 今後輸入流中讀取一個數據字節。 |
int read(byte[] b) | 今後輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中。 |
int read(byte[] b, int off, int len) | 今後輸入流中將最多 len 個字節的數據讀入一個 byte 數組中。 |
void close() | 關閉此文件輸入流並釋放與此流有關的全部系統資源。 |
long skip(long n) | 從輸入流中跳過並丟棄 n 個字節的數據。 |
protected void finalize() | 確保在再也不引用文件輸入流時調用其 close 方法。 |
int available() | 返回下一次對此輸入流調用的方法能夠不受阻塞地今後輸入流讀取(或跳過)的估計剩餘字節數。 |
FileChannel getChannel() | 返回與此文件輸入流有關的惟一 FileChannel 對象。 |
FileDescriptor getFD() | 返回表示到文件系統中實際文件的鏈接的 FileDescriptor 對象,該文件系統正被此 FileInputStream 使用。 |
*在文件字節輸入流中,read()底層調用本地方法read0()
其餘兩個read方法調用本地方法readBytes(byte b[], int off, int len)
package IO; import java.io.FileInputStream; import java.io.IOException; public class FileInputStream_in { public static void main(String args[]) throws IOException{ //read("1.txt"); //readMore("1.txt"); readAll("1.txt"); } public static void read(String path) throws IOException{ FileInputStream fis = new FileInputStream(path); int len =0; while((len = fis.read())!=-1) System.out.print((char)len); fis.close(); } public static void readMore(String path) throws IOException{ FileInputStream fis = new FileInputStream(path); int len =0; byte[] bytes = new byte[2]; while((len = fis.read(bytes))!=-1) System.out.println(new String(bytes)); fis.close(); } //優化上一個方法 public static void readAll(String path) throws IOException{ FileInputStream fis = new FileInputStream(path); int len =0; byte[] bytes = new byte[1024]; while((len = fis.read(bytes))!=-1) System.out.print(new String(bytes,0,len));//只取有效部分 fis.close(); } }
java.io.OutputStream
抽象類是表示字節輸出流的全部類的超類,將指定的字節信息寫出到目的地。
它定義了字節輸出流的基本共性功能方法。
public void close()
:關閉此輸出流並釋放與此流相關聯的任何系統資源。public void flush()
:刷新此輸出流並強制任何緩衝的輸出字節被寫出。public void write(byte[] b)
:將 b.length字節從指定的字節數組寫入此輸出流。public void write(byte[] b, int off, int len)
:從指定的字節數組寫入 len字節,從偏移量 off開始輸出到此輸出流。public abstract void write(int b)
:將指定的字節輸出流。方法 | 描述 |
---|---|
void close() | 關閉此輸出流並釋放與此流有關的全部系統資源。 |
void flush() | 刷新此輸出流並強制寫出全部緩衝的輸出字節。 |
void write(byte[] b) | 將 b.length 個字節從指定的 byte 數組寫入此輸出流。 |
void write(byte[] b, int off, int len) | 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此輸出流。 |
abstract void write(int b) | 將指定的字節寫入此輸出流。 |
*在字節輸出流中,write的重載方法都調用write(int b) 方法
java.io.FileInputStream
類是文件輸入流,從文件中讀取字節。
寫入數據的原理(內存->硬盤):Java程序-->JVM-->操做系統-->調用本地方法-->把數據寫入文件
FileInputStream(File file)
: 經過打開與實際文件的鏈接來建立一個 FileInputStream ,該文件由文件系統中的 File對象 file命名。FileInputStream(String name)
: 經過打開與實際文件的鏈接來建立一個 FileInputStream ,該文件由文件系統中的路徑名 name命名。當你建立一個流對象時,必須傳入一個文件路徑。該路徑下,若是沒有該文件,會拋出FileNotFoundException
。
Constructor | Description |
---|---|
FileOutputStream(File file, boolean append) ** |
建立文件輸出流以寫入由指定的 File 對象表示的文件。 |
FileOutputStream(String name, boolean append) |
建立文件輸出流以指定的名稱寫入文件。append是追加開關,默認false(關)。 |
FileOutputStream(String name) |
建立文件輸出流以指定的名稱寫入文件。 |
FileOutputStream(File file) |
建立文件輸出流以寫入由指定的 File 對象表示的文件。 |
FileOutputStream(FileDescriptor fdObj) * |
建立文件輸出流以寫入指定的文件描述符,表示與文件系統中實際文件的現有鏈接。 |
其實無論哪一個構造器都轉成FileOutputStream(File file, boolean append)
形式
方法 | 描述 |
---|---|
void write(int b) **核心 | 將指定字節寫入此文件輸出流。 |
void write(byte[] b) | 將 b.length 個字節從指定 byte 數組寫入此文件輸出流中。 |
void write(byte[] b, int off, int len) | 將指定 byte 數組中從偏移量 off 開始的 len 個字節寫入此文件輸出流。 |
void close() | 關閉此文件輸出流並釋放與此流有關的全部系統資源。 |
protected void finalize() | 清理到文件的鏈接,並確保在再也不引用此文件輸出流時調用此流的 close 方法。 |
FileChannel getChannel() | 返回與此文件輸出流有關的惟一FileChannel 對象。 |
FileDescriptor getFD() | 返回與此流有關的文件描述符。 |
底層調用本地(native)方法write(int b, boolean append)
和writeBytes(byte b[], int off, int len, boolean append)
在文件字節輸出流中,write重載方法調用不一樣的本地方法。
//用文件字節輸出流向文件寫入一個字節 import java.io.*; public class fileIO { public static void main(String args[]) throws IOException{ FileOutputStream fos = new FileOutputStream("1.txt"); fos.write(97);//輸入一個字節 97的二進制1100001 fos.close();//打開記事本默認讀字符97對應的ASCII表是a } }
package IO; import java.io.*; import java.util.Arrays; public class FileOutputStream_ { public static void main(String args[]) throws IOException{ fileOutOne("1.txt",97);//向1文件寫入1個字節(8位)01100001 byte[] t = "你好".getBytes(); System.out.println(Arrays.toString(t)); //gdk中英都佔兩個字節。 utf-8 英文一字節,中文三字節 fileOutMore("2.txt",t);//向2文件寫入你好字符串轉化的字節數組。 byte[] b = {97,98,49,48,48}; fileOutMore1("3.txt",b);//向3文件寫入一個規定字節數組。 } //使用字節輸出流向文件寫入一個字節 public static void fileOutOne(String path,int num) throws IOException{ FileOutputStream fos = new FileOutputStream(path);//指向路徑的文件 fos.write(num);//輸入一個字節 97的二進制1100001 fos.close();//打開記事本默認讀字符97對應的ASCII表是a } //使用字節輸出流向文件寫入多個字節 public static void fileOutMore(String path,byte[] bytes) throws IOException{ File f = new File(path); FileOutputStream fos = new FileOutputStream(f);//指向具體文件 fos.write(bytes);//寫入一個字節數組 fos.close(); } //使用字節輸出流向文件寫入偏移的多個字節 public static void fileOutMore1(String path,byte[] bytes) throws IOException{ File f = new File(path); FileOutputStream fos = new FileOutputStream(f);//指向具體文件 //byte[] b = {97,98,49,48,48}; 本應該是 ab100 偏移兩位,寫入三位得100 fos.write(bytes,2,3);//輸入一個字節數組 fos.close(); } }
package IO; import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStrean_append { public static void main(String args[]) throws IOException{ fileOutAppend("1.txt","append".getBytes());//向1文件追加換行和寫入一個單詞 } public static void fileOutAppend(String path,byte[] bytes) throws IOException{ FileOutputStream fos = new FileOutputStream(path,true);//true 標記追加 fos.write("\r\n".getBytes());//window系統下文件的換行符號 fos.write(bytes);//寫入一個字節數組 fos.close(); } }
package bytestream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyFile { public static void main(String[] args) throws IOException { // 1. 建立一個字節輸入流對象,構造方法中綁定要讀取的數據源 FileInputStream fis = new FileInputStream("test.txt"); // 2. 建立一個字節輸出流對象,構造方法中綁定要寫入的目的地 FileOutputStream fos = new FileOutputStream("test2.txt"); // 3. 使用字節輸入流對象的read方法讀取數據 byte[] bytes = new byte[1024]; int len = 0; while ((len = fis.read(bytes)) != -1) { // 4. 使用直接輸出流對象的write方法將讀取到的數據寫入目的地文件 fos.write(bytes, 0, len); } // 5. 釋放資源(棧順序,先進後出) fos.close(); fis.close(); } }
中文字符的編碼
package bytestream; import java.io.FileInputStream; import java.io.IOException; public class ByteStreamTest { public static void main(String[] args) throws IOException { // 當使用字節流讀取字符時,存在一些問題 FileInputStream fis = new FileInputStream("test.txt"); int len = 0; while ((len = fis.read()) != -1) { System.out.println((char)len); } fis.close(); } }
test.txt
123789456你好
運行結果
1 2 3 7 8 9 4 5 6 ä ½ å ¥ ½
使用字節流讀取字符數據出現亂碼!
字節流存在的問題:當使用字節流讀取文本文件時,可能會有一個小問題。就是遇到中文字符時,可能不會顯示完整的字符,
那是由於一箇中文字符可能佔用多個字節存儲。因此Java提供一些字符流類,以字符爲單位讀寫數據,專門用於處理文本文件。