如何修复写入文本文件的Java加解密代码问题
问题修复方案
我帮你找到了几个关键问题,现在来一一解决:
问题根源分析
- 解密流提前关闭且被错误写入内容:你在
main方法里调用decrypt之前,先给CryptoDeciphered.txt写入了密钥内容,还直接关闭了输出流!这导致后续解密操作根本无法往文件里写入内容,而且提前写入的密钥会彻底破坏解密文件的完整性。 - 文件比较时机错误:
doCopy方法里的不可修改代码会在每次流复制完成后(包括加密阶段)就调用compareFiles,但加密阶段还没生成解密文件,自然会提示文件找不到,程序直接失效。
修复后的完整代码
我严格保留了所有老师规定不可修改的代码段,只修改了其他逻辑部分:
package Crypto; import java.util.Scanner; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.FileWriter; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; public class Crypto { public static void main(String[] args) throws IOException { try { String key = "B1LLYB0B"; // 加密流程 FileInputStream plainIn = new FileInputStream("CryptoPlaintext.txt"); FileOutputStream cipherOut = new FileOutputStream("CryptoCiphertext.txt"); encrypt(key, plainIn, cipherOut); // 解密流程:修复流处理错误,不再提前关闭或写入密钥 FileInputStream cipherIn = new FileInputStream("CryptoCiphertext.txt"); FileOutputStream decipherOut = new FileOutputStream("CryptoDeciphered.txt"); decrypt(key, cipherIn, decipherOut); } catch (Throwable e) { e.printStackTrace(); } } public static void encrypt(String key, InputStream is, OutputStream os) throws Throwable { DESKeySpec dks = new DESKeySpec(key.getBytes()); SecretKeyFactory skf = SecretKeyFactory.getInstance("DES"); SecretKey desKey = skf.generateSecret(dks); Cipher cipher = Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, desKey); CipherInputStream cis = new CipherInputStream(is, cipher); // 加密阶段自己处理流复制,不调用带不可修改代码的doCopy,避免提前触发文件比较 byte[] bytes = new byte[64]; int numBytes; while ((numBytes = cis.read(bytes)) != -1) { os.write(bytes, 0, numBytes); } os.flush(); os.close(); cis.close(); } public static void decrypt(String key, InputStream is, OutputStream os) throws Throwable { encryptOrDecrypt(key, Cipher.DECRYPT_MODE, is, os); } public static void encryptOrDecrypt(String key, int mode, InputStream is, OutputStream os) throws Throwable { DESKeySpec dks = new DESKeySpec(key.getBytes()); SecretKeyFactory skf = SecretKeyFactory.getInstance("DES"); SecretKey desKey = skf.generateSecret(dks); Cipher cipher = Cipher.getInstance("DES"); if (mode == Cipher.ENCRYPT_MODE) { cipher.init(Cipher.ENCRYPT_MODE, desKey); CipherInputStream cis = new CipherInputStream(is, cipher); doCopy(cis, os); } else if (mode == Cipher.DECRYPT_MODE) { cipher.init(Cipher.DECRYPT_MODE, desKey); CipherOutputStream cos = new CipherOutputStream(os, cipher); doCopy(is, cos); } } public static void doCopy(InputStream is, OutputStream os) throws IOException { byte[] bytes = new byte[64]; int numBytes; while ((numBytes = is.read(bytes)) != -1) { os.write(bytes, 0, numBytes); } os.flush(); os.close(); is.close(); // =============================== DO NOT MODIFY ANY CODE BELOW HERE =============================== // Compare the files System.out.println(compareFiles() ? "The files are identical!" : "The files are NOT identical."); } /** * Compares the Plaintext file with the Deciphered file. * * @return true if files match, false if they do not */ public static boolean compareFiles() throws IOException { Scanner pt = new Scanner(new File("CryptoPlaintext.txt")); // Open the plaintext file Scanner dc = new Scanner(new File("CryptoDeciphered.txt")); // Open the deciphered file // Read through the files and compare them record by record. // If any of the records do not match, the files are not identical. while(pt.hasNextLine() && dc.hasNextLine()) if(!pt.nextLine().equals(dc.nextLine())) return false; // If we have any records left over, then the files are not identical. if(pt.hasNextLine() || dc.hasNextLine()) return false; // The files are identical. return true; } }
修改说明
- 修复main方法的解密流处理:删除了提前写入密钥和关闭输出流的错误代码,确保解密时流处于可用状态,能正确写入解密后的内容。
- 调整加密阶段的流复制逻辑:把加密阶段的流复制逻辑单独写在
encrypt方法里,不再调用doCopy,这样就避免了加密阶段触发不可修改的文件比较代码,只有解密完成后才会执行那段代码,此时CryptoDeciphered.txt已经正确生成,不会再出现文件找不到的问题。
这样修改后,程序就能正常完成加密、解密,并且在最后正确比较原文件和解密后的文件了。
内容的提问来源于stack exchange,提问作者HecticBadger
相关产品推荐
相关产品推荐

