【问题标题】:How can I read a Lync conversation file containing HTML?如何读取包含 HTML 的 Lync 对话文件?
【发布时间】:2015-10-17 10:18:07
【问题描述】:

我在用 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;

但它并没有按预期工作。

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

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

但在第一种情况下,代码似乎跳过了这些行,只打印“Office Communicator 生成的文档...”

【问题讨论】:

  • 那是二进制数据吗?您可以读取二进制流并转换为字符串。
  • 请从文件的开头发布 binary 数据 - 基本上用 hex 文件编辑器查看它。
  • 它看起来像一个简单的html文件,实际上它有一个HTML标签,加上所有其他部分,如body、style等。当用chrome打开时,它是一个简单的网页,有一些垃圾顶部。
  • 这不是文本文件。它是使用“.html”扩展名保存的其他格式。它是如何准确地生成的? “由 Lync 生成”不是答案 - Lync 生成了什么?您是否尝试将某些内容保存为附件?是会话的记录吗?传输的文件?在用户的 Lync 数据文件夹中找到原始文件?如果不知道二进制文件的类型或格式,就无法处理
  • 这是重要的信息,应该在标题本身中。我建议您发布一个 问题,询问如何阅读 Lync 对话历史记录文件。可能有一个 API 可以使这变得微不足道。另请查看 Lync 的文档和编程指南。确保提及使用的 Lync 版本。另请注意,有很多关于从服务器或客户端读取 Lync 历史记录的 SO 问题。确保指定适当的大小写

标签: c# file lync


【解决方案1】:

我不知道这是否是回答这个问题的正确方法,但这是我到目前为止所做的:

        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)

跳过不可打印的字符:)

【讨论】:

    【解决方案2】:

    如果您可以使用 API 或 SDK,甚至对您尝试阅读的格式进行描述,您的任务会更轻松。但是二进制格式看起来并没有那么复杂,并且安装了hexviewer 后,我已经从您提供的示例中获取了 html。

    要解析非文本文件,请回退到BinaryReader,然后使用Read methods 之一从字节流中读取正确的类型。我使用了ReadByteReadInt32。请注意在方法的描述中如何解释读取了多少字节。当您尝试破译您的文件时,这会变得很方便。

        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 并计算出哪些其他字节结构是新的或与您已有的不同。这不是我打算帮助你的事情,留给你做练习。

    【讨论】:

    • 嗨,我很想试试你的代码!我想出了一个解决方案,包括跳过文件的前 n 个字符。似乎只有 textBox 组件受此影响,仅显示“-”字符。控制台输出工作正常...所以,这就是我想出的:pastebin.com/gaEZW8ari.imgur.com/X3eFdUQ.jpg 我知道这不是最好和最安全的解决方案,但它是一个起点。
    • 跳过 n 个字节是失败的保证,因为下一个文件将与文件开头的名称/地址不同
    • 在文件末尾重复了类似类型的数据,包括参与者。顶部只是一个标题和 CSS 标记。所以我仍然可以从该文件中提取信息。直接将文件读入字符串,只是不起作用:/
    • 我能够使用 HtmlAgilityPack 成功解析和提取数据,如下所述:stackoverflow.com/questions/19870116/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多