gpt4 book ai didi

java - 如何通过 FileWriter 在 BufferedWriter 上设置缓冲区大小

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:27:22 25 4
gpt4 key购买 nike

当我使用一些线程将数据写入单个文件时,我遇到了 BufferedWriter 的问题。

我设置了 BufferedWriter 的缓冲区大小,但无论我设置多少,它都会在缓冲区为 8192(默认缓冲区大小)而不是我设置的大小时将数据刷新到磁盘(这里是 16384)。我的代码有问题吗?

这就是我构建 BufferedWriter 的方式:

new BufferedWriter(new FileWriter(fileName, true), 16384);

这是完整的代码:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class Test1 {
public static void main(String[] args) throws IOException {
for(int i =0;i<10;i++){
MyThread r = new MyThread();
Thread t = new Thread(r);
t.start();
}
}
}

class MyThread implements Runnable {
public void run() {
String s = "{addffffffkkkljlkj2015dd}\n";
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(
"/Users/liaoliuqing/Downloads/1.txt", true),16384);
} catch (IOException e) {
e.printStackTrace();
}
for(int i =0 ; i<1000; i++){
try {
bw.write(String.format("%03d", i)+s);
//bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

最佳答案

Is there a problem with my code?

一些。主要是:潜在的IO和并发错误。文件缓冲区大小可能不是一个值得关注的问题(也是您无法有效处理的问题)。

  • 正在尝试打开已经打开的文件。您的所有线程都试图写入同一个文件 (1.txt)。这可能是个问题。 FileWriter documentation says:

    Some platforms, in particular, allow a file to be opened for writing by only one FileWriter (or other file-writing object) at a time. In such situations the constructors in this class will fail if the file involved is already open.

  • 线条可能会被剪切和混合。如果您有多个线程,它们各自的缓冲区在某个时刻刷新到相同的输出中,您甚至可能不需要奇怪的竞争条件或线程在中间停止或写操作来查看您的输出损坏。

    作为我的解决方案(如果您的线程必须共享相同的输出),您可以使用具有同步访问权限的共享对象来处理实际的写入。我在示例中实现了 SafeAppender,但可能还有更好的替代方案。

  • 没有flushingclosing 缓冲区将意味着您的数据(尾部)将丢失(就像雨中的泪水)。 finally block 通常可以很好地解决这个问题。

  • 此外,正如其他用户所述,BufferedWriter 缓冲区大小 不会影响 FileOutputStream 中的缓冲区大小(因此 FileWriter)。看起来 java.iojava.nio API 没有提供任何方法来解决这个问题。如果您查看 Java 库源代码,您可能会注意到 BufferedWriter 缓冲区大小仅表示在实际写入委托(delegate)输出之前存储的字符数量。对于大多数情况,默认大小 (8192) 是最佳的,增加它可能意味着更多麻烦(可能丢失更多数据)而不是好处。

这是我的代码,如果对你有用的话:

// http://stackoverflow.com/questions/32451526/how-to-set-the-buffer-size-on-a-bufferedwriter-over-a-filewriter
public class TestWriter {

public static class SafeAppender {
private BufferedWriter bw;
private int users = 0;
public SafeAppender(File f) throws IOException {
bw = new BufferedWriter(new FileWriter(f));
}

public synchronized void append(String s) throws IOException {
bw.write(s);
}
public synchronized void incrUsers() {
users ++;
}
public synchronized void decrUsers() {
if (--users <= 0) {
try {
bw.flush();
System.err.println("INFO-appender-flush()");
} catch (Throwable whatever) { /* log-if-you-care*/}
}
}
// Might be called by GC, or not
@Override protected void finalize() throws Throwable {
try {
bw.close();
System.err.println("INFO-appender-close()");
} catch (Throwable whatever) { /* log-if-you-care */}
super.finalize();
}
}

private static class MyRunnable implements Runnable {
final static String S = "{addffffffkkkljlkj2015dd}";
SafeAppender appender;
String threadId;
public MyRunnable (SafeAppender a, String tid) {
appender = a; threadId = tid;
}

public void run() {
appender.incrUsers();
try {
for(int i =0 ; i<1000; i++){
// NOTE: Not a good idea to printStackTrace if each line fails. Let thread fail
String line = String.format("%s-%03d-%s\n", threadId, i, S);
appender.append(line);
}
} catch (IOException e) {
System.err.printf("ERROR-%s-%s\n", threadId, e.toString());
} finally {
appender.decrUsers();
}
}
}

public static void main(String[] args) {
try {
File f = File.createTempFile("TestWriter", ".txt");
System.err.printf("INFO-main-Writing into %s\n", f.getCanonicalPath());
SafeAppender appender = new SafeAppender (f);
for(int i =0;i<10;i++){
MyRunnable r = new MyRunnable(appender, ""+i);
Thread t = new Thread(r);
t.start();
}
} catch (Throwable e) {
e.printStackTrace(System.err);
}
}

}

关于java - 如何通过 FileWriter 在 BufferedWriter 上设置缓冲区大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32451526/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com