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