⚡文件工具类⚡

目录

🌳.文件工具类的介绍

🌳.文件工具类的功能简介

🌳.stat接口

🍎. 获取文件的大小

🍎.判断文件是否存在

🍎.获取文件最后一次进入时间

🍎.获取文件最后一次修改时间

🌳.获取文件名

🌳.获取文件的内容

🌳.往文件中写入内容

🌳.获取目录下所有文件的相对路径

🌳.压缩文件

🌳.解压文件

🌳.删除文件

🚀.Json工具类



🌳.文件工具类的介绍

文件工具类主要是创建一个文件对象将磁盘上的一个文件关联起来,方便对该文件进行操作和获取文件的信息等操作,包括获取文件的内容文件的大小,文件的访问时间,往文件中写入内容等操作。

🌳.文件工具类的功能简介

  • 获取文件的大小
  • 判断文件是否存在
  • 获取文件最后一次进入时间
  • 获取文件最后一次修改时间
  • 获取文件名
  • 获取文件名
  • 获取文件的内容
  • 往文件中写入内容
  • 获取目录下所有文件的相对路径
  • 压缩文件
  • 解压文件
  • 删除文件

文件的 成员变量是filename,它存储程序能够访问到文件的相对路径绝对路径,通过filename能够对文件进行各种操作。

   
    class FileUtil{
      private:
        std::string filename;
      public:
        FileUtil(const char* str){                                                          
          filename=str;
        }
  
        FileUtil(const std::string s){
          filename=s;
        }
        size_t GetFileSize();       //获取文件大小
        size_t GetFileAccessTime() ;//获取文件最后一次访问时间
        size_t GetFileModfityTime();//获取文件最后一次修改时间
        std::string GetFilename();  //获取文件名
        bool Exist();               //判断文件是否存在
        bool SetContent(std::string& body);//往文件中写入body的内容
        bool GetContent(std::string& body);//获取文件内容,将文件内容放入body中
        //获取文件的部分内容
        bool GetPosContent(size_t pos,size_t n,std::string& body);
        bool Remove();//删除文件
        //压缩文件,压缩文件名为packname
        bool PackFile(const std::string&packname);
        //解压缩文件,解压缩文件名为packname
        bool UnpackFile(const std::string& unpackname);
        //获取目录下的所有文件的相对路径
        bool GetPathInDir(std::vector<std::string>& arry);
        //创建目录
        bool CreateDir(std::string& dirname);
    };

🌳.stat接口

stat接口可以直接判断文件是否存在,直接获取到文件的大小,文件最后一次进入时间,文件最后一次修改时间

 stat接口通过文件相对路径或者绝对路径来访问到文件,获取到文件属性信息.

int stat(const char *path, struct stat *buf);

返回值: 如果通过文件路径找不到文件,则返回-1,找到了返回0.

文件的属性信息存储到struct stat对象中,struct stat结构体的成员有:
 

           struct stat {
               dev_t     st_dev;     /* 包含文件的设备IDe */
               ino_t     st_ino;     /* inode number */
               mode_t    st_mode;    /* protection */
               nlink_t   st_nlink;   /* 硬链接数 */
               uid_t     st_uid;     /* 文件所用者的ID*/
               gid_t     st_gid;     /* 文交所属组的ID */
               dev_t     st_rdev;    /* 设备ID */
               off_t     st_size;    /* 文件的总大小*/
               blksize_t st_blksize; /* 文件系统I/O的块大小 */
               blkcnt_t  st_blocks;  /* 分配的512B块数 */
               time_t    st_atime;   /* 最后一次进入的时间 */
               time_t    st_mtime;   /* 最后一次访问的时间 */
               time_t    st_ctime;   /* 上次状态更改时*/
           };

🍎. 获取文件的大小

size_t sjp::FileUtil::GetFileSize(){    
    struct stat buf;    
    if(stat(filename.c_str(),&buf)==-1){    
      cout<<"GetFileSize fail.."<<endl;    
    }    
    return buf.st_size;    
}    
    

🍎.判断文件是否存在

bool sjp::FileUtil::Exist(){
  struct stat buf;
  if(stat(filename.c_str(),&buf)==-1){
    return false; 
  }
  return true;
}

🍎.获取文件最后一次进入时间

size_t sjp::FileUtil::GetFileAccessTime(){    
    struct stat buf;    
    if(stat(filename.c_str(),&buf)==-1){    
      cout<<"GetFielAccessTime fail.."<<endl;    
    }    
    return buf.st_atime;    
}    
    

🍎.获取文件最后一次修改时间

size_t sjp::FileUtil::GetFileModfityTime(){    
    struct stat buf;    
    if(stat(filename.c_str(),&buf)==-1){    
      cout<<"GetFileSize fail.."<<endl;    
    }    
    return buf.st_mtime;    
}    

🌳.获取文件名

功能:

FIleUtil中filename存储的时路径,GetFilename的功能仅仅获取文件名,例如文件的路径是wwwroot/filename,获取文件名就是filename.

std::string sjp::FileUtil::GetFilename(){
  size_t pos=filename.rfind("/");
  if(pos==std::string::npos)
  {
    return filename;
  }
  return filename.substr(pos+1);
}

🌳.获取文件的内容

功能:

GetPosContent 获取FileUtil中的文件中从pos位置到pos+n的数据,获取到的文件数据存储在body中.

//获取文件的部分内容
bool sjp::FileUtil::GetPosContent(size_t pos,size_t n,std::string& body){
  if(!Exist()){
    cout<<"GetPostContent: file is not exist"<<endl;
    return false;
  }                                                                                         

  if(GetFileSize()<pos+n){
    cout<<"GetFileSize fail:42"<<endl;
    return false;
  }
  //按照二进制流的方式打开文件
  std::ifstream ifs;
  ifs.open(filename,std::ios::binary);
  //将文件位置偏移到pos位置
  ifs.seekg(pos,std::ios::beg);
  body.resize(n);
  //获取到的数据放进body中
  ifs.read(&body[0],n);
  if(ifs.good()==false){
    std::cout<<"get file content failed\n"<<endl;
    return false;
  }
  ifs.close();
  return true;
}

//获取文件的所有的内容
bool sjp::FileUtil::GetContent(std::string& body){
  size_t size=GetFileSize();
  return GetPosContent(0,size,body);
}
  • ifstream对象能够将文件中的数据关联起来,并可以读取文件中的内容。
  • ifs.seekg(pos,std::ios::beg) :将文件从起始位置偏移到pos的位置

🌳.往文件中写入内容

功能:

SetContent将body中的数据写入到FileUtil关联的文件中。

bool sjp::FileUtil::SetContent(std::string& body)
{
  //打开文件将文件与ofs关联起来
  std::ofstream ofs;
  ofs.open(filename,std::ios::binary);
  //将body的数据写入文件中
  ofs.write(body.c_str(),body.size());
  if(ofs.good()==false)
  {
    cout<<"FileUtil.cpp 52 line:SetContent failing"<<endl;
    return false;
  }
  return true;
}

  • ofstream对象能够与文件进行关联起来,并可以往文件中写入数据

🌳.获取目录下所有文件的相对路径

功能:

如果FileUtil存储的是一个目录,GetPathInDir可以获取到目录下的所有文件的相对路径。

#include<experimental/filesystem> 
namespace fs = std::experimental::filesystem;
bool sjp::FileUtil::GetPathInDir(std::vector<std::string>& arry)
{
  for(auto & p:fs::directory_iterator(filename)){
    arry.push_back(p.path().relative_path());
  }
  return true;
}

  • 获取目录下所有文件信息,需要使用c++17中的目录迭代器,目录迭代器能够目录下所有的文件信息.
  • 迭代器获取到的文件信息存放在directory_entry对象里面,在directory_entry类中包括一个path的类型的变量,path类里面有一个relative_path接口。这个接口是获取文件的相对路径
  • 使用c++17的目录迭代器需要包含filesystem文件。
  • 如果使用g++编译器,需要在编译指令中添加-lstdc++fs,例如:
g++ -o main main.cc FileUtil.cpp  -std=c++11 -lstdc++fs -g 

🌳.压缩文件

功能:

将FileUtil对象中的文件进行压缩,压缩的文件为packname

bool sjp::FileUtil::PackFile(const std::string& packname)
{
  //将打开文件
  std::ifstream ifs;
  ifs.open(filename.c_str(),std::ios::binary);
  ifs.seekg(0,ifs.end);
  int size=ifs.tellg();
  ifs.seekg(0,ifs.beg);
  
  //将文件信息往提取到文件中
  std::string body;
  body.resize(size);
  ifs.read(&body[0],size);
  
  //压缩文件       
  std::string packed=bundle::pack(bundle::LZIP,body);                                            
  std::ofstream ofs;    
  ofs.open(packname.c_str());    
  ofs.write(&packed[0],packed.size());    
  ofs.close();    
  ifs.close();     
  return true;
}

压缩文件需要使用bundle库中接口,bundle的具体使用在下面这篇文章中有详细解析:

bundle文件压缩库的使用

🌳.解压文件

功能:

将FileUtil对象中的文件进行解压缩,压缩的文件为unpackfile.

bool sjp::FileUtil::UnpackFile(const std::string& unpackfile){    
    std::ifstream ifs;        
    ifs.open(filename.c_str(),std::ios::binary);        
    ifs.seekg(0,ifs.end);        
    int size=ifs.tellg();        
    ifs.seekg(0,ifs.beg);    
    
    std::string body;                                                        
    body.resize(size);                                                  
    ifs.read(&body[0],size);                                            
    std::string unpacked=bundle::unpack(body);      
    
    std::ofstream ofs;    
    ofs.open(unpackfile.c_str(),std::ios::binary);    
    ofs.write(unpacked.c_str(),unpacked.size());    
    ifs.close();    
    ofs.close();    
    return true;    
}    

解压缩文件也是需要使用bundle库中接口。

🌳.删除文件

功能:

删除FileUtil中的文件

bool sjp::FileUtil::Remove(){
  remove(filename.c_str());
  return true;
}

🚀.Json工具类

Json工具类的设计需要使用到Jsoncpp接口,Jsoncpp接口和Json的详解在这篇文章有详细解析:
【Json】——jsoncpp的序列化以及反序列化

  • Serialize将Json::Value对象root序列化 Json字符串body。
  • UnSerialize将Json字符串body反序列化为Json::Value对象root.
    class JsonUtil    
    {    
    public:    
      //将root序列化为Json字符串    
     static bool Serialize(Json::Value& root,std::string& body)        
      {        
        Json::StreamWriterBuilder swb;            
        std::unique_ptr<Json::StreamWriter> s(swb.newStreamWriter());            
        std::stringstream ss;            
        //将value对象转换为Json数据流            
        s->write(root,&ss);          
        body=ss.str();        
        return true;        
      }        
            
    //将Json字符串反序列化为Json::Value    
    static bool UnSerialize(Json::Value& root,std::string& body)        
    {        
      Json::CharReaderBuilder crb;        
      std::unique_ptr<Json::CharReader> cr(crb.newCharReader());        
      std::string err;        
W>    bool ret=cr->parse(body.c_str(),body.c_str()+body.size(),&root,&err);        
      return true;    
    }        
    };    

<think>嗯,用户想了解O文件和SO文件的区别与作用。用户可能是开发人员或者学习系统编程的学生,需要明确这两种文件类型在IT开发中的具体用途。 O文件是编译过程中的中间产物,对应目标文件(Object File)。这类文件包含机器码和符号表,但尚未解决外部引用。当用户编译C/C++程序时,每个源文件会生成对应的.o文件。例如gcc -c main.c会生成main.o。目标文件的作用在于分模块编译,提高大型项目的编译效率。 SO文件则是共享对象文件(Shared Object),也就是动态链接库。这类文件在程序运行时被加载,后缀通常是.so(Unix/Linux)或.dll(Windows)。典型的例子是Linux系统的glibc库文件。动态链接库的核心价值在于资源共享和内存优化,多个程序可以共用同一个so文件,且更新库时无需重新编译主程序。 用户可能混淆了编译时和运行时两种场景。需要强调O文件是编译阶段的临时产物,而SO文件是发布阶段的最终产物。另外,用户可能没意识到动态链接带来的性能权衡:虽然节省内存,但首次加载会有轻微延迟。 可以补充说明两种文件的技术细节差异:O文件使用特定目标格式(如ELF),包含重定位信息;SO文件需要位置无关代码(PIC)支持。开发场景中,O文件通过ar命令打包成静态库(.a),而SO文件通过gcc -shared生成。 用户深层需求可能是想优化项目结构,或是解决链接错误。可以预判ta接下来会问如何创建/使用动态库,或者遇到"undefined reference"错误时的处理方法。</think>在IT开发中,O文件和SO文件是两种关键的文件类型,它们在编译和运行过程中扮演不同角色: ### 🧩 O文件(目标文件) 1. **定义** - 扩展名通常为`.o`(Unix/Linux)或`.obj`(Windows) - **编译阶段产物**:由源代码文件(如`.c/.cpp`)经编译器生成 - **内容**:包含机器码、符号表、重定位信息等,但未解决外部依赖 2. **核心作用** ```mermaid graph LR A[源代码.c] -->|编译器| B(O文件) B -->|链接器| C[可执行文件] ``` - ✅ **模块化编译**:大型项目拆分编译,修改单文件只需重编译对应.o文件 - ✅ **静态库基础**:通过`ar`命令打包成`.a`静态库(如`libmath.a`) - ✅ **保留调试信息**:支持GDB等工具进行符号级调试 ### 🔄 SO文件(共享对象文件) 1. **定义** - 扩展名为`.so`(Linux)或`.dll`(Windows),即**动态链接库** - **链接阶段产物**:由多个O文件经链接器生成`gcc -shared -o libfoo.so foo.o bar.o` 2. **核心作用** ```mermaid graph TB P[程序启动] --> Q{加载SO?} Q -->|是| R[动态链接器加载SO] R --> S[内存映射] S --> T[程序运行] ``` - 🌐 **资源共享**:多个程序可共用同一SO(如`libc.so`),减少内存占用 - **热更新能力**:更新SO无需重新编译主程序 - 📦 **减小体积**:可执行文件仅保留动态链接引用(对比静态链接) --- ### 🆚 关键区别对比 | 特性 | O文件 | SO文件 | |--------------|----------------------------|----------------------------| | **生成阶段** | 编译阶段 | 链接阶段 | | **独立性** | 不可直接执行 | 可被动态加载 | | **内存占用** | 静态链接时复制到可执行文件 | 内存中仅存一份副本 | | **更新影响** | 需重新链接主程序 | 替换文件即可生效 | | **典型操作** | `gcc -c file.c → file.o` | `gcc -shared -o lib.so *.o`| > 💡 **开发场景示例**: > 修改`utils.c`后只需重生成`utils.o`并重新链接,而更新`libnetwork.so`时,所有依赖程序在下次启动时自动加载新版本[^1]。 --- ### ❓相关问题 1. 动态链接(SO)与静态链接(.a)在性能上有何差异? 2. 如何解决Linux程序运行时出现的"cannot open shared object file"错误? 3. 在CMake项目中如何正确配置动态库的生成和链接? 4. 为什么Windows系统需要同时提供.dll和.lib文件? 5. 位置无关代码(PIC)在SO文件中起什么关键作用? [^1]: 动态链接技术显著优化了系统资源利用率,尤其在依赖复杂的大型应用中——《程序员的自我修养:链接、装载与库》
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值