IO 流详细分析

IO 流是输入输出机制

输入:表示读取外部数据(网络或者硬盘)流向内存的流叫输入流。

输出: 表示程序将流输出到外部,这种从内存流出的流叫做输出流。

输入和输出的概念都是以内存为出发点。比如读取文件,表面上分析好像是输出流,但是从内存分析,应该是读取文件中的内容流入内存,所以实际上是输入流。搞清楚这一点其实最容易混淆的已经被解决了。

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();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值