各位,InputStream is = new FileInputStream("D:\\Work_beiruan\\source\\1.txt"); int c;
while ((c = is.read()) != -1) {
System.out.print((char) c);
}
System.out.println();这段代码,在1.txt中有英文也有中文,可是读中文时打印出来是乱码,读英文就正常。请问:
字节流读写英文和汉字时有什么区别?为什么读英文没事?读中文就乱码?有人说是因为一个汉字占两个字节,可是一个英文字母不也是一个char吗?也是占两个字节啊。请高手帮忙解释一下,不胜感激。
while ((c = is.read()) != -1) {
System.out.print((char) c);
}
System.out.println();这段代码,在1.txt中有英文也有中文,可是读中文时打印出来是乱码,读英文就正常。请问:
字节流读写英文和汉字时有什么区别?为什么读英文没事?读中文就乱码?有人说是因为一个汉字占两个字节,可是一个英文字母不也是一个char吗?也是占两个字节啊。请高手帮忙解释一下,不胜感激。
在读中文的时候,1个字分2次来读,所以会变成乱码
public static void main(String[] args)throws Exception {
InputStream is = new FileInputStream("1.txt");
Reader reader = new InputStreamReader(is);
int c;
while ((c = reader.read()) != -1) {
System.out.print((char) c);
}
System.out.println();
}
如果需要读取中文的话建议还是用字符流,用InputStreamReader 转换成Reader就行了- -
Reader reader = new InputStreamReader(new FileInputStream(path));
reader.read();
utf-8是不等长的,用utf-8表示"中"占用2个字节,"a"则是1个字节。
InputStream is = new FileInputStream("1.txt");
Reader reader = new InputStreamReader(is, "UTF-8");//GB2312
int c;
while ((c = reader.read()) != -1) {
System.out.print((char) c);
}
System.out.println();
}
InputStream is = new FileInputStream("1.txt");
Reader reader = new InputStreamReader(is, "UTF-8");//GB2312
int c;
while ((c = reader.read()) != -1) {
System.out.print((char) c);
}
System.out.println();
InputStream is = new FileInputStream("D:\\1.txt");
int c;
while ((c = is.read()) != -1) {
System.out.print((char) c);
System.out.println("---");
}
System.out.println();输出为:
t---
e---
s---
t---
?---
?---
?---
°---
从输出可以看出,一次确实只读了一个字节
这么说吧,字节流使一次读取一个字节的,而英文的unicode是只用了一个字节,所以读取没有问题,而中文是占用了两个字节,所以当你读取一个字节的时候会造成截断。
然后java把一个byte的数据转换成int,高位用0补上,然后再截断,变成2个字节,高位那个字节还是0,至于你说的为什么没有问题,是因为你不是把它转换城 char 型输出吗,这样的话就一次读取了2个字节啦,这两个字节作为一个整体输出,既然是整体的一个char,高位的0为什么又会变成乱码呢?
不知道有没有达到重点- -
InputStream is = new FileInputStream("D:\\1.txt"); byte[] u = {'a','a'};
while (is.read(u) != -1) {
System.out.print(new String(u));
}
System.out.println();这样的代码能正确读出中文,说明不是在封装的时候出现乱码的。应该是在is.read()的时候读到了不认识的字符而产生的乱码。至于为什么不认识,我觉得字母的高8位存在某种特征,read()的时候发现了,就会认识是字母,所以能正常显示。读到中文的时候,因为只读了一半的字,java不认识这个字符,就会解成u003F,就会显示?
具体的的底层实现我也不太清楚,菜鸟一只,很难回答你的问题。
不过我想操作系统里面应该有类似字符分隔一类的特殊字符或者用了什么算法吧,反正操作系统是能够分得清哪几个字节是一个字的吧。不过我想应该是统一的字节数才对,而不是说英文一个字节,中文两个字节。说到底,中文英文什么的在都是1010的数据罢了,哪里分得清哪几个字节是英文,那几个是中文(当然,如果说有所谓的字符分隔的方式存在的话,还是可能分辨得出的)。至于你说的为什么英文没有乱码我大概懂你问什么了,如果说写进去的unicode两个字节里面高位是 0 然后读出来的 0 为什么没有乱码,我想大概是因为,00000000 在unicode里面和在ascii里面都是空字符的意思。而空字符打印出来就是什么都没有,那么既然你什么都没有看到,也就会认为没有乱码出现什么的咯,事实上也的确没有。
可以验证一下
试着读取一个全英文的文件,用一个计数器,每读取一次就输出一个字符,计数器自增1,然后再把输出次数跟
你看到的字符数目比较一下,如果比例大概是2:1的话,上面的推论就是正确的了。
也就是说改为的0有输出,但是你看不到。我用同学的电脑上网,做实验因该不太可能的了,哪位有兴趣可以试一试,期待结果。
英文会变成一个字符,而中文变成了2个字符,而read()的时候是一个字符一个字符的读,所以会产生这种情况。
记得以前看过说用字符流去读取中英文混搭的文本,里面提到过一种识别中文的方法。
因为文本里面只有中英文两种字符(标点符号除外,不过标点符号是属于ascii码的范围的)
考虑到unicode前127个字符兼容ascii,所以把标点符号和英文统一处理,读到就输出。而如果读到中文,就把下一个字节读进来,两个字节处理一下再装进一个String 或char里面输出,貌似可以把两个字节放进一个字节数组里面,然后 用String 的构造方法构造字符串输出。当然,还有很多方法。
至于识别一个字节是一个英文还是中文的办法,我记得不太清楚了,只记得书上说一个字节有八位,而127个字符只2能占据后7位,也就是说,英文和标点由于是这127个字符之一,所以最高位一定是0,而根据中文在unicode离得位置,可以判断中文两个字节里面最高位一定是1,所以,当读取一个字节之后,判断它的大小是否大于127(最高位是不是1),是的话说明这是一个中文的第一个字节,把下一个字节读进来处理然后输出。
如果没记错的话,大概就是这样子了
不过现实中应该用不到这么麻烦的方法- -
Reader reader = new InputStreamReader(is, "UTF-8");
BufferedReader r=new BufferedReader(reader);
r.readLine();
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;public class readText { /**
* @param args
*/
public static void main(String[] args) {
// InputStream is = null;
// try {
// is = new FileInputStream("E:\\1.txt");
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
// int c;
// try {
// while ((c = is.read()) != -1) {
// System.out.print((char) c);
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// System.out.println(); try {
String encoding = "GBK"; // 字符编码(可解决中文乱码问题 )
File file = new File("E:\\1.txt");
if (file.isFile() && file.exists()) {
InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
BufferedReader bufferedReader = new BufferedReader(read);
String lineTXT = null;
while ((lineTXT = bufferedReader.readLine()) != null) {
// System.out.println(lineTXT );
// 将文本读取出来的字符去掉"," 因为读取出来的字符是用","来分隔的
String text = lineTXT.replaceAll(",", "");
// 用字符分隔成数组
String[] version_1 = text.split("-");
for (int i = 0; i < version_1.length; i++) {
String[] version_2 = version_1[i].split(":");
for (int j = 0; j < version_2.length; j++) {
System.out.println(version_2[j]);
}
System.out.println("-------");
}
}
read.close();
} else {
System.out.println("找不到指定的文件!");
}
} catch (Exception e) {
System.out.println("读取文件内容操作出错");
e.printStackTrace();
}
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;public class readText { /**
* @param args
*/
public static void main(String[] args) {
// InputStream is = null;
// try {
// is = new FileInputStream("E:\\1.txt");
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// }
// int c;
// try {
// while ((c = is.read()) != -1) {
// System.out.print((char) c);
// }
// } catch (IOException e) {
// e.printStackTrace();
// }
// System.out.println(); try {
String encoding = "GBK"; // 字符编码(可解决中文乱码问题 )
File file = new File("E:\\1.txt");
if (file.isFile() && file.exists()) {
InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);
BufferedReader bufferedReader = new BufferedReader(read);
String lineTXT = null;
while ((lineTXT = bufferedReader.readLine()) != null) {
// System.out.println(lineTXT );
// 将文本读取出来的字符去掉"," 因为读取出来的字符是用","来分隔的
String text = lineTXT.replaceAll(",", "");
// 用字符分隔成数组
String[] version_1 = text.split("-");
for (int i = 0; i < version_1.length; i++) {
String[] version_2 = version_1[i].split(":");
for (int j = 0; j < version_2.length; j++) {
System.out.println(version_2[j]);
}
System.out.println("-------");
}
}
read.close();
} else {
System.out.println("找不到指定的文件!");
}
} catch (Exception e) {
System.out.println("读取文件内容操作出错");
e.printStackTrace();
}
}
}
while ((c = is.read()) != -1) {
System.out.print((char) c);
}
想想看,英文都是一个byte,而中文为二个byte,这样一个byte读取中文不出现乱码才奇怪呢!
比较好的方法参考:
contentByte = new byte[BYTELENGTH];
while ((byteReturnSize = bis.read(contentByte, 0, contentByte.length)) >= 0) {
byteBuffer.append(contentByte, 0, byteReturnSize);
}
xmlBody = new String(byteBuffer.toByteArray());楼上readline也会有问题