首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >.NET解析.mht格式文件

.NET解析.mht格式文件

原创
作者头像
软件架构师Michael
修改2025-08-18 10:09:14
修改2025-08-18 10:09:14
930
举报

.mht格式文件在日常工作中比较少见。可能只有从事工业项目开发的朋友才有机会遇到。

在.NET中解析.mht文件本质上仍然是的二进制文件的解析。以下直接上代码实例。

代码语言:csharp
复制
public static JToken ParseItemsFromMht(string filePath)
{
    // 处理不同编码格式
    string fileContent = DetectAndReadFile(filePath);

    // 尝试通过多种方式定位JSON数据
    string jsonData = ExtractJsonData(fileContent);

    return ParseAndExtractItems(jsonData);
}

private static string DetectAndReadFile(string filePath)
{
    // 先以UTF-8读取,失败时尝试自动检测编码
    try
    {
        return File.ReadAllText(filePath, Encoding.UTF8);
    }
    catch (DecoderFallbackException)
    {
        byte[] bytes = File.ReadAllBytes(filePath);
        Encoding encoding = DetectEncoding(bytes);
        return encoding.GetString(bytes);
    }
}

private static Encoding DetectEncoding(byte[] bytes)
{
    // 检测可能的编码格式(针对中文环境)
    if (bytes.Length >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF)
        return Encoding.UTF8;

    if (bytes.Length >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE)
        return Encoding.Unicode;

    // 检测GB2312/GBK编码特征
    bool hasGbChars = false;
    for (int i = 0; i < Math.Min(bytes.Length, 1000); i++)
    {
        if (bytes[i] >= 0x81 && bytes[i] <= 0xFE)
        {
            hasGbChars = true;
            break;
        }
    }

    return hasGbChars ? Encoding.GetEncoding("GB2312") : Encoding.Default;
}

private static string ExtractJsonData(string fileContent)
{
    // 策略1:按MIME边界分割
    string boundary = ExtractBoundary(fileContent);
    if (!string.IsNullOrEmpty(boundary))
    {
        var jsonContent = FindJsonInMimeParts(fileContent, boundary);
        if (!string.IsNullOrEmpty(jsonContent))
            return jsonContent;
    }

    // 策略2:直接扫描整个文件
    return ScanForJsonDirectly(fileContent);
}

private static string FindJsonInMimeParts(string content, string boundary)
{
    List<string> parts = content.Split(
            new[] { "--" + boundary },
            StringSplitOptions.RemoveEmptyEntries)
        .Where(part => !part.Contains("--"))
        .ToList();

    // 在HTML部分中查找内嵌的JSON
    foreach (var part in parts)
    {
        // 放宽JSON识别条件
        if (part.Contains("items") && (part.Contains('{') || part.Contains('[')))
        {
            // 尝试分离HTML标签
            string cleanContent = StripHtmlTags(part);

            // 验证是否是有效的JSON格式
            if (IsValidJson(cleanContent))
                return cleanContent;
        }
    }

    return null;
}

 private static JToken ParseAndExtractItems(string jsonStr)
 {
     // 容忍性更强的JSON解析
     jsonStr = NormalizeJson(jsonStr);

     // 尝试解析为JSON
     var token = JToken.Parse(jsonStr);

     // 自动探测items位置
     if (token is JObject obj)
     {
         // 检查第一层级
         if (obj.ContainsKey("items"))
             return obj["items"];

         // 检查常见嵌套结构
         foreach (var child in obj.Children<JProperty>())
         {
             if (child.Value is JObject childObj && childObj.ContainsKey("items"))
                 return childObj["items"];
         }
     }

     throw new KeyNotFoundException("'items' section not found in JSON structure");
 }

 private static string NormalizeJson(string json)
 {
     // 替换JavaScript格式的属性名(无引号)
     json = Regex.Replace(json, @"([,{]\s*)(?<name>\w+)\s*:", "$1\"${name}\":");

     // 处理注释
     json = Regex.Replace(json, @"//.*?(\r\n?|\n)", "");
     json = Regex.Replace(json, @"/\*.*?\*/", "", RegexOptions.Singleline);

     // 处理JSONP格式
     int startPos = json.IndexOf('{');
     int endPos = json.LastIndexOf('}');
     if (startPos > -1 && endPos > startPos)
         json = json.Substring(startPos, endPos - startPos + 1);

     return json;
 }

注意:最终输出的结果为一个字符串。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档