【问题标题】:Why would StreamReader.ReadLine do a better job of reading XML than XmlTextReader.Read?为什么 StreamReader.ReadLine 在读取 XML 方面会比 XmlTextReader.Read 做得更好?
【发布时间】:2014-08-29 10:27:25
【问题描述】:

我的这段代码可以在 Winforms 应用程序调用 Web API 应用程序时正常工作(它成功地将 XML 文件复制到服务器):

public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

    request.KeepAlive = false;
    request.ProtocolVersion = HttpVersion.Version10;
    request.ContentType = "application/xml";
    request.Method = "POST";

    StringBuilder sb = new StringBuilder();
    using (StreamReader sr = new StreamReader(xmlFilepath))
    {
        String line;
        while ((line = sr.ReadLine()) != null)
        {
            sb.AppendLine(line);
        }
        MessageBox.Show(sb.ToString());
        byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

        if (timeout < 0)
        {
            request.ReadWriteTimeout = timeout;
            request.Timeout = timeout;
        }

        request.ContentLength = postBytes.Length;

        try
        {
            Stream requestStream = request.GetRequestStream();

            requestStream.Write(postBytes, 0, postBytes.Length);
            requestStream.Close();

            HttpWebResponse response = null; //<= uncomment for older versions of .NET
            try
            {
                response = (HttpWebResponse)request.GetResponse(); //<= uncomment for older versions of .NET (comment out using)
            }
            finally
            {
                IDisposable disposableResponse = response as IDisposable;
                if (disposableResponse != null) disposableResponse.Dispose();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            request.Abort();
            return string.Empty;
        }
    }
}

但是,当试图弄清楚为什么与此工作代码尽可能相似的代码在尝试将 xml 文件从手持设备发送到同一服务器时不起作用时,我尝试改用 XmlTextReader(因为建议here(“你在这里没有使用 XML 类和方法”),我在这里详细介绍了我的辛苦);唯一的区别是:

using (StreamReader sr = new StreamReader(xmlFilepath))
{
    String line;
    while ((line = sr.ReadLine()) != null)
    {
        sb.AppendLine(line);
    }
    MessageBox.Show(sb.ToString());
    byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

...在工作(StreamReader)代码中更改为:

XmlTextReader reader = new XmlTextReader(xmlFilepath);
while (reader.Read())
{
    switch (reader.NodeType)
    {
        case XmlNodeType.Element: // The node is an Element.
            sb.Append("<" + reader.Name);

            while (reader.MoveToNextAttribute()) // Read attributes.
                sb.Append(" " + reader.Name + "='" + reader.Value + "'");
            sb.Append(">");
            sb.Append(">");
            break;
        case XmlNodeType.Text: //Display the text in each element.
            sb.Append(reader.Value);
            break;
        case XmlNodeType.EndElement: //Display end of element.
            sb.Append("</" + reader.Name);
            sb.Append(">");
            break;
    }
}

MessageBox.Show(sb.ToString());
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

使用 StreamReader 代码,读取的数据看起来就像在磁盘上一样:

但是,使用 XmlTextReader,一切都变得混乱起来,就像从大炮中射出的什锦饭一样:

...XmlTextReader 版本失败,出现“远程服务器返回错误:(500) Internal Server Error.

所以 StreamReader.ReadLine 比 XmlTextReader.Read 更适用于 XML 文件;看起来很奇怪......我在这里做错了吗?

【问题讨论】:

  • 查看 XmlSettings。你必须告诉读者格式化/缩进。

标签: c# xml streamreader readline xmltextreader


【解决方案1】:

默认情况下,XmlTextReader 将忽略空格。您需要明确告诉它包含空格并开始在您的开关中处理空格。

另请注意,所有XmlReader 实现都是一次性的,因此请将它们包装在using 中。

XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreWhitespace = false;
using(XmlReader reader = XmlReader.Create(xmlFilepath, settings)) {
    while (reader.Read())
    {
        switch (reader.NodeType)
        {
            case XmlNodeType.Element: // The node is an Element.
                sb.Append("<" + reader.Name);

                while (reader.MoveToNextAttribute()) // Read attributes.
                    sb.Append(" " + reader.Name + "='" + reader.Value + "'");
                sb.Append(">");
                sb.Append(">");
                break;
            case XmlNodeType.Text: 
            case XmlNodeType.Whitespace:
                sb.Append(reader.Value);
                break;
            case XmlNodeType.EndElement: //Display end of element.
                sb.Append("</" + reader.Name);
                sb.Append(">");
                break;
        }
    }
}
MessageBox.Show(sb.ToString());
byte[] postBytes = Encoding.UTF8.GetBytes(sb.ToString());

【讨论】:

  • 好的,如果在我这里使用的旧版本 .NET 中可以使用 using,我会试试。
  • @B.ClayShannon,是的,using 在 C# 中一直可用。这真的很重要,你应该经常使用using,每次你创建任何实现IDisposable的东西。
  • 好吧,那么某些对象在较新版本的 .NET 中“可用”,但在旧版本中“不可用”,因为我肯定在版本之间遇到了这个问题 - 我有有时在使用较旧的位时恢复到尼安德特人的编码方式。
猜你喜欢
  • 2017-08-06
  • 1970-01-01
  • 2014-11-03
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多