如何通过结构识别文本文件格式?
How to identify text file format by its structure?
我有一些文本文件类型,其中包含产品信息、库存、供应商信息等数据,它们的结构各不相同。除了结构本身之外,该类型没有其他标识符(没有 headers、没有文件名约定等)
这些文件的一些示例:
(产品和库存)
2326 | 542212 | Bananas | 00023 | 1 | pack
2326 | 297875 | Apples | 00085 | 1 | bag
2326 | 028371 | Pineapple | 00007 | 1 | can
...
(产品和价格)
12556 Meat, pork 0098.57
58521 Potatoes, mashed 0005.20
43663 Chicken wings 0009.99
...
(产品和供应商 - 这里 N 是分隔符)
03038N92388N9883929
28338N82367N2837912
23002N23829N9339211
...
(产品信息-多行)
VIN|Mom & Pops|78 Haley str.
PIN|BLT Bagel|5.79|FRESH
LID|0239382|283746
... (repeats this type of info for different products)
还有其他几个。
我想创建一个函数来识别给定文件是这些类型中的哪一种,只使用内容。 Google 没有任何帮助,部分原因是我不知道该使用什么搜索词。不用说,"identify file type by content/structure" 没有任何帮助,它只是给我关于如何查找 jpg、pdf 等的结果。如果我看到其他人为处理类似问题而编写的一些代码,那将会很有帮助。
到目前为止,我的想法是为每种类型制作一个 FileIdentifier class,然后在给定文件时尝试解析它,如果它不起作用,则继续下一种类型。但这对我来说似乎很容易出错,而且我将不得不对大量信息进行硬编码。此外,如果出现另一种格式并且与任何现有格式非常相似,但列中的信息不同,会发生什么情况?
除非您可以限制可能发生的文件格式,否则确实没有放之四海而皆准的答案。您将始终只能找到用于识别格式的启发式方法,除非您可以让设计这些格式的人为其提供唯一标识符,或者您询问用户文件是什么格式。
也就是说,您可以采取一些措施来改善结果,例如确保尝试所有类似格式的实例,然后选择最适合的而不是第一个匹配项。
一般方法总是相同的:尽可能严格地进行每次解码尝试,并且不仅要了解语法,还要了解语义。 IE。如果您知道一个项目只能包含 5 个值之一,或特定范围内的数字,请使用该知识进行检测。另外,不要只是在组件上调用 strtol() 并接受它,检查它是否解析了整个字符串。如果没有,要么就在那里失败,要么保持一个“置信度”值,如果文件有任何可能无效的部分,则降低该值。
然后最后,遍历所有解析结果并选择置信度最高的一个。或者如果你不能,你可以要求用户在最可能的格式之间进行选择。
PS - Unixes 上的文件命令行工具做类似的事情:它查看文件的开头并识别指示特定文件格式的公共序列。
我有一些文本文件类型,其中包含产品信息、库存、供应商信息等数据,它们的结构各不相同。除了结构本身之外,该类型没有其他标识符(没有 headers、没有文件名约定等)
这些文件的一些示例:
(产品和库存)
2326 | 542212 | Bananas | 00023 | 1 | pack
2326 | 297875 | Apples | 00085 | 1 | bag
2326 | 028371 | Pineapple | 00007 | 1 | can
...
(产品和价格)
12556 Meat, pork 0098.57
58521 Potatoes, mashed 0005.20
43663 Chicken wings 0009.99
...
(产品和供应商 - 这里 N 是分隔符)
03038N92388N9883929
28338N82367N2837912
23002N23829N9339211
...
(产品信息-多行)
VIN|Mom & Pops|78 Haley str.
PIN|BLT Bagel|5.79|FRESH
LID|0239382|283746
... (repeats this type of info for different products)
还有其他几个。 我想创建一个函数来识别给定文件是这些类型中的哪一种,只使用内容。 Google 没有任何帮助,部分原因是我不知道该使用什么搜索词。不用说,"identify file type by content/structure" 没有任何帮助,它只是给我关于如何查找 jpg、pdf 等的结果。如果我看到其他人为处理类似问题而编写的一些代码,那将会很有帮助。
到目前为止,我的想法是为每种类型制作一个 FileIdentifier class,然后在给定文件时尝试解析它,如果它不起作用,则继续下一种类型。但这对我来说似乎很容易出错,而且我将不得不对大量信息进行硬编码。此外,如果出现另一种格式并且与任何现有格式非常相似,但列中的信息不同,会发生什么情况?
除非您可以限制可能发生的文件格式,否则确实没有放之四海而皆准的答案。您将始终只能找到用于识别格式的启发式方法,除非您可以让设计这些格式的人为其提供唯一标识符,或者您询问用户文件是什么格式。
也就是说,您可以采取一些措施来改善结果,例如确保尝试所有类似格式的实例,然后选择最适合的而不是第一个匹配项。
一般方法总是相同的:尽可能严格地进行每次解码尝试,并且不仅要了解语法,还要了解语义。 IE。如果您知道一个项目只能包含 5 个值之一,或特定范围内的数字,请使用该知识进行检测。另外,不要只是在组件上调用 strtol() 并接受它,检查它是否解析了整个字符串。如果没有,要么就在那里失败,要么保持一个“置信度”值,如果文件有任何可能无效的部分,则降低该值。
然后最后,遍历所有解析结果并选择置信度最高的一个。或者如果你不能,你可以要求用户在最可能的格式之间进行选择。
PS - Unixes 上的文件命令行工具做类似的事情:它查看文件的开头并识别指示特定文件格式的公共序列。