1. 程式人生 > >Java : java基礎(3) IO流

Java : java基礎(3) IO流

log 讀一行 改變 上一個 system.in 指定 cti 前行 效果

流按操作類型分為兩種,字節流,字符流,按流向分為輸入流,輸出流,輸入流的抽象父類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時間:

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塊):

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);
}
}


---------------------------------------------------------------------------------------------
字符流,讀的時候把字節轉換為字符,寫的時候把字符轉換為字節寫入,可以通過項目默認的編碼一次讀取一個字符(如果是中文,就一次讀取兩個字節)

字符流 基礎父類Reader-InputStreamReader-FileReader,一般用FileReader,Writer類也一樣.

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

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

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"), "描述");保存配置文件

Java : java基礎(3) IO流