【发布时间】:2012-03-23 02:07:25
【问题描述】:
我的程序中有一个小故障,当我对字符串进行加密时,它会导致一个问号 (\u003f) 出现在字符串的第六个 (index = 5) 插槽中。通常,这在解密时被反转。但是,如果我先将字符串保存到文件中,则不会反转。我已经确定,当我将包含 Unicode 字符的字符串保存到文件时,我将无法确定文件的正确长度。我设法重现了以下功能中的故障...
public static void testFileIO(String[] args)
{
System.out.println("TESTING FILE IO FUNCTIONS...");
try
{
String filename = "test.txt";
String testString = "UB\u4781ERBLAH\u037f\u8746";
System.out.println("Output: " + testString);
FileWriter fw = new FileWriter(filename);
fw.write(testString);
fw.close();
FileReader fr = new FileReader(filename);
int length;
for(length = 0; fr.read() != -1; length++);
if(length != testString.length())
System.out.println("Failure on file length measurement.");
fr.close();
fr = new FileReader(filename);
char[] buffer = new char[length];
fr.read(buffer);
String result = new String(buffer);
fr.close();
System.out.println("Input: " + result);
if(result.equals(testString)) System.out.println("SUCCESS!");
else System.out.println("FAILURE.");
}
catch (Throwable e)
{
e.printStackTrace();
System.out.println("FAILURE.");
return;
}
}
作为附加说明,文件长度测量失败也被捕获。
这是我用来加密和解密字符串的 Crypto 类...
abstract public class Crypto
{
/**
* Encrypt the plaintext with a bitwise xor cipher
* @param plainText The plaintext to encrypt
* @param password The key for the bitwise xor cipher
* @return Ciphertext yielded by given plaintext and password
*/
public static String encrypt(String plainText, String key)
{
char[] data = plainText.toCharArray();
Random rand = new Random();
rand.setSeed(key.hashCode());
char[] pass = new char[data.length];
for(int i = 0; i < pass.length; i++)
{
pass[i] = (char)rand.nextInt();
}
for(int i = 0; i < data.length; i++)
{
data[i] ^= pass[i % pass.length];
}
return new String(data);
}
/**
* Decrypt an encrypted message using the same key as for encryption
* @param cipherText The cipherText message to be deciphered
* @param password The seed for the random generator to get the right keys
* @return The plaintext message corresponding to 'cipherText'
*/
public static String decrypt(String cipherText, String key)
{
char[] data = cipherText.toCharArray();
Random rand = new Random();
rand.setSeed(key.hashCode());
char[] pass = new char[data.length];// = key.getBytes("ASCII");
for(int i = 0; i < pass.length; i++)
{
pass[i] = (char)rand.nextInt();
}
for(int i = 0; i < data.length; i++)
{
data[i] ^= pass[i % pass.length];
}
return new String(data);
}
}
【问题讨论】:
-
您的问题是您忽略了设置流编码。 Java 有一个明显的愚蠢错误,它默认为不可映射的字符提供
?。 -
您假设文件长度是字符串长度的 2,但这取决于用于将字符串保存到文件中的编码。
-
啊! @Luciano:这是我犯的一个愚蠢的错误。我将尝试将其减少为字符串长度 1。
-
@tchrist:非常感谢。我会调查一下并告诉你进展如何。
-
fr.read() 逐字节读取,而 unicode 字符超过一个字节宽。因此,在处理 unicode 时,应始终使用字符流方法而不是字节流方法。
标签: java string encryption encoding file-io