Java 文件读取写入的编码问题


关于编码解码的知识背景:

内           编码 --->>     目

容       <<----解码       标

编码解码跟翻译语言一样。内容是本质的东西,无论怎么编码,它所表达的内容不能变。

而无论怎么编码解码,表现形式都是字节数组,它的值会随着编码解码方式的不同而不同。

编码解码要做的,就是对这些byte数组进行操作,将它还原成我们需要的内容。

对于一段汉字的编码解码,汉字本身就是内容文件,我们需要将他们用数字的形式表示,即编码为对应的二进制串(目标)

常见的字符集:

ANSI :ASCII字符集,以及由此派生并兼容的字符集,如:GB2312(汉字支持,GB是“国标”的缩写),对GB2312向下兼容的GBK(其中能表达的汉字数量比GB2312多),正式的名称为MBCS(Multi-Byte Chactacter System,多字节字符系统),通常也称为ANSI字符集。

UNICODE:   由于每种语言都制定了自己的字符集,导致最后存在的各种字符集实在太多,在国际交流中要经常转换字符集非常不便。因此,产生了Unicode字符集,它固定使用16 bits(两个字节)来表示一个字符,共可以表示65536个字符。标准的Unicode称为UTF-16(UTF:UCS Transformation Format ,每两个字节作为一个编码单元,编码效率高。这让能够用一个字节存放的ASCII字符浪费了一个字节,不适于网络传输,多用于本地的编码)。后来为了双字节的Unicode能够在现存的处理单字节的系统上正确传输,出现了UTF-8(变长编码,有更好的鲁棒性:UTF16顺序编码,如果中间丢失一个bit位,将全盘皆输,但UTF8的编码方式中,每个单元都有一个特定几个bit位的头,这让它能抵抗这种情况),使用类似MBCS的方式对Unicode进行编码。(Unicode字符集有多种编码形式)

-----------------------************正文************-----------------------

java中读取文件的解码

文件以字节的形式存储在磁盘,这些数据实际上是文件的内容通过某种字符集编码后的结果,而我们读取文件后对文件的处理就是对这些数据的解码。

按照java IO 的框架,Java读取文件的方式总体可以分为两类:按字节读取和按字符读取。下面依次分析。

按字节读取

按字节读取的层次结构是各种stream 。可以使用InputStream.read()方法来读取字节。需要的话,可以将字节数组转换成String字符串。

而编码也就隐式发生在由字节数组转换到字符串数组的过程中。

String str = new String(byteArray);

参见String构造函数的doc , 如上的转换实际上使用的是系统的默认字符集。如果需要制定字符集解码,可以使用String(byte[] bytes, Charset charset) 构造函数

只要能用文件的编码字符集进行解码,就不会出现乱码问题。

以下为实践代码。我存储了a.txt到我的用户目录下。内容为:  biaobiaoqi编码问题

  1. package biaobiaoqi.thinkingInJava;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.FileNotFoundException;  
  5. import java.io.IOException;  
  6.   
  7. public class Test {  
  8.   
  9.     public static void main(String[] args){  
  10.         try {  
  11.             FileInputStream in = new FileInputStream("/home/biaobiaoqi/a.txt");  
  12.             byte[] bytes = new byte[100];  
  13.             while((in.read(bytes)) != -1);  
  14.               
  15.             in.close();  
  16.             String strGB2312 = new String(bytes,"GB2312");  
  17.             String strGBK = new String(bytes,"GBK");  
  18.             String strUTF8 = new String(bytes,"UTF-8");  
  19.             String strUTF16 = new String(bytes,"UTF-16");  
  20.               
  21.             System.out.println("strGB2312: "+strGB2312);  
  22.             System.out.println("strGBK: "+strGBK);  
  23.             System.out.println("strUTF8: "+strUTF8);  
  24.             System.out.println("strUTF16: "+strUTF16);  
  25.               
  26.         } catch (FileNotFoundException e) {  
  27.             // TODO Auto-generated catch block   
  28.             e.printStackTrace();  
  29.         } catch (IOException e) {  
  30.             // TODO Auto-generated catch block   
  31.             e.printStackTrace();  
  32.         }  
  33.           
  34.           
  35.           
  36.     }  
  37. }  

分别用GB2312 ,GBK ,UTF8, UTF16 并用system.out.println显示,结果如下:

  1. strGB2312: biaobiaoqi编码问题  
  2. strGBK: biaobiaoqi编码问题  
  3. strUTF8: biaobiaoqi��������  
  4. strUTF16: 扩慯扩慯煩뇠싫컊쳢਀

可以推断,a.txt的文本文件编码为ANSI,GBK向下兼容GB2312,所以两者都能显示。而UTF则不是那么顺利了。

  • 1
  • 2
  • 下一页

相关内容