我必须在Java中处理这个场景:
我从声明为encoding = utf-8的客户端获取XML格式的请求。不幸的是,它可能不包含utf-8字符,并且需要从我这边的xml中删除这些字符(遗留)。
让我们考虑这个无效XML包含£(磅)的示例。
1)我将xml作为带有£的java String(我现在无法访问接口,但我可能将xml作为java String)。我可以使用replaceAll(£,“”)来摆脱这个角色吗?任何潜在的问题?
2)我把xml作为一个字节数组 - 在这种情况下如何安全地处理这个操作?
答案 0 :(得分:25)
1)我将xml作为带有£的java String(我现在无法访问接口,但我可能将xml作为java String)。我可以使用replaceAll(£,“”)来摆脱这个角色吗?
我假设你想要摆脱非 ASCII 字符,因为你在谈论的是“传统”方面。您可以使用以下正则表达式删除printable ASCII range之外的任何内容:
string = string.replaceAll("[^\\x20-\\x7e]", "");
2)我把xml作为一个字节数组 - 在这种情况下如何安全地处理这个操作?
您需要将byte[]
包装在ByteArrayInputStream
中,以便您可以使用InputStreamReader
在UTF-8编码的字符流中读取它们,其中您指定编码然后使用BufferedReader
逐行阅读。
E.g。
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]", "");
// ...
}
// ...
答案 1 :(得分:17)
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);
...
答案 2 :(得分:7)
"test text".replaceAll("[^\\u0000-\\uFFFF]", "");
此代码从string中删除所有4字节的utf8字符。执行Mysql innodb varchar条目时,出于某些目的可能需要这样做
答案 3 :(得分:3)
我在从本地目录中读取文件时遇到了同样的问题,并尝试了这个:
BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "UTF-8"));
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document xmlDom = db.parse(new InputSource(in));
您可能必须使用网络输入流而不是FileInputStream。
- 卡皮尔
答案 4 :(得分:1)
请注意,第一步应该是您要求XML的创建者(最有可能是本地“仅打印数据”XML生成器)在发送给您之前确保其XML正确无误。如果他们使用Windows,最简单的测试是让他们在Internet Explorer中查看它,并在第一个违规字符处看到解析错误。
虽然他们解决了这个问题,但您只需编写一个小程序来更改标题部分,以声明编码是ISO-8859-1:
<?xml version="1.0" encoding="iso-8859-1" ?>
并保持其余部分不受影响。
答案 5 :(得分: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
, ""));
}
或者如果你想验证某些字符串是否包含非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
, ""));
}
要使整个网络应用程序兼容UTF8,请在此处阅读:
How to get UTF-8 working in Java webapps
More on Byte Encodings and Strings。
您可以检查您的模式here
PHP here中也是如此。