在Java中编写文件时计算文本文件的大小

4
这个问题是关于这个问题中被接受的答案的后续。我正在尝试实现Aaron提出的方法:包装FileOutputStream以包含保持已写入字节数计数的逻辑,但该方法似乎并没有按预期工作。 OutputStreamWriter似乎使用StreamEncoder在委托调用FileOutputStream.write()方法之前缓冲数据。以下是一个小的演示:
package Utils;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class MyFileOutputStream extends FileOutputStream{

private int byteCount;
public int getByteCount() {
    return byteCount;
}

public void setByteCount(int byteCount) {
    this.byteCount = byteCount;
}

public MyFileOutputStream(String arg0) throws FileNotFoundException {
    super(arg0);
    byteCount = 0;
}

@Override
public void write(byte[] b) throws IOException{
    byteCount += b.length;
    super.write(b);
}

@Override
public void write(byte[] b , int off , int len) throws IOException{
    byteCount += len;
    super.write(b, off, len);
}
}

驱动程序类:

  package main;
  import java.io.BufferedWriter;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.OutputStreamWriter;
  import java.io.Writer;

  import Utils.MyFileOutputStream;

  public class Driver {

/**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    MyFileOutputStream fos = new MyFileOutputStream("testFile");
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
    for(int i=0;i<1000;i++){
        bw.write("Writing this string\n");
        System.out.println("Bytes Written : "+fos.getByteCount());
    }
    bw.close();
    System.out.println(fos.getByteCount());
}

}

输出结果:

已写入字节数:0
已写入字节数:0
...
已写入字节数:8192
已写入字节数:8192
...

根据输出结果,StreamEncoder会在调用FileOutputStream的write()方法之前缓冲最多8192个字节。是否有任何解决办法来获取文件中任何时刻写入的字节数?


1
这就是重点,BufferedWriter会缓存输出内容直到其内部缓冲区被填满,或者调用flushclosed方法时,它才会将缓冲区输出到底层的写入流。 - MadProgrammer
设计看起来有点不对(在我看来),我会创建一个通过OutputStream的传递,它需要一个源OutputStream。 "counter"流将覆盖write(int)并记录通过它传递的字节数,调用父流的write方法。 这样,您可以使用任何类型的流... - MadProgrammer
3个回答

1
你可以使用flush()刷新最外层的writer/stream。这会强制BufferedWriter将其缓冲区中的所有字符转换为字节并发送到底层的FileOutputStream
请注意,这是一种比较耗费资源的操作:它不仅会转换字节,而且实际上会写入磁盘。因此,如果你过于频繁地调用flush(),那么对整体性能会有不利影响。
另一个选项是将缓冲区大小减小到128,这会导致IO次数增加64倍,但能够提供更精细的画面。
如果性能成问题,那么就需要将缓冲向下移动。直接向OutputStreamWriter写入,并将FileOutputStream包装在扩展BufferedOutputStream的类中。
这样,字符将立即转换为字节并添加到BufferedOutputStream的缓冲区中。现在你只需要询问你的BufferedOutputStream已经将多少字节写入了FileOutputStream+this.count即可。

1

是否有任何方法可以在任何时刻获取写入文件的字节数?

你所获得的是已经写入文件的字节数。

你似乎真正想要的是已经写入BufferedWriter的字符数。如果是这样,你需要包装/扩展BufferedWriter


不,我需要写入文件的字节数,但我不想以8K块的形式得到答案(因为缓冲区)。我意识到除了在写入缓冲区之前计算字符串的字节数之外别无选择。 - Kumaran
1
你没有理解。数据是以8k块的形式写入文件的,单个字节不会被写入。在StreamEncoder中有缓冲区。你无法改变这一点。它以较小的块写入StreamEncoder,但你只能按字符计算,而不能按字节计算。 - user207421
是的,我明白。但是,我正在处理用UTF-8编码写入文件中的日语汉字字符。因此,仅计算字符数将无法给出准确的文件大小。因此,我想要字节计数。 - Kumaran
1
你正在获取它。每次8192字节。因为FileOutputStream正在接收这个。没有其他答案。 - user207421

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接