我将某些字符存在文本文档(.txt),unicode格式,用的是.getBytes("UTF-8");结果输出的是EFBFBD,按照道理应该是EF BB BF 啊
所以我想问,怎么回事?
还有就是存为.txt,utf-8格式,读出来的不符合unicode编码,也就是码位跟unicode上规定的不一样
怎么回事?
所以我想问,怎么回事?
还有就是存为.txt,utf-8格式,读出来的不符合unicode编码,也就是码位跟unicode上规定的不一样
怎么回事?
windows 的unicode采用的是UTF-16(貌似还是little endian,也就是UTF-16 LE)。 假如你在windows下用文本工具save as unicode,那么是保存为UTF-16格式。BOM不是EF BB BF 而是FFFE(UTF-16LE),UTF-16BE是FEFF。再来看你的代码:你应该是类似于这样的方式读取的文件内容: public static void main(String[] args) {
String path = "test.txt";
BufferedReader reader = null;
try {
try {
reader = new BufferedReader(new FileReader(new File(path))); String line;
while (null != (line = reader.readLine())) {
byte[] bytes = line.getBytes("UTF-8");
for(byte b : bytes) {
System.out.println(Integer.toHexString(b & 0xFF));
}
}
}finally {
if(bis != null) {
bis.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}没有指定读取文件的字符集,默认用System.getProperty("file.encoding")这个字符集。这很有可能不是UTF-16,比如我设置的是UTF-8(你读出来是EFBFBD,那么你的有可能是GBK)。所以在你读取文件内容的时候就没有读出正确的内容。然后用.getBytes("UTF-8");就不可能得到正确的UTF-8的BOM。
程序要改: public static void main(String[] args) {
String path = "out.txt";
BufferedReader bis = null;
try {
try {
bis = new BufferedReader(new InputStreamReader(new FileInputStream(new File(path)), "UTF-16LE" ));// 在这里指定字符集,根据你的操作系统指定,如果是windows,应该就是"UTF-16LE" String line;
while (null != (line = bis.readLine())) {
// 这里你用UTF-8在返回的byte数组的开头就是UTF-8的BOM
byte[] bytes = line.getBytes("UTF-8");
for(byte b : bytes) {
System.out.println(Integer.toHexString(b & 0xFF));
}
}
}finally {
if(bis != null) {
bis.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
但是我觉得这没啥影响吧
我试着去理解你的意思,我用的是file读入,然后filereader读入
你后来改成了fileinputstream,是不是这个意思,字节流和字符流的区别??
我觉得没有区别吧。
另外问下(b & 0xFF)和ff与操作有什么用??,和全1做与操作,没啥用途啊
重点不是字节流和字符流的区别,用fileInputStream的时候我指定了编码方式:"UTF-16LE",这是重点。
关于 b & 0xFF:
b是一个byte,占8位。计算机中是用补码表示二进制的,比如FE,是111111110,这在byte中是个负数(-2),因为最高位符号位是1.
然后调用的是Integer.toHexString(int i) 这个方法,注意,参数是int类型。
现在b是byte,要转成int类型,那么就要做类型提升。我想这个大家都比较清楚,计算机组成原理,计算机导论等..学校讲的很多了,就是高位补符号位。
将8为二进制数1111 1110转成32位的int类型,就是高位用补符号位补足32位,结果是 1111 1111 1111 1111 1111 1111 1111 1110
算算这个负数的原码:负数的原码 = 补码-1 然后取反码。
1111 1111 1111 1111 1111 1111 1111 1110
-) 0000 0000 0000 0000 0000 0000 0000 0001
---------------------------------------------
1111 1111 1111 1111 1111 1111 1111 1101
反) 1000 0000 0000 0000 0000 0000 0000 0010 (-2)现在看看这个32位数的16进制表示,
1111 1111 1111 1111 1111 1111 1111 1110
F F F F F F F E
看到了吧,本来是FE,现在变成了FFFFFFFE
所以用Integer.toHexString()求一个byte的16进制表示先把这个整形的高24位清零。
注意:直接写0xFF,这在java中是一个int类型的数,也就是说他是一个正整数。
看看 b & 0xFF 是什么结果(由于0xFF是int,所以会先把b提升类型,然后再做计算)
1111 1111 1111 1111 1111 1111 1111 1110(byte类型的0xFE提升到int类型的表示)
&) 0000 0000 0000 0000 0000 0000 1111 1111 (int 类型的0xFF)
-------------------------------------------
0000 0000 0000 0000 0000 0000 1111 1110
结果会把高位的0丢掉,没意义。所以最后结果是FE。
明白为什么要 b & 0xFF 了吧。最后:关键是我开始那段文字,代码只是做个演示,你还是不明白的话,可以把你的代码贴上来,一起看看。
我现在遇到的问题是基于GB2312编码的需要保存为默认的ANSI的文本文档才能读出
基于Unicode的必须保存为Unicode的文本文档才能读出
能不能有一种统一的方法,对任何编码类型保存为统一的类型的文本文档都能读出
如果不能做到文本文档是统一类型的
那么能否在读入的时候都能传String是都是一致类型的
我现在遇到的问题是基于GB2312编码的需要保存为默认的ANSI的文本文档才能读出
基于Unicode的必须保存为Unicode的文本文档才能读出
能不能有一种统一的方法,对任何编码类型保存为统一的类型的文本文档都能读出
如果不能做到文本文档是统一类型的
那么能否在读入的时候都能传String是都是一致类型的