IllegalArgumentException 使用 Java8 Base64 解码器
IllegalArgumentException using Java8 Base64 decoder
我想用Base64.java来编码和解码文件。 Encode.wrap(InputStream)
和 decode.wrap(InputStream)
工作但 运行 慢。所以我使用了以下代码。
public static void decodeFile(String inputFileName,
String outputFileName)
throws FileNotFoundException, IOException {
Base64.Decoder decoder = Base64.getDecoder();
InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName);
byte[] inBuff = new byte[BUFF_SIZE]; //final int BUFF_SIZE = 1024;
byte[] outBuff = null;
while (in.read(inBuff) > 0) {
outBuff = decoder.decode(inBuff);
out.write(outBuff);
}
out.flush();
out.close();
in.close();
}
但是,它总是抛出
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Input byte array has wrong 4-byte ending unit
at java.util.Base64$Decoder.decode0(Base64.java:704)
at java.util.Base64$Decoder.decode(Base64.java:526)
at Base64Coder.JavaBase64FileCoder.decodeFile(JavaBase64FileCoder.java:69)
...
我把final int BUFF_SIZE = 1024;
改成final int BUFF_SIZE = 3*1024;
后,代码就可以用了。由于 "BUFF_SIZE" 也用于对文件进行编码,我认为编码的文件有问题(1024 % 3 = 1,这意味着在文件中间添加了填充)。
此外,正如@Jon Skeet 和@Tagir Valeev 提到的,我不应该忽略 InputStream.read()
中的 return 值。所以,我修改了如下代码。
(但是,我不得不提到代码 运行 比使用 wrap()
快得多。我注意到速度差异是因为我已经编码并大量使用 Base64.encodeFile() /decodeFile() 在 jdk8 发布之前很久。现在,我的 buffed jdk8 代码 运行s 和我的原始代码一样快。所以,我不知道 wrap()
发生了什么......)
public static void decodeFile(String inputFileName,
String outputFileName)
throws FileNotFoundException, IOException
{
Base64.Decoder decoder = Base64.getDecoder();
InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName);
byte[] inBuff = new byte[BUFF_SIZE];
byte[] outBuff = null;
int bytesRead = 0;
while (true)
{
bytesRead = in.read(inBuff);
if (bytesRead == BUFF_SIZE)
{
outBuff = decoder.decode(inBuff);
}
else if (bytesRead > 0)
{
byte[] tempBuff = new byte[bytesRead];
System.arraycopy(inBuff, 0, tempBuff, 0, bytesRead);
outBuff = decoder.decode(tempBuff);
}
else
{
out.flush();
out.close();
in.close();
return;
}
out.write(outBuff);
}
}
特别感谢@Jon Skeet 和@Tagir Valeev。
我强烈怀疑问题是您忽略了 InputStream.read
中的 return 值,而不是检查流的结尾。所以这个:
while (in.read(inBuff) > 0) {
// This always decodes the *complete* buffer
outBuff = decoder.decode(inBuff);
out.write(outBuff);
}
应该是
int bytesRead;
while ((bytesRead = in.read(inBuff)) > 0) {
outBuff = decoder.decode(inBuff, 0, bytesRead);
out.write(outBuff);
}
不过,我预计这会比使用wrap
更快。
尝试使用decode.wrap(new BufferedInputStream(new FileInputStream(inputFileName)))
。有了缓冲,它应该至少和你手工制作的版本一样快。
至于为什么您的代码不起作用:那是因为最后一个块可能小于 1024 字节,但您尝试解码整个 byte[]
数组。有关详细信息,请参阅@JonSkeet 的回答。
嗯,我改了
"final int BUFF_SIZE = 1024;"
进入
"final int BUFF_SIZE = 1024 * 3;"
成功了!
所以,我想填充可能有问题...我的意思是,在对文件进行编码时,(因为 1024 % 3 = 1)必须有填充。这些可能会在解码时引发问题...
- 你应该记录下你读取的字节数,除此之外,
- 你应该确保你的缓冲区大小可以被3整除,因为在Base64中,每3个字节有四个输出(64是2^6,3*8等于4*6),这样做,你可以避免填充问题。(这样你的输出就不会有错误的“=”结尾)
我想用Base64.java来编码和解码文件。 Encode.wrap(InputStream)
和 decode.wrap(InputStream)
工作但 运行 慢。所以我使用了以下代码。
public static void decodeFile(String inputFileName,
String outputFileName)
throws FileNotFoundException, IOException {
Base64.Decoder decoder = Base64.getDecoder();
InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName);
byte[] inBuff = new byte[BUFF_SIZE]; //final int BUFF_SIZE = 1024;
byte[] outBuff = null;
while (in.read(inBuff) > 0) {
outBuff = decoder.decode(inBuff);
out.write(outBuff);
}
out.flush();
out.close();
in.close();
}
但是,它总是抛出
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Input byte array has wrong 4-byte ending unit
at java.util.Base64$Decoder.decode0(Base64.java:704)
at java.util.Base64$Decoder.decode(Base64.java:526)
at Base64Coder.JavaBase64FileCoder.decodeFile(JavaBase64FileCoder.java:69)
...
我把final int BUFF_SIZE = 1024;
改成final int BUFF_SIZE = 3*1024;
后,代码就可以用了。由于 "BUFF_SIZE" 也用于对文件进行编码,我认为编码的文件有问题(1024 % 3 = 1,这意味着在文件中间添加了填充)。
此外,正如@Jon Skeet 和@Tagir Valeev 提到的,我不应该忽略 InputStream.read()
中的 return 值。所以,我修改了如下代码。
(但是,我不得不提到代码 运行 比使用 wrap()
快得多。我注意到速度差异是因为我已经编码并大量使用 Base64.encodeFile() /decodeFile() 在 jdk8 发布之前很久。现在,我的 buffed jdk8 代码 运行s 和我的原始代码一样快。所以,我不知道 wrap()
发生了什么......)
public static void decodeFile(String inputFileName,
String outputFileName)
throws FileNotFoundException, IOException
{
Base64.Decoder decoder = Base64.getDecoder();
InputStream in = new FileInputStream(inputFileName);
OutputStream out = new FileOutputStream(outputFileName);
byte[] inBuff = new byte[BUFF_SIZE];
byte[] outBuff = null;
int bytesRead = 0;
while (true)
{
bytesRead = in.read(inBuff);
if (bytesRead == BUFF_SIZE)
{
outBuff = decoder.decode(inBuff);
}
else if (bytesRead > 0)
{
byte[] tempBuff = new byte[bytesRead];
System.arraycopy(inBuff, 0, tempBuff, 0, bytesRead);
outBuff = decoder.decode(tempBuff);
}
else
{
out.flush();
out.close();
in.close();
return;
}
out.write(outBuff);
}
}
特别感谢@Jon Skeet 和@Tagir Valeev。
我强烈怀疑问题是您忽略了 InputStream.read
中的 return 值,而不是检查流的结尾。所以这个:
while (in.read(inBuff) > 0) {
// This always decodes the *complete* buffer
outBuff = decoder.decode(inBuff);
out.write(outBuff);
}
应该是
int bytesRead;
while ((bytesRead = in.read(inBuff)) > 0) {
outBuff = decoder.decode(inBuff, 0, bytesRead);
out.write(outBuff);
}
不过,我预计这会比使用wrap
更快。
尝试使用decode.wrap(new BufferedInputStream(new FileInputStream(inputFileName)))
。有了缓冲,它应该至少和你手工制作的版本一样快。
至于为什么您的代码不起作用:那是因为最后一个块可能小于 1024 字节,但您尝试解码整个 byte[]
数组。有关详细信息,请参阅@JonSkeet 的回答。
嗯,我改了
"final int BUFF_SIZE = 1024;"
进入
"final int BUFF_SIZE = 1024 * 3;"
成功了!
所以,我想填充可能有问题...我的意思是,在对文件进行编码时,(因为 1024 % 3 = 1)必须有填充。这些可能会在解码时引发问题...
- 你应该记录下你读取的字节数,除此之外,
- 你应该确保你的缓冲区大小可以被3整除,因为在Base64中,每3个字节有四个输出(64是2^6,3*8等于4*6),这样做,你可以避免填充问题。(这样你的输出就不会有错误的“=”结尾)