在我的Android应用中保存XML数据文件时,当用户放置表情符号字符时出现异常。
据我了解,d83d字符就是这个字符:http://apps.timwhitlock.info/unicode/inspect?s=%F0%9F%98%84-smily😄字符。
相关的堆栈跟踪:
java.lang.IllegalArgumentException: Illegal character (d83d)
at org.kxml2.io.KXmlSerializer.reportInvalidCharacter(KXmlSerializer.java:144)
at org.kxml2.io.KXmlSerializer.writeEscaped(KXmlSerializer.java:130)
at org.kxml2.io.KXmlSerializer.attribute(KXmlSerializer.java:465)
最重要的问题是:如何解决它,以便我的用户不会因为表情符号而使应用程序崩溃...
后续问题是:
这个KXmlSerializer是否应该支持表情符号/ Unicode?
某处有更新版本吗?到目前为止我找不到。
图书馆是否积极维护?
谁在维护KXmlSerializer?
是http://kxml.org/吗?我在那里找不到很多...
如果放在类路径中,更新版本是否会与Android内置版本冲突?
我应该/可以使用什么其他的XML编写库来替换KXmlSerializer?
编辑:我要补充一点,该应用程序通过xml保存的文本来自标准的Android EditText UI小部件,用户可以在其中输入文本(我不对字符串进行任何Unicode级别的操作)。
最佳答案
我在测试设备(API17)上遇到了相同的异常,这是代码:
final XmlSerializer serializer = new Xml.newSerializer();
final StringWriter stringWriter = new StringWriter();
serializer.setOutput(stringWriter);
serializer.startDocument("UTF-8", true);
serializer.startTag("", "XXXX");
....
serializer.endTag("", "XXXX");
serializer.endDocument();
writer.write(stringWriter.toString());
writer.close();
但是代码在API21和API23上还可以。
在API17中,KXmlSerializer的关键代码:
// BEGIN android-changed: refuse to output invalid characters
// See http://www.w3.org/TR/REC-xml/#charsets for definition.
// No other Java XML writer we know of does this, but no Java
// XML reader we know of is able to parse the bad output we'd
// otherwise generate.
// Note: tab, newline, and carriage return have already been
// handled above.
boolean valid = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
if (!valid) {
reportInvalidCharacter(c);
}
if (unicode || c < 127) {
writer.write(c);
} else {
writer.write("&#" + ((int) c) + ";");
}
// END android-changed
在API23中,KXmlSerializer的关键代码:
// BEGIN android-changed: refuse to output invalid characters
// See http://www.w3.org/TR/REC-xml/#charsets for definition.
// No other Java XML writer we know of does this, but no Java
// XML reader we know of is able to parse the bad output we'd
// otherwise generate.
// Note: tab, newline, and carriage return have already been
// handled above.
boolean allowedInXml = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
if (allowedInXml) {
if (unicode || c < 127) {
writer.write(c);
} else {
writer.write("&#" + ((int) c) + ";");
}
} else if (Character.isHighSurrogate(c) && i < s.length() - 1) {
writeSurrogate(c, s.charAt(i + 1));
++i;
} else {
reportInvalidCharacter(c);
}
// END android-changed
出现异常的原因,您可以阅读Stephen C的答案。
最后,我从kXML(https://sourceforge.net/projects/kxml/files/kxml2/2.3.0/)下载了类 KXmlSerializer 的最新代码。并将其添加到我的项目中,将该类重命名为TestKXmlSerializer。
final XmlSerializer serializer = new TestKXmlSerializer();
可以使用API17,API20,API23。