有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

从文件中读取文本Java。输入流与读取器

在我看到的每个从文件读取的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

那么,为什么人们使用阅读器而不是流呢

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


共 (3) 个答案

  1. # 1 楼答案

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

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

    Convenience class for reading character files. The constructors of this class assume that the default character encoding and the default byte-buffer size are appropriate ... FileReader is meant for reading streams of characters.

  2. # 2 楼答案

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

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

    如果选择正确的缓冲区大小,则速度会更快

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

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

    另一点,你的代码在这里

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

    这是不对的。{a1}告诉我们

    Note that while some implementations of InputStream will return the total number of bytes in the stream, many will not. It is never correct to use the return value of this method to allocate a buffer intended to hold all data in this stream.

    所以请注意,你需要修复它

  3. # 3 楼答案

    你把苹果比作香蕉。与尽可能快地抓取数据相比,即使使用bufferedReader,一次读取一行数据的效率也会更低。请注意,不鼓励使用available,因为它并非在所有情况下都准确。当我开始使用密码流时,我自己发现了这一点