蓝天白云

成功= 一个明确的职业目标+持续的行业积累+不断的知识补充。

Java 中的编码问题2

1、file 读取 编码

public static List<String> getLines(String fileName){     
        List<String> lines=new ArrayList<String>();     
        try {     
            BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream(fileName),"UTF-8"));     
            String line = null;     
            while ((line = br.readLine()) != null) {     
               lines.add(line);     
           }     
          br.close();     
       } catch (FileNotFoundException e) {     
       }catch (IOException e) {}     
       return lines;     
 }   

注意:这个UTF-8是 你想要以什么编码方式 来读取这个文件,也就是解码的方式。


2、读取ANSI 乱码问题

	private static String forTest(String file) throws IOException {
		File f = new File(file);
		InputStreamReader read = new InputStreamReader(new FileInputStream(f),
				"GBK");
		BufferedReader reader = new BufferedReader(read);
		String line;
		String s = "";
		while ((line = reader.readLine()) != null) {
			s = s+line;
		}
		return s;
	}



3、JavaUnicode

原文:http://blog.csdn.net/wangshfa/article/details/8562304  



Javaclass文件采用utf8的编码方式,JVM运行时采用utf16Java的字符串是unicode编码的。总之,Java采用了unicode字符集,使之易于国际化。

 

Java支持哪些字符集:

Java能识别哪些字符集并对它进行正确地处理?查看Charset 类,最新的JDK支持160种字符集。可以通过static方法availableCharsets拿到所有Java支持的字符集。

assertEquals(160, Charset.availableCharsets().size());  

 

Set<String> charsetNames = Charset.availableCharsets().keySet();  

 

assertTrue(charsetNames.contains("utf-8"));  

assertTrue(charsetNames.contains("utf-16"));  

assertTrue(charsetNames.contains("gb2312"));  

 

assertTrue(Charset.isSupported("utf-8"));

 

需要在哪些时候注意编码问题?

1.         从外部资源读取数据:

这跟外部资源采取的编码方式有关,我们需要使用外部资源采用的字符集来读取外部数据:

InputStream is = new FileInputStream("res/input2.data");  

InputStreamReader streamReader = new InputStreamReader(is, "GB18030");

这里可以看到,我们采用了GB18030编码读取外部数据,通过查看streamReaderencoding可以印证:

assertEquals("GB18030", streamReader.getEncoding());

正是由于上面我们为外部资源指定了正确的编码,当它转成char数组时才能正确地进行解码(GB18030 -> unicode):

char[] chars = new char[is.available()];  

streamReader.read(chars, 0, is.available());

但我们经常写的代码就像下面这样:

InputStream is = new FileInputStream("res/input2.data");  

InputStreamReader streamReader = new InputStreamReader(is);

这时候InputStreamReader采用什么编码方式读取外部资源呢?Unicode?不是,这时候采用的编码方式是JVM的默认字符集,这个默认字符集在虚拟机启动时决定,通常根据语言环境和底层操作系统的 charset来确定。可以通过以下方式得到JVM的默认字符集:

Charset.defaultCharset(); 

为什么要这样?因为我们从外部资源读取数据,而外部资源的编码方式通常跟操作系统所使用的字符集一样,所以采用这种默认方式是可以理解的。

好吧,那么我通过我的IDE Ideas创建了一个文件,并以JVM默认的编码方式从这个文件读取数据,但读出来的数据竟然是乱码。为何?呵呵,其实是因为通过Ideas创建的文件是以utf-8编码的。要得到一个JVM默认编码的文件,通过手工创建一个txt文件试试吧。

2.         字符串和字节数组的相互转换

我们通常通过以下代码把字符串转换成字节数组:

"string".getBytes();

但你是否注意过这个转换采用的编码呢?其实上面这句代码跟下面这句是等价的:

"string".getBytes(Charset.defaultCharset());

也就是说它根据JVM的默认编码(而不是你可能以为的unicode)把字符串转换成一个字节数组。

反之,如何从字节数组创建一个字符串呢?

new String("string".getBytes());

同样,这个方法使用平台的默认字符集解码字节的指定数组(这里的解码指从一种字符集到unicode)。

 

字符串编码迷思:

new String(input.getBytes("ISO-8859-1"), "GB18030")

上面这段代码代表什么?有人会说: “把input字符串从ISO-8859-1编码方式转换成GB18030编码方式”。如果这种说法正确,那么又如何解释我们刚提到的java字符串都采用unicode编码呢?

这种说法不仅是欠妥的,而且是大错特错的,让我们一一来分析,其实事实是这样的:我们本应该用GB18030的编码来读取数据并解码成字符串,但结果却采用了ISO-8859-1的编码,导致生成一个错误的字符串。要恢复,就要先把字符串恢复成原始字节数组,然后通过正确的编码GB18030再次解码成字符串(即把以GB18030编码的数据转成unicode的字符串)。注意,字符串永远都是unicode编码的。

但编码转换并不是负负得正那么简单,这里我们之所以可以正确地转换回来,是因为 ISO8859-1 是单字节编码,所以每个字节被按照原样 转换为 String ,也就是说,虽然这是一个错误的转换,但编码没有改变,所以我们仍然有机会把编码转换回来! 

 

总结:

所以,我们在处理java的编码问题时,要分清楚三个概念:Java采用的编码:unicodeJVM平台默认字符集和外部资源的编码。




阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。http://blog.csdn.net/lan861698789 https://blog.csdn.net/lan861698789/article/details/17153269
个人分类: Java
上一篇Java 中的中文编码问题
下一篇【闲话程序员生涯】哪些人有可能遇到职业瓶颈
想对作者说点什么? 我来说一句

深入分析 Java 中的中文编码问题

2014年06月22日 689KB 下载

web编码问题小结.doc

2012年01月14日 35KB 下载

Java中文乱码

2014年08月27日 298KB 下载

JAVA中文字符编码问题详解.doc

2010年09月16日 142KB 下载

java编码问题详解

2012年06月20日 44KB 下载

Java 中的中文编码问题

2012年07月09日 836KB 下载

java字符编码问题

2008年04月18日 3KB 下载

Java中文编码问题小结

2008年08月21日 281KB 下载

没有更多推荐了,返回首页

关闭
关闭