-1

我想优化我的文件阅读器功能,但不确定在 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();
}

}

4

2 回答 2

3

建议:

  1. 正确缩进你的代码。你问题中的东西看起来像狗的早餐。

  2. 您不需要f在 try / catch 块内进行初始化。构造函数不能抛出Exception你使用它的方式。

  3. 实际上,您根本不需要声明它。只需内联new File(...).

  4. 事实上,你甚至不需要这样做。使用FileReader(String)构造函数。

  5. StringBuffer初始化循环内部没有意义。潜在的性能优势很小,仅适用于文件为空或不存在的边缘情况。在所有其他情况下,这是一种反优化。

  6. 不抓Exception。捕获您期望抛出的异常并允许所有其他异常传播。意外异常将是由于您的程序中的错误造成的,并且需要与其他异常进行不同的处理。

  7. 当你发现异常时,不要丢弃证据。对于意外异常,要么打印/记录异常、其消息和堆栈跟踪,要么将其作为您抛出异常的“原因”传递。

  8. FileReader应该在一个子句finally中结束。在您的代码版本中,FileReader如果在创建对象之后和调用之前出现异常,则不会关闭close()。这将导致文件描述符泄漏,并可能在以后的应用程序中引起问题。

  9. 更好的是,使用新的 Java 7“尝试使用资源”语法,它会自动关闭“资源”(见下文)。

  10. 您一次从文件中读取一个字符。这是非常低效的。您需要将Readera包装起来BufferedReader,或者使用(例如)一次读取大量字符read(char[], int, int)

  11. 使用StringBuilder而不是StringBuffer... 除非您需要线程安全的字符串汇编器。

  12. 包装异常RuntimeException是不好的做法。它使调用者难以处理特定的异常......如果需要......甚至使打印一个体面的诊断更加困难。(并且假设您没有像您的代码那样丢弃原始异常。)

注意:如果你按照第8点而不是第9点的建议,你会发现如果你在块中打开文件,你会发现frto的初始化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. 但是,如果文件通常很小,这可能会使应用程序变慢。

于 2012-02-25T03:00:32.623 回答
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 次并取平均值

  • 不需要在try里面放任何不需要异常处理的东西
  • 不需要那个 if 子句,因为它只会为真一次,所以你在浪费时间——检查每个字符
  • 没有运行时异常可以抛出。

结果:最快组合到最慢:

  1. 字符串生成器和缓冲读取器逐行:211 毫秒
  2. 字符串缓冲区和缓冲读取器逐行:213 ms
  3. 字符串生成器和缓冲读取器 char by char:348 ms
  4. 字符串缓冲区和按字符缓冲的读取器字符:372 毫秒
  5. 字符串生成器和文件读取器 char by char: 878
  6. 字符串缓冲区和文件读取器 char by char:935 ms
  7. 字符串:非常慢

所以使用字符串生成器+缓冲阅读器并使其逐行读取以获得最佳效果。

于 2012-02-25T04:08:59.423 回答