Java中String字符编码(CharSet)转换的相关问题
有用的资料
最近在字符编码上遇到一些问题,查阅了很多资料,有了一点领悟。以下是几个比较重要的资料:
《彻底搞懂字符编码》:
《深入分析 Java 中的中文编码问题》:
看了以上两篇文章,基本就能搞懂字符编码问题了。
下面是关于Java的字符编码问题的一个帖子,解释了Java的String中的字符存储问题:
个人小结:
在任何平台上,String中的char[]都是UTF-16类型的数组。String的所有操作都是在这个char[]上完成的。
Java的String是一个中间结果,可以通过getBytes(charset)函数得到指定编码的byte[]。
String.getBytes(charset)实际上是将UTF-16数组按照对应的charset编码为byte[]。网络程序中,将byte[]传输到其他平台,其他平台再用new String(byte[], charset)将byte[]转化为该平台本地的UTF-16字符串。
网上有一种转化字符串编码的方法:
String newString=new String(oldString.getBytes(oldCharSet),newCharSet),这种方式实际上没有任何意义,。下面简单解释一下。
以上转换的初衷通常是想在控制台(或文件)输出字符串。乱码是由于控制台(或文件)通常是GBK或UTF-8的,而String的char[]是UTF-16类型的。这时就需要使用 String.getBytes("GBK") 或者 String.getBytes("UTF-8") 得到byte[],然后使用 OutputStream.write(byte[]) 即可得到正确的输出。
另外,UTF-8通常比较省空间,一般通过String.getBytes("UTF-8")得到byte[],再进行网络传输。
示例程序
下面的程序简单的展示了这个过程:
import java.io.*; public class TestCharSetConvert { /*程序功能: * 从文件中读入数据,以其他编码输出到其他文件中 */ public static void main(String[] args){ //首先在程序目录下创建一个GBK编码的名为GBK.txt,里面可以包含任何汉字和英文等 String inCharsetName="GBK"; String[] outCharsetNames=new String[]{"GBK","GB2312","Unicode","UTF-8","UTF-16"}; String content=readStringByStream(inCharsetName+".txt",inCharsetName); for(String outCharsetName: outCharsetNames){ writeStringByStream(content,outCharsetName+".txt",outCharsetName); } } public static String readStringByStream(String inFilePath, String inCharsetName){ try { FileInputStream fin=new FileInputStream(inFilePath); byte[] bytes=new byte[1024]; int count=fin.read(bytes); String content=new String(bytes,0,count,inCharsetName);//解码为UTF-16字符串,inCharsetName必须与文件的字符编码一致,否则会失败或产生乱码 System.out.format("read %s from %s with charset %s ",content,inFilePath,inCharsetName); fin.close(); return content; } catch (Exception e) { e.printStackTrace(); } return ""; } public static void writeStringByStream(String content, String outFilePath, String outCharsetName){ try { FileOutputStream fout=new FileOutputStream(outFilePath); byte[] bytes=content.getBytes(outCharsetName);//将UTF-16字符串编码为指定字符集的字节流 fout.write(bytes); fout.close(); System.out.format("wrote %s to %s with charset %s ",content,outFilePath,outCharsetName); } catch (Exception e) { e.printStackTrace(); } } }
以上程序使用了InputStream和OutputStream以字节流的方式输入输出。实际上Java的Reader和Writer已经封装了这个过程,可以使用它们进行面向字符和字符串的操作。