赞
踩
首先看下面一个例子:
File file1=new File("F:/Wangchuang/eclipse/eclipse.exe-0");
byte[] bytes2=new byte[(int) file1.length()];
FileInputStream fis=new FileInputStream(file1);
fis.read(bytes2);
fis.close();
System.out.println(bytes2.length);
String s2=new String(bytes2);
System.out.println(s2.length());
执行结果:
102400
78479
public static void ceshi(String filepath) {
File file=new File(filepath);
try(FileInputStream fis=new FileInputStream(file)){
byte[] b=new byte[(int)file.length()];
fis.read(b);
System.out.println("文件编码方式为UTF-8,内容为中国,占用三个字节");
System.out.println("采用系统默认的译码方式:"+new String(b));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
执行结果
文件编码方式为UTF-8,内容为中国,占用三个字节
采用系统默认的译码方式:涓浗
可以看出这字节数组和字符串的长度不一致。不一致的原因是一个字符占用一个或者多个字节。new String()函数会将字节本身所携带的编码方式抛弃,然后改用系统默认的编码方式对字节信息进行译码。这可能导致文件是”中国“,而经过new String()之后就不是“中国”了。
下面为测试代码:
先把这个问题放一放,看下面一个代码,执行出来,数据没有发生损失。
File file1=new File("F:/Wangchuang/eclipse/eclipse.exe-0");
byte[] bytes2=new byte[(int) file1.length()];
FileInputStream fis=new FileInputStream(file1);
fis.read(bytes2);
fis.close();
char[] char1=new char[bytes2.length];
//用循环会很麻烦,对于大数据的话,计算时间很久
for(int i=0;i<bytes2.length;i++) {
char1[i]=(char)bytes2[i];
}
System.out.println(char1.length);
String s3=new String(char1);
System.out.println(s3.length());
执行结果:
102400
102400
虽然对于char[]数组不会发生数据损失,但是当这个字符串直接转换为字节数组的时候,会发生文件损坏,解决办法是,字符串先转换为char数组然后在转换为byte[]。
从上面两个代码块就知道,String函数对于char和byte的处理是不一样的,至于哪里不一样,现在研究一下。
Java中String内置的public String(byte[] bytes)和public byte[] getBytes()对于不合法的utf-8字节流在解析时会增删字节。
查了几个文章,有助于对这个问题的理解:
对于这个问答里面有一个解答是说,字符编码遇到了终止符,经过测试不可靠。主要原因是因为有字节的增删。
参考
程序中用到了MD5加密和IDEA加密,通过这些算法得出的结果均是字节码,但是我程序中使用一个通讯接口,其接受的参数类型为String。所以在发送时,需要转换为String。
对于java来说,byte只能表示有符号的数据即范围为-128~127,所以对于编码后,如果原本字节流中的信息有大于127的话,将其转换成String类型,发送的时候再转换为byte[]时,会出现与原始字节码不一致的现象。
因为在java中如果找不到合适的字符的话,默认会用’?‘代替,如对于0xC9,很显然无法表示成字符,所以在进行byte[]->String->byte[]的时候,就会变成0x3F(’?’)。
此时可以通过字符编码的方式来解决:在进行byte[]->String的转换时,利用"new String(byteArray, “ISO-8859-1”);"得到String。在进行String->byte[]的时候,再通过pkt.getBytes(“ISO-8859-1”)得到原始byte[],这样数据就不会出现错误。
经过测试,这个方法可以解决数据丢失的问题,文件的合并不会发生损坏
可以参考这篇文章里的:练习合并文件
什么是字节?
位是计算机内部的最小数据储存单位,8位就组成了1字节,也就是java中的byte。
什么是字符?
字符是指字母、数字、特殊符号的集合,也就是java中的char和String。
字节怎么就变成了字符?
答案是字符编码。比较出名的字符集是ascii、gb2312、utf-8等。其中ascii和gb2312是定长字符编码,一个字符分别占用1字节、2字节,而utf-8是变长字符编码,最短为1字节,最常为4字节。
以ascii为例,字母A在计算机中的存储为0b0100 0001。
Java中String内置的public String(byte[] bytes)和public byte[] getBytes()对于不合法的utf-8字节流在解析时会增删字节。
立贴再此!以后查看!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。