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

Program design when using BufferedWriter, do I repeatedly open and close file?

我有一个程序,它使用循环进行大量处理,并在许多不同的点将字符串写入文件。我不确定如何最好地做到这一点的整体设计。我在 运行 期间的任何时候都不需要读取文件,但之后会想查看它。

首先,带有 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
}

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

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

But if I use try with resources then I'd have to put practically the entire program inside that try, is this normal?

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

以上框架将不起作用,因为第一个 try 将打开和关闭您的编写器;

Firstly, is a BufferedWriter with FileWriter a reasonable way of doing this?

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

Secondly, presumably I don't want to be opening and closing this every time I want to write something (several times per second).

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

But if I use try with resources then I'd have to put practically the entire program inside that try, is this normal?

我认为这没有问题。您可以(并且应该)始终将您的逻辑移动到自己的方法或 类 中,这可能 return String 可以编写。通过这种方式,您可以将实际业务逻辑与技术文件编写逻辑分开,并构建您的代码,使其更易于理解。

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

将整个代码放入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:// 因为它会注释掉整行。

这是一个可以更好地处理异常的替代方法。在许多情况下,这是首选。让 catch 块处理太多异常会变得非常混乱:控制流变得模糊,诊断错误会困难得多。

在程序 运行 的整个过程中打开一个文件是很常见的。日志文件通常就是这种情况。 If 你知道你的程序会 运行 很长时间,并且 if 你怀疑输出到 a 之间会有很长的延迟单个文件,您可以为每批及时关闭操作打开和关闭文件。但是您必须清楚地了解 activity 的模式才能执行此操作,因为您需要将文件的打开时间与预期的关闭时间批次写入相匹配。您应该非常避免高频打开和关闭操作。这有各种不需要的额外开销。

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;
            }
        }
    }
}