C#调用ExifTool读取XML元数据遇未闭合错误,求替代方案
解决ExifTool XML输出不完整问题的替代方案
你的代码在异步读取输出时,可能因OutputDataReceived回调的行读取特性(丢失无换行的末尾数据)、或部分文件元数据异常导致ExifTool生成不规范XML,引发标签未闭合错误。以下是几种可靠的替代方案:
方案1:修复原代码的同步读取方式
异步读取容易丢失部分输出内容,改用同步读取所有输出可避免这个问题:
try { string args = $"-X \"{file}\""; ProcessStartInfo pi = new ProcessStartInfo("exiftool.exe", args) { StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using (Process proc = new Process()) { proc.StartInfo = pi; proc.Start(); // 一次性读取全部输出,避免分段丢失 string stdout = proc.StandardOutput.ReadToEnd(); string stderr = proc.StandardError.ReadToEnd(); proc.WaitForExit(10000); if (proc.ExitCode == 0) { xml.LoadXml(stdout); } else { throw new Exception(stderr); } } } catch (Exception ex) { Console.WriteLine(ex.Message); }
方案2:转用JSON输出再转换为XML
ExifTool的JSON输出稳定性远高于XML,不会出现标签未闭合问题,可先获取JSON再转成XML结构:
using System.Xml; using Newtonsoft.Json; try { string args = $"-j \"{file}\""; // 用-j参数输出JSON格式 ProcessStartInfo pi = new ProcessStartInfo("exiftool.exe", args) { StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using (Process proc = new Process()) { proc.StartInfo = pi; proc.Start(); string jsonOutput = proc.StandardOutput.ReadToEnd(); string stderr = proc.StandardError.ReadToEnd(); proc.WaitForExit(10000); if (proc.ExitCode == 0) { // 将JSON序列化为XML var jsonObj = JsonConvert.DeserializeObject(jsonOutput); XmlDocument xmlDoc = new XmlDocument(); using (var stringWriter = new StringWriter()) { JsonConvert.SerializeXmlNode(jsonObj, stringWriter, Newtonsoft.Json.Formatting.Indented); xmlDoc.LoadXml(stringWriter.ToString()); } // xmlDoc即为目标XML元数据 } else { throw new Exception(stderr); } } } catch (Exception ex) { Console.WriteLine(ex.Message); }
方案3:使用原生/第三方.NET库替代ExifTool
如果不想依赖外部工具,可选择以下库:
MetadataExtractor(轻量开源,NuGet可安装)
using MetadataExtractor; using System.Xml.Linq; try { var directories = ImageMetadataReader.ReadMetadata(file); // 构建符合需求的XML结构 XNamespace rdfNs = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; XElement root = new XElement(rdfNs + "RDF"); XElement description = new XElement(rdfNs + "Description"); foreach (var directory in directories) { foreach (var tag in directory.Tags) { description.Add(new XElement(tag.Name, tag.Description)); } } root.Add(description); // root就是生成的XML元数据 } catch (Exception ex) { Console.WriteLine(ex.Message); }
.NET原生API(适用于图片/文档)
对于图片文件,可使用System.Drawing.Imaging读取元数据;对于Office文档,可使用DocumentFormat.OpenXml。这类API无需外部依赖,但支持的文件类型相对有限。
方案4:优化ExifTool参数
给ExifTool添加参数强制输出规范XML:
-n:禁用友好格式化,输出原始值,避免特殊字符导致的输出截断-l:使用长标签名,提升XML可读性
修改后的参数:
string args = $"-X -n \"{file}\"";
内容的提问来源于stack exchange,提问作者mgsingletrack
相关产品推荐
相关产品推荐

