我想优化我的文件阅读器功能,但不确定最佳做法是在try循环之外声明空值。是否循环并将字符追加到被认为是不良做法的Stringbuffer?我想在这里使用异常处理,但也许最好使用另一个结构?任何建议最受欢迎,谢谢。
public String readFile(){
File f = null;
FileReader fr = null;
StringBuffer content = null;
try{
f = new File("c:/test.txt");
fr = new FileReader(f);
int c;
while((c = fr.read()) != -1){
if(content == null){
content = new StringBuffer();
}
content.append((char)c);
}
fr.close();
}
catch (Exception e) {
throw new RuntimeException("An error occured reading your file");
}
return content.toString();
}
}
答案 0 :(得分:3)
建议:
正确缩进代码。你问题中的东西看起来像狗的早餐。
您无需在try / catch块中初始化f
。构造函数不能按照您使用它的方式抛出Exception
。
实际上,您根本不需要声明它。只需内联new File(...)
。
事实上,你甚至不需要这样做。使用FileReader(String)
构造函数。
在循环中初始化StringBuffer
毫无意义。潜在的性能优势很小,仅适用于文件为空或不存在的边缘情况。在所有其他情况下,这是一种反优化。
不要抓住Exception
。捕获您希望抛出的异常并允许传播所有其他异常。意外的异常将由于程序中的错误而导致,并且需要以不同的方式处理。
当您发现异常时,请不要丢弃证据。对于意外的异常,请打印/记录异常,其消息及其堆栈跟踪,或将其作为您抛出的异常的“原因”传递。
应在FileReader
子句中关闭finally
。在您的代码版本中,如果在创建对象之后和FileReader
调用之前存在异常,则close()
将不会关闭。这将导致泄漏的文件描述符,可能在您的应用程序中导致问题。
更好的是,使用新的Java 7“try with resource”语法,该语法负责自动关闭“资源”(见下文)。
您正在从文件中一次读取一个字符。这非常效率低下。您需要将Reader
包裹在BufferedReader
中,或者使用(例如)read(char[], int, int)
使用StringBuilder
而不是StringBuffer
...除非您需要线程安全的字符串汇编程序。
在RuntimeException
中包装例外是不好的做法。它使调用者难以处理特定的异常......如果需要......甚至使得打印体面的诊断更加困难。 (并且假设您没有像您的代码那样丢弃原始异常。)
注意:如果您遵循第8点而不是第9点的建议,如果您在fr
块中打开文件,则会发现null
到try
的初始化是必要的
以下是我写这个的方法:
public String readFile() throws IOException {
// Using the Java 7 "try with resource syntax".
try (FileReader fr = new FileReader("c:/test.txt")) {
BufferedReader br = new BufferedReader(fr);
StringBuilder content = new StringBuilder();
int c;
while ((c = br.read()) != -1) {
content.append((char)c);
}
return content.toString();
}
}
进一步的优化是使用File.length()
来查找文件大小(以字节为单位)的内容,并将其用作StringBuilder
的初始大小。但是,如果文件通常较小,则可能会使应用程序变慢。
答案 1 :(得分:0)
public String readFile() {
File f = new File("/Users/Guest/Documents/workspace/Project/src/test.txt");
FileReader fr = null;
BufferedReader br = null;
StringBuilder content = new StringBuilder();;
try {
fr = new FileReader(f);
br = new BufferedReader(fr);
//int c;
//while ((c = fr.read()) != -1) {
//content.append((char) c);
//}
String line = null;
while((line = br.readLine()) != null) {
content.append(line);
}
fr.close();
br.close();
} catch (Exception e) {
// do something
}
return content.toString();
}
使用缓冲读取器,你将获得70%以上的改进,除非你需要同步,否则使用字符串构建器而不是字符串缓冲区。
在10MB文件上运行50次并取平均值
结果: 最慢的组合:
因此请使用字符串构建器+缓冲读取器,并逐行读取以获得最佳效果。