[Java]关于中文编码问题

1.把一种文字按照某种码表转换成二进制比特序列的过程叫做编码,把一堆二进制比特码按照某种码表转换成某种文字叫做解码。举中文为例:用一种码表编码的文字,需要用同一种码表进行解码,才能得到同样的文字,如果把这一堆二进制比特按另一种码表来解,就会出现乱码。

2.字符流和字节流:无论什么文字,存储的文件都是比特序列。只有在高级语言文本级别上的字符串才是文字。字符流底层都是用字节流进行文件读写,但不同的是它在高级语言文本层面还要按照某种默认码表进行编码和解码。举中文为例,FileReader默认以UTF-8解码二进制比特,FileWriter默认以UTF-8编码中文字符。如果要自定义码表,就要用到转换流。转换流接受字节流对象为参数,InputStreamReader将原始字节流按照指定码表进行解码读出,OutputStreamWriter将文字按照指定码表编码写入原始字节流。

3.所谓编码解码,都不过是利用码表对底层字节流的一种高级语言层面的解析,底层都是以字节的方式存储。编码和解码的码表一致才能不乱码--抓住这一点,就明白了码表原理,也就会用各种流来操作文本数据了。

4.各种编辑器查看器软件也像我们写的程序一样,默认或按照我们的指定来存储或显示文件。如果一个中文文件本身以UTF-8的码表进行的编码,如果查看器以gb2312解码成文字,同样会出现乱码,这时就要更改查看时码表。软件和我们写程序一样,编码和解码文字要用相同的码表。

5.关于html,xml码表声明(指定浏览器解析),数据库字符集指定(指定数据库软件解析):待查。

xml声明:(html也一样)让外界根据指定码表读取和写入,所以一般来说xml声明和这个中文文件实际编码码表应该保持一致,否则用程序读写或软件存储、打开也会出现乱码,因为程序或软件是按照xml声明指定形式来读写解析文件的。这也是Eclipse默认让xml码表声明和文件存储编码保持一致的原因。

6.关于Eclipse编程软件:程序会默认根据xml码表声明更改文件存储编码:待查。

7.举例验证:(注:这里dom4j的OutputFormat方式指定码表是将内存中的Document对象按指定码表编码输出,涉及中文时建议直接用这种方式一步到位,避免各种繁琐难解的乱码问题!)

xml文件:存储编码和xml声明编码默认一致

<?xml version="1.0" encoding="utf8"?>

<书架> 
  <书> 
    <书名 name="中科大">javaweb开发</书名>  
    <作者>张孝祥</作者>  
    <售价>99.00元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>
  </书>  
  <书> 
    <书名>JavaScript网页开发</书名>  
    <作者>黎活明</作者>  
    <售价>28.00元</售价> 
  </书>  
  <页面作者 个人爱好="上网" 网站职务="页面作者" 联系信息="aaaa"/>  
  <!--实际三个属性,还有一个固定属性和一个默认属性--> 
</书架>

添加节点的一个方法:

@Test
	public void add() throws Exception {
		SAXReader reader = new SAXReader();// 按照xml声明(也是按文件存储编码格式,默认二者一致)解码文件字节,解码出正确文字
		Document document = reader.read(new File("src/book.xml"));

		Element book = document.getRootElement().element("书");// 第一本书,直接用element
		book.addElement("售价").setText("209元");

	
		OutputFormat format = OutputFormat.createPrettyPrint();
		// 这里可以随意指定!!!检验过了,因为是将整个正确的中文字符串重新编码写入!!(完全重写覆盖文件内容)!而文件打开那边Eclipes默认以同样的编码读出显示!!!
		format.setEncoding("gb2312");

		
		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),
				format);// 字符转字节存入文件,按format查指定码表,底层都是调用字节流
		writer.write(document);
		writer.close();
	}// 弄清什么叫编码,什么叫解码!

执行后xml文件的变化:注意xml声明处被自动修改成gb2312,并且没有乱码(因为是按gb2312整体重新存储)

<?xml version="1.0" encoding="gb2312"?>

<书架> 
  <书> 
    <书名 name="中科大">javaweb开发</书名>  
    <作者>张孝祥</作者>  
    <售价>99.00元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>
  </书>  
  <书> 
    <书名>JavaScript网页开发</书名>  
    <作者>黎活明</作者>  
    <售价>28.00元</售价> 
  </书>  
  <页面作者 个人爱好="上网" 网站职务="页面作者" 联系信息="aaaa"/>  
  <!--实际三个属性,还有一个固定属性和一个默认属性--> 
</书架>

把程序的格式化输出器改成用UTF-8写入:

@Test
	public void add() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));
		Element book = document.getRootElement().element("书");
		book.addElement("售价").setText("209元");

		
		OutputFormat format = OutputFormat.createPrettyPrint();
		
		format.setEncoding("UTF-8");//----------------------------------------->注意这里改了!而此时的xml文件是gb2312编码格式

		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),
				format);
		writer.write(document);
		writer.close();
	}

程序执行后的xml文件:注意编码声明再次变为UTF-8!是程序改的不是我改的!(注意第一本书售价多了一行)

<?xml version="1.0" encoding="UTF-8"?>

<书架> 
  <书> 
    <书名 name="中科大">javaweb开发</书名>  
    <作者>张孝祥</作者>  
    <售价>99.00元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>
  </书>  
  <书> 
    <书名>JavaScript网页开发</书名>  
    <作者>黎活明</作者>  
    <售价>28.00元</售价> 
  </书>  
  <页面作者 个人爱好="上网" 网站职务="页面作者" 联系信息="aaaa"/>  
  <!--实际三个属性,还有一个固定属性和一个默认属性--> 
</书架>

为了再次验证,操作这个修改后的xml文件,再次更改程序为按gb2312写入:

@Test
	public void add() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));
		Element book = document.getRootElement().element("书");
		book.addElement("售价").setText("209元");

		
		OutputFormat format = OutputFormat.createPrettyPrint();
		
		format.setEncoding("gb2312");//----------------------------------------->注意这次改成了gb2312!而此时的xml文件是UTF-8编码格式

		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),
				format);
		writer.write(document);
		writer.close();
	}
再次执行后的xml文件:注意编码声明的变化,注意下面的售价又多了一行

<?xml version="1.0" encoding="gb2312"?>

<书架> 
  <书> 
    <书名 name="中科大">javaweb开发</书名>  
    <作者>张孝祥</作者>  
    <售价>99.00元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>  
    <售价>209元</售价>
  </书>  
  <书> 
    <书名>JavaScript网页开发</书名>  
    <作者>黎活明</作者>  
    <售价>28.00元</售价> 
  </书>  
  <页面作者 个人爱好="上网" 网站职务="页面作者" 联系信息="aaaa"/>  
  <!--实际三个属性,还有一个固定属性和一个默认属性--> 
</书架>


即使是我自己手动改文件编码(默认把声明和存储编码都改成另一种码表,Eclipse自动支持这种转换形式),程序指定一种格式化输出器后,也能按照其指定的码表正确修改文件,亲自验证过!


展开阅读全文

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