黑马程序员技术交流社区

标题: IO输入中文为什么出错啊 [打印本页]

作者: 广驰    时间: 2012-9-11 19:19
标题: IO输入中文为什么出错啊
本帖最后由 应广驰 于 2012-9-13 00:36 编辑

这个代码是用Eclipse完成的,输入纯英文没有错误,可是输入中文的时候结果就变了
  1. package io;

  2. import java.io.*;

  3. public class KeyTest
  4. {
  5.         
  6.         public static void main(String[] args) throws IOException
  7.         {
  8.                 BufferedReader isr = new BufferedReader(new InputStreamReader(System.in));
  9.                 BufferedWriter ow = new BufferedWriter(new OutputStreamWriter(System.out));
  10.                 while(true)
  11.                 {
  12.                         String s =  lineRead(isr);
  13.                         if(s.toString().equals("over\r\n"))
  14.                         {
  15.                                 break;
  16.                         }
  17.                         ow.write(s);
  18.                         ow.flush();
  19.                         s = null;
  20.                 }
  21.         }
  22.         
  23.         public static String lineRead(Reader is)//读取控制台的一行文字
  24.         {
  25.                 StringBuilder sb = new StringBuilder();
  26.                 int i = 0;
  27.                 while(true)
  28.                 {
  29.                         try
  30.                         {               
  31.                                 //\r和\n不论是单独出现还是一起出现都放到容器中,
  32.                                 //当两个同时出现代表换行符,一次输入结束
  33.                                 if((i = is.read())=='\r')
  34.                                 {
  35.                                         sb.append((char)i);
  36.                                         if((i = is.read())=='\n')
  37.                                         {
  38.                                                 sb.append((char)i);
  39.                                                 break;
  40.                                         }                                       
  41.                                 }
  42.                                 sb.append((char)i);
  43.                         }
  44.                         catch(IOException io)
  45.                         {
  46.                                 System.out.println("读取失败");
  47.                         }
  48.                 }
  49.                 return sb.toString();        
  50.         }

  51. }
复制代码
一下是输入和输出结果,红色的输入
黑马训练营
黑马训练营
黑马程序员
h'm'c'x黑马程序员
over
'yh'm'c'xh'm'ch'mhover
over
overoveo'voover
over
为什么会出现这种情况

作者: 王陶成    时间: 2012-9-11 20:12
楼主,我在我的机子上测试了一下,没有问题啊,MyEclipse

黑马训练营
黑马训练营
黑马程序员
黑马程序员
over
作者: 方志亮    时间: 2012-9-11 20:26
这个应该是字符编码的问题吧
作者: 杨震    时间: 2012-9-11 20:58
这个估计是eclipse编码的问题吧,我在dos命令下行没有问题
作者: 黑马-李勇    时间: 2012-9-11 21:34
is.read()应该是字节吧,一次读一个字节?
编码表不同可能会出现 问题。
为什么不用readLine()
作者: AngieFans85    时间: 2012-9-11 21:37
  1. import java.io.BufferedReader;
  2. import java.io.BufferedWriter;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.io.OutputStreamWriter;
  6. import java.io.Reader;

  7. public class KeyTest {

  8.         public static void main(String[] args) throws IOException {
  9.                 BufferedReader isr = new BufferedReader(
  10.                                 new InputStreamReader(System.in));
  11.                 BufferedWriter ow = new BufferedWriter(new OutputStreamWriter(
  12.                                 System.out));
  13.                 while (true) {
  14.                         String s = lineRead(isr);
  15.                         if (s.toString().equals("over\r\n")) {
  16.                                 break;
  17.                         }
  18.                         ow.write(s);
  19.                         ow.flush();
  20.                         s = null;
  21.                 }
  22.                 ow.close();
  23.                 isr.close();
  24.         }

  25.         public static String lineRead(Reader is)// 读取控制台的一行文字
  26.         {
  27.                 StringBuilder sb = new StringBuilder();
  28.                 int i = 0;
  29.                 while (true) {
  30.                         try {
  31.                                 // \r和\n不论是单独出现还是一起出现都放到容器中,
  32.                                 // 当两个同时出现代表换行符,一次输入结束
  33.                                 i = is.read();
  34.                                 if (i == '\r') {
  35.                                         // sb.append((char) i);
  36.                                         break;
  37.                                 } else if (i == '\n') {
  38.                                         // sb.append((char) i);
  39.                                         break;
  40.                                 } else {
  41.                                         sb.append((char) i);
  42.                                 }
  43.                         } catch (IOException io) {
  44.                                 io.printStackTrace();
  45.                                 System.out.println("读取失败");
  46.                         }
  47.                 }
  48.                 return sb.toString();
  49.         }

  50. }
复制代码

作者: 寇龙飞    时间: 2012-9-12 00:32
经过2个小时的苦苦思索、测试、简化,一万次后终于理清思路得到简化代码(此代码与楼主代码出现同样的问题):
  1. package com.itheima.test;

  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;

  5. public class KeyTest {

  6.         public static void main(String[] args) throws IOException {
  7.                 BufferedReader isr = new BufferedReader(new InputStreamReader(System.in));
  8.                 while (true) {
  9.                         System.out.println(isr.readLine());
  10.                 }
  11.         }
  12. }
复制代码
我得出结论,问题的出现与控制台的输入有关!
当时我认为:
现象为:输入英文后敲回车,打印正常;复制中文粘贴到控制台后敲回车,打印正常;快速拼写出中后敲回车,打印正常;拼写中途稍作停顿后,敲空格让中文显现在控制台上,然后敲回车,打印异常,多出现了一些有规律的拼音字母!

无图无真相嘛。我要截真相图时,难倒我了。。。。。因为,有时候会印证我的结论,有时不能。

终于又在一万次测试之后,我终于测试出问题的根源!!!!!

原因居然还是控制台录入中文的问题。

后来我在想,eclipse,呵呵,老外用0、1与英语开发的编程语言工具嘛。对中文支持效果不佳,极不稳定,我想得出一个出错的准确规律,无奈夜已深,明早要去一家公司面试,想想作罢。总之各种情况都会有,对中文兼容不好就对了。
这是在GBK编码下测试的。
其它格式就别想了,又不支持中文编码,情况更糟糕。
  1. 你好
  2. 你好
  3. 你好
  4. ni'h你好



  5. nihani'hnin



复制代码
太晚了 就不截图了。反正就是这个意思。大家以后要写程序,做交互,让客户输入内容,尽量给出选项提示信息,让客户输入阿拉伯数字选择避免此类问题就行了。

唉。为这道题目花了我三个小时。版主至少给三分把。明天的面试都没做准备。大家祝我明天好运吧。
作者: 广驰    时间: 2012-9-12 10:31
寇龙飞 发表于 2012-9-12 00:32
经过2个小时的苦苦思索、测试、简化,一万次后终于理清思路得到简化代码(此代码与楼主代码出现同样的问题 ...

我倒是也想过, eclipse兼容的问题,可是对为什么会出现这样的情况,有些好奇, eclipse是怎样实现录入的,不过还是谢谢了
作者: 广驰    时间: 2012-9-12 10:36
黑马-李勇 发表于 2012-9-11 21:34
is.read()应该是字节吧,一次读一个字节?
编码表不同可能会出现 问题。
为什么不用readLine() ...

我这个是自己模拟的readLine(),再说java定义好的readLine()底层也是用的read()吧
作者: AngieFans85    时间: 2012-9-12 15:05
其实这问题和eclipse没有关系,这和操作系统的语言环境有关.如果你的操作系统的语言环境不是中文(中国),那么你想输入或输出中文,就必须要在在实例化输入流或输出流对象时,要传入"gbk"的编码,这样才可以读取到中文字符.由于你的操作系统的语言环境不是中文(中国),比如说如果是英语(美国),那么就要将输入流取得的中文字符先用某一种编码格式(比如说utf-8)编码为英语(美国)语言环境可以接受的字节,再将编码后的字节以同一种编码格式(utf-8)解码为英语(美国)语言环境可以接受的字符,这样就可以在控制台中打印出来了,以下是代码示例:
  1. import java.io.BufferedReader;
  2. import java.io.BufferedWriter;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.io.OutputStreamWriter;
  6. import java.io.Reader;
  7. import java.io.UnsupportedEncodingException;

  8. public class KeyTest {

  9.         public static void main(String[] args) throws IOException {
  10.                 BufferedReader isr = new BufferedReader(new InputStreamReader(
  11.                                 System.in, "gbk"));

  12.                 BufferedWriter ow = new BufferedWriter(new OutputStreamWriter(
  13.                                 System.out, "gbk"));
  14.                 while (true) {
  15.                         String s = lineRead(isr);
  16.                         if (s.equals("over")) {
  17.                                 break;
  18.                         }
  19.                         ow.write(s);
  20.                         ow.flush();
  21.                         s = null;
  22.                 }
  23.                 ow.close();
  24.                 isr.close();
  25.         }

  26.         public static String lineRead(Reader is)// 读取控制台的一行文字
  27.         {
  28.                 StringBuilder sb = new StringBuilder();
  29.                 int i = 0;
  30.                 String string = null;
  31.                 while (true) {
  32.                         try {
  33.                                 // \r和\n不论是单独出现还是一起出现都放到容器中,
  34.                                 // 当两个同时出现代表换行符,一次输入结束
  35.                                 i = is.read();
  36.                                 if (i == '\r') {
  37.                                         break;
  38.                                 } else if (i == '\n') {
  39.                                         break;
  40.                                 } else {
  41.                                         sb.append((char) i);
  42.                                 }
  43.                         } catch (IOException io) {
  44.                                 io.printStackTrace();
  45.                                 System.out.println("读取失败");
  46.                         }
  47.                 }
  48.                 try {
  49.                         // 必须要将把从gbk语言环境中取得的中文字符先编码为utf-8格式的字节,再将此编码后的
  50.                         // 字节解码为utf-8格式的字符,才可以在各种不同语言环境的操作系统上正确显示出中文字符,
  51.                         // 因为utf-8是全球通用的编码格式,包括了所有国家使用的语言文字.
  52.                         string = new String(sb.toString().getBytes("utf-8"), "utf-8");
  53.                 } catch (UnsupportedEncodingException e) {
  54.                         e.printStackTrace();
  55.                 }
  56.                 return string;
  57.         }

  58. }
复制代码

作者: 广驰    时间: 2012-9-12 16:34
马镱洵 发表于 2012-9-12 15:05
其实这问题和eclipse没有关系,这和操作系统的语言环境有关.如果你的操作系统的语言环境不是中文(中国),那么 ...

但是我的操作系统语言环境是中文的啊
作者: AngieFans85    时间: 2012-9-12 17:23
应广驰 发表于 2012-9-12 16:34
但是我的操作系统语言环境是中文的啊

中文的操作系统自然就不需要给输入和输出流传入"gbk"编码了:
  1. BufferedReader isr = new BufferedReader(
  2.                                 new InputStreamReader(System.in));
  3.                 BufferedWriter ow = new BufferedWriter(new OutputStreamWriter(
  4.                                 System.out));
复制代码





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2