【问题标题】:Want to throw exception when encounter special UTF-8 characters in an XML file在 XML 文件中遇到特殊的 UTF-8 字符时想要抛出异常
【发布时间】:2014-09-19 13:45:54
【问题描述】:

我正在解析一个具有 UTF-8 编码的 XML 文件。

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

现在我们的业务应用程序有一组由不同团队开发的组件,并且没有使用相同的库来解析 XML。我的组件使用 JAXB,而其他一些组件使用 SAX 等等。现在,当 XML 文件具有特殊字符,如“ä”或“ë”或“é”(带有变音符号的字符)时,JAXB 会正确解析它,但其他组件(子应用程序)无法正确解析它们并引发异常。

由于业务需要,我无法更改其他组件的编程,但我必须对我的应用程序进行限制/验证,以确保 XML(数据加载)文件不包含任何此类字符。

什么是确保文件不包含上述(或类似)字符的最佳方法,并且我可以在开始使用 JAXB 解析 XML 文件之前在那里抛出异常(或给出错误)。

【问题讨论】:

  • 听起来和你的问题一样简单 - 检查文件,如果它包含无效字符......如果你不能依赖标题信息,那么你必须自己对文件进行编码,看看它是否崩溃...您可以使用某种编码读取文件,请参阅stackoverflow.com/questions/3043710/…
  • 您描述的行为实际上是不可能的除非您的 XML 状态为 encoding="UTF-8" 而实际上不是,或者您提供给它的其他组件忽略了 XML声明并尝试将其解析为遗留编码(非常不可能)。我敢打赌第一种情况:您使用错误的编码创建 XML。更正声明以匹配您的文件编码,或将您的文件编码更正为 UTF-8。 为了说明这里的情况,我们需要来自受影响文件的十六进制 sn-p。
  • 在此处查看另一篇相关帖子stackoverflow.com/questions/499010/…
  • 这是可能的,因为这些文件来自不同的客户,他们正在生成我们期望格式的 XML 文件,但可能只是放置 XML 标头而不考虑他们放入的数据。我们不确定是什么这些客户可能正在使用的工具和技术。
  • @MartinFrank 我不确定所有字符都会造成问题,因此最好确保该文件没有特殊字符。我只是在大声思考有没有办法针对所有非 ascii 字符验证文件?

标签: java xml utf-8 character-encoding jaxb


【解决方案1】:

如果您的客户向您发送一个带有编码与文件内容不匹配的标头的 XML 文件,您不妨放弃尝试对该文件做任何有意义的事情。 - 他们真的在发送标头与实际编码不匹配的数据吗?那不是XML。而且您应该向他们收取更多费用;-)

只需将文件作为 FileInputStream 逐字节读取。如果包含负字节值,则拒绝处理。

您可以保留 UTF-8 或 ISO 8859-1 等编码设置,因为它们都将 US-ASCII 作为真子集。

【讨论】:

    【解决方案2】:

    是的,我的回答和 laune 提到的一样……

    static boolean readInput() {
        boolean isValid = true;
        StringBuffer buffer = new StringBuffer();
        try {
            FileInputStream fis = new FileInputStream("test.txt");
            InputStreamReader isr = new InputStreamReader(fis);
            Reader in = new BufferedReader(isr);
            int ch;
            while ((ch = in.read()) > -1) {
                buffer.append((char)ch);
                System.out.println("ch="+ch);
                //TODO - check range for each character 
                //according the wikipedia table http://en.wikipedia.org/wiki/UTF-8
                //if it's a valid utf-8 character
                //if it's not in range, the isValid=false;
                //and you can break here...
            }
            in.close();
            return isValid;
        } 
        catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    

    我只是添加一个代码 sn-p...

    【讨论】:

    • 我会使用grep "[^\t\r\f -~]" $file && rm $file ;-)
    【解决方案3】:

    您应该能够将 XML 输入包装在 java.io.Reader 中,您可以在其中指定实际编码,然后正常处理。 Java 将利用 XML 中为 InputStream 指定的编码,但当使用 Reader 时,将使用 Reader 的编码。

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    InputStream inputStream = new FileInputStream("input.xml");
    Reader reader = new InputStreamReader(inputStream, "UTF-16");
    try {
        Address address = (Address) unmarshaller.unmarshal(reader);
    } finally  {
        reader.close();
    }
    

    【讨论】:

      猜你喜欢
      • 2018-02-11
      • 1970-01-01
      • 2011-01-21
      • 2016-05-24
      • 2011-02-21
      • 1970-01-01
      • 2015-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多