使用BufferedWriter时的程序设计,是否需要反复打开和关闭文件?

时间:2019-04-17 18:34:01

标签: java bufferedwriter

我有一个程序,它使用循环进行大量处理,并在许多不同的点将字符串写入文件。我不确定如何最好地进行总体设计。在运行过程中,我将不需要随时从文件中读取内容,尽管以后需要查看。

首先,带有FileWriter的BufferedWriter是这样做的合理方法吗?

第二,大概我不想每次想写东西(每秒几次)时都打开和关闭它。

但是,如果我使用try资源,那么实际上我必须将整个程序放入try中,这正常吗?

此刻骨架看起来像:

try (FileWriter writer = new FileWriter("filename.txt");
     BufferedWriter bw = new BufferedWriter(writer)) {

} catch (IOException e) {
    //catch IO error
}

for (//main loop){
    bw.write(string);
    for (//several sub loops){
        bw.write(//more strings);
    }
    for (//several sub loops){
        bw.write(//more strings);
    }
}

bw.write(//final string);

try {
    bw.close();
} catch (IOException ex) {
    //catch IO error
}

这看起来合理还是有更好的方法?非常感谢您的帮助。

编辑-感谢大家的帮助,完全回答了我的问题。

4 个答案:

答案 0 :(得分:2)

  
    

首先,带有FileWriter的BufferedWriter是这样做的合理方法吗?

  

是的,这应该是最方便的方法。

  

第二,大概我不想每次想写东西(每秒几次)时都打开和关闭它。

您真的不应该。但是无论如何,每次打开文件时,您实际上都会以这种方式覆盖进度。那是因为您没有告诉FileWriter附加到现有文件(通过new FileWriter("filename.txt", true);

  

但是,如果我使用try资源,那么实际上我必须将整个程序放入try中,这正常吗?

我认为没有问题。您可以(并且应该)始终将逻辑移到自己的方法或类中,这可能会返回String进行编写。这样,您就可以将实际的业务逻辑与技术文件的编写逻辑分开,并对代码进行结构化,使其更易于理解。

您也可以只写一个巨大的String,然后在String块中写那个try-with-resources。但这对于真正的大文件是有限制的,有时可能不是最佳选择。

答案 1 :(得分:1)

  

但是,如果我尝试使用资源,那么我实际上必须将   尝试整个程序,这正常吗?

那就是try-catch-with-resources的工作方式-在退出Host块时关闭资源。如果这让您感到困扰,请不要使用该构造,您可以自己管理try

上面的骨架将无法工作,因为第一个writer将打开和关闭您的作家;

答案 2 :(得分:1)

完全可以将整个代码放入try-catch例程中。每当您有问题要写入文件时,它只会捕获该文件,并且不会给您错误。但是,我建议您仅使用一个try-catch例程尝试这种结构。

try  { (FileWriter writer = new FileWriter("filename.txt");
 BufferedWriter bw = new BufferedWriter(writer)) 

for (/*main loop*/){
   bw.write(string);
   for (/*several sub loops*/){
    bw.write(/*more strings*/);
    }
for (/*several sub loops*/){
    bw.write(/*more strings*/);
    }
   }

bw.write(/*final string*/);


bw.close(); 


} catch (IOException e) {
   System.out.println("error");
}

PS:如果您在某些代码之间添加注释,请使用this:/ * comment * /而不是this://,因为它将注释掉整行。

答案 3 :(得分:1)

这里是替代方法,可以进行更精细的异常处理。在许多情况下,这是首选。具有catch块处理太多异常的情况会非常令人困惑:控制流被遮盖了,诊断错误可能要困难得多。

在程序运行的整个过程中都打开文件是很常见的。日志文件通常是这种情况。 如果您知道程序将运行很长时间,并且如果您怀疑输出到单个文件之间会有很长的延迟,则可以打开和关闭文件对于每批近距离操作。但是,您必须对活动模式有一个清晰的认识,才能做到这一点,因为您希望将文件的打开时间与预期的及时关闭批量写入相匹配。您应该非常避免高频打开和关闭操作。这会带来各种不必要的额外开销。

package my.tests;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.function.Consumer;

public class WriterTest {
    public static final String TARGET_NAME = "filename.txt";

    public void performMainLoop() {
        performWrites( this::mainLoop, TARGET_NAME );
    }

    public void performWrites( Consumer<Writer> writeActor, String targetName ) {
        FileWriter fileWriter;
        try {
            fileWriter = new FileWriter(targetName);
        } catch ( IOException e ) {
            System.out.println("Open failure: " + e.getMessage());
            e.printStackTrace();
            return;
        }

        BufferedWriter bufferedWriter = null;
        try {
            bufferedWriter = new BufferedWriter(fileWriter);
            writeActor.accept(bufferedWriter);

        } finally {
            if ( bufferedWriter != null ) {
                try {
                    bufferedWriter.close();
                } catch ( IOException e ) {
                    System.out.println("Unexpected close failure: " + e.getMessage());
                    e.printStackTrace();
                }
            } else {
                try {
                    fileWriter.close();
                } catch ( IOException e ) {
                    System.out.println("Unexpected close failure: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    }

    public void mainLoop(Writer writer) {
        for ( int loopNo = 0; loopNo < 10; loopNo++ ) {
            try {
                writer.write("Loop [ " + Integer.toString(loopNo) + " ]\n");

            } catch ( IOException e ) {
                System.out.println("Unexpected write failure: " + e.getMessage());
                e.printStackTrace();
                return;
            }
        }
    }
}