欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException :1字节的 UTF-8 序列的字节 1 无效

程序员文章站 2022-07-14 19:21:10
...

最近做Ftp文件操作,发现读取ftp的xml文件时,把读取到的流放到工具类转成document就会报错,报错信息如标题所示。

报错原因分析:

我为了复现读取ftp服务器上的xml文件流异常原因,就把ftp上的文件先拿到本地,用工具类读取对应的流,报错信息和直接读取ftp的流一样。然后我把拿过来的文件另存为UTF-8的编码方式,在用工具类读取就不出现异常。说明问题确实 是xml文件的编码方式问题导致的。

com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException :1字节的 UTF-8 序列的字节 1 无效

我们正常新建一个文本文档,保存默认的编码方式是ANSI,而ANSI在Windows系统的编码处理中,ANSI编码一般代表系统默认编码方式,而且并不是确定的某一种编码方式——在简体中文操作系统中ANSI编码默认指的是GB系列编码(GB2312、GBK、GB18030);在繁体中文操作系统中ANSI编码默认指的是BIG5;在日文操作系统中ANSI编码默认指的是Shift JIS,等等。可在系统区域设置的系统Locale中更改。
这也是为什么选择UTF-8编码则不会异常,选择ANSI会异常的原因,就是因为UTF-8指定死了编码方式,在任何local环境中都不会变,相当于没有设置编码方式,ANSI会随着local而编码方式发生改变。由于windows简体中文的编码格式为GBK,所以读进来inputstream的编码就是gbk!,但是我们XML工具读取流转成String或者Document时,看源码你会看到这样一句话:

/**
*the encoding must be a string acceptable for an XML encoding declaration (see section 4.3.3 of the XML 1.0 recommendation)
*译文:编码必须是XML编码声明可以接受的字符串(参见XML 1.0推荐的第4.3.3节)
**/
public void setEncoding(String encoding){
    this.encoding=encoding
}

当我们用工具类:XMLUtils.parse(inputStream)时,由于读取的xml本身设置了编码方式为utf-8:<?xml version="1.0" encoding="utf-8">,所以会读取编码为utf-8的流时,而流默认编码是系统的gbk,就会异常。
分析完原因,下面看下如何解决吧~

解决办法:

1.如果能通过直接修改xml文件本身的编码方式,就保存为utf-8形式。就可以了。
2.如果第一种方式行不通。就可以先通过把InputStream转成编码方式为gbk的InputStreamReader,然后工具类读取这个reader就可以。

具体部分代码截取示例:

a.开始读取流有问题的代码

in=ftpClient.retrieveFileStream(directory);
document=XMLUtils.parse(in);

异常报错:
com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException :1字节的 UTF-8 序列的字节 1 无效。

b.修改后能正常转成documen的代码

in=ftpClient.retrieveFileStream(directory);
InputStreamReader reader=new InputStreamReader(in,Charset.forName("GBK"));
document=XMLUtils.parse(reader);

参考博文:刨根究底字符编码之七——ANSI编码与代码页(Code Page)