`
pengfeng
  • 浏览: 231735 次
  • 性别: Icon_minigender_1
  • 来自: 河南
社区版块
存档分类
最新评论

OutputStreamWriter类getEncoding方法的应用

阅读更多

      今天在写打包程序时,发现了一个及其奇怪的问题,就是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:

 

// we may still be able to figure out the encoding:
            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:

// we may still be able to figure out the encoding:
            if (enc == null) {
                if (w instanceof OutputStreamWriter) {
                    enc = Charset.forName(((OutputStreamWriter) w).getEncoding()).name();
                }
            }

Tatu Saloranta added a comment - 18/Mar/08 02:09 PM
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).

 

Tatu Saloranta added a comment - 26/Mar/08 12:57 PM
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和OutputStreamWriter源码分析_动力节点Java学院整理

    Java中的InputStreamReader和...InputStreamReader和OutputStreamWriter是Java中用于将字节流和字符流进行转换的类,它们都是Reader和Writer的子类,提供了多种构造方法和成员方法,可以满足不同的应用需求。

    Java中Writer类.pdf

    Writer 类提供了很多关于字符流输出操作的方法,包括: * write(int c):写入单个字符 * write(char[] cbuf):写入字符数组 * write(char[] cbuf, int off, int len):写入字符数组的一部分 * write(String str):...

    J2SE API应用程序接口使用文档

    Java 2 Standard Edition (J2SE) API 应用程序接口使用文档是Java开发者的重要参考资料,它包含了Java语言的核心库,这些库提供了大量的类和接口,用于构建各种类型的桌面应用程序、服务器端应用以及网络服务。...

    JAVA设计模式在JDK中的应用

    接下来我们将分别探讨这三类模式在JDK中的应用。 ### 结构型模式 结构型模式关注于如何组织类和对象的组合方式,以便形成更大的结构。以下是几种结构型模式在JDK中的应用: #### 1. 适配器模式(Adapter) 适配器...

    深入研究java.lang.Runtime类.doc

    从 JDK 1.1 开始,将 Unicode 字符流转换为本地编码字节流的首选方法是使用 OutputStreamWriter、BufferedWriter 和 PrintWriter 类。 14. getRuntime():返回与当前 Java 应用程序相关的运行时对象。 15. halt(int ...

    java编程基础,应用与实例

    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版本的更新,特别是Android 6.0(API级别23)引入的运行时权限管理,开发者还需要在运行时检查并请求存储...

    Java IO 工具类大全

    本篇文章将全面解析Java IO工具类,帮助你理解并掌握其在实际开发中的应用。 一、Java IO基础 Java IO体系主要由流(Stream)组成,分为字节流和字符流两大类,分别处理字节数据和字符数据。字节流包括InputStream...

    超级有影响力霸气的Java面试题大全文档

     声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,...

    java IO 类层次图

    通过对这些类的理解和应用,可以更加高效地完成数据的读写任务。无论是处理简单的文件读写,还是复杂的网络通信,Java IO都能提供相应的解决方案。希望本文能帮助您更好地理解和掌握Java IO系统的精髓。

    Android移动应用开发基础教程第5章.pptx

    Context 类的 openFileOutput() 方法用于打开一个内部存储文件,向文件写入数据,其基本格式如下: FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE); openFileOutput() 方法第一个参数为...

    2023年JavaSE知识点总结个人整理.docx

    final可以修饰类、方法和变量,被final修饰的类无法被继承,方法无法被重写,变量为常量只能赋值一次。finally是异常解决,和try、catch结合使用,可以添加也可以不添加,用于执行一些必须执行的代码,如释放资源等...

    开发常用工具类

    在Java开发过程中,工具类(Utility Class)是程序员经常使用的代码模块,它们提供了一系列静态方法,用于执行特定的辅助任务,提升代码复用性。"开发常用工具类"这个主题涵盖了各种不同领域的实用功能,例如字符串...

    JAVA经典教材笔记

    - InputStreamReader与OutputStreamWriter类。 - **内存操作流** - 内存操作流的特点:在内存中操作数据。 - ByteArrayOutputStream与ByteArrayInputStream类。 - **管道流** - 管道流的作用:连接两个线程的...

    Android应用源码SdCard读写文件实例

    使用`File`类的方法`createNewFile()`创建文件,`mkdir()`或`mkdirs()`创建目录,`delete()`删除文件或目录。 ```java File newFile = new File(sdCardRoot, "new_file.txt"); newFile.createNewFile(); // ...

    android笔记—socket应用定义.pdf

    最后,文档没有展示如何关闭Socket,但在实际应用中,当数据发送完毕或者需要断开连接时,应调用`Socket`的`close()`方法,以释放资源。这通常会在一个异常处理结构中或者在特定的用户操作(如点击关闭按钮)后执行...

    常用类--自己.docx

    【Java.lang 包】 在Java编程语言中,`java.lang`是最基础的包,它包含了所有Java程序都必需的一些核心类和接口。其中最基础的类是`...通过不断学习和实践,开发者可以熟练运用这些类和方法来构建复杂的应用程序。

    Android高级应用源码-Android应用源码安卓与PC的Socket通信项目java版.zip

    在Java中,Socket类和ServerSocket类是进行Socket通信的基础组件。ServerSocket用于监听客户端连接,而Socket用于建立客户端和服务器端的连接。 2. **Android中创建Socket**: 在Android应用中,要建立Socket连接...

Global site tag (gtag.js) - Google Analytics