java写入文件中文乱码问题_解决Java写入UTF-8文件中文乱码问题

a30484276864445cb334a8a1c8e72bec.png最近需要从Java中输出UTF-8编码的XML文件,遇到了两次中文乱码问题。一是奇数个汉字出现乱码,二是写入文件的实际编码与XML声明的编码不符。经过几番折腾,终于解决这两个问题,也对Java的字符编码加深了了解。

问题重现

以下面XML为例:

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

<test>一一一</test>

1

2

<?xmlversion="1.0"encoding="UTF-8"standalone="no"?>

<test>一一一</test>

生成XML代码如下:

Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

Element elem = doc.createElement("test");

elem.setTextContent("一一一");

doc.appendChild(elem);

DOMSource source = new DOMSource(doc);

ByteArrayOutputStream bytes = new ByteArrayOutputStream();

Transformer transformer = TransformerFactory.newInstance().newTransformer();

StreamResult result = new StreamResult(bytes);

Properties properties = transformer.getOutputProperties();

properties.setProperty(OutputKeys.INDENT, "yes");

properties.setProperty(OutputKeys.ENCODING, "UTF-8");

properties.setProperty("{http://xml.apache.org/xslt}indent-amount", "2");

transformer.setOutputProperties(properties);

transformer.transform(source, result);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

Documentdoc=DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

Elementelem=doc.createElement("test");

elem.setTextContent("一一一");

doc.appendChild(elem);

DOMSourcesource=newDOMSource(doc);

ByteArrayOutputStreambytes=newByteArrayOutputStream();

Transformertransformer=TransformerFactory.newInstance().newTransformer();

StreamResultresult=newStreamResult(bytes);

Propertiesproperties=transformer.getOutputProperties();

properties.setProperty(OutputKeys.INDENT,"yes");

properties.setProperty(OutputKeys.ENCODING,"UTF-8");

properties.setProperty("{http://xml.apache.org/xslt}indent-amount","2");

transformer.setOutputProperties(properties);

transformer.transform(source,result);

至此,XML已存储至bytes中。

接下来我想XML保存至文件,想当然地写了以下代码:

String xmlStr = bytes.toString();

FileWriter writer = new FileWriter("test.xml");

writer.write(xmlStr);

writer.close();

1

2

3

4

5

StringxmlStr=bytes.toString();

FileWriterwriter=newFileWriter("test.xml");

writer.write(xmlStr);

writer.close();

不料得到的XML文件中文部分出现乱码,且XML标签的一个字符'

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

<test>丿؀丿/test>

1

2

<?xmlversion="1.0"encoding="UTF-8"standalone="no"?>

<test>丿؀丿/test>

该问题只出现在中文字符为奇数个时,原因见参考链接1。

经过一番修改,写出如下代码:

String xmlStr = bytes.toString("UTF-8");

FileWriter writer = new FileWriter("test.xml");

writer.write(xmlStr);

writer.close();

1

2

3

4

5

StringxmlStr=bytes.toString("UTF-8");

FileWriterwriter=newFileWriter("test.xml");

writer.write(xmlStr);

writer.close();

得到另一种乱码:

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

<test>һһһ</test>

1

2

<?xmlversion="1.0"encoding="UTF-8"standalone="no"?>

<test>һһһ</test>

经观察,该文件实际为GB编码,因Notepad++根据XML的encoding属性自动识别并显示为UTF-8造成乱码,将该文件以GB编码显示正常。

搜索得到原因,Java的FileWriter以平台默认编码写入文件。于是修改代码如下:

String xmlStr = bytes.toString("UTF-8");

FileOutputStream fos = new FileOutputStream("test.xml");

OutputStreamWriter writer = new OutputStreamWriter(fos, "UTF-8");

writer.write(xmlStr);

writer.close();

1

2

3

4

5

StringxmlStr=bytes.toString("UTF-8");

FileOutputStreamfos=newFileOutputStream("test.xml");

OutputStreamWriterwriter=newOutputStreamWriter(fos,"UTF-8");

writer.write(xmlStr);

writer.close();

String xmlStr = bytes.toString("UTF-8");

FileOutputStream fos = new FileOutputStream("test.xml");

fos.write(bytes.toByteArray());

fos.close();

1

2

3

4

5

StringxmlStr=bytes.toString("UTF-8");

FileOutputStreamfos=newFileOutputStream("test.xml");

fos.write(bytes.toByteArray());

fos.close();

至此得到无乱码的XML文件。

问题分析

Transformer得到的bytes为UTF-8的二进制数据,若使用toString()会使用系统默认编码对此数据进行编码并转为字符串(Unicode存储),造成奇数个汉字乱码问题。使用toString(“UTF-8”)指定编码格式即可解决此问题。

使用FileWriter将字符串写入文件时仍会将字符串(Unicode存储)转换为系统默认编码写入文件,这就造成文件实际编码格式与XML中声明的编码格式不同。使用OutputStreamWriter指定编码格式,或者将UTF-8的二进制数据用FileOutputStream直接写入文件,即可解决此问题。

参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值