今天在写打包程序时,发现了一个及其奇怪的问题,就是OutputStreamWriter.getEncoding()的应用,在官方文
档上解释是这样说的:
返回此流使用的字符编码的名称。
如果此编码具有历史名称,则返回该名称;否则返回该编码的规范化名称。
如果此实例是用 OutputStreamWriter(OutputStream, String)
构造方法创建的,则返回的由此编码生成的
惟一名称可能与传递给该构造方法的名称不一样。如果流已经关闭,则此方法可能返回 null。
(注意红色标记的关键字,就是问题的关键)
在这里给大家推荐一个高效生成XML的开源项目WAX
(http://www.ociweb.com/mark/programming/WAX.html),生成5000条数据100M左右的XML文件只需要20秒左右
的时间(个人感觉这个效率还是很强的),正是在使用该项目的过程中发现问题。问题描述如下:
//在WAX.java源文件中有如下一段代码
if (writer instanceof OutputStreamWriter) {
encoding = ((OutputStreamWriter) writer).getEncoding();
}
而我在构造OutputStreamWriter对象时采用的是 OutputStreamWriter(OutputStream, String)
构造方法,传
递的字符编码是“UTF-8”,但是,通过OutputStreamWriter.getEncoding()返回的却是“UTF8”,这样,通过WAX
生成XML文件的XML declaration部分的encoding就变成了UTF8,导致生成的XML文件其它解析器无法解析。将
上面的一段源码进行修改如下:
if (writer instanceof OutputStreamWriter) {
//encoding = ((OutputStreamWriter) writer).getEncoding();
//pengfeng modify
encoding = Charset.forName(((OutputStreamWriter) writer).getEncoding()).name();
}
OK,一切问题解决!
呵呵,上面只说了问题的解决办法,该办法主要来源于http://jira.codehaus.org/browse/WSTX-146,引用如下:
The code in the attached unit test incorrectly creates a document with an encoding in the XML
declaration of 'UTF8'. According to section 4.3.3 of the XML 1.0 spec, all XML parsers must support
encoding 'UTF-8', but not 'UTF8'. So many parsers including Xerces, won't parse that document.
The problem appears to be caused by the following code in WstxOutputFactory:
if (enc == null) {
if (w instanceof OutputStreamWriter) {
enc = ((OutputStreamWriter) w).getEncoding();
}
}
According to the Javadoc for OutputStreamWriter.getEncoding(), "If the encoding has an historical
name then that name is returned; otherwise the encoding's canonical name is returned." The historical
name for UTF-8 is UTF8.
I believe the correct code would be:
if (enc == null) {
if (w instanceof OutputStreamWriter) {
enc = Charset.forName(((OutputStreamWriter) w).getEncoding()).name();
}
}
Thanks! This does indeeed look like sub-optimal behavior. As a work-around, applications shouldn't
rely on auto-detection of the encoding, but I definitely want to improve this auto-detection as well.
One minor note: since Charset class was introduced in JDK 1.4, the fix as suggested can only be added
to Woodstox 4.0. For 3.2, if the fix is to be backported I could just add specific work-around for UTF-8,
since that is likely to be the most common case (additionally if others are identified they can be added
of course).
I will fix this shortly for trunk (4.0).
Easy to fix, will call Charset.normalize() for the value (which already knows many legacy conversions).
I think I'll also backport it to 3.2.x, since there's no API change and this should be a safe fix.
分享到:
相关推荐
Java中的InputStreamReader和...InputStreamReader和OutputStreamWriter是Java中用于将字节流和字符流进行转换的类,它们都是Reader和Writer的子类,提供了多种构造方法和成员方法,可以满足不同的应用需求。
Writer 类提供了很多关于字符流输出操作的方法,包括: * write(int c):写入单个字符 * write(char[] cbuf):写入字符数组 * write(char[] cbuf, int off, int len):写入字符数组的一部分 * write(String str):...
Java 2 Standard Edition (J2SE) API 应用程序接口使用文档是Java开发者的重要参考资料,它包含了Java语言的核心库,这些库提供了大量的类和接口,用于构建各种类型的桌面应用程序、服务器端应用以及网络服务。...
接下来我们将分别探讨这三类模式在JDK中的应用。 ### 结构型模式 结构型模式关注于如何组织类和对象的组合方式,以便形成更大的结构。以下是几种结构型模式在JDK中的应用: #### 1. 适配器模式(Adapter) 适配器...
从 JDK 1.1 开始,将 Unicode 字符流转换为本地编码字节流的首选方法是使用 OutputStreamWriter、BufferedWriter 和 PrintWriter 类。 14. getRuntime():返回与当前 Java 应用程序相关的运行时对象。 15. halt(int ...
13.4.1 InputStreamReader、OutputStreamWriter 191 13.4.2 BufferedReader与BufferedWriter 191 13.4.3 FileReader与FileWriter 193 13.4.4 从System.in获取数据 193 13.4.5 PrintStream与PrintWriter ...
以上这些方法构成了一个基本的文件管理工具类,可以方便地在Android应用中进行文件操作。然而,随着Android版本的更新,特别是Android 6.0(API级别23)引入的运行时权限管理,开发者还需要在运行时检查并请求存储...
本篇文章将全面解析Java IO工具类,帮助你理解并掌握其在实际开发中的应用。 一、Java IO基础 Java IO体系主要由流(Stream)组成,分为字节流和字符流两大类,分别处理字节数据和字符数据。字节流包括InputStream...
声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,...
通过对这些类的理解和应用,可以更加高效地完成数据的读写任务。无论是处理简单的文件读写,还是复杂的网络通信,Java IO都能提供相应的解决方案。希望本文能帮助您更好地理解和掌握Java IO系统的精髓。
Context 类的 openFileOutput() 方法用于打开一个内部存储文件,向文件写入数据,其基本格式如下: FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); openFileOutput() 方法第一个参数为...
final可以修饰类、方法和变量,被final修饰的类无法被继承,方法无法被重写,变量为常量只能赋值一次。finally是异常解决,和try、catch结合使用,可以添加也可以不添加,用于执行一些必须执行的代码,如释放资源等...
在Java开发过程中,工具类(Utility Class)是程序员经常使用的代码模块,它们提供了一系列静态方法,用于执行特定的辅助任务,提升代码复用性。"开发常用工具类"这个主题涵盖了各种不同领域的实用功能,例如字符串...
- InputStreamReader与OutputStreamWriter类。 - **内存操作流** - 内存操作流的特点:在内存中操作数据。 - ByteArrayOutputStream与ByteArrayInputStream类。 - **管道流** - 管道流的作用:连接两个线程的...
使用`File`类的方法`createNewFile()`创建文件,`mkdir()`或`mkdirs()`创建目录,`delete()`删除文件或目录。 ```java File newFile = new File(sdCardRoot, "new_file.txt"); newFile.createNewFile(); // ...
最后,文档没有展示如何关闭Socket,但在实际应用中,当数据发送完毕或者需要断开连接时,应调用`Socket`的`close()`方法,以释放资源。这通常会在一个异常处理结构中或者在特定的用户操作(如点击关闭按钮)后执行...
【Java.lang 包】 在Java编程语言中,`java.lang`是最基础的包,它包含了所有Java程序都必需的一些核心类和接口。其中最基础的类是`...通过不断学习和实践,开发者可以熟练运用这些类和方法来构建复杂的应用程序。
在Java中,Socket类和ServerSocket类是进行Socket通信的基础组件。ServerSocket用于监听客户端连接,而Socket用于建立客户端和服务器端的连接。 2. **Android中创建Socket**: 在Android应用中,要建立Socket连接...