如何读取包含 HTML 的 Lync 对话文件?

How can I read a Lync conversation file containing HTML?

我在用 c# 将本地文件读入字符串时遇到问题。

这是我到目前为止的想法:

 string file = @"C:\script_test\{5461EC8C-89E6-40D1-8525-774340083829}.html";
 using (StreamReader reader = new StreamReader(file))
 {
      string line = "";
      while ((line = reader.ReadLine()) != null)
      {
           textBox1.Text += line.ToString();
      }
 }

这是唯一似乎有效的解决方案。

我尝试了一些其他推荐的文件读取方法,例如:

string file = @"C:\script_test\{5461EC8C-89E6-40D1-8525-774340083829}.html";
string html = File.ReadAllText(file).ToString();
textBox1.Text += html;

然而它并没有像预期的那样工作。

这是我正在尝试读取的文件的前几行:

如您所见,它有一些古怪的字符,老实说,我不知道这是否是造成这种奇怪行为的原因。

但在第一种情况下,代码似乎跳过了这些行,只打印了 "Document generated by Office Communicator..."

如果您可以使用 API 或 SDK,甚至可以对您尝试阅读的格式进行描述,那么您的任务会更容易。然而,二进制格式看起来并没有那么复杂,并且安装了 hexviewer 我已经走了这么远才能从您提供的示例中得到 html。

要解析非文本文件,您可以回退到 BinaryReader and then use one of the Read methods to read the correct type from the bytestream. I used ReadByte and ReadInt32。请注意在方法的描述中如何解释读取了多少字节。当你试图破译你的文件时,这会变得很方便。

    private string ParseHist(string file)
    {
        using (var f = File.Open(file, FileMode.Open))
        {
            using (var br = new BinaryReader(f))
            {
                // read 4 bytes as an int
                var first = br.ReadInt32();
                // read integer / zero ended byte arrays as string
                var lead = br.ReadInt32();
                // until we have 4 zero bytes
                while (lead != 0)
                {
                    var user = ParseString(br);
                    Trace.Write(lead);
                    Trace.Write(":");
                    Trace.Write(user.Length);
                    Trace.Write(":");
                    Trace.WriteLine(user);
                    lead = br.ReadInt32();
                    // weird special case
                    if (lead == 2)
                    {
                        lead = br.ReadInt32();
                    }
                }

                // at the start of the html block
                var htmllen = br.ReadInt32();
                Trace.WriteLine(htmllen);
                // parse the html
                var html = ParseString(br);
                Trace.Write(len);
                Trace.Write(":");
                Trace.Write(html.Length);
                Trace.Write(":");
                Trace.WriteLine(html);
                // other structures follow, left unparsed

                return html.ToString();
            }
        }
    }

    // a string seems to be ascii encoded and ends with a zero byte.
    private static string ParseString(BinaryReader br)
    {
        var ch = br.ReadByte();
        var sb = new StringBuilder();
        while (ch != 0)
        {
            sb.Append((char)ch);
            ch = br.ReadByte();
        }
        return sb.ToString();
    }

您可以在 winform 应用程序中使用简单的解析逻辑,如下所示:

    private void button1_Click(object sender, EventArgs e)
    {
        webBrowser1.DocumentText = ParseHist(@"5461EC8C-89E6-40D1-8525-774340083829-Copia.html");
    }

请记住,这不是万无一失的方法,也不是推荐的方法,但它应该可以帮助您入门。对于不能很好解析的文件,您需要返回到 hexviewer 并找出哪些其他字节结构是新的或与您已有的不同。这不是我打算帮助你的,那是留给你弄清楚的练习。

我不知道这样回答这个问题是否正确,但到目前为止我已经做到了:

        string file = @"C:\script_test\{1C0365BC-54C6-4D31-A1C1-586C4575F9EA}.hist";
                    string outText = "";
        //Encoding iso = Encoding.GetEncoding("ISO-8859-1");
        Encoding utf8 = Encoding.UTF8;
        StreamReader reader = new StreamReader(file, utf8);
        char[] text = reader.ReadToEnd().ToCharArray();
        //skip first n chars
        /*
        for (int i = 250; i < text.Length; i++)
        {
            outText += text[i];
        }
        */
        for (int i = 0; i < text.Length; i++)
        {
            //skips non printable characters
            if (!Char.IsControl(text[i]))
            {
                outText += text[i];
            }
        }
        string source = "";
        source = WebUtility.HtmlDecode(outText);
        HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
        htmlDoc.LoadHtml(source);

        string html = "<html><style>";
        foreach (HtmlNode node in htmlDoc.DocumentNode.SelectNodes("//style"))
        {
            html += node.InnerHtml+ Environment.NewLine;
        }
        html += "</style><body>";
        foreach (HtmlNode node in htmlDoc.DocumentNode.SelectNodes("//body"))
        {
            html += node.InnerHtml + Environment.NewLine;
        }
        html += "</body></html>";
        richTextBox1.Text += html+Environment.NewLine;

        webBrowser1.DocumentText = html;

会话显示正确,包括样式和编码。

所以这对我来说是一个开始。

感谢大家的支持!

编辑

Char.IsControl(char)

跳过不可打印的字符:)