.mht格式文件在日常工作中比较少见。可能只有从事工业项目开发的朋友才有机会遇到。
在.NET中解析.mht文件本质上仍然是的二进制文件的解析。以下直接上代码实例。
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 删除。