IO 流是輸入輸出機制
輸入:表示讀取外部數據(網絡或者硬盤)流向內存的流叫輸入流。
輸出: 表示程序將流輸出到外部,這種從內存流出的流叫做輸出流。
輸入和輸出的概念都是以內存爲出發點。比如讀取文件,表面上分析好像是輸出流,但是從內存分析,應該是讀取文件中的內容流入內存,所以實際上是輸入流。搞清楚這一點其實最容易混淆的已經被解決了。
字節流
字節流可以讀取字節,在創建緩存的時候採用byte[]
字節流又包括 InputStream 和 OutputStream 具體有包含很多子類,這裏拿其中我個人最常用的兩個爲例。
FileInputStream
從輸入流中讀取 b.length 個字節的數據,當所有的字節都被讀取到緩存區中會返回 -1
/**
* Reads up to <code>b.length</code> bytes of data from this input
* stream into an array of bytes. This method blocks until some input
* is available.
*
* @param b the buffer into which the data is read.
* @return the total number of bytes read into the buffer, or
* <code>-1</code> if there is no more data because the end of
* the file has been reached.
* @exception IOException if an I/O error occurs.
*/
public int read(byte b[]) throws IOException {
return readBytes(b, 0, b.length);
}
FileOutputStream
從輸出流中獲取的字節流中 off 到 len 的字節。
/**
* Writes <code>len</code> bytes from the specified byte array
* starting at offset <code>off</code> to this file output stream.
*
* @param b the data.
* @param off the start offset in the data.
* @param len the number of bytes to write.
* @exception IOException if an I/O error occurs.
*/
public void write(byte b[], int off, int len) throws IOException {
writeBytes(b, off, len, append);
}
代碼實現
private static void readFile(String path) {
if (StringUtils.isBlank(path)){
System.out.println("未指定準確路徑!");
return;
}
File file = new File(path); // 目的是創建一個file對象並且檢查path路徑是否正常
File fileNew = new File("D:/file/1/test.txt"); // 將 file 的字節流 保存到 fileSave 文件中
if (!file.exists()){
System.out.println("路徑下未發現文件!");
return;
}
try (FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(fileNew);) { // 創建一個讀取文件的輸入流(將文件讀入內存所以是輸入流)
byte[] b = new byte[2048]; // 定義讀取數據的緩衝區
int n = 0;// 得到實際讀取到的字節數
// 循環讀取,每次最多讀取b.length個字節數據
while((n = fis.read(b))!=-1){ // 讀取 數組b 大小的字節 讀取完成後返回 -1
// 把字節轉成String
String s = new String(b, 0, n);
System.out.println(s);
fos.write(b, 0, n);
}
} catch (IOException e) {
e.printStackTrace();
}
}
字符流
字符流可以讀取字符,不能操作字節在創建緩存的時候採用char[]
字符流又包括 Reader 和 Writer 具體有包含很多子類,這裏同樣拿其中我個人最常用的爲例。
FileReader & FileWriter
FileReader 和 FileWriter 代碼上與 FileInputStream, FileOutputStream 操作方法上區別不大,而關鍵在於配合 BufferedReader 使用可以提高效率
BufferedReader & BufferedWriter
BufferedReader 之所以可以提高效率在於 BufferedReader 在初始化時候默認設置 8k 的緩存區,這樣減少了 IO 操作,優先從緩存區獲取。
BufferReader 構造方法如下
private static int defaultCharBufferSize = 8192;
/**
* Creates a buffering character-input stream that uses a default-sized
* input buffer.
*
* @param in A Reader
*/
public BufferedReader(Reader in) {
this(in, defaultCharBufferSize);
}
/**
* Creates a buffering character-input stream that uses an input buffer of
* the specified size.
*
* @param in A Reader
* @param sz Input-buffer size
*
* @exception IllegalArgumentException If {@code sz <= 0}
*/
public BufferedReader(Reader in, int sz) {
super(in);
if (sz <= 0)
throw new IllegalArgumentException("Buffer size <= 0");
this.in = in;
cb = new char[sz];
nextChar = nChars = 0;
}
BufferReader 還有一個非常好用的方法 readLine ,也就是說會讀取一行數據,但是通過源代碼可以知道並不會讀取回車或換行,所以實際寫入文件的時候需要添加換行。
/**
* Reads a line of text. A line is considered to be terminated by any one
* of a line feed ('\n'), a carriage return ('\r'), or a carriage return
* followed immediately by a linefeed.
*
* @return A String containing the contents of the line, not including
* any line-termination characters, or null if the end of the
* stream has been reached
*
* @exception IOException If an I/O error occurs
*
* @see java.nio.file.Files#readAllLines
*/
public String readLine() throws IOException {
return readLine(false);
}
代碼實現
private static void readFileByBuffer(String path) {
if (StringUtils.isBlank(path)){
System.out.println("未指定準確路徑!");
return;
}
File file = new File(path); // 目的是創建一個file對象並且檢查path路徑是否正常
File fileNew = new File("D:/file/1/test.txt"); // 將 file 的字節流 保存到 fileSave 文件中
if (!file.exists()){
System.out.println("路徑下未發現文件!");
return;
}
try (FileReader fr = new FileReader(file);
FileWriter fw = new FileWriter(fileNew);
BufferedReader br = new BufferedReader(fr); // 創建使用默認大小的緩衝字符輸入流
BufferedWriter bw = new BufferedWriter(fw)) {
String s="";
while((s=br.readLine())!=null)
{
System.out.println(s); //readLine 不會獲取換行和回車,所以這裏打印需要加上換行
s = s+"\n";
bw.write(s);
}
} catch (IOException e) {
e.printStackTrace();
}
}