使用声明的encoding = utf-8 – Java从xml中删除非UTF-8字符

我必须在Java中处理这种情况:

我从声明为encoding = utf-8的客户端获取XML格式的请求。 不幸的是,它可能不包含utf-8字符,并且需要从我这边的xml中删除这些字符(遗留)。

让我们考虑这个无效XML包含£(磅)的示例。

1)我得到xml作为带有£的java字符串(我现在没有访问接口,但我可能得到xml作为java字符串)。 我可以使用replaceAll(£,“”)来摆脱这个角色吗? 任何潜在的问题?

2)我得到xml作为字节数组 – 在这种情况下如何安全地处理这个操作?

1)我得到xml作为带有£的java字符串(我现在没有访问接口,但我可能得到xml作为java字符串)。 我可以使用replaceAll(£,“”)来摆脱这个角色吗?

我假设您宁愿意味着要摆脱非ASCII字符,因为您正在谈论“遗留”方面。 您可以使用以下正则表达式删除可打印ASCII范围之外的任何内容:

string = string.replaceAll("[^\\x20-\\x7e]", ""); 

2)我得到xml作为字节数组 – 在这种情况下如何安全地处理这个操作?

您需要将byte[]包装在ByteArrayInputStream ,以便您可以使用InputStreamReader在UTF-8编码的字符流中读取它们,其中您指定编码,然后使用BufferedReader逐行读取它。

例如

 BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8")); for (String line; (line = reader.readLine()) != null;) { line = line.replaceAll("[^\\x20-\\x7e]", ""); // ... } // ... 

UTF-8是一种编码; Unicode是一个字符集。 但GBP符号绝对是Unicode字符集,因此在UTF-8中肯定是可以表示的。

如果你确实意味着UTF-8,并且你实际上试图删除不是UTF-8中字符的有效编码的字节序列,那么……

 CharsetDecoder utf8Decoder = Charset.forName("UTF-8").newDecoder(); utf8Decoder.onMalformedInput(CodingErrorAction.IGNORE); utf8Decoder.onUnmappableCharacter(CodingErrorAction.IGNORE); ByteBuffer bytes = ...; CharBuffer parsed = utf8Decoder.decode(bytes); ... 
 "test text".replaceAll("[^\\u0000-\\uFFFF]", ""); 

此代码从string中删除所有4字节的utf8字符。在执行Mysql innodb varchar条目时,出于某些目的可能需要这样做

我从本地目录中读取文件时遇到了同样的问题,并尝试了这个:

 BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8")); DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document xmlDom = db.parse(new InputSource(in)); 

您可能必须使用网络输入流而不是FileInputStream。

– 卡皮尔

请注意,第一步应该是您要求XML的创建者(最有可能是本地“仅打印数据”XML生成器)在发送给您之前确保其XML正确无误。 如果他们使用Windows,最简单的测试是要求他们在Internet Explorer中查看它,并在第一个违规字符处查看解析错误。

虽然他们解决了这个问题,但您可以简单地编写一个小程序来更改标题部分,以声明编码是ISO-8859-1:

  

并保持其余部分不受影响。

在java机器上将字节数组转换为String后,您将获得(默认情况下在大多数机器上)UTF-16编码的字符串。 摆脱非UTF-8字符的正确解决方案是使用以下代码:

 String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa"}; for (int i = 0; i < values.length; i++) { System.out.println(values[i].replaceAll( "[\\\\x00-\\\\x7F]|" + //single-byte sequences 0xxxxxxx "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences 110xxxxx 10xxxxxx "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences 1110xxxx 10xxxxxx * 2 "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3 , "")); } 

或者如果你想validation某些字符串是否包含非utf8字符,你可以使用Pattern.matches:

 String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa"}; for (int i = 0; i < values.length; i++) { System.out.println(Pattern.matches( ".*(" + "[\\\\x00-\\\\x7F]|" + //single-byte sequences 0xxxxxxx "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences 110xxxxx 10xxxxxx "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences 1110xxxx 10xxxxxx * 2 "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3 + ").*" , values[i])); } 

如果您有可用的字节数组,则可以使用以下方法更正确地过滤它们:

 BufferedReader bufferedReader = null; try { bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "UTF-8")); for (String currentLine; (currentLine = bufferedReader.readLine()) != null;) { currentLine = currentLine.replaceAll( "[\\x00-\\x7F]|" + //single-byte sequences 0xxxxxxx "[\\xC0-\\xDF][\\x80-\\xBF]|" + //double-byte sequences 110xxxxx 10xxxxxx "[\\xE0-\\xEF][\\x80-\\xBF]{2}|" + //triple-byte sequences 1110xxxx 10xxxxxx * 2 "[\\xF0-\\xF7][\\x80-\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3 , "")); } 

要使整个Web应用程序兼容UTF8,请在此处阅读:
如何让UTF-8在Java webapps中运行
有关字节编码和字符串的更多信息 。
你可以在这里查看你的模式。
这里的 PHP也一样。