`

java编码解析

    博客分类:
  • java
 
阅读更多
java编码解析(转)

Java的class文件采用utf8的编码方式,JVM运行时采用utf16。

Java的字符串是unicode编码的。

总之,Java采用了unicode字符集,使之易于国际化。


Java支持哪些字符集:



即Java能识别哪些字符集并对它进行正确地处理?



查看Charset 类,最新的JDK支持160种字符集。可以通过static方法availableCharsets拿到所有Java支持的字符集。



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"));  
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. 从外部资源读取数据:



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



Java代码 
InputStream is = new FileInputStream("res/input2.data");   
InputStreamReader streamReader = new InputStreamReader(is, "GB18030");  
InputStream is = new FileInputStream("res/input2.data"); InputStreamReader streamReader = new InputStreamReader(is, "GB18030");


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



Java代码 
assertEquals("GB18030", streamReader.getEncoding());  
assertEquals("GB18030", streamReader.getEncoding());


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



Java代码 
char[] chars = new char[is.available()];   
streamReader.read(chars, 0, is.available());  
char[] chars = new char[is.available()]; streamReader.read(chars, 0, is.available());
 
但我们经常写的代码就像下面这样:



Java代码 
InputStream is = new FileInputStream("res/input2.data");   
InputStreamReader streamReader = new InputStreamReader(is);  
InputStream is = new FileInputStream("res/input2.data"); InputStreamReader streamReader = new InputStreamReader(is);


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



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



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



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



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



Java代码 
"string".getBytes();  
"string".getBytes();


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



Java代码 
"string".getBytes(Charset.defaultCharset());  
"string".getBytes(Charset.defaultCharset());


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



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



Java代码 
new String("string".getBytes());  
new String("string".getBytes());


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





字符串编码迷思:



Java代码 
new String(input.getBytes("ISO-8859-1"), "GB18030")  
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采用的编码:unicode,JVM平台默认字符集和外部资源的编码。
分享到:
评论

相关推荐

    tlv的java编码和解码

    本文将详细讲解如何在Java环境中实现TLV的编码与解码,并结合提供的`ber-tlv`资源进行分析。 TLV结构简单明了,由三个部分组成: 1. **Tag**:标识数据的类型或者含义,通常是一个整数。 2. **Length**:表示Value...

    java 解析ASN.1 编码格式cdr话单文件例子

    本话题主要关注如何使用Java解析ASN.1编码格式的CDR(Call Detail Record)话单文件。 CDR是通信系统中记录通话、短信等通信活动详细信息的数据文件,包含诸如呼叫时间、时长、主叫号码、被叫号码、通话状态等多种...

    java对mht文件解析

    本文详细介绍了使用Java解析MHT文件的基本原理和技术实现,包括如何提取HTML内容、解码Quoted-Printable编码、构建DOM树以及提取所需数据。这对于需要处理MHT文件的应用开发具有很高的参考价值。

    Java读取解析GRIB2文件

    下面将详细介绍如何使用Java进行GRIB2文件的读取和解析。 1. **理解GRIB2文件结构**: GRIB2文件由多个消息组成,每个消息包含一组相关的气象数据。消息由一个固定长度的头部(Header)和可变长度的数据部分(Data...

    java字符编码解析.zip

    Java字符编码解析是一个重要的主题,尤其对于移动开发,如Android平台,因为良好的字符处理能力是构建国际化应用的基础。本文将深入探讨Java中的字符编码概念、常见的编码格式、以及如何在Java程序中正确处理字符...

    java解析dbf文件方案.pdf

    Java 解析 DBF 文件方案 Java 解析 DBF 文件方案是使用 Java 语言来读取和解析 DBF 文件的方法。DBF 文件是一种常见的数据库文件格式,广泛应用于许多行业。为了读取和解析 DBF 文件,需要使用 Java 语言中的数据库...

    使用OSS_tool解析OER编码

    本主题聚焦于“使用OSS_tool解析OER编码”,这涉及到ASN.1(Abstract Syntax Notation One)编码规范、JNI(Java Native Interface)以及如何通过这些技术实现跨平台的数据处理。 首先,ASN.1是一种国际标准,它...

    java 音频解析 代码

    每种格式都有其特定的编码方式和数据存储结构,因此解析这些文件需要对应的理解和处理方法。 Java平台提供了Java Media Framework (JMF) 和Java Sound API来处理音频文件。JMF是一个可扩展的媒体处理框架,用于播放...

    JavaTxt解析文本代码或输出指定编码文本

    `JavaTxt解析文本代码或输出指定编码文本`这个主题聚焦于如何使用Java有效地识别和处理不同编码类型的TXT文件。这个工具类,如`TxtEncodingDetect.java`所示,提供了一种方法来检测和解析文本文件的编码格式,比如...

    java 解析 chm 文件

    Java解析CHM文件是将Microsoft的 Compiled HTML Help (CHM) 文件转换成HTML网页的过程。CHM文件是一种常见的帮助文档格式,它包含了多个HTML页面、图像和其他资源,并使用了一种特殊的压缩方法存储。在Java中处理CHM...

    java 解析 tar gz文件 两种方法

    在Java中解析这种类型的文件,通常需要两个步骤:首先解压gzip,然后解包tar。这里我们将详细探讨两种不同的方法来实现这个过程。 方法一:使用Apache Commons Compress库 Apache Commons Compress库是Java社区...

    读取创建CSV文件并自动解析文件编码方式

    本文将深入探讨如何读取和创建CSV文件,并特别关注自动解析文件编码方式这一关键环节。我们将使用Java语言进行示例,同时引入第三方库来辅助处理编码问题。 首先,创建CSV文件的基本过程涉及将数据写入具有特定分隔...

    用java解析DXF文件中的实体信息

    在本主题中,我们关注的是如何利用Java解析DXF(Drawing Exchange Format)文件,这是一种由AutoCAD软件生成的二进制或ASCII格式的文件,用于存储二维图形数据。DXF文件通常包含各种几何实体,如圆(circle)、椭圆...

    Java解析FTP服务器文本文件

    Java解析FTP服务器文本文件 Java解析FTP服务器文本文件是指使用Java语言连接FTP服务器,上传、下载、递归目录遍历等基本操作的集合。在这个过程中,我们需要引入相关的jar包,例如cpdetector.jar、jchardet-1.0.jar...

    java解析ASN.1文件的实例和简要使用说明

    Java解析ASN.1文件主要涉及的是对ASN.1(Abstract Syntax Notation One)编码规则的理解和使用,这是一种在通信协议、数据存储等领域广泛使用的标准化表示法。ASN.1定义了一种高级的数据表示语言,用于描述数据结构...

    java读取解析DXF文件信息.rar

    java解析DXF文件信息,这里涉及到各种转换字符串编码的操作,解决了解析过程中遇到中文的乱码问题,包括circle,ellipse,line,lwpolyline等,还涉及到从DXF文件中读取一个字符串、判断CIRCLE实体、判断ellipse实体、...

    java解析txt

    //考虑到编码格式 BufferedReader bufferedReader = new BufferedReader(read); String lineTxt = null; while((lineTxt = bufferedReader.readLine()) != null){ System.out.println(lineTxt); } read....

    环保212协议解析java

    2. **XML解析**:Java中可以使用DOM、SAX或StAX API来解析XML文档。DOM一次性加载整个文档,适合小型文件;SAX是事件驱动的,按需读取,适合大文件;StAX允许程序逐个读取事件,提供了更细粒度的控制。 3. **字节流...

    编码解析工具类

    编码解析工具类

    Java 解析国标hj212协议

    在Java开发环境中,解析这种协议通常涉及到网络通信、数据编码与解码、XML或JSON处理等多个技术领域。下面将详细探讨相关知识点。 1. **hj212协议**:全称为《污染源在线自动监控(监测)系统数据传输标准》,是...

Global site tag (gtag.js) - Google Analytics