1

我正在构建一个小型应用程序,将文本文件中的文本转换为 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();
    }



}

加密()之前的文本文件之前:

起司

番茄

土豆

火腿

山药

加密后的文本文件() //5jAGgAZQBlAHMAZQANAAoAdABvAG0AYQB0AG8AZQBzAA0ACgBwAG8AdABhAHQAbwBlAHMADQAKAGgAYQBtAHMADQAKAAHkAYQBtAHMA

解密后的文本文件

뿯붿奶酪

番茄

土豆

火腿

山药

在 encrypt() 之前:

解密()之后:

4

2 回答 2

1

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

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

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

于 2018-04-13T13:14:03.583 回答
1

您的加密和解密功能不会做出相同的假设。encrypt Base64 对任何文件进行编码,除了变量名和注释表明该文件是文本文件外,一切都很好。不必如此。

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 可能在几百年前就被认为是加密(和破解),但它并非用于此目的。这样称呼它有点危险(而且令人困惑)。

于 2018-04-14T18:02:19.720 回答