我试图使用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对象
答案 0 :(得分:3)
char的范围介于0
和65535
之间,因此不能-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万次。