Base64. Декодер, возвращающий иностранные символы
Я строю небольшое приложение, чтобы превратить текст в текстовом файле в 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 () // 5jAGgAZQBlAHMAZQANAAoAdABvAG0AYQB0AG8AZQBzAA0ACgBwAG8AdABhAHQAbwBlAHMADQAKAGgAYQBtAHMADQAKAHkAYQBtAHMA
Текстовый файл после расшифровки
뿯붿 сыр
помидоры
картофель
окороков
ямс
2 ответа
Ваши функции шифрования и дешифрования не делают одинаковых предположений. Шифрование Base64-кодирует любой файл, и это нормально, за исключением имен переменных и комментариев, которые предполагают, что файл является текстовым файлом. Это не должно быть.
decrypt преобразует данные в кодировке Base64 обратно в байты, но затем "перерабатывает", предполагая, что байты были кодированием текста с помощью UTF-8, затем декодирует и перекодирует их перед записью в файл. Если бы предположение было верным, это было бы просто NOP; Это явно не так в вашем случае, и это искажает данные.
Возможно, вы сделали это, потому что пытались использовать PrintWriter. В Java (и.NET) многопоточные и файловые классы ввода / вывода часто сбивают с толку - особенно учитывая их десятилетнюю эволюцию. Иногда есть тот, который делает именно то, что вам нужно, но это может быть трудно найти; в других случаях нет. И иногда широко используемая библиотека, такая как Apache Commons, заполняет пробел.
Итак, просто запишите байты в файл. Есть много современных и исторических вариантов, как объяснено в ответах на этот прямой вопрос byte[] для файла в Java. Вот один с Files.write:
Files.write(appFile.toPath(), decodedByteArray, StandardOpenOption.CREATE);
Примечание. Хотя Base64, возможно, считался бы шифрованием (и взломанным) пару сотен лет назад, он не предназначен для этой цели. Это немного опасно (и запутанно) называть это так.
Ваш входной файл - UTF-16, а не UTF-8. Начинается с FF FE
знак порядка байтов с прямым порядком байтов. StandardCharsets.UTF_16
справится с этим правильно. (Или вместо этого установите ваш текстовый редактор на UTF-8 вместо UTF-16.)
Когда вы расшифровали fffe
как UTF-8, у вас есть два символа замены "��"
по одному на каждый из двух байтов, недопустимых в UTF-8. Затем, когда вы распечатали это, каждый символ замены '�'
был закодирован как ef bf bd
в UTF-8. Затем вы интерпретировали результат как UTF-16, взяв их в группы по два, прочитав его как efbf bdef bfbd
, Остальная часть файла была UTF-16 все время, но нулевые байты будут безопасно в обоих направлениях.
(Если бы файл представлял собой текст ASCII, закодированный как UTF-16 без метки порядка байтов, вы бы не заметили, насколько это было нарушено!)