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

时间:2015-06-26 14:33:56

标签: java

我试图使用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对象

3 个答案:

答案 0 :(得分:3)

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很昂贵,但与写入控制台相比它很便宜。写入控制台是唯一对性能而言至关重要的事情。

答案 1 :(得分:1)

相反,您可以按行阅读

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();
}

PS。不知道你的子问题

答案 2 :(得分:0)

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

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

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

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