Java字符串打破文件操作 [英] Java Strings breaking file operations

查看:124
本文介绍了Java字符串打破文件操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的程序中有一个毛刺,当我加密它时会导致一个问号(\\\?)出现在第六个(索引= 5)字符串中。通常,这在解密时是相反的。但是,如果我首先将字符串保存到文件,则不会反转。我已经确定,当我将一个包含Unicode字符的字符串保存到文件中时,我将无法确定文件的正确长度。我已经设法在以下功能中重现故障。

  public static void testFileIO(String [] args)
{
System.out.println(TESTING FILE IO FUNCTIONS ...);
try
{
String filename =test.txt;
String testString =UB\\\䞁ERBLAH\\\Ϳ\\\蝆;
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(文件长度测量失败);
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类...

 抽象公共类Crypto 
{
/ **
*使用按位xor cipher加密明文
* @param plainText明文加密
* @param密码按位xor密码
* @return的密钥由给定的明文和密码
* /
生成的密文public static String encrypt(String plainText,String key)
{
char [] data = plainText.toCharArray();
随机rand = new Random();
rand.setSeed(key.hashCode());

char [] pass = new char [data.length]; (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。长度];
}
return new String(data);
}

/ **
*使用与加密相同的密钥解密加密的邮件
* @param cipherText要解密的cipherText消息
* @param password随机生成器的种子获取右键
* @return对应于'cipherText'的明文消息
* /
public static String decrypt(String cipherText,String key )
{
char [] data = cipherText.toCharArray();
随机rand = new Random();
rand.setSeed(key.hashCode());

char [] pass = new char [data.length]; // = key.getBytes(ASCII); (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。长度];
}
return new String(data);
}
}


解决方案

代码是正确的,但几乎从来没有工作 - 根据经验,避免 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(文件文件,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 是使用一个或多个枚举实现的界面 s:

 code> public interface Encoding {
String encoding();
Charset charset();
}


I have a glitch in my program that causes a question mark (\u003f) to appear in the sixth (index = 5) slot in strings when I encrypt them. Normally, this is reversed upon decryption. However, it is not reversed if I save the string to a file first. I have determined that when I save a string containing Unicode characters to a file, I will not be able to determine the correct length for the file. I have managed to reproduce the glitch in the following function...

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

As an additional note, a failure in file length measurement is also caught.

Here is the Crypto class that I use to encrypt and decrypt Strings...

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

解决方案

The code is correct but almost never works - As a rule of thumb, avoid FileReader and FileWriter and build your own readers/writers using InputStreamReader and OutputStreamWriter which allow you to specify the encoding to use (and hence how to protect 16bit Unicode characters when you write 8bit data).

I use a helper class for this because I need it all the time:

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

The type Encoding is an interface which I implement using one or more enums:

public interface Encoding {
    String encoding();
    Charset charset();
}

这篇关于Java字符串打破文件操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆