You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复写入文本文件的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;
    }
}

修改说明

  1. 修复main方法的解密流处理:删除了提前写入密钥和关闭输出流的错误代码,确保解密时流处于可用状态,能正确写入解密后的内容。
  2. 调整加密阶段的流复制逻辑:把加密阶段的流复制逻辑单独写在encrypt方法里,不再调用doCopy,这样就避免了加密阶段触发不可修改的文件比较代码,只有解密完成后才会执行那段代码,此时CryptoDeciphered.txt已经正确生成,不会再出现文件找不到的问题。

这样修改后,程序就能正常完成加密、解密,并且在最后正确比较原文件和解密后的文件了。

内容的提问来源于stack exchange,提问作者HecticBadger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:53:48