Строки Java, нарушающие файловые операции - PullRequest
1 голос
/ 05 марта 2012

В моей программе есть сбой, который вызывает вопросительный знак (\ u003f) в шестом (индекс = 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;
    }
}

В качестве дополнительного примечания также обнаруживается сбой при измерении длины файла.Я использую для шифрования и дешифрования строк ...

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);
    }
}

1 Ответ

3 голосов
/ 05 марта 2012

Код правильный, но почти никогда не работает - как правило, избегайте FileReader и FileWriter и создавайте свои собственные устройства чтения / записи, используя InputStreamReader и OutputStreamWriter, которые позволяют указать кодировку для использования(и, следовательно, как защитить 16-битные символы Unicode при записи 8-битных данных).

Я использую вспомогательный класс для этого, потому что он мне нужен постоянно:

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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...