我的程序出现故障,导致问号(\ 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);
}
}
答案 0 :(得分:3)
代码是正确的,但几乎从不起作用 - 根据经验,避免FileReader
和FileWriter
并使用InputStreamReader
和OutputStreamWriter
建立自己的读者/作者允许您指定要使用的编码(以及在编写8位数据时如何保护16位Unicode字符)。
我使用辅助类是因为我一直需要它:
private static final String FILE = "file";
private static final String CHARSET = "charset";
public static BufferedReader createReader( File file, Encoding charset ) throws IOException {
JavaUtils.notNull( FILE, file );
JavaUtils.notNull( CHARSET, charset );
FileInputStream stream = null;
try {
stream = new FileInputStream( file );
return createReader( stream, charset );
} catch( IOException e ) {
IOUtils.closeQuietly( stream );
throw e;
} catch( RuntimeException e ) {
IOUtils.closeQuietly( stream );
throw e;
}
}
public static BufferedReader createReader( InputStream stream, Encoding charset ) throws IOException {
JavaUtils.notNull( "stream", stream );
JavaUtils.notNull( "charset", charset );
try {
return new BufferedReader( new InputStreamReader( stream, charset.encoding() ) );
} catch( UnsupportedEncodingException e ) {
IOUtils.closeQuietly( stream );
throw new UnknownEncodingException( charset, e );
} catch( RuntimeException e ) {
IOUtils.closeQuietly( stream );
throw e;
}
}
public static BufferedWriter createWriter( File file, Encoding charset ) throws IOException {
JavaUtils.notNull( FILE, file );
JavaUtils.notNull( CHARSET, charset );
FileOutputStream stream = null;
try {
stream = new FileOutputStream( file );
return new BufferedWriter( new OutputStreamWriter( stream, charset.encoding() ) );
} catch( UnsupportedEncodingException e ) {
IOUtils.closeQuietly( stream );
throw new UnknownEncodingException( charset, e );
} catch( IOException e ) {
IOUtils.closeQuietly( stream );
throw e;
} catch( RuntimeException e ) {
IOUtils.closeQuietly( stream );
throw e;
}
}
类型Encoding
是我使用一个或多个enum
s实现的接口:
public interface Encoding {
String encoding();
Charset charset();
}