繁体   English   中英

尝试使用 FileReader 对象读取文件时发生无限循环

[英]infinite loop occurs when trying to read a file with FileReader object

我试图使用 FileReader 从文件中读取,但程序进入无限循环:这是我的代码:

import java.io.FileReader;

public class Test {
    public static void main(String[] args)  {
        try(FileReader f = new FileReader("sales.dat");){
            char ch = (char)f.read();
            while(ch != -1){
                ch = (char)f.read();
                System.out.print(ch);
            }
        }catch (Exception e){
        }
    }
}

为什么只使用 FileReader 读取文件效率不高,而最好使用 BufferedReader 对象

char 的范围在065535之间,因此它不能为-1因此char != -1始终为真。

while(int ch; (ch = f.read()) >= 0;)
   System.out.print((char) ch);

这将在转换为char之前检查值是否为非负

为什么仅使用 FileReader 读取文件效率不高,而最好使用 BufferedReader 对象

BufferedReader 使用 FileReader 所以也许问题应该是; 为什么不单独使用 FileReader?

答案是; 调用操作系统是昂贵的。 每次调用可能是几微秒,而进程内存访问可能是纳秒。

通过使用缓冲区,例如 BufferedReader,您调用操作系统的次数要少得多(默认情况下最多为 1/8192),这提高了获取每个字节数据的效率。

在上面的例子中,这并不重要。 虽然调用 FileReader 很昂贵,但与写入控制台相比,它很便宜。 写入控制台是这里唯一影响性能的事情。

相反,您可以像这样逐行阅读

final File file = new File("your_file");
try (final InputStream fileStream = new FileInputStream(file.getAbsolutePath()); final Reader decoder = new InputStreamReader(fileStream);
        final BufferedReader buffered = new BufferedReader(decoder)) {
    String line;
    while ((line = buffered.readLine()) != null) {
        // do stuff
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

附: 不知道你的子问题

您无法获得负的 char 值,因此小于 -1 的检查将始终为假。

使用子类InputStreamReader ,您应该依靠ready()来检查您是否已到达流的末尾。

while(reader.ready()){
    // do stuff
}

使用缓冲流更快,因为它减少了操作系统 IO 调用的数量。 如果您有一个 100 万字节的文件并一次读取一个字节,对于每个非缓冲调用,JVM 需要从操作系统请求读取。 这是 Java 进程请求从操作系统读取的 100 万次。 对于缓冲流,它尝试在一次读取中填充其缓冲区。 因此,即使您请求 1 个字节,底层流在内存中也会有 N 个字节,从而将底层操作系统的调用次数减少大约 FILE_SIZE/BUFFER_SIZE。 对于 1 MB 的文件,如果缓冲区大小为 1024,并且每次都能填满,则 OS 调用数将为 1M/1K,即 1000 次读取 vs 100 万次。

暂无
暂无

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

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