Filereader null声明和附加最佳实践

时间:2012-02-25 02:46:18

标签: java loops exception-handling filereader stringbuffer

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

}

2 个答案:

答案 0 :(得分:3)

建议:

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

  2. 您无需在try / catch块中初始化f。构造函数不能按照您使用它的方式抛出Exception

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

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

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

  6. 不要抓住Exception。捕获您希望抛出的异常并允许传播所有其他异常。意外的异常将由于程序中的错误而导致,并且需要以不同的方式处理。

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

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

  9. 更好的是,使用新的Java 7“try with resource”语法,该语法负责自动关闭“资源”(见下文)。

  10. 您正在从文件中一次读取一个字符。这非常效率低下。您需要将Reader包裹在BufferedReader中,或者使用(例如)read(char[], int, int)

  11. 一次读取大量字符
  12. 使用StringBuilder而不是StringBuffer ...除非您需要线程安全的字符串汇编程序。

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

  14. 注意:如果您遵循第8点而不是第9点的建议,如果您在fr块中打开文件,则会发现nulltry的初始化是必要的


    以下是我写这个的方法:

    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次并取平均值

  • 无需在try
  • 中放置任何不需要异常处理的内容
  • 不需要那个if子句,因为它只会是一次,所以你在浪费时间 - 检查每个字符
  • 不会抛出运行时异常。

结果: 最慢的组合:

  1. 字符串构建器和缓冲读取器逐行:211 ms
  2. 字符串缓冲区和缓冲读取器逐行:213 ms
  3. 字符串构建器和char缓冲读取器char:348 ms
  4. 字符串缓冲区和char缓冲读取器char:372 ms
  5. 字符串构建器和文件读取器char by char:878
  6. 字符串缓冲区和文件读取器char by char:935 ms
  7. string:极慢
  8. 因此请使用字符串构建器+缓冲读取器,并逐行读取以获得最佳效果。