我遇到了一个问题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();
}
}
}
}
我的代码有问题吗?
一些。主要是:潜在的IO和并发错误。文件缓冲区大小可能不太重要(而且您无法有效处理)。
-
尝试打开已经打开的文件。您的所有线程都试图写入同一个文件(1.txt
)。这可能是一个问题。FileWriter 文档说:
特别是某些平台允许一次仅由一个 FileWriter(或其他文件写入对象)打开文件进行写入。在这种情况下,如果涉及的文件已经打开,则此类中的构造函数将失败。
-
线条可能会被剪切和混合。如果您有多个线程,其各自的缓冲区在某个时刻刷新到同一输出中,您甚至可能不需要奇怪的竞争条件或线程在中间停止或写入操作来查看输出损坏。
正如我的解决方案(如果您的线程必须共享相同的输出),您可以使用具有同步访问的共享对象来处理实际的写入。我实施了SafeAppender
在我的例子中,但可能有更好的选择。
No flushing and closing缓冲区将意味着您的数据(尾部)将丢失(就像雨中的眼泪)。 finally 块通常可以很好地解决这个问题。
另外,正如其他用户所说,BufferedWriter
缓冲区大小不影响缓冲区大小FileOutputStream
(所以FileWriter
)。它看起来java.io
and java.nio
API 没有提供任何方法来解决这个问题。如果您查看 Java 库源代码,您可能会注意到BufferedWriter
缓冲区大小只是指在实际写入委托输出之前存储的字符数量。默认大小 (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);
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)