繁体   English   中英

c# XmlReader 与 base64 内文

[英]c# XmlReader with base64 innertext

好的,这是我的问题。 我正在尝试截取屏幕截图,将其添加到 xmldocument,通过套接字发送,然后使用 XmlReader 读取它。

这是一些代码...

服务器端

private void SendRandomData(object data)
{
    XMLShitSock sock = data as XMLShitSock;
    if(sock != null)
    {
        int incnum = 0;
        while(sock.Connected)
        {
            XmlDocument doc = new XmlDocument();
            XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
            doc.AppendChild(docNode);

            XmlNode productsNode = doc.CreateElement("image");

            productsNode.InnerText = Convert.ToBase64String(Program.CaptureImageToBytes(new Point(0, 0), new Rectangle(0, 0, Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height), ImageFormat.Png));
            doc.AppendChild(productsNode);
            string s = XMLShitSock.GetXmlString(doc);
            doc.Save("temp.xml");
            sock.WriteXMLMessage(doc);
            incnum++;
            Thread.Sleep(5000);
        }
    }
}

sock.WriteXMLMessage

public bool WriteXMLMessage(XmlDocument doc)
{
    try
    {
        ShittySocket.Client.Send(Encoding.ASCII.GetBytes(GetXmlString(doc)));
        return true;
    }
    catch(SocketException se)
    {
        this.Close();
        return false;
    }
}

读取输入

private void doInput()
{
    MemoryStream ms = new MemoryStream();
    NetworkStream ns = new NetworkStream(ShittySocket.Client, false);
    while(_connected)
    {
        if(ns.DataAvailable)
        {
            StreamReader sr = new StreamReader(ns);
            char[] b = new char[512];
            int nread = sr.Read(b, 0, 512);

            ms.Write(System.Text.Encoding.ASCII.GetBytes(b, 0, nread), 0, nread);
            ms.Seek(0, System.IO.SeekOrigin.Begin);

            XmlReaderSettings xrs = new XmlReaderSettings();

            XmlReader reader = XmlReader.Create(ms);
            if(reader.Read())
            {
                XmlDocument objXmlDocument = new XmlDocument();
                objXmlDocument.Load(reader);
                onInput(this, objXmlDocument);
                ms.Close();
                ms = new MemoryStream();
            }
        }
        Thread.Sleep(100);
    }
}

我遇到的问题是我在 doInput() 中收到一个错误,说在没有找到标签的情况下到达了文档的末尾。 我保存了 xml 文件并查看了它并且它存在,除了实际标签中的那些之外,我什至没有找到任何 < 字符,所以我不确定这里发生了什么。 我显然错过了一些东西。

此外,如果您对语义或编码风格或任何无法真正回答问题的内容有疑虑,请将其作为评论留下,因为它不是答案。

Also I've look through this ->> http://msdn.microsoft.com/en-us/library/system.xml.xmltextreader.readbase64.aspx and I'm hoping that there is a better way to deal with base64数据而不是将其与 XMLDocument 本身分开。 谢谢。

看起来您假设整个数据将在一个 512 字节的块中读取。 因此,如果实际数据长度为 513 个字节,那么您将不会在文档末尾获得右尖括号 >,因此 XML 解析器将失败。

我不知道您使用的是哪种类型的网络 ZF7B44CFFAFD5C52223D5498196C8A2E7BZ 但如果它是普通的 sockets 那么您需要某种分隔符才能知道何时到达“发送”的结尾和下一个“发送”的开头,因为vanilla sockets 只是一个数据管道。 通过一次读取,您可能会收到一半、一个、两个、三个和一个位的实际块。

方便地,您有一个结束标记形式的分隔符。

关于doInput()的两件事:

  1. XmlReaderSettings xrs = new XmlReaderSettings(); 不需要,因为您不会在后续XmlReader.Create()中使用它。 除非你先设置它的一些属性,否则没有必要。

  2. 您不能假设reader.Read()在那里阅读了整个 xml。 使用XmlReader您必须执行Read()直到您得到false的响应。

using(var reader = XmlReader.Create(...)) {... }也是一个好主意,所以当它完成阅读时,一切都很好地包裹起来。

尝试

ms.Position = 0; 

代替

ms.Seek(0, System.IO.SeekOrigin.Begin);

doInput()

你也可以尝试更换

Encoding.ASCII

Encoding.UTF8

或者只是用以下代码替换很多代码:

    private void doInput()
    {
        NetworkStream ns = new NetworkStream(ShittySocket.Client, false);
        while (_connected)
        {
            if (ns.DataAvailable)
            {
                using (StreamReader sr = new StreamReader(ns, System.Text.Encoding.UTF8))
                {
                        XmlDocument objXmlDocument = new XmlDocument();
                        objXmlDocument.LoadXml(sr.ReadToEnd());
                        onInput(this, objXmlDocument);
                }
            }
            Thread.Sleep(100);
        }
    }

好的,所以我想出了一个解决方案。 这是 function

public static XmlDocument GrabXmlDocFromStream(StreamReader reader)
{
    using(MemoryStream ms = new MemoryStream())
    {
        byte b = 0;
        while(!reader.EndOfStream)
        {
            b = (byte)reader.Read();
            ms.WriteByte(b);
            ms.Seek(0, System.IO.SeekOrigin.Begin);

            using(XmlReader xmlreader = XmlReader.Create(ms))
            {
                XmlDocument doc = new XmlDocument();
                try
                {
                    if(Encoding.ASCII.GetChars(new byte[1] { b })[0] == '>')
                    {
                        if(xmlreader.Read())
                        {
                            XmlDocument objXmlDocument = new XmlDocument();
                            objXmlDocument.Load(xmlreader);
                            return objXmlDocument;
                        }
                    }
                }
                catch(XmlException xe) { }
            }
        }
    }
    return null;
}

你像这样使用它

            using(NetworkStream ns = new NetworkStream(ShittySocket.Client, false))
{
            using(StreamReader sr = new StreamReader(ns))
            {
                XmlDocument xdoc = new XmlDocument();
                while(xdoc != null)
                {
                    xdoc = Program.GrabXmlDocFromStream(sr);
                    if(xdoc != null)
                        Program.Handle_Document(xdoc);
                }
            }
}

这里是代码中提到的另外两个function

    public static string GetXmlString(XmlDocument doc)
    {
        StringWriter sw = new StringWriter();
        XmlTextWriter xw = new XmlTextWriter(sw);
        doc.WriteTo(xw);
        return sw.ToString();
    }

    public static void Handle_Document(XmlDocument doc)
    {
        MessageBox.Show(GetXmlString(doc));
    }

这可能不是最好的解决方案,但我使用了 if(Encoding.ASCII.GetChars(new byte[1] { b })[0] == '>') 行,这样我就不会每次都遇到异常特点。 据我了解,以这种方式使用 try-catch 并不完全是解决问题的“正确”方法,但它确实有效,而且我认为我可能会遭受轻微的时间损失。 任何想法都会很好,如果您发现这有问题,请告诉我。 谢谢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM