【问题标题】:Invalid XML during serialization序列化期间无效的 XML
【发布时间】:2013-06-13 14:32:57
【问题描述】:

我附上了这段代码,它一直有效,就像一年一样:

// prepare serializer (XSContent)
XmlSerializer serializer = new XmlSerializer(typeof(XSContent));

using (TextWriter textWriter = new StreamWriter(this.fileName, false, Encoding.UTF8))
{
   // prepare the content for xml serialization
   XSContent content = new XSContent();
   content.UserList = XSConverter.ConvertList<XSUser, TBSUser>(input.UserList);
   content.GroupList = XSConverter.ConvertList<XSGroup, TBSGroup>(input.GroupList);

   // perform serialization
   serializer.Serialize(textWriter, content);                
 }

但是今天,我用大量数据测试的相同代码:xml 结果变得无效(请注意整个内容末尾的“剩余”):

 <?xml version="1.0" encoding="utf-8"?>
 <Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <UserList>
      <User UserID="CI-0123">
          {...}
      </User>
      {...} 
    </UserList>
    <GroupList>
      <Group GroupID="TEST01">
        <GroupName>Test</GroupName>
        <UserList>
          <UserID>CI-0123</UserID>
        </UserList>
      </Group>    
      {...}
    </GroupList>
 </Content>rID>AT-TEST-2348</UserID>
    <UserID>AT-TEST-2349</UserID>
    <UserID>AT-TEST-2350</UserID>

这让我发疯,我被困住了。你觉得我应该去哪里找?我做错了什么?

也许值得一提的是,这个 xml 文件约为 200Mb。另外,如果有不清楚的地方,我可以提供更多信息。

EDIT1: 没有可能干扰的现有文件。文件在我的测试中创建为新文件!

EDIT2: 如果我在末尾添加一个textWriter.WriteLine("XYZ"),它会出现在&lt;/Content&gt; 之后,但我仍然看到XYZ 之后的垃圾(例如:&lt;/Content&gt;XYZ&gt;AT-TEST-2348&lt;/UserID&gt;

EDIT3: 很奇怪,当我将缓冲区增加到 8192 时,它工作正常。之后,我又回到 4096 继续正常工作。我看到了这个FileOptions.SequencialScan,他们写道:“正确的操作仍然有保证”。好吧,我开始认为这可能有问题(?)

谢谢

【问题讨论】:

    标签: .net xml serialization


    【解决方案1】:

    怎么样

        using(var stream = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.Read, 4096)) {
          using (var textWriter = new StreamWriter(stream, Encoding.UTF8)) {
            ...
          }
        }
    

    如果你检查 StreamWriter 构造函数,它是这样完成的:

    [SecurityCritical]
    private static Stream CreateFile(string path, bool append, bool checkHost)
    {
        FileMode mode = append ? FileMode.Append : FileMode.Create;
        return new FileStream(path, mode, FileAccess.Write, FileShare.Read, 4096, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);
    }
    

    有关枚举值,请参阅 http://msdn.microsoft.com/en-us/library/system.io.filemode.aspx

    【讨论】:

    • 有趣的想法,我可以试一试。谢谢!
    • 嗯,它没有帮助......同样的行为......呃......如果我能找到哪个是默认的 FileOptions 值。我不知道这是否真的很重要,但 SequentialScan 听起来不错
    • 由于第三个参数是编码,你能更正 StreamWriter 构造函数吗?顺便说一句,我怎么能看到这些东西?
    • 我不知道您使用的是哪个版本的 .NET FW;但对我来说,新的 StreamWriter(stream, Encoding.UTF8) 有效;至于在哪里可以看到这些东西——下载反射器工具(如ILSpy);它允许您查看 .NET 内部结构。只是为了清楚起见 - 问题在于 File.CreateNew 与 File.Create;默认的 StreamWriter 构造函数,如果它没有获取流引用,则使用 FileMode.Create 创建自己的流,它不会删除现有文件。所以剩菜是你之前跑的(至少这是我的理论)。
    • 是的,我知道你为什么会这么说,但我之前自己删除了这个文件。所以,我确信任何现有文件都没有剩余
    【解决方案2】:

    最后它似乎在使用Truncate 模式时工作(在我的情况下,该文件始终存在,在应用程序启动期间创建)。

    【讨论】:

      猜你喜欢
      • 2020-04-02
      • 1970-01-01
      • 2012-05-28
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      • 2019-01-26
      相关资源
      最近更新 更多