C ++:如何检查没有扩展名的文件类型
C++: How to check type of files without extension
我正在使用 boost::filesystem
搜索和处理目录中的文件。
但是我不想处理每个文件(使用 boost::filesystem::is_regular_file()
检查)我只想处理文本文件(或至少忽略二进制文件)。
即使文件没有扩展名,有什么方法可以实现吗?
我非常感谢独立于平台的解决方案。
没有完美的解决方案。
您可以进行有根据的猜测,检查文件的内容。文本文件通常只包含可打印的 ASCII 文本,这会给您一些提示,但它们可能包含误导性的 UTF8 序列,例如,如果文本是用象形文字书写的。许多文件格式的 headers 中都包含魔法词,但对于在哪里可以找到魔法词并没有共同的约定,因此您可以轻松地构建一个包含 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-script,C源代码还是f77源代码?
我建议您深入查看命令 file
的源代码,它会尽最大努力完成您尝试做的事情。
你可以从 less
偷东西。 less
如果前 256 个字节中超过 5 个字符在当前语言环境中 !isprint(c) && !iscntrl(c)
,则将文件视为二进制文件。
这也是一种启发式方法(这就是为什么 less
总是说 "this may be a binary file"),但它是一种通常有效的常见方法,如果您有一些文件有问题。
使用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
Using libmagic , you can find the type of file . man libmagic will
give the detailed info.
查看示例
` 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);
`
我正在使用 boost::filesystem
搜索和处理目录中的文件。
但是我不想处理每个文件(使用 boost::filesystem::is_regular_file()
检查)我只想处理文本文件(或至少忽略二进制文件)。
即使文件没有扩展名,有什么方法可以实现吗?
我非常感谢独立于平台的解决方案。
没有完美的解决方案。
您可以进行有根据的猜测,检查文件的内容。文本文件通常只包含可打印的 ASCII 文本,这会给您一些提示,但它们可能包含误导性的 UTF8 序列,例如,如果文本是用象形文字书写的。许多文件格式的 headers 中都包含魔法词,但对于在哪里可以找到魔法词并没有共同的约定,因此您可以轻松地构建一个包含 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-script,C源代码还是f77源代码?
我建议您深入查看命令 file
的源代码,它会尽最大努力完成您尝试做的事情。
你可以从 less
偷东西。 less
如果前 256 个字节中超过 5 个字符在当前语言环境中 !isprint(c) && !iscntrl(c)
,则将文件视为二进制文件。
这也是一种启发式方法(这就是为什么 less
总是说 "this may be a binary file"),但它是一种通常有效的常见方法,如果您有一些文件有问题。
使用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
Using libmagic , you can find the type of file . man libmagic will give the detailed info.
查看示例
` 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);
`