C++實現文件名(後綴名)批量修改

C++實現文件名批量修改

問題

用戶選擇需要修改文件後綴名的目錄,輸入後綴名後,對該目錄下的所有文件後綴名進行修改

實現

讀取目錄下的所有文件,同時修改文件後綴。在這個過程中,主要用到了幾個windows API:
- FindFirstFileA()
- FindNextFileA()
- FindClose()
以及C函數rename()

 所用函數

  • HANDLE FindFirstFileA (LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData);
    • 含義:查找目錄下的第一個文件
    • 參數:lpFileName:目錄名,如:”D:/Web/new/*” 或者 “D:\\Web\\new\\*” 用雙反斜槓是爲了防止目錄被轉義。同時要匹配目錄下的文件,最後應該使用通配符*,表示匹配目錄內文件
    • 參數:lpFindFileData: 文件數據,這個一個定義好的數據結構,用於保存讀取到的文件的一些屬性。其中cFileName表示文件名;具體定義如下
      typedef struct _WIN32_FIND_DATAA {
      DWORD dwFileAttributes;
      FILETIME ftCreationTime;
      FILETIME ftLastAccessTime;
      FILETIME ftLastWriteTime;
      DWORD nFileSizeHigh;
      DWORD nFileSizeLow;
      DWORD dwReserved0;
      DWORD dwReserved1;
      CHAR cFileName[MAX_PATH];
      CHAR cAlternateFileName[14];
      } WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
    • 返回:返回一個文件句柄,用於之後的關閉或者查找下一個文件的操作
  • BOOL FindNextFileA (HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData);
    • 含義:查找下一個文件
    • 參數:hFindFile:文件句柄,由FindFirstFileA返回獲得
    • 參數:lpFindFileData: 文件數據,這個一個定義好的數據結構,用於保存讀取到的文件的一些屬性。其中cFileName表示文件名
    • 返回:布爾值,表示是否查找到下一個文件
  • BOOL FindClose (HANDLE hFindFile);
    • 含義:關閉文件句柄
    • 參數:hFindFile:文件句柄,由FindFirstFileA返回獲得
    • 返回:布爾值,表示關閉成功或失敗
  • int rename(const char *_OldFilename,const char *_NewFilename);
    • 含義:將文件名OldFilename重命名爲NewFiename
    • 參數:*_OldFilename:舊文件名
    • 參數: *_NewFilename:新文件名
    • 返回:修改成功返回0,失敗返回非0,可用== 0判斷是否修改成功

具體實現

在知道所用函數後,具體實現就比較簡單了,通過文件查找函數找到文件,再使用rename函數將文件重命名即可,在這個過程中,可以查找到一個文件就修改其後綴,也可以將文件全部查找遍歷完存入數組中來循環重命名

#ifndef FILEOPERATION_H
#define FILEOPERATION_H
#include <stdio.h>
#include <string>
#include <vector>
#include <windows.h>

class FileOperation
{
public:
    FileOperation();
    FileOperation(std::string dir, std::string suffix);
    ~FileOperation();
    std::string err_msg() const { return err_msg_;}
    int error_code() const { return error_code_;}
    void set_error_code(int error_code) { error_code_ = error_code;}
    void set_err_msg(std::string err_msg) { err_msg_ = err_msg;}
    int Count() const { return file_list_->size();}
    bool RenameFile();
protected:
    void FindFiles();
private:
    std::string dirname_;
    std::string suffix_;
    std::string err_msg_;
    std::vector<std::string> *file_list_;
    WIN32_FIND_DATAA current_file_;
    HANDLE handle_;
    int error_code_;
    bool FindNext();
};

#endif // FILEOPERATION_H
  • 具體實現
#include "FileOperation.h"
#include <algorithm>
#include <iterator>
#include <windows.h>

FileOperation::FileOperation() : dirname_("D:/web/new/"), suffix_("html"),
    file_list_(new std::vector<std::string>()), error_code_(0)
{

}

FileOperation::FileOperation(std::string dir, std::string suffix) :
    dirname_(dir), suffix_(suffix), file_list_(new std::vector<std::string>()),  error_code_(0)
{
    dirname_+= "/";
}

FileOperation::~FileOperation()
{
    delete file_list_;
}

bool FileOperation::RenameFile()
{
    this->FindFiles();
    for(std::string &file_data : *file_list_) {
        //從尾部開始找‘.’,中間的.不修改
//        auto name_iter = std::find(file_data.cbegin(), file_data.cend(), '.');
        auto name_iter = std::find(file_data.crbegin(), file_data.crend(), '.');
        std::string name = std::string(file_data.cbegin(), name_iter.base());
        name += suffix_;
        name = dirname_ + name;

        if ( rename((dirname_ + file_data).c_str(), name.c_str()) != 0) {
            error_code_ = -1;
            err_msg_ += "文件"+ file_data +"更改失敗";
        }
    }
    return true;
}

void FileOperation::FindFiles()
{
    LPCSTR dirname = (dirname_ + "*").c_str();
    handle_ = ::FindFirstFileA(dirname, &current_file_);
    if (handle_ != INVALID_HANDLE_VALUE) {
        if (FindNext())  
            while (FindNext()) {
                file_list_->push_back(current_file_.cFileName); //從第三個文件開始,前兩個不寫入
            }
    }
    ::FindClose(handle_);
}

bool FileOperation::FindNext()
{
    return ::FindNextFileA(handle_, &current_file_);
}

需要注意的是:在windows目錄下,讀取出來的文件中,前兩個文件分別爲/.,/ ..,因此,爲了避免這種情況,在讀取到第三個文件時開始往vector裏寫入數據

點擊獲取源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章