Java实现Vigenere密码解密失败,请求排查代码问题
问题分析与修复代码
核心问题
你的解密逻辑完全没有执行字符转换操作——当mode为D时,代码仅修改了shift值,但没有对字符c进行解密计算,也没有更新keywordIndex。这就导致解密时字符根本没被处理,输出自然和输入一致,看起来像“再次加密”。
另外还有两个次要问题:
- 加密时先计算再转大写,若输入是小写字母,
c - 'A'会得到负数,导致计算结果错误 - 解密时直接用
26 - shift,但字符计算时未考虑模运算的负数情况
修复后的代码
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Do you want to encrypt or decrypt? (E/D): "); String mode = scanner.nextLine().toUpperCase(); System.out.print("Input file name: "); String inputFileName = scanner.nextLine(); System.out.print("Output file name: "); String outputFileName = scanner.nextLine(); System.out.print("Keyword (all capitals): "); String keyword = scanner.nextLine().toUpperCase(); scanner.close(); try { BufferedReader reader = new BufferedReader(new FileReader(inputFileName)); BufferedWriter writer = new BufferedWriter(new FileWriter(outputFileName)); int keywordIndex = 0; String line = reader.readLine(); while (line != null) { for (int i = 0; i < line.length(); i++) { char c = line.charAt(i); if (Character.isLetter(c)) { // 先统一转大写,避免小写字母计算错误 c = Character.toUpperCase(c); int shift = keyword.charAt(keywordIndex) - 'A'; if (mode.equals("D")) { // 解密时用减法,加26再模26避免负数错误 c = (char) (((c - 'A' - shift) % 26 + 26) % 26 + 'A'); } else { // 加密时的计算,模26确保在字母范围内 c = (char) (((c - 'A' + shift) % 26) + 'A'); } // 无论加密解密,都要更新关键词索引 keywordIndex = (keywordIndex + 1) % keyword.length(); } writer.write(c); } writer.newLine(); line = reader.readLine(); } reader.close(); writer.close(); System.out.println("Done."); } catch (IOException e) { e.printStackTrace(); } } }
修复说明
- 统一字符大小写:先把字母转成大写再计算,避免小写字母参与运算时出现负数偏移
- 解密逻辑补全:解密分支中添加了字符转换代码,并且无论加密还是解密,都会更新
keywordIndex,确保关键词循环使用正确 - 处理模运算负数:解密时用
((c - 'A' - shift) % 26 + 26) % 26,确保即使计算结果为负数,也能转换为0-25之间的正数,正确映射回字母
内容的提问来源于stack exchange,提问作者Terrance Smith
相关产品推荐
相关产品推荐

