使用Java8 Base64解码器的IllegalArgumentException

Leo*_*o.W 5 java base64 illegalargumentexception java-8

我想使用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();
}
Run Code Online (Sandbox Code Playgroud)

然而,它总是抛出

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)
    ...
Run Code Online (Sandbox Code Playgroud)

之后我换final int BUFF_SIZE = 1024;final int BUFF_SIZE = 3*1024;的代码工作.由于"BUFF_SIZE"也用于编码文件,我认为编码的文件有问题(1024%3 = 1,这意味着在文件中间添加了填充).

另外,正如@Jon Skeet和@Tagir Valeev所提到的,我不应该忽略来自的返回值InputStream.read().所以,我修改了如下代码.

(但是,我必须提到代码运行速度比使用速度快得多wrap().我注意到速度差异,因为我在jdk8发布之前很久就编码并集中使用了Base64.encodeFile()/ decodeFile().现在,我的buffed jdk8代码运行速度和原始代码一样快.所以,我不知道发生了什么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);
    }
}
Run Code Online (Sandbox Code Playgroud)

特别感谢@Jon Skeet和@Tagir Valeev.

Jon*_*eet 5

我强烈怀疑问题是你忽略了返回值InputStream.read,而不是检查流的结尾.所以这:

while (in.read(inBuff) > 0) {
    // This always decodes the *complete* buffer
    outBuff = decoder.decode(inBuff);
    out.write(outBuff);
}
Run Code Online (Sandbox Code Playgroud)

应该

int bytesRead;
while ((bytesRead = in.read(inBuff)) > 0) {
    outBuff = decoder.decode(inBuff, 0, bytesRead);
    out.write(outBuff);
}
Run Code Online (Sandbox Code Playgroud)

我不希望这比使用wrap它更快.