繁体   English   中英

Java - 从文件中读取。输入流与读者

[英]Java — reading from a file. Input stream vs. reader

在我看到的从文件中读取的每个Java实现中,我几乎总是看到用于逐行读取的文件读取器。 我的想法是,这将是非常低效的,因为它需要每行系统调用。

我一直在做的是使用输入流并直接获取字节。 在我的实验中,这明显更快。 我的测试是一个1MB的文件。

    //Stream method
    try {
        Long startTime = new Date().getTime();

        InputStream is = new FileInputStream("test");
        byte[] b = new byte[is.available()];
        is.read(b);
        String text = new String(b);
        //System.out.println(text);

        Long endTime = new Date().getTime();
        System.out.println("Text length: " + text.length() + ", Total time: " + (endTime - startTime));

    }
    catch (Exception e) {
        e.printStackTrace();
    }

    //Reader method
    try {
        Long startTime = new Date().getTime();

        BufferedReader br = new BufferedReader(new FileReader("test"));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
            sb.append("\n");
        }
        String text = sb.toString();

        Long endTime = new Date().getTime();
        System.out.println("Text length: " + text.length() + ", Total time: " + (endTime - startTime));

    }
    catch (Exception e) {
        e.printStackTrace();
    }

这给出了以下结果:

Text length: 1054631, Total time: 9
Text length: 1034099, Total time: 22

那么,为什么人们使用读者而不是流?

如果我有一个方法接受一个文本文件并返回一个包含所有文本的字符串,那么使用流做它是否更好?

你正在比较苹果和香蕉。 即使使用bufferedReader,一次读取一行也会降低效率,而不是尽可能快地抓取数据。 请注意,不鼓励使用可用,因为它在所有情况下都不准确。 当我开始使用密码流时,我发现了这一点。

FileReader通常与BufferedReader一起使用,因为通常逐行读取文件是有意义的,特别是如果文件具有明确定义的记录结构,其中每个记录对应一行。

此外, FileReader可以简化处理字符编码和转换的一些工作,如javadoc中所述:

用于读取字符文件的便捷类。 此类的构造函数假定默认字符编码和默认字节缓冲区大小是合适的... FileReader用于读取字符流。

尝试增加BufferedReader缓冲区大小。 例如:

BufferedReader br = new BufferedReader(new FileReader("test"),2000000);

如果选择合适的缓冲区大小,则速度会更快。

然后在使用Reader的示例中,您将花时间填充StringBuilder。 如果需要处理行,则必须逐行读取文件。 但是,如果您只需要读取字符串中的文本,则使用public int read(char[] cbuf)读取更大的文本块,并将块写入使用适当大小初始化的StringWriter

选择使用InputStreamReader不依赖于性能。 通常,在阅读文本数据时使用Reader ,因为使用阅读器可以更轻松地处理字符集。

还有一点,你的代码在这里

byte[] b = new byte[is.available()];
is.read(b);
String text = new String(b);

这是不正确的。 文档说明

请注意,虽然InputStream的某些实现将返回流中的总字节数,但许多实现不会。 使用此方法的返回值来分配用于保存此流中所有数据的缓冲区绝对不正确。

所以要注意,你需要解决它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM