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

时间:2015-01-05 16:35:27

标签: c++ linux boost

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

即使文件没有扩展名,我有没有办法实现这一目标?

我非常感谢独立于平台的解决方案。

3 个答案:

答案 0 :(得分:4)

使用 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

答案 1 :(得分:2)

没有完美的解决方案。

你可以做一个有根据的猜测,检查文件的内容。文本文件通常只包含可打印的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
*/

that是sh脚本,C源代码还是f77源代码?

我建议您仔细查看命令file的来源,尽最大努力做您尝试做的事情。

答案 2 :(得分:1)

你可以从less窃取。如果当前语言环境中前256个字节中的5个以上字符为less,则!isprint(c) && !iscntrl(c)会将文件视为二进制文件。

这也是一种启发式(这就是为什么less总是说&#34;这个可能是一个二进制文件&#34;),但它通常是常见的如果您遇到某些文件有问题,可以调整阈值。