Java : java基礎(3) IO流

流按操做類型分爲兩種,字節流,字符流,按流向分爲輸入流,輸出流,輸入流的抽象父類InputStream,輸出流抽象父類OutputStream,字符流的抽象父類是Reader和Writer數組

通常用字節流copy文件能夠用小數組的方式分批拷進去,實例代碼以下:多線程

FileInputStream fis = new FileInputStream("111.png");
FileOutputStream fos = new FileOutputStream("222.png");
byte[] a = new byte[1024 * 8];
int length;
// 返回值length是讀出的字節個數, fis.read(a)是讀取最多a.length大小的字節數據,存入a裏面
while ((length = fis.read(a)) != -1) {
// 把數據從a中寫出,數組偏移量爲0,即從a[0]開始,寫出length字節大小的數據
fos.write(a, 0, length);
}
fis.close();
fos.close();

還有一種方式,用輸入輸出緩衝區包裝類,緩衝區類一次從文件中取出8192個字節,存儲在緩衝區數組裏,而後一個一個存入輸出緩衝區類的緩衝區數組裏,滿了以後一次性存到硬盤文件中大大減小IO時間:dom

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("部署.png"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("222.png"));
int a;
while ((a = bis.read()) != -1) {
bos.write(a);
}
bis.close();
bos.close();

flush()方法能夠刷新緩衝區,把緩衝區的數據寫入文件中.而close()方法在關閉輸出以前,也會把緩衝區的數據寫入文件中,由於緩衝區的數據是存滿8192字節才寫入文件中,若是最後還剩下不到8192字節的數據在緩衝區中,不刷新緩衝區的話,裏面的數據是不會寫入文件中去的,會形成數據丟失,因此輸出流必定要關閉.編碼

若是不想本身調用close()方法的話,能夠把可關閉的流的聲明和賦值放到try()代碼裏面(小括號裏面叫ARM塊):spa

try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("部署.png"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("222.png"))) {
int a;
while ((a = bis.read()) != -1) {
bos.write(a);
}
}


---------------------------------------------------------------------------------------------
字符流,讀的時候把字節轉換爲字符,寫的時候把字符轉換爲字節寫入,能夠經過項目默認的編碼一次讀取一個字符(若是是中文,就一次讀取兩個字節).net

字符流 基礎父類Reader-InputStreamReader-FileReader,通常用FileReader,Writer類也同樣.線程

字符流Reader和Writer類默認都帶2k的緩衝區,BufferedReader和BufferedWriter是帶緩衝區(16k)的字符流類,直接父類Reader和Writer,BufferedReader的readLine()方法能夠讀一行(沒有數據返回null),BufferedWriter的newLine()方法能夠寫出一個換行符(根據系統寫出不一樣的換行符).指針

LineNumberReader是BufferedReader的子類,多了能夠記住當前行號和設置當前行號的功能.code

InputStreamReader能夠指定用什麼碼錶讀取字符流,建立對象須要包裝一個InputStream對象,OutputStreamWriter也同樣,通常搭配BufferedReader或者BufferedWriter來高效的讀取與寫入,如:
new BufferedReader(new InputStreamReader(new FileInputStream("xxx.txt"),"utf-8"))對象

new String("bytes", "UTF-8")是按UTF-8碼錶把字節解碼成字符,若是解碼時有字節找不到對應碼錶中的字符,那麼會以?代替. (解碼:字節數據 --> 字符串)

getBytes("UTF-8")的意思是將(字符)數據按照UTF-8碼錶來編碼成字節數組(此時字節數組的編碼格式爲UTF-8,若是沒有指定那麼會採用系統默認編碼格式). (編碼:字符串 --> 字節數據)

關於解碼和編碼: https://blog.csdn.net/mdreamlove/article/details/78468864

平時推薦使用 InputStreamReader 和 OutputStreamWriter 由於這兩個能夠顯示指定解碼編碼字符集.
----------------------------------------------------------------------------------------------
其餘流:

SequenceInputStream : 序列化輸入流,能夠吧多個InputStream放到裏面,依次接收流數據.它從一個有序的輸入流集合開始,從第一個讀取到文件的結尾,而後從第二個文件讀取,依此類推,直到最後一個輸入流達到文件的結尾。 構造能夠傳入一個Enumeration對象

ByteArrayOutputStream : 內存中會建立一個緩衝區.輸出的數據會寫入這個緩衝區.緩衝區自動增加,能夠用toByteArray和toString獲取裏面的數據.這個流不會形成IO異常,並且close方法沒有任何效果

RandomAccessFile: 讀取和寫入隨機訪問文件,有一種遊標,或索引到隱含的數組,稱爲文件指針 ; 輸入操做讀取從文件指針開始的字節,並使文件指針超過讀取的字節。 若是在讀/寫模式下建立隨機訪問文件,則輸出操做也可用; 輸出操做從文件指針開始寫入字節,並將文件指針提早到寫入的字節。 (適合用來多線程大文件拷貝或下載)

DataInputStream DataOutputStream: 數據輸入輸出流,能夠直接寫出或讀入好比int long類型的數據.

ObjectInputStream : 對象輸入流,.使用readObject能夠讀取一個被序列化存儲的對象.

ObjectOutputStream : 對象輸出流,能夠把一個實現了Serializable接口的對象序列化存儲到文件中或者是進行傳輸.使用
writeObject方法.

提示:若是有個對象須要序列化存儲,那麼最好加上一個版本id: private static final long serialVersionUID = 1L;
若是這個類修改過了,那麼反序列化的時候會報異常,能夠根據異常的版本號來判斷是哪次修改出了問題.

PrintStream : 打印字節流,能夠將對象的toString方法的結果輸出,System.out返回的就是一個PrintStream
print類的方法會先用toString轉換爲字符串並打印,而write方法會直接根據碼錶查找字符打印.

PrintWriter : 打印字符流,具體使用方法與通常輸出字符流差很少.

標準輸入輸出流: System.in System.out 默認標準輸入流是鍵盤,標準輸出流爲控制檯. 能夠用System.setIn setOut的方法改變標準流

Properties 類是Hashtable的子類,能夠用load方法讀取一個配置文件,如新建一個a.properties文件裏面寫入name=xxx,那麼能夠用properties.load(new FileInputStream("a.properties")); 讀取文件,而後用properties.getProperty("name", "yyy") 獲取值.第二個參數是默認值,若是沒有這個屬性那麼就會使用默認值.一樣也能夠用properties.setProperty("name2", "22222222");添加新屬性,用properties.store(new FileOutputStream("a.properties"), "描述");保存配置文件

相關文章
相關標籤/搜索