有时我的类中属性的字符串值会变得奇怪。它们包含非法字符,并显示如下(带框):
123[]45[]6789
我假设这些是非法/无法识别的字符。我将所有对象序列化为 XML,然后通过 Web 服务上传它们。当我再次检索它们时,一些字符被替换为奇怪的字符。使用 Word 键入的连字符和破折号最常发生这种情况。这是它的原因吗?
无论如何我可以通过正则表达式或其他方式检查字符串是否包含任何这些无法识别的字符?
有时我的类中属性的字符串值会变得奇怪。它们包含非法字符,并显示如下(带框):
123[]45[]6789
我假设这些是非法/无法识别的字符。我将所有对象序列化为 XML,然后通过 Web 服务上传它们。当我再次检索它们时,一些字符被替换为奇怪的字符。使用 Word 键入的连字符和破折号最常发生这种情况。这是它的原因吗?
无论如何我可以通过正则表达式或其他方式检查字符串是否包含任何这些无法识别的字符?
就我个人而言,我不认为使用正则表达式来检查这些字符是正确的解决方案。如果您不存储这些字符,那么显然存在某种编码问题。
验证 XML 文档本身是使用正确的编码存储的,以支持您需要存储的字符。然后验证您在读取文件时是否使用与文档相同的编码,即如果您的 XML 文档存储为 UTF-8,那么您需要确保在读取时将其编码为 UTF-8。
首先要记住的是,没有“特殊字符”或“非法字符”之类的东西。在某些情况下有特殊字符,有非字符,但一般没有“特殊字符”或“非法字符”。
您在这里拥有的是:
首先要弄清楚那个角色是什么。找到字符的整数值,然后查找。
需要注意的一个重要问题是 U+FFFD (�),因为它有时在解码器收到一堆在其尝试使用的编码上下文中没有意义的字节时使用(例如,0x80 后跟 0x20 使在 UTF-8 中没有意义,一种可能的响应是使用 U+FFFD 作为“这里有些奇怪”的标记,其他可能的响应是抛出错误,并且还默默地忽略错误或试图猜测最后两个的意图带来安全问题)。
一旦你弄清楚了这一点,你就可以开始推理它为什么会进入那里,如果它不是预期的。可能是一个编码问题(写入的字符集不是读入的字符集)?它是否真的打算在那里?会不会是别的东西?在您获得有关该错误的更多信息之前,您无法开始回答这个问题。
最后,还有如何处理它的问题。希望从您在上述研究中找到的答案中可以明显看出这一点。答案可能是“没关系”,可能是简单的或困难的。还不能说。
不要只使用正则表达式进行过滤。也许这将是正确的解决方案,但你还不知道,所以也许你正在制造比现在更难找到的更深层次的错误,或者破坏完美的数据。
定义允许的字符并阻止其他所有字符,即:
// only lowercase letters and digits
if(Regex.IsMatch(yourString, @"^[a-z0-9]*$"))
{
// allowed
}
但我认为您的问题可能出在其他地方,因为您说它来自序列化(有效)字符串然后反序列化(无效)字符串。您可能使用默认序列化并且您没有ISerializable
为您的类应用正确的实现(或正确使用Serializable
属性),导致属性或字段被序列化而您不想被序列化。
PS:其他人提到了编码问题,这是一个可能的原因,可能意味着您根本无法读取数据。关于编码,有一个简单的规则:在任何地方(流、数据库、xml)都使用相同的编码并且是特定的。如果不是,则使用默认编码,这可能因系统而异。
根据新信息(请参阅原始问题下的线程),很明显该问题与编码有关。OP 提到它以破折号出现,—
当在某些花哨的编辑环境中使用时,通常会用漂亮的破折号代替,例如“—”()。由于似乎在如何修复 SQL Server 以接受正确的编码字符串方面存在一些不确定性,你也可以在你的 XML 中解决这个问题。
创建 XML 时,只需将编码更改为最基本的可能 ( US-ASCII
)。这将自动强制 XML 编写器使用正确的数字实体。当您反序列化时,这将在您的字符串中正确解析,无需多言。这些方面的东西:
Stream stream = new MemoryStream();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.ASCII;
XmlWriter writer = XmlWriter.Create(stream, settings);
// make sure to output the xml-prolog header
但是请注意使用StringBuilder
or StringWriter
,因为它固定为使用 UTF-16,并且 XmlWriter 将始终以该编码写入,有关该问题的更多信息在我的博客中,这与 SQL Server 不兼容。
注意:使用 ASCII 编码时,任何高于 ASCII 的字符0x7F
都会被编码。因此,é 看起来像é
,破折号可能看起来像—
,但这意味着相同,您不必担心。每个支持 XML 的工具都会正确地解释这个输入。
注意 2:您要更改 XML 编写方式的位置是您所说的 Web 服务,它接收 XML,然后将其存储到 SQL Server 数据库中。在存储到 SQL Server 之前,必须应用更改。在链条的前面是没用的。
深入了解字符本身,实际的 char 值是多少?
当一个字符显示为一个正方形时,这意味着您无法在视觉上表示它。这要么是因为它是一个非视觉字符,要么是在您当前的字符集之外。
编辑,没有
在您的示例中,我冒险猜测您看到的是嵌入的换行符。
public static T DeserializeFromXml<T>(string xml)
{
T result;
XmlSerializerFactory serializerFactory = new XmlSerializerFactory();
XmlSerializer serializer =serializerFactory.CreateSerializer(typeof(T));
using (StringReader sr3 = new StringReader(xml))
{
XmlReaderSettings settings = new XmlReaderSettings()
{
CheckCharacters = false // default value is true;
};
using (XmlReader xr3 = XmlTextReader.Create(sr3, settings))
{
result = (T)serializer.Deserialize(xr3);
}
}
return result;
}