java字节流和字符流的实例练习(OutputStream、BufferedOutputStream、InputStream、BufferedInputStream)

31 篇文章 4 订阅
21 篇文章 1 订阅

一、字节流输入输出:

下面是一个字节流的输入输出案例练习,包括的类有OutputStream(输出流)、BufferedOutputStream(缓冲输出流)、InputStream(输入流)、BufferedInputStream(缓冲输输入流):

public class xxPutStreamTest {
    public static void main(String[] args) throws IOException {

        String currentPath = "src/main/java/ssl/ioTest/byteStream/document/";

        //输出字节流
        File forWriteFile = new File(currentPath + "forWrite.txt");
        StringBuilder sb = new StringBuilder();
        //缓冲区一次读取8192(2的13次方)个字节Byte
        for (int i = 0; i < 1368; i++) {
            sb.append("write");
        }
        byte[] forWriteBytes = sb.toString().getBytes();
        long outputStreamStart = System.currentTimeMillis();
        write(forWriteFile, forWriteBytes);
        long outputStreamEnd = System.currentTimeMillis();
        System.out.println("普通输出字节流耗时:" + (outputStreamEnd - outputStreamStart) + " ms");
        long bufferedOutputStreamStart = System.currentTimeMillis();
        bufferedWrite(forWriteFile, forWriteBytes);
        long bufferedOutputStreamEnd = System.currentTimeMillis();
        System.out.println("缓冲输出字节流耗时:" + (bufferedOutputStreamEnd - bufferedOutputStreamStart) + " ms");


        //输入字节流
        File forReadFile = new File(currentPath + "forRead.txt");
        byte[] forReadBytes = new byte[120000000];
        long inputStreamStart = System.currentTimeMillis();
        read(forReadFile,forReadBytes);
        long inputStreamEnd = System.currentTimeMillis();
        System.out.println("普通输入字节流耗时:" + (inputStreamEnd - inputStreamStart) + " ms");
        long bufferedInputStreamStart = System.currentTimeMillis();
        bufferedRead(forReadFile,forReadBytes);
        long bufferedInputStreamEnd = System.currentTimeMillis();
        System.out.println("缓冲输入字节流耗时:" + (bufferedInputStreamEnd - bufferedInputStreamStart) + " ms");
    }

    /**
     * 普通输出字节流OutputStream
     * @param file 输出文件路径
     * @param bytes 要输出的内容
     * @throws IOException
     */
    public static void write(File file, byte[] bytes) throws IOException {
        OutputStream outputStream = new FileOutputStream(file);
        outputStream.write(bytes);
        outputStream.close();
    }

    /**
     * 缓冲输出字节流BufferedOutputStream
     */
    public static void bufferedWrite(File file, byte[] bytes) throws IOException {
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
        bufferedOutputStream.write(bytes);
        bufferedOutputStream.close();
    }


    /**
     * 普通输入字节流InputStream
     * @return resultLength 返回读到的byte数组的长度
     */
    public static int read(File file, byte[] bytes) throws IOException {
        InputStream inputStream = new FileInputStream(file);
        int resultLength = inputStream.read(bytes);
        inputStream.close();
        return resultLength;
    }

    /**
     * 缓冲输入字节流BufferedInputStream
     */
    public static int bufferedRead(File file, byte[] bytes) throws IOException {
        BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
        int resultLength = bufferedInputStream.read(bytes);
        bufferedInputStream.close();
        return resultLength;
    }
}

输出结果:

普通输出字节流耗时:7 ms
缓冲输出字节流耗时:2 ms
普通输入字节流耗时:53 ms
缓冲输入字节流耗时:50 ms

经过多次输出,对结果进行分析,使用缓冲输入(出)流一般要比普通输入(出)流所使用的时间更短,即速度更快,但是当输入或者输出字符串的长度过长时,两者之间的速度差异会变小,即缓冲输入(出)流的速度优势会减弱,个人对其原因进行初步分析,下面是BufferedOutPutStream中的其中一个write方法的源码:

public synchronized void write(byte b[], int off, int len) throws IOException {
        if (len >= buf.length) {
            /* If the request length exceeds the size of the output buffer,
               flush the output buffer and then write the data directly.
               In this way buffered streams will cascade harmlessly. */
            flushBuffer();
            out.write(b, off, len);
            return;
        }
        if (len > buf.length - count) {
            flushBuffer();
        }
        System.arraycopy(b, off, buf, count, len);
        count += len;
    }

方法中注释翻译:如果请求长度超过了输出缓冲区的大小,刷新输出缓冲区,然后直接写入数据。以这种方式缓冲的流将无害地级联。 

那么缓冲区的大小到底是多少呢,我们在新建BufferedOutputStream的时候使用的构造函数:

/**
     * Creates a new buffered output stream to write data to the
     * specified underlying output stream.
     *
     * @param   out   the underlying output stream.
     */
    public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }

/**
     * Creates a new buffered output stream to write data to the
     * specified underlying output stream with the specified buffer
     * size.
     *
     * @param   out    the underlying output stream.
     * @param   size   the buffer size.
     * @exception IllegalArgumentException if size &lt;= 0.
     */
    public BufferedOutputStream(OutputStream out, int size) {
        super(out);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

可以看到在新建的时候就给定了缓冲区的大小(size)为8192,至于为什么是8192(2的13次方)而不是其他长度的原因我并不清楚,只是看到一篇博客说是跟网络请求套接字有关系,但是java本地文件的传输好像用不到网络传输,所以此点暂时存疑。

同样缓冲输入流也是一样的,在下面BufferedInputStream类的源码中同样通过构造方法限制了输入缓冲流的数组的长度为8192:

    private static int DEFAULT_BUFFER_SIZE = 8192;   

    /**
     * Creates a <code>BufferedInputStream</code>
     * and saves its  argument, the input stream
     * <code>in</code>, for later use. An internal
     * buffer array is created and  stored in <code>buf</code>.
     *
     * @param   in   the underlying input stream.
     */
    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }

    /**
     * Creates a <code>BufferedInputStream</code>
     * with the specified buffer size,
     * and saves its  argument, the input stream
     * <code>in</code>, for later use.  An internal
     * buffer array of length  <code>size</code>
     * is created and stored in <code>buf</code>.
     *
     * @param   in     the underlying input stream.
     * @param   size   the buffer size.
     * @exception IllegalArgumentException if {@code size <= 0}.
     */
    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }

二、字符输入输出流

package ssl.ioTest.characterStream;

import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBaseIterators;

import java.io.*;

public class Filexx {
    public static void main(String[] args) throws IOException {

        // 数据准备
        String currentPath = "src/main/java/ssl/ioTest/characterStream/document/";
        File data = new File(currentPath + "data.txt");
        dataReady(data);

        File a = new File(currentPath + "a.txt");
        File b = new File(currentPath + "b.txt");
        File c = new File(currentPath + "c.txt");

        long start = System.currentTimeMillis();
        copy(data, a);
        long end = System.currentTimeMillis();
        System.out.println("普通字节流1耗时:" + (end - start) + " ms,文件大小:" + a.length() / 1024 + " kb");

        long start2 = System.currentTimeMillis();
        copyChars(data, b);
        long end2 = System.currentTimeMillis();
        System.out.println("普通字节流2耗时:" + (end2 - start2) + " ms,文件大小:" + b.length() / 1024 + " kb");

        long start3 = System.currentTimeMillis();
        bufferedCopy(data, c);
        long end3 = System.currentTimeMillis();
        System.out.println("缓冲字节流耗时:" + (end3 - start3) + " ms,文件大小:" + c.length() / 1024 + " kb");
    }

        // 普通字符流不使用数组
    public static void copy(File in, File out) throws IOException {
        Reader reader = new FileReader(in);
        Writer writer = new FileWriter(out);

        int ch = 0;
        while ((ch = reader.read()) != -1) {
            writer.write((char) ch);
        }
        reader.close();
        writer.close();
    }

    // 普通字符流使用字符流
    public static void copyChars(File in, File out) throws IOException {
        Reader reader = new FileReader(in);
        Writer writer = new FileWriter(out);

        char[] chs = new char[1024];
        while ((reader.read(chs)) != -1) {
            writer.write(chs);
        }
        reader.close();
        writer.close();
    }

    // 缓冲字符流
    public static void bufferedCopy(File in, File out) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(in));
        BufferedWriter bw = new BufferedWriter(new FileWriter(out));

        String line = null;
        while ((line = br.readLine()) != null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }

        // 释放资源
        bw.close();
        br.close();
    }

    // 数据准备
    public static void dataReady(File file) throws IOException {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 600000; i++) {
            sb.append("read&write");
        }
        OutputStream os = new FileOutputStream(file);
        os.write(sb.toString().getBytes());

        os.close();
        System.out.println("数据填充结束");
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肆〇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值