最近项目有个判断文件类型的需求,经过调研发现目前判断文件类型的方式主要有两种:一是打开文件,匹配文件内容(当然通过文件后缀判断也可以,但是不准确。)。二是使用libmagic库进行判断,linux操作系统中file命令就是使用了libmagic库。这里我介绍使用libmagic静态库的方式。
libmagic静态库链接到项目中进行文件类型判断。使用静态库适合打包成可执行程序在不同的机器上执行,但是同时需要将magic.mgc文件一起打包,缺少该文件则无法判断文件类型。
首先下载libmagic静态库,下载地址(https://anaconda.org/bioconda/libmagic/files)
然后引用头文件magic.h并且链接静态库libmagic.a到工程中,同时还需要将/share/misc/magic.mgc文件拷贝到项目配置文件中。
最后编写代码如下
#include "magic.h"
#include <stdio.h>
#include <string>
bool isELFFilePath(magic_t handle_, std::string path) {
if (handle_ == NULL)
{
return false;
}
auto type = magic_file(handle_, path.c_str());
if (type == NULL)
{
return false;
}
std::string file_type = type;
if (file_type.find("ELF") != std::string::npos)//判断文件是否为ELF文件
{
return true;
}
return false;
}
magic_t initFileHandle() {
std::string magic_path = "/usr/local/magic.mgc";//数据库文件路径
auto handle_ = magic_open(MAGIC_NONE | MAGIC_COMPRESS);
if (handle_ == NULL)
{
printf("magic_open handle failed!");
return NULL;
}
if (magic_load(handle_, magic_path.c_str()) != 0) {
magic_close(handle_);
return NULL;
}
return handle_;
}
int main() {
auto handle_ = initFileHandle();
if (handle_ == NULL) {
return -1;
}
std::string file = "/home/test.jpg";
if (isELFFilePath(handle_, file)) {
printf("file:%s is ELF file!", file.c_str());
}
else {
printf("file:{} is not ELF file!", file.c_str());
}
}
需要注意的是数据库文件路径如果填写NULL,默认路径为/usr/share/misc/magic.mgc
编译时候发现出现报错:
经查阅得知是没有指定链接参数-lz(/usr/lib/libz.so,/usr/lib/libz.a ),链接命令加上-lz问题解决。
执行结果如下:
通过命令查看/home/test.jpg文件如下:
可以证实这个代码判断正确,事实上这确实是一个执行程序重命名后的文件。同时也反应通过后缀名的方式判断文件类型存在不准确性。