当我有要打印的字符数量时,如何计算文本文件的估计大小?
How do I calculate the estimated size of a text file when I have the amount of chars to be printed?
实际上我写了一个 Java 程序,它在 .txt 文件中打印一个大字符串!现在我想知道文件在生成之前有多大。其实我有字符的数量,但我不知道如何计算这个文件的大小。
当你说 "how big the file will be" 时,我假设你指的是文件中存储的字节数。
假设您使用 UTF-8 编码,悲观估计是字符串中字符数的 3 倍,因为它使用 3 字节代码字对一些 Unicode 代码点进行编码。它还使用 4 字节代码字,但这些代码字与 UTF-16 代理项对完全匹配。代理项对由两个 Java 个字符组成,因此它们的字节字符比仅为 2。
如果您的文件仅保留 Unicode 的 ASCII 子集,则估计值等于字符串中的字符数。
要获得 UTF-8 编码的确切字节数,您实际上必须逐个字符地扫描字符串并添加每个特定代码字的大小。您可以参考 Wikipedia page on UTF-8 了解这些尺寸。
据我所知,Java 并没有让这变得非常容易。我相信你确实必须对所有内容进行编码,但你不需要创建一个大字节数组......你可以使用 CharsetEncoder
将编码保持为 ByteBuffer
以获得长度它编码的每个部分。这是一些示例代码,我相信是正确的...
import java.nio.*;
import java.nio.charset.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
String ascii = createString('A', 2500);
String u00e9 = createString('\u00e9', 2500); // e-acute
String euro = createString('\u20ac', 2500); // Euro sign
// 4 UTF-16 code units, 3 Unicode code points
String surrogatePair = "X\ud800\udc00Y";
System.out.println(getEncodedLength(ascii, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(ascii, StandardCharsets.UTF_16BE));
System.out.println(getEncodedLength(u00e9, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(u00e9, StandardCharsets.UTF_16BE));
System.out.println(getEncodedLength(euro, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(euro, StandardCharsets.UTF_16BE));
System.out.println(getEncodedLength(surrogatePair, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(surrogatePair, StandardCharsets.UTF_16BE));
}
private static String createString(char c, int length) {
char[] chars = new char[length];
Arrays.fill(chars, c);
return new String(chars);
}
public static int getEncodedLength(String text, Charset charset) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
CharBuffer charBuffer = CharBuffer.wrap(text);
CharsetEncoder encoder = charset.newEncoder();
int length = 0;
while (encoder.encode(charBuffer, byteBuffer, false) == CoderResult.OVERFLOW) {
length += byteBuffer.position();
byteBuffer.clear();
}
encoder.encode(charBuffer, byteBuffer, true);
length += byteBuffer.position();
return length;
}
}
输出:
2500
5000
5000
5000
7500
5000
6
8
实际上我写了一个 Java 程序,它在 .txt 文件中打印一个大字符串!现在我想知道文件在生成之前有多大。其实我有字符的数量,但我不知道如何计算这个文件的大小。
当你说 "how big the file will be" 时,我假设你指的是文件中存储的字节数。
假设您使用 UTF-8 编码,悲观估计是字符串中字符数的 3 倍,因为它使用 3 字节代码字对一些 Unicode 代码点进行编码。它还使用 4 字节代码字,但这些代码字与 UTF-16 代理项对完全匹配。代理项对由两个 Java 个字符组成,因此它们的字节字符比仅为 2。
如果您的文件仅保留 Unicode 的 ASCII 子集,则估计值等于字符串中的字符数。
要获得 UTF-8 编码的确切字节数,您实际上必须逐个字符地扫描字符串并添加每个特定代码字的大小。您可以参考 Wikipedia page on UTF-8 了解这些尺寸。
Java 并没有让这变得非常容易。我相信你确实必须对所有内容进行编码,但你不需要创建一个大字节数组......你可以使用 CharsetEncoder
将编码保持为 ByteBuffer
以获得长度它编码的每个部分。这是一些示例代码,我相信是正确的...
import java.nio.*;
import java.nio.charset.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
String ascii = createString('A', 2500);
String u00e9 = createString('\u00e9', 2500); // e-acute
String euro = createString('\u20ac', 2500); // Euro sign
// 4 UTF-16 code units, 3 Unicode code points
String surrogatePair = "X\ud800\udc00Y";
System.out.println(getEncodedLength(ascii, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(ascii, StandardCharsets.UTF_16BE));
System.out.println(getEncodedLength(u00e9, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(u00e9, StandardCharsets.UTF_16BE));
System.out.println(getEncodedLength(euro, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(euro, StandardCharsets.UTF_16BE));
System.out.println(getEncodedLength(surrogatePair, StandardCharsets.UTF_8));
System.out.println(getEncodedLength(surrogatePair, StandardCharsets.UTF_16BE));
}
private static String createString(char c, int length) {
char[] chars = new char[length];
Arrays.fill(chars, c);
return new String(chars);
}
public static int getEncodedLength(String text, Charset charset) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
CharBuffer charBuffer = CharBuffer.wrap(text);
CharsetEncoder encoder = charset.newEncoder();
int length = 0;
while (encoder.encode(charBuffer, byteBuffer, false) == CoderResult.OVERFLOW) {
length += byteBuffer.position();
byteBuffer.clear();
}
encoder.encode(charBuffer, byteBuffer, true);
length += byteBuffer.position();
return length;
}
}
输出:
2500
5000
5000
5000
7500
5000
6
8