CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
花落谁家,你作主! 盛大widget设计大赛英雄榜
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Java >  J2SE / 基础类

如何输出中文?

楼主bluerain006(weilai_w)2002-02-09 21:20:46 在 Java / J2SE / 基础类 提问

在jsp中,使用流复制文件时,为何遇到中文无法复制,如何才能做到?  
  <html>  
  <head>  
  <meta   http-equiv="Content-Type"   content="text/html;   charset=gb2312">  
  <meta   name="GENERATOR"   content="Microsoft   FrontPage   4.0">  
  <meta   name="ProgId"   content="FrontPage.Editor.Document">  
  <title>New   Page   1</title>  
  </head>  
  <body>  
  <%@   page   import="java.io.*"%>  
  <%  
  try{  
  String   fileName   =   request.getParameter("file");  
  String   fileName1   =   "d:\\aa.txt";  
  FileInputStream   is   =   new   FileInputStream(fileName);  
  FileOutputStream   is1   =   new   FileOutputStream(fileName1);  
  byte   ch=0;  
  while   ((ch   =(byte)   is.read())   >=   0)  
  {  
  out.print(   (char)ch);  
  out.print(   "|");  
  out.print(   ch);  
  out.print(   "|");  
  is1.write(ch);  
  }  
  is.close();  
  }  
    catch(Exception   e)    
  {out.println(e);}  
  %>      
  </body>  
  </html> 问题点数:100、回复次数:7Top

1 楼sojkey()回复于 2002-02-09 23:31:27 得分 20

你一个byte一个byte的读出来应该是有问题,因为一个中文要占两个byte,你应该读出一个byte数组,再用GBK或ISO8859_1转码。对于文本文件,可以用BufferedInputStream的readLine()一行一行的读。Top

2 楼pengji(彭乃超)回复于 2002-02-10 08:46:30 得分 60

File   file   =   new   File(fileName1);  
  int   size   =   (int)file.length();  
  FileReader   in   =   new   FileReader(file);  
              char[]   data   =   new   char[size];  
              while(in.ready())   {  
                  chars_read   +=   in.read(data,   chars_read,   size   -   chars_read);  
              }  
              in.close();Top

3 楼hyhong_h(黄黄)回复于 2002-02-10 08:56:08 得分 10

同意楼上的。Top

4 楼JavaGir1(JavaGirl)回复于 2002-02-10 11:54:51 得分 0

是啊,在用smartupload的时候,就是用char数组才能正确输出中文的  
  可这是为什么啊!Top

5 楼remote_roamer(心灵捕手)回复于 2002-02-10 12:01:27 得分 10

我觉得最好不要用char,而是用byte比较好一点erTop

6 楼bluerain006(weilai_w)回复于 2002-02-12 23:07:56 得分 0

谢谢各位的帮助!  
  另从网上拷的一片有关中文资料:  
  预备知识:    
   1.字节和unicode    
    Java内核是unicode的,就连class文件也是,但是很多媒体,包括文件/流的保存方式    
    是使用字节流的。   因此Java要对这些字节流经行转化。char是unicode的,而byte是字节.    
    Java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度,    
    可以用来告诉你,你用的Convertor。其中两个很常用的静态函数是    
       public   static   ByteToCharConverter   getDefault()   ;    
       public   static   ByteToCharConverter   getConverter(String   encoding);    
    如果你不指定converter,则系统会自动使用当前的Encoding,GB平台上用GBK,EN平台上用    
    8859_1    
        
    我们来就一个简单的例子:    
       "你"的gb码是:0xC4E3   ,unicode是0x4F60    
       你用:    
       --encoding="gb2312";    
       --byte   b[]={(byte)'\u00c4',(byte)'\u00E3'};    
       --convertor=ByteToCharConverter.getConverter(encoding);    
       --char   []   c=converter.convertAll(b);    
       --for(int   i=0;i<c.length;c++)    
       --{    
       --   System.out.println(Integer.toHexString(c[   i]));    
       --}    
       --打印出来是0x4F60    
       --但是如果使用8859_1的编码,打印出来是    
       --0x00C4,0x00E3    
       ----例1    
         反过来:    
         --encoding="gb2312";    
            char   c[]={'\u4F60'};    
            convertor=ByteToCharConverter.getConverter(encoding);    
       --byte   []   b=converter.convertAll(c);    
       --for(int   i=0;i<b.length;c++)    
       --{    
       --   System.out.println(Integer.toHexString(b[i]));    
       --}    
        --打印出来是:0xC4,0xE3    
        ----例2    
        --如果用8859_1就是0x3F,?号,表示无法转化      --    
          很多中文问题就是从这两个最简单的类派生出来的。而却有很多类      
    不直接支持把Encoding输入,这给我们带来诸多不便。很多程序难得用encoding    
    了,直接用default的encoding,这就给我们移植带来了很多困难    
    --    
    2.UTF-8    
    --UTF-8是和Unicode一一对应的,其实现很简单    
    --    
       --   7位的Unicode:   0   _   _   _   _   _   _   _    
    --11位的Unicode:   1   1   0   _   _   _   _   _   1   0   _   _   _   _   _   _    
    --16位的Unicode:   1   1   1   0   _   _   _   _   1   0   _   _   _   _   _   _   1   0   _   _   _   _   _   _    
    --21位的Unicode:   1   1   1   1   0   _   _   _   1   0   _   _   _   _   _   _   1   0   _   _   _   _   _   _   1   0   _   _   _   _   _   _    
    --大多数情况是只使用到16位以下的Unicode:    
    --"你"的gb码是:0xC4E3   ,unicode是0x4F60    
    --我们还是用上面的例子    
    --  --例1:0xC4E3的二进制:    
    --  --      1   1   0   0   0   1   0   0   1   1   1   0   0   0   1   1    
    --  --      由于只有两位我们按照两位的编码来排,但是我们发现这行不通,    
    --  --      因为第7位不是0因此,返回"?"    
    --  --       
    --  --例2:0x4F60的二进制:    
    --  --      0   1   0   0   1   1   1   1   0   1   1   0   0   0   0   0    
    --  --      我们用UTF-8补齐,变成:    
    --  --      11100100   10111101   10100000    
    --  --      E4--BD--   A0    
    --  --      于是返回0xE4,0xBD,0xA0    
    --  --    
    3.String和byte[]    
    --String其实核心是char[],然而要把byte转化成String,必须经过编码。    
    --String.length()其实就是char数组的长度,如果使用不同的编码,很可    
    --能会错分,造成散字和乱码。    
    --例:    
    ----byte   []   b={(byte)'\u00c4',(byte)'\u00e3'};    
    ----String   str=new   String(b,encoding);  ----    
    ----如果encoding=8859_1,会有两个字,但是encoding=gb2312只有一个字  ----    
    --这个问题在处理分页是经常发生    
    4.Reader,Writer/InputStream,OutputStream    
    --Reader和Writer核心是char,InputStream和OutputStream核心是byte。    
    --但是Reader和Writer的主要目的是要把Char读/写InputStream/OutputStream    
  --一个reader的例子:    
  --文件test.txt只有一个"你"字,0xC4,0xE3--    
  --String   encoding=;    
  --InputStreamReader   reader=new   InputStreamReader(    
  ----new   FileInputStream("text.txt"),encoding);    
  --char   []c=new   char[10];    
  --int   length=reader.read(c);    
  --for(int   i=0;i<c.length;i++)    
  ----System.out.println(c[i]);    
    --如果encoding是gb2312,则只有一个字符,如果encoding=8859_1,则有两个字符    
    --------    
  --    
  --    
        
       ----    
  Top

7 楼bluerain006(weilai_w)回复于 2002-02-12 23:08:50 得分 0

(接上)  
  2.我们要对Java的编译器有所了解:    
   --javac   -encoding    
      我们常常没有用到ENCODING这个参数。其实Encoding这个参数对于跨平台的操作是很重要的。    
      如果没有指定Encoding,则按照系统的默认Encoding,gb平台上是gb2312,英文平台上是ISO8859_1。     
   --Java的编译器实际上是调用sun.tools.javac.Main的类,对文件进行编译,这个类 --    
   有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。    
   编译器就是根据这个变量来读取java文件的,然后把用UTF-8形式编译成class文件。    
   一个例子:    
   --public   void   test()    
   --{    
   ----String   str="你";    
   ----FileWriter   write=new   FileWriter("test.txt");    
   ----write.write(str);    
   ----write.close();    
   --}    
   ----例3    
  --如果用gb2312编译,你会找到E4   BD   A0的字段    
  --    
  --如果用8859_1编译,    
  --00C4   00E3的二进制:    
  --00000000   11000100   00000000   11100011--    
  --因为每个字符都大于7位,因此用11位编码:    
  --11000001   10000100   11000011   10100011    
  --C1--   84-- C3--    A3    
  --你会找到C1   84   C3   A3   --    
          
    但是我们往往忽略掉这个参数,因此这样往往会有跨平台的问题:    
    --  例3在中文平台上编译,生成ZhClass    
    --  例3在英文平台上编译,输出EnClass    
    --1.    ZhClass在中文平台上执行OK,但是在英文平台上不行    
    --2.    EnClass在英文平台上执行OK,但是在中文平台上不行    
    原因:    
   --1.在中文平台上编译后,其实str在运行态的char[]是0x4F60, ----    
   --在中文平台上运行,FileWriter的缺省编码是gb2312,因此    
   --CharToByteConverter会自动用调用gb2312的converter,把str转化    
   --成byte输入到FileOutputStream中,于是0xC4,0xE3放进了文件。    
   --但是如果是在英文平台下,CharToByteConverter的缺省值是8859_1,    
   --FileWriter会自动调用8859_1去转化str,但是他无法解释,因此他会    
   --输出"?" ----    
   --2. 在英文平台上编译后,其实str在运行态的char[]是0x00C4   0x00E3, ----    
   --在中文平台上运行,中文无法识别,因此会出现??    
   --  在英文平台上,0x00C4-->0xC4,0x00E3->0xE3,因此0xC4,0xE3被放进了    
   --文件    
  ----    
  1.对于JSP正文的解释:    
  --Tomcat首先看一下你的叶面中有没有"<%@page   include的符号。有,则在相同    
  --地方设定response.setContentType(..);按照encoding的来读,没有他按照8859_1    
  --读取文件,然后用UTF-8写成.java文件,然后用sun.tools.Main去读取这个文件,    
  --(当然它使用UTF-8去读),然后编译成class文件    
  --setContentType改变的是out的属性,out变量缺省的encoding是8859_1    
   
  2.对Parameter的解释    
  --很不幸Parameter只有ISO8859_1的解释,这个质料可以在servlet的实现代码中找到。    
   
  3.对include的解释    
  格式的,但是很不幸,由于那个写"org.apache.jasper.compiler.Parser"的人    
  在数组JspUtil.ValidAttribute[]忘记加了一个参数:encoding,因此导致不支    
  持这种方式。你完全可以编译源代码,加上对encoding的支持    
   
  总结:    
   
  如果你在NT底下,最简单的方法就是欺骗java,不加任何Encoding变量:    
  <html>    
  你好<%=request.getParameter("value")%>    
  </html>    
   
  http://localhost/test/test.jsp?value=你    
   
  结果:你好你    
   
  但这种方法局限性较大,比如对上传的文章分段,这样的做法是死定的,最好的    
  解决方案是用这种方案:    
  <%@   page   contentType="text/html;charset=gb2312"   %>    
  <html>    
  你好<%=new   String(request.getParameter("value").getBytes("8859_1"),"gb2312")%>    
  </html>    
   
   
  必读好文,但解决方案不敢恭维    
   
   
  --------------------------------------------------------------------------------    
   
  1.网页传参数不提倡用get方法,而且用户可以调整是否用utf-8发送    
  2.建议jsp中最好不要用,实际上加不加这句都有实现中文正常显示的方案,我认为不加方便些,至少不用写这些代码,如下的配置我认为可以使中文正常显示:    
  a.所有的javabean用iso8859-1编译    
  b.jsp文件中不要写以上charset=gb2312的语句(写了反而错)    
   
  在tomcat情况下注意以上2点就行---了,等等,对于其他有可能不行的jsp服务器,加上以下    
  c.服务器上的操作系统语言设为英文(像没有装类似bluepoint中文系统的linux一般本来就是英文)    
  就行---了    
   
  谁要是还不对,请报告....    
   
   
  Re:必读好文,但解决方案不敢恭维    
   
   
  --------------------------------------------------------------------------------    
   
  Tomcat的参数问题无论是GET或是POST方式都是用8859_1编码的。这个可以看Tomcat   Servlet实现的源代码:    
  a)   对于POST方法    
   javax.servlet.http.HttpUtils的parsePostData方法:   (对于POST的Form数据)    
   String   postedBody   =   new   String(postedBytes,   0,   len,   "8859_1");)这里是没有问题的因为中文都会用%来说明。但是parseName这个函数,却没有把是中文的东西整合起来,他只是简单的拼凑,因此可以认定他是使用8859_1的编码规则    
      sb.append((char)   Integer.parseInt(s.substring(i+1,   i+3),   16));    
  ----  i   +=   2;    
  --    
  b)   对于GET方法    
   org.apache.tomcat.service.http.HttpRequestAdapter    
     -- line=new   String(buf,   0,   count,    
           Constants.CharacterEncoding.Default);    
  ----Constants.CharacterEncoding.Default=8859_1    
   这段代码不好跟踪,千万不要被一些假象迷惑住。HttpRequestAdapter是从RequestImpl中派生的。但是,实际上用8080端口的Server并没有直接用到RequestImpl,而是用了HttpRequestAdapter来获得queryString    
   
  对于加不加encoding,我保留我的意见,因为如果要解决上传文件分页问题,必须要用他来编码。而且编码能保证在一些Beans当中的传递性。    
   
  看来我要在这里说明一下了    
   
   
  --------------------------------------------------------------------------------    
   
  Tomcat仅仅是一个对jsp1.1,servlet2.2的一个标准的实现,我们不应该要求这个免费软件在细致末节上和性能上都面面俱到,它主要考虑的英文用户,这也是为什么不作特殊转换我们的汉字用url方法传递有问题的原因,我们大部分浏览器ie其高级设置中始终以utf-8发送url的选项缺省是选上的,如果说这是tomcat的bug也是可以的,另外Tomcat不管当前的操作系统是什么语言,好像都按iso8859去编译jsp,我觉得也有点欠妥,但是不管怎么说,新标准的实现和热门的软件在语言的支持方面永远都是先考虑英文    
   
  我的方案什么说要好一些呢    
  1.还是那句话,英文国家的软件永远都是先考虑英文,java虚拟机的规范中要求虚拟机内部必须实现iso8859,unicode,UTF-8三种,其他的不作要求,我们用的jdk中的虚拟机就是这样,嵌入式的就更不用说了,也就是说其他的ENCODE都很可能不是java虚拟机内部直接支持的,我们的中文自然也不在其列,需要外部的包支持转换,sun   jdk应该在i18n.jar中,用iso8859速度最快,不需要其它调用和交换什么的,更没有读包的io操作    
  2.至少少写了代码,没有额外操作,简洁的风格谁不喜欢    
  3.所写的jsp页面国际性化好,我才写了一个jsp+javabeans的聊天室软件(没有用到servlet,jsp真的确实很好),同样的程序美国人用他们的浏览器进入就是英文界面,中文进入就是中文界面,如果加上charset=gb2312至少很麻烦    
  4.限定了gb2312,如果用户要用GBK,怎么办,不加更好,不管什么的字符集,只要我当前浏览器设定的是,我就能显示出来    
   
  总结:无论从速度上,开发效率上,和可扩展性上考虑,我的方案都比你的好,另外,我找不到你的方案比我的好的地方.    
   
   
  [已被   webmaster   编辑过,   在   2001-01-21   11:23]  
   
   
  --------------------------------------------------------------------------------  
   
  由   javafan   发布于:   2001-04-10   01:06  
   
   
  如下的配置我认为可以使中文正常显示:    
  a.所有的javabean用iso8859-1编译    
  b.jsp文件中不要写以上charset=gb2312的语句(写了反而错)    
   
  我用的是tomcat,根据上面配置,基本显示正常。    
  但是从数据库中取出的中文数据不能正常显示。    
  我用的数据库是sybase的。    
   
  而我用iso8859-1编译javabean,在jsp文件中写上charset=gb2312.    
  在javabean中所有String都用native2unicode编码,    
  在jsp中都用unicode2native解码,可以在自己机子上正常显示.    
  我用的是中文win2k.    
  不知道在其他平台上能否正常显示???  
   
  Top

相关问题

  • 绘图中如何输出中文?
  • perl绘图中如何输出中文?
  • servlet如何能输出中文?????
  • 如何让<html:errors/>输出中文呀?
  • 如何逆序中文输出
  • 如何输出中文! 不是用TextOut( “中文” )!!!
  • 请问在servlet中如何输出中文?
  • 急急急,请问在servlet中,如何输出中文?
  • pb8如何输出带中文表头的EXCEL表格
  • 如何输出中文或其他文字和字符?

关键词

得分解答快速导航

  • 帖主:bluerain006
  • sojkey
  • pengji
  • hyhong_h
  • remote_roamer

相关链接

  • CSDN Java频道
  • Java类图书
  • Java类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo