【问题标题】:Base64.Decoder returning foreign charactersBase64.Decoder 返回外来字符
【发布时间】:2018-09-23 04:52:59
【问题描述】:

我正在构建一个小型应用程序,将文本文件中的文本转换为 Base64,然后恢复正常。解码后的文本总是在第一行的开头返回一些汉字。

public EncryptionEngine(File appFile){
    this.appFile= appFile;
}


public void encrypt(){

    try {
        byte[] fileText = Files.readAllBytes(appFile.toPath());// get file text as bytes

        Base64.Encoder encoder = Base64.getEncoder();
        PrintWriter writer = new PrintWriter(appFile);

        writer.print("");//erase old, readable text
        writer.print(encoder.encodeToString(fileText));// insert encoded text
        writer.close();


    } catch (IOException e) {

        e.printStackTrace();
    }

}

public void deycrpt(){

    try {
        byte[] fileText = Files.readAllBytes(appFile.toPath());

        String s = new String (fileText, StandardCharsets.UTF_8);//String s = new String (fileText);


        Base64.Decoder decoder = Base64.getDecoder();
        byte[] decodedByteArray = decoder.decode(s);

        PrintWriter writer = new PrintWriter(appFile);
        writer.print("");
        writer.print(new String (decodedByteArray,StandardCharsets.UTF_8)); //writer.print(new String (decodedByteArray));
        writer.close();


    } catch (IOException e) {

        e.printStackTrace();
    }



}

encrypt() 之前的文本 FileBefore:

奶酪

西红柿

土豆

火腿

山药

加密后的文本文件 //5jAGgAZQBlAHMAZQANAAoAdABvAG0AYQB0AG8AZQBzAA0ACgBwAG8AdABhAHQAbwBlAHMADQAKAGgAYQBtAHMADQAKAHkAYQBtAHMA

解密后的文本文件

뿯붿奶酪

西红柿

土豆

火腿

山药

Before encrypt() :

After decrypt() :

【问题讨论】:

  • 能否在问题中包含 base64 内容?
  • 将输出作为文本包含在您的问题中,而不是作为图像。
  • (import java.util.Base64;)
  • 我强烈怀疑使用了不一致的编码。您还没有为PrintWriters 中的任何一个指定编码。
  • 我怀疑输入文本文件以byte order mark (0xEF 0xBB 0xBF) 开头。在 Windows 上,您无法通过记事本看到 byte order mark

标签: java utf-8 decoder encoder-decoder


【解决方案1】:

您的输入文件是 UTF-16,而不是 UTF-8。它以 FF FE 开头,即 little-endian 字节顺序标记。 StandardCharsets.UTF_16 将正确处理此问题。 (或者,将您的文本编辑器设置为 UTF-8 而不是 UTF-16。)

当您将 fffe 解码为 UTF-8 时,您会得到两个替换字符 "��",一个用于在 UTF-8 中无效的两个字节中的每一个。然后,当您将其打印出来时,每个替换字符 '�' 在 UTF-8 中被编码为 ef bf bd。然后您将结果解释为 UTF-16,将它们分成两组,读取为efbf bdef bfbd。文件的其余部分一直是 UTF-16,但空字节将安全地往返。

(如果文件是编码为 UTF-16 且没有字节顺序标记的 ascii 文本,您将不会注意到这是多么糟糕!)

【讨论】:

    【解决方案2】:

    您的加密和解密函数没有做出相同的假设。 encrypt Base64 对任何文件进行编码,除了变量名和 cmets 表明该文件是文本文件外,一切正常。不必如此。

    decrypt 将 Base64 编码的数据反转回字节,但随后通过假设字节是使用 UTF-8 的文本编码并随后解码并在将它们写入文件之前重新编码它们来“过度处理”。如果假设是正确的,那将只是一个 NOP;在您的情况下,这显然不是真的,它会破坏数据。

    也许您这样做是因为您尝试使用 PrintWriter。在 Java(和 .NET)中,多流和文件 I/O 类经常令人困惑——特别是考虑到它们长达数十年的演变。有时有一个可以完全满足您的需要,但可能很难找到;其他时候,没有。而且,有时,像 Apache Commons 这样的常用库可以填补这一空白。

    所以,只需将字节写入文件。正如这个直接问题byte[] to file in Java 的答案中所解释的那样,有许多现代和历史选择。这是Files.write

    Files.write(appFile.toPath(), decodedByteArray, StandardOpenOption.CREATE);
    

    注意:虽然 Base64 可能在几百年前就被认为是加密(和破解),但它并非用于此目的。这么称呼它有点危险(而且令人困惑)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-27
      • 2023-03-21
      • 1970-01-01
      相关资源
      最近更新 更多