C ++:如何检查没有扩展名的文件的types

我正在使用boost :: filesystem来search和处理目录中的文件。 但是,而不是处理每个文件(使用boost :: filesystem :: is_regular_file()检查)我只想处理文本文件 (或至less忽略二进制文件)。

即使文件没有扩展名 ,我可以如何实现这一点

我会高度赞赏平台独立的解决scheme。

使用libmagic

所有主要平台(和许多未成年人)都可以使用Libmagic。

 #include <boost/filesystem.hpp> #include <boost/range.hpp> #include <iostream> #include <magic.h> using namespace boost; namespace fs = filesystem; int main() { auto handle = ::magic_open(MAGIC_NONE|MAGIC_COMPRESS); ::magic_load(handle, NULL); for (fs::directory_entry const& x : make_iterator_range(fs::directory_iterator("."), {})) { auto type = ::magic_file(handle, x.path().native().c_str()); std::cout << x.path() << "\t" << (type? type : "UNKOWN") << "\n"; } ::magic_close(handle); } 

打印,例如

 sehe@desktop:~/custom/boost/status$ /tmp/test "./Jamfile.v2" ASCII text "./explicit-failures.xsd" XML document text "./expected_results.xml" XML document text "./explicit-failures-markup.xml" XML document text 

您可以使用标志来控制分类的细节,例如MAGIC_MIME:

 sehe@desktop:~/custom/boost/status$ /tmp/test "./Jamfile.v2" text/plain; charset=us-ascii "./explicit-failures.xsd" application/xml; charset=us-ascii "./expected_results.xml" application/xml; charset=us-ascii "./explicit-failures-markup.xml" application/xml; charset=utf-8 

或者只加载/etc/magic

 sehe@desktop:~/custom/boost/status$ /tmp/test "./Jamfile.v2" ASCII text "./explicit-failures.xsd" ASCII text "./expected_results.xml" ASCII text, with very long lines "./explicit-failures-markup.xml" UTF-8 Unicode text 

没有完美的解决方案。

你可以做一个有根据的猜测,检查文件的内容。 文本文件通常只包含可打印的ASCII文本,这会给你一些提示,但是如果文本是用象形文字写的,它们可能包含误导性的UTF8序列。 许多文件格式在标题中都包含了魔法字,但是没有关于魔法字在哪里找到的常见约定,因此您可以轻松构建一个包含5种不同格式的魔法字的文件,所有这些文件都在正确的位置。

有时候很难确定你看到的是什么类型的文件:

 cat =13 /*/ >/dev/null 2>&1; echo "Hello, world!"; exit * * This program works under cc, f77, and /bin/sh. * */; main() { write( cat-~-cat /*,'( */ ,"Hello, world!" , cat); putchar(~-~-~-cat); } /* ,)') end */ 

这是一个sh脚本,C源代码或f77源代码?

我建议你深入了解一下命令file的来源,尽力做你想做的事情。

你可以从less偷。 如果在前256个字节中有超过5个字符!isprint(c) && !iscntrl(c)在当前语言环境中,则认为文件不是二进制文件。

这也是一个启发式的(这就是为什么less “这可能是一个二进制文件”),但它是一个常见的,通常工作,你可以调整阈值,如果你有一些文件的麻烦。

使用libmagic,你可以找到文件的类型。 man libmagic会给出详细的信息。

通过这个例子

  ` magic_t myt = magic_open(MAGIC_NONE); sprintf(fullfilename, "%s/%s", dir_name,filename); magic_load(myt,NULL); printf("file type is %s", magic_file(myt,fullfilename)); magic_close(myt); `