Java 用于流的缓冲 base64 编码器
Java buffered base64 encoder for streams
我有很多 PDF 文件需要使用 base64 对其内容进行编码。我有一个 Akka 应用程序,它以流的形式获取文件并分发给许多工作人员以对这些文件和 returns 每个文件的字符串 base64 进行编码。我得到了编码的基本解决方案:
org.apache.commons.codec.binary.Base64InputStream;
...
Base64InputStream b64IStream = null;
InputStreamReader reader = null;
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
try {
b64IStream = new Base64InputStream(input, true);
reader = new InputStreamReader(b64IStream);
br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
} finally {
if (b64IStream != null) {
b64IStream.close();
}
if (reader != null) {
reader.close();
}
if (br != null) {
br.close();
}
}
它有效,但我想知道使用缓冲区对文件进行编码的最佳方式是什么,以及是否有更快的替代方法。
我测试了一些其他方法,例如:
- Base64.getEncoder
- sun.misc.BASE64编码器
- Base64.encodeBase64
- javax.xml.bind.DatatypeConverter.printBase64
- com.google.guava.BaseEncoding.base64
它们速度更快,但需要整个文件,对吗?另外,我不想在编码 1 个 PDF 文件时阻塞其他线程。
任何输入都非常有用。谢谢!
关于 Base64 的有趣事实:它需要三个字节,并将它们转换为四个字母。这意味着如果您读取可被三整除的块中的二进制数据,您可以将这些块提供给 any Base64 编码器,它会以与您提供给它相同的方式对其进行编码整个文件。
现在,如果您希望输出流只是一长串 Base64 数据(这是完全合法的),那么您需要做的就是:
private static final int BUFFER_SIZE = 3 * 1024;
try ( BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE); ) {
Base64.Encoder encoder = Base64.getEncoder();
StringBuilder result = new StringBuilder();
byte[] chunk = new byte[BUFFER_SIZE];
int len = 0;
while ( (len = in.read(chunk)) == BUFFER_SIZE ) {
result.append( encoder.encodeToString(chunk) );
}
if ( len > 0 ) {
chunk = Arrays.copyOf(chunk,len);
result.append( encoder.encodeToString(chunk) );
}
}
这意味着只有最后一个块的长度不能被三整除,因此将包含填充字符。
上面的示例是 Java 8 Base64,但您实际上可以使用任何采用任意长度的字节数组和 returns 该字节数组的 base64 字符串的编码器。
这意味着您可以随意调整缓冲区大小。
但是,如果您希望输出与 MIME 兼容,则需要将输出分成多行。在这种情况下,我会将上例中的块大小设置为乘以 4/3 后的整数行数。例如,如果你想每行有 64 个字符,则每行编码 64 / 4 * 3,即 48 个字节。如果你编码 48 个字节,你会得到一行。如果你编码 480 个字节,你将得到 10 整行。
所以将上面的 BUFFER_SIZE 修改为 4800 之类的东西。用 Base64.getMimeEncoder(64,new byte[] { 13, 10})
代替 Base64.getEncoder()
。然后,当它编码时,你将从每个块中获得 100 行全尺寸行,最后一个除外。您可能需要在 while 循环中添加 result.append("\r\n")
。
我有很多 PDF 文件需要使用 base64 对其内容进行编码。我有一个 Akka 应用程序,它以流的形式获取文件并分发给许多工作人员以对这些文件和 returns 每个文件的字符串 base64 进行编码。我得到了编码的基本解决方案:
org.apache.commons.codec.binary.Base64InputStream;
...
Base64InputStream b64IStream = null;
InputStreamReader reader = null;
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
try {
b64IStream = new Base64InputStream(input, true);
reader = new InputStreamReader(b64IStream);
br = new BufferedReader(reader);
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
} finally {
if (b64IStream != null) {
b64IStream.close();
}
if (reader != null) {
reader.close();
}
if (br != null) {
br.close();
}
}
它有效,但我想知道使用缓冲区对文件进行编码的最佳方式是什么,以及是否有更快的替代方法。
我测试了一些其他方法,例如:
- Base64.getEncoder
- sun.misc.BASE64编码器
- Base64.encodeBase64
- javax.xml.bind.DatatypeConverter.printBase64
- com.google.guava.BaseEncoding.base64
它们速度更快,但需要整个文件,对吗?另外,我不想在编码 1 个 PDF 文件时阻塞其他线程。
任何输入都非常有用。谢谢!
关于 Base64 的有趣事实:它需要三个字节,并将它们转换为四个字母。这意味着如果您读取可被三整除的块中的二进制数据,您可以将这些块提供给 any Base64 编码器,它会以与您提供给它相同的方式对其进行编码整个文件。
现在,如果您希望输出流只是一长串 Base64 数据(这是完全合法的),那么您需要做的就是:
private static final int BUFFER_SIZE = 3 * 1024;
try ( BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE); ) {
Base64.Encoder encoder = Base64.getEncoder();
StringBuilder result = new StringBuilder();
byte[] chunk = new byte[BUFFER_SIZE];
int len = 0;
while ( (len = in.read(chunk)) == BUFFER_SIZE ) {
result.append( encoder.encodeToString(chunk) );
}
if ( len > 0 ) {
chunk = Arrays.copyOf(chunk,len);
result.append( encoder.encodeToString(chunk) );
}
}
这意味着只有最后一个块的长度不能被三整除,因此将包含填充字符。
上面的示例是 Java 8 Base64,但您实际上可以使用任何采用任意长度的字节数组和 returns 该字节数组的 base64 字符串的编码器。
这意味着您可以随意调整缓冲区大小。
但是,如果您希望输出与 MIME 兼容,则需要将输出分成多行。在这种情况下,我会将上例中的块大小设置为乘以 4/3 后的整数行数。例如,如果你想每行有 64 个字符,则每行编码 64 / 4 * 3,即 48 个字节。如果你编码 48 个字节,你会得到一行。如果你编码 480 个字节,你将得到 10 整行。
所以将上面的 BUFFER_SIZE 修改为 4800 之类的东西。用 Base64.getMimeEncoder(64,new byte[] { 13, 10})
代替 Base64.getEncoder()
。然后,当它编码时,你将从每个块中获得 100 行全尺寸行,最后一个除外。您可能需要在 while 循环中添加 result.append("\r\n")
。