windows 合并linux的分卷文件

一般在linux上使用tar命令和split命令对文件进行分卷压缩,在linux上可以用cat命令合并分卷。但在windows上我不知道怎么合并,就写了一个小工具。

程序假设分卷个数小于等于99个,后缀是%02d形式的

传入前缀即可,生成一个前缀的文件,需要提前保证这个文件不存在

比如1.mp4

在linux上分卷压缩成了

1.mp4.gz.00
1.mp4.gz.01
1.mp4.gz.02
1.mp4.gz.03

那么使用方法为

mergefile.exe 1.mp4.gz.

最后会生成一个1.mp4.gz的文件

因为windows的文件不能以.结束,所以就变成了1.mp4.gz

解压这个文件即可

#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <stack>
#include <stdio.h>
#include <direct.h>
#include <io.h>

using namespace std;

bool check_args(int argc, char **argv)
{
    // 传输的路径参数不能以*结尾,否则cmd会自动补全成对应的匹配文件
//    cout<<argc<<endl;
//    for(int i=0;i<argc;i++)
//    {
//        cout<<argv[i]<<endl;
//    }
    return argc==2;
}

string get_cwd()
{
    char buffer[1024];
    memset(buffer, '\0', sizeof(buffer));
    _getcwd(buffer, 1024);
    return buffer;
}

vector<string> split_string(string s, vector<char> cs)
{
    vector<string> ans;
    string t="";
    for(int i=0;i!=s.size();i++)
    {
        bool flag = 0;
        for(int j=0;j!=cs.size();j++)
        {
            if(s[i]==cs[j])
            {
                flag=1;
                break;
            }
        }
        if(flag&&t.size()>0)
        {
            ans.push_back(t);
            t="";
        }
        else
        {
            t+=s[i];
        }
    }
    if(t.size())ans.push_back(t);
    t = "";
    return ans;
}


string get_file_folder(string file_path)
{
    int index = -1;
    for(int i=file_path.size()-1;i>=0;i--)
    {
        if(file_path[i]=='/'||file_path[i]=='\\')
        {
            index = i;
            break;
        }
    }
    string folder_path = "";
    for(int i=0;i<index;i++)folder_path+=file_path[i];
    return folder_path;
}


string get_file_name_from_file_path(string file_path)
{
    int index = -1;
    for(int i=file_path.size()-1;i>=0;i--)
    {
        if(file_path[i]=='/'||file_path[i]=='\\')
        {
            index = i;
            break;
        }
    }
    string file_name = "";
    for(int i=index+1;i<file_path.size();i++)
    {
        file_name+=file_path[i];
    }
    return file_name;
}

string refine_file_path(string file_path)
{
    // 路径有可能是绝对路径。有可能是相对路径。有可能是错误路径

    // 首先去掉文件名,拿到文件的文件夹路径
    string folder_path = "";
    int index = -1;
    for(int i=file_path.size()-1;i>=0;i--)
    {
        if(file_path[i]=='/'||file_path[i]=='\\')
        {
            index = i;
            break;
        }
    }
    for(int i=0;i<index;i++)
        folder_path+=file_path[i];
    string file_template_name = "";
    for(int i=index+1;i<file_path.size();i++)
        file_template_name+=file_path[i];
    // 此时拿到文件夹路径后,再去除路径中的.和..
    vector<string> folder_path_split = split_string(folder_path, {'/', '\\'});
    stack<string> folder_path_stack;
    for(int i=0;i!=folder_path_split.size();i++)
    {
        if(folder_path_split[i]==".")continue;
        if(folder_path_split[i]==".."&&folder_path_stack.size()>0)
            folder_path_stack.pop();
        else
            folder_path_stack.push(folder_path_split[i]);
    }
    folder_path = "";
    while(folder_path_stack.size())
    {
        if(folder_path.size())folder_path="/"+folder_path;
        folder_path=folder_path_stack.top()+folder_path;
        folder_path_stack.pop();
    }
    if(folder_path.size()==0)folder_path=get_cwd();
    return folder_path+"/"+file_template_name;
}

vector<string> get_folder_files(string folder_path)
{
    vector<string> files;
    _finddata_t fileinfo;
    intptr_t handle;
    handle = _findfirst((folder_path+"/*").c_str(), &fileinfo);
    if (handle == -1) {
        printf("path %s is exist\n", folder_path.c_str());
        return files;
    }
    do
    {
        if (fileinfo.attrib & _A_SUBDIR)
            continue;
        else
            files.push_back(folder_path+"/"+fileinfo.name);
    } while (_findnext(handle, &fileinfo) == 0);

    _findclose(handle);

    return files;
}

inline bool is_file_exists(const std::string& file_path) {
    return ( access( file_path.c_str(), F_OK ) != -1 );
}

bool check_merge_files(string file_path, vector<string> files)
{
    string file_template_name = get_file_name_from_file_path(file_path);
    string folder_path = get_file_folder(file_path);
    // 1.mp4.gz*
    string first_file_path = folder_path + "/"+ file_template_name+ "00";
    string output_file_path = folder_path + "/"+ file_template_name;
    return is_file_exists(first_file_path) && (!is_file_exists(output_file_path));
}

void merge_files(string file_path, vector<string> files)
{
    string file_template_name = get_file_name_from_file_path(file_path);
    string folder_path = get_file_folder(file_path);
    // 1.mp4.gz*
    const int max_num = 99;
    string prefix_file_path = folder_path + "/"+ file_template_name;
    string output_file_path = folder_path + "/"+ file_template_name;
    int cnt=0;
    const int buffsize=2048;
    char buff[buffsize];
    int read_count=0;
    FILE *output_fp = fopen(output_file_path.c_str(), "wb");
    if(output_fp==NULL)return;
    while(cnt<=max_num)
    {
        string s_no = to_string(cnt);
        if(s_no.size()==1)s_no = "0"+s_no;
        string t_file_path = (prefix_file_path + s_no);
        if(is_file_exists(t_file_path))
        {
            FILE *t_fp = fopen(t_file_path.c_str(), "rb");
            while(!feof(t_fp))
            {
                read_count = fread(buff,sizeof(char),buffsize,t_fp);
                fwrite(buff,sizeof(char),read_count,output_fp);
            }
            fclose(t_fp);
        }
        cnt++;
    }
    fclose(output_fp);
}

int main(int argc, char **argv) {
    if(!check_args(argc, argv))
    {
        printf("usage: mergerfile.exe 1.mp4.gz.\n");
        exit(0);
    }
    string file_path = refine_file_path(argv[1]);
    string folder_path = get_file_folder(file_path);
    vector<string> files = get_folder_files(folder_path);
    if(!check_merge_files(file_path, files))
    {
        printf("can't find files like %s, or %s already exists!\n", argv[1], argv[1]);
        exit(0);
    }
    merge_files(file_path, files);
    return 0;
}

文章目录