`
沙漠绿树
  • 浏览: 430206 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Java中的字符集编码入门(五)Java代码中的字符编码转换

阅读更多

    如果你是JVM的设计者,让你来决定JVM中所有字符的表示形式,你会不会允许使用各种编码方式的字符并存? 

    我想你的答案是不会,如果在内存中的Java字符可以以GB2312,UTF-16,BIG5等各种编码形式存在,那么对开发者来说,连进行最基本的字符串打印、连接等操作都会寸步难行。例如一个GB2312的字符串后面连接一个UTF-8的字符串,那么连接后的最终结果应该是什么编码的呢?你选哪一个都没有道理。

    因此牢记下面这句话,这也是Java开发者的共同意志:在Java中,字符只以一种形式存在,那就是Unicode(注意到我们没有选择特定的编码,直接使用它们在字符集中的编号,这是统一的唯一方法)。

    但“在Java中”到底是指在哪里呢?就是指在JVM中,在内存中,在你的代码里声明的每一个char,String类型的变量中。例如你在程序中这样写 


char han='汉'; 

 

    在内存的相应区域,这个字符就表示为0x6C49.可以用下面的代码证明一下: 


char han='汉';
System.out.format("%x",(short)han);
 

    输出是:6c49反过来用Unicode编号来指定一个字符也可以,像这样: 


char han=0x6c49;
System.out.println(han);

 

    输出是: 

    这其实也是说,只要你正确的读入了“汉”这个字,那么它在内存中的表示形式一定是0x6C49,没有任何其他的值能代表这个字(当然,如果你读错了,那结果是什么就不知道了,范伟说:读,读错了呀,那还等于好几亿呢;本山大哥说:好几亿你也没答上,请听下一题)。

    JVM的这种约定使得一个字符存在的世界分为了两部分:JVM内部和OS的文件系统。在JVM内部,统一使用Unicode表示,当这个字符被从JVM内部移到外部(即保存为文件系统中的一个文件的内容时),就进行了编码转换,使用了具体的编码方案(也有一种很特殊的情况,使得在JVM内部也需要转换,不过这个是后话)。 

    因此可以说,所有的编码转换就只发生在边界的地方,JVM和OS的交界处,也就是你的各种输入输出流(或者Reader,Writer类)起作用的地方


    话头扯到这里就必须接着说Java的IO系统。

    尽管看上去混乱繁杂,但是所有的IO基本上可以分为两大阵营:面向字符的Reader啊Wrtier啊,以及面向字节的输入输出流


    下面我来逐一分解,其实一点也不难。

    面向字符和面向字节中的所谓“面向”什么,是指这些类在处理输入输出的时候,在哪个意义上保持一致。如果是面向字节,那么这类工作要保证系统中的文件二进制内容和读入JVM内部的二进制内容要一致。不能变换任何0和1的顺序(也就是文件是怎么存的就怎么取,与文件保存的编码一致)。因此这是一种非常“忠实于原著”的做法(偶然间让我想起郭敬明抄袭庄羽的文章,那家伙,太忠实于原著了,笑)。


    这种输入输出方式很适合读入视频文件或者音频文件,或者任何不需要做变换的文件内容

    而面向字符的IO是指希望系统中的文件的字符和读入内存的“字符”(注意和字节的区别)要一致例如我们的中文版WindowsXP系统上有一个GBK的文本文件,其中有一个“汉”字,这个字的GBK编码是0xBABA(而Unicode编号是0x6C49),当我们使用面向字符的IO把它读入内存并保存在一个char型变量中时,我希望IO系统不要傻傻的直接把0xBABA放到这个char型变量中,我甚至都不关心这个char型变量具体的二进制内容到底是多少,我只希望这个字符读进来之后仍然是“汉”这个字。 

    从这个意义上也可以看出,面向字符的IO类,也就是Reader和Writer类,实际上隐式的为我们做了编码转换,在输出时,将内存中的Unicode字符使用系统默认的编码方式进行了编码,而在输入时,将文件系统中已经编码过的字符使用默认编码方案进行了还原。我两次提到“默认”,是说Reader和Writer的聪明也仅此而已了,它们只会使用这个默认的编码来做转换,你不能为一个Reader或者Writer指定转换时使用的编码。这也意味着,如果你使用中文版WindowsXP系统,而上面存放了一个UTF-8编码的文件,当你使用Reader类来读入的时候,它会傻傻的使用GBK来做转换,转换后的内容当然驴唇不对马嘴! 

    这种笨,有时候其实是一种傻瓜式的功能提供方式,对大多数初级用户(以及不需要跨平台的高级用户)来说反而是件好事。 
    但我们不一样啦,我们都是国家栋梁,肩负着赶英超美的责任,必须师夷长技以治夷,所以我们总还要和GBK编码以外的文件打交道。

    说了上面这些内容,想必聪明的读者已经看出来,所谓编码转换就是一个字符与字节之间的转换,因此Java的IO系统中能够指定转换编码的地方,也就在字符与字节转换的地方,那就是(读者:InputStreamReaderOutputStreamWriter!作者:太强了,都会抢答了!)

 

    PrintStream也可以对OutputStream进行包装并指定编码方式:PrintStream(OutputStream out, boolean autoFlush, String encoding),但实质上也是调用OutputStreamWriter来实现的。System.err在eclipse中输出时是红色的字体。

 

    这两个类是字节流和字符流之间的适配器类,因此他们肩负着编码转换的任务简直太自然啦!要注意,实际上也只能在这两类实例化的时候指定编码,是不是很好记呢?

    下面来写一段小程序,来把“汉”字用我们非常崇拜的UTF-8编码写到文件中! 

Java代码 复制代码
  1. try {   
  2.     PrintWriter out = new PrintWriter(new OutputStreamWriter(   
  3.             new FileOutputStream("c:/utf-8.txt"), "UTF-8"));   
  4.     try {   
  5.         out.write("汉");   
  6.     } finally {   
  7.         out.close();   
  8.     }   
  9. catch (IOException e) {   
  10.     throw new RuntimeException(e);   
  11.   
  12. }

     运行之后到c盘下去找utf-8.txt这个文件,用UltraEdit打开,使用16进制查看,看到了什么?它的值是0xE6B189!噢耶!(读者:这,这有什么好高兴的……)

 

文章转至:http://jiangzhengjun.iteye.com/blog/512072

分享到:
评论

相关推荐

    Java中的字符集编码入门(五)Java代码中的字符编码转换Part1.pdf

    Java中的字符编码转换是编程实践中一个至关重要的概念,尤其是在处理多语言环境和跨平台交互时。Java通过统一采用UTF-16编码格式在JVM内部处理字符,简化了字符操作的复杂性。UTF-16是一种变长的Unicode编码,它可以...

    Java中的字符集编码入门(五)Java代码中的字符编码转换Part1.doc

    ### Java中的字符集编码入门(五):Java代码中的字符编码转换Part1 #### 核心知识点概述: 本文档深入探讨了Java编程语言中字符集编码的基础知识,并着重讲解了字符编码转换的基本原理及其在Java代码中的应用。...

    Java中的字符集编码入门(五)Java代码中的字符编码转换Part1[参考].pdf

    Java中的字符编码转换是编程实践中不可或缺的一部分,尤其是在处理多语言和跨平台的场景下。Java选择了UTF-16作为其内部字符表示的标准,这确保了在JVM内存中,所有字符都以统一的方式存储,避免了编码不一致带来的...

    Java中的字符集编码入门(二)编码字符集与字符集编码的区别[参考].pdf

    在Java编程语言中,理解和掌握字符集编码是至关重要的,特别是在处理各种文本数据时。本文主要探讨了编码字符集和字符集编码的区别,这对于软件开发人员来说是基础且必要的知识。 首先,我们要区分两个概念:编码...

    Java中的字符集编码入门(清晰书签版)[借鉴].pdf

    Java中的字符集编码是编程领域中的重要概念,尤其在处理多语言环境时显得至关重要。本文主要探讨了字符编码的历史发展,特别是ASCII、Unicode和UCS的关系及其在Java中的应用。 ASCII,即美国标准信息交换码,是最早...

    125集专攻JAVA基础 JAVA零基础入门学习视频教程 动力节点JAVA视频教程.txt

    北京动力节点-Java编程零基础教程-049-Java基本语法-通过ASCII再理解字符编码.avi 北京动力节点-Java编程零基础教程-050-Java基本语法-ASCII.avi 北京动力节点-Java编程零基础教程-051-Java基本语法-ISO8859-1....

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让知识环环相扣,降低了学习的难度 通过大量的比喻、类比、对比和图示等多种讲解方式,学习效果好 对Java语言的每个语法都提供了一个或多个例程讲解 ...

    java源码 java ee基础入门实例 2018127

    例如,过滤器可以用来实现权限验证、字符编码转换、日志记录等功能。通过实现javax.servlet.Filter接口并配置在web.xml中,即可定义和注册过滤器。 5. **JDBC实例**: JDBC(Java Database Connectivity)是Java...

    java编程入门第八章输入与输出

    - Java中的字符编码默认使用Unicode,通过`Charset` 类可以处理不同的字符编码。 10. **文件复制** - 使用Java I/O可以实现文件的复制,通常结合`InputStream` 和 `OutputStream` 的read和write方法完成。 11. *...

    java中的IO的基础教学(1)

    4. InputStreamReader和OutputStreamWriter:作为字节流与字符流之间的桥梁,它们可以根据指定的字符集将字节流转换为字符流,反之亦然。 5. DataInputStream和DataOutputStream:用于读写基本数据类型的字节流,如...

    动力节点Java基础301集_史上最全的Java基础教程

    进一步深入,讲解了关键字、标识符、字面量、进制转换、字符编码、变量的分类和内存分析,基本数据类型的转换规则、运算符、算术表达式,以及流程控制语句等。 总的来说,《Java基础301集》是一套系统且全面的Java...

    Apache common io转码工具类入门教程

    Apache Commons IO是Apache软件基金会开发的一个Java库,它提供了大量的实用工具类,简化了I/...通过这个教程,你可以了解到Apache Commons IO库在处理文件编码转换时的强大功能,以及如何在实际项目中应用这些工具类。

    Java NIO入门

    6. **字符集转换(Charset)**:NIO提供了一套完善的字符集转换机制,可以方便地进行字符编码和解码。 学习NIO,首先要理解如何创建和使用通道、缓冲区以及选择器。例如,通过`FileChannel`打开文件,然后使用`...

    动力节点Java基础301集

    InputStreamReader、OutputStreamWriter等转换流用于字符编码转换。 - **对象流**:ObjectInputStream和ObjectOutputStream用于序列化和反序列化对象。 ### 九、多线程 - **线程的基本概念**:理解进程与线程的...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    一一击破Java入门可能会遇到的难点和疑惑 抽丝剥茧,层层推进,让知识环环相扣,降低了学习的难度 通过大量的比喻、类比、对比和图示等多种讲解方式,学习效果好 对Java语言的每个语法都提供了一个或多个例程讲解 ...

    java SE.docx

    6. **转义字符**:在Java字符串中,反斜杠(\)用来表示转义字符,例如`\n`表示换行,`\t`表示制表符。 7. **Js与Java**:JavaScript和Java虽然名字相似,但实际上是两种不同的编程语言。JavaScript主要用于前端网页...

    孙卫琴Java Web全套源码

    9. **charset**: 这个目录可能涉及到字符编码问题,如UTF-8和GBK,以及在Java Web开发中如何处理字符编码转换。 通过学习这些源代码,开发者不仅可以掌握Java Web的基础知识,还能了解到实际项目开发中的最佳实践。...

    Java基础入门教程 含习题 第08章 IO(输入输出流)(共79页).pptx

    在字符编码方面,Java支持多种字符集,如ASCII、ISO-8859-1、GB2312、GBK和UTF-8等。字符编码和解码是字符流处理过程中的关键步骤,确保数据在不同系统间正确无损地传输。例如,`InputStreamReader`和`...

    java开源包8

    WARTS是一个纯Java数据库工具,可以执行字符编码识别的数据同步。开发它是用于在UTF-8 Oracle实例中使用ASCII编码的Oracle 数据库中来正确的传输非ASCII字符。 Java模板语言 Beetl Beetl,是Bee Template Language的...

Global site tag (gtag.js) - Google Analytics