我已经在Java 8中实现了凯撒密码算法。
问题
Heute ist Freitag.
使用 22 作为 key 生成此编码文本:
^{
{6
6{
w}D
再次解码得到这个输出:
Heu
e is
Frei
ag.
代码和描述
应该注意的是,我的算法不关心像“\n”这样的字符,这意味着某些字符可能会被转换为转义序列或空格等。 这也完全是我想要发生的事情,但认为它不起作用。
public String encode(String txt, int key) {
if(key <= 0)
return txt;
String result = "";
for (int i = 0; i < txt.length(); i++) {
int x = (txt.charAt(i) + key) % 128;
result += (char) x;
}
System.out.println(result);
return result;
}
public String decipherM(String txt, int key) {
if(key <= 0)
return txt;
String result = "";
for (int i = 0; i < txt.length(); i++) {
int x = (txt.charAt(i) - key) % 128;
if(x < 0)
x += 128;
result += (char) x;
}
System.out.println(result);
return result;
}
问题
我真的很想知道为什么它不适用于转义序列或其他非字母字符。
最佳答案
控制字符具有定义的含义,文本处理工具可能会保留该含义,甚至删除那些没有有效含义的控制字符,而不是保留确切的字节表示形式。
请注意,当您超出 ASCII 范围时,普通字符甚至可能会发生这种情况,例如由于您使用的是德语示例文本,因此您必须注意两个 Unicode 代码点序列 \u00E4
和 \u0061\u0308
在语义上是等效的,两者都引用字符 ä
并且您不能依赖文本处理工具来保留这两种形式。
毕竟,像Base 64这样的编码是有原因的。已被发明用于通过文本处理工具无损传输字节序列。
对于像您这样简单的编码,最好只是禁止源字符串中的控制字符并仅在 ASCII 非控制字符范围内循环:
public String encodeRotation(String txt, int distance) {
int first = ' ', last = 128, range = last - first;
while(distance<0) distance+=range;
if(distance == 0) return txt;
char[] buffer = txt.toCharArray();
for (int i = 0; i < txt.length(); i++) {
char c = buffer[i];
if(c<first || c>=last)
throw new IllegalArgumentException("unsupported character "+c);
buffer[i] = (char) ((c - first + distance) % range + first);
}
return String.valueOf(buffer);
}
public String decodeRotation(String txt, int key) {
return encodeRotation(txt, -key);
}
System.out.println(encodeRotation("Heute ist Freitag.", 22));
^{+*{6)*6\({*w}D
System.out.println(decodeRotation("^{+*{6)*6\\({*w}D", 22));
Heute ist Freitag.
关于java - 凯撒密码在 Java 中被错误解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46234086/