最近想把台式机上的虚拟机用U盘拷贝到笔记本上,但是U盘太小,又不想花钱买大的,只好自己动手用 C 写一个 拆分器和粘合器,把大文件拆分成若干小文件,这样就可以用U盘分片段运输,最后把片段文件粘合一下就行了。
其实大文件的拆分和粘合是挺有用的,比如你可以在拆分时,分别对每个片段动一下手脚(每隔几个字节插入一个字节),这样就相当于文件加密了,因为,只有你知道是怎么拆分的,所以只有你知道怎么粘合最终文件。废话不多说,我们先来最简单的拆分(就是不动手脚的那种)。
我用的开发环境是 Visual Studio 2012 Express Desktop 中文版
拆分器源码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
void f拆分文件(FILE * o文件, int size);
int main()
{
_a1:
printf("请输入分隔后每个片段的大小(单位:10mb)\n");
int n片段大小 = 0;
scanf("%d", &n片段大小);
if(n片段大小 < 1 || n片段大小 > 50)
{
printf("片段大小超出预定范围,必须介于 1 和 50 之间\n");
goto _a1;
}
printf("请输入要分隔的文件的完全路径(不要超过100个字符)\n");
_a2:
char s目标文件路径[256];
scanf("%s", s目标文件路径);
FILE * o文件 = fopen(s目标文件路径, "rb"); /// BUG 记录:此处打开模式如果写成 “br”,则会在运行时抛出打开模式错误的异常
if(o文件 == NULL)
{
printf("指定的文件打开时发生了错误,请重新指定文件\n");
goto _a2;
}
f拆分文件(o文件, n片段大小);
fclose(o文件);
getchar();getchar();
}
void f全部写入(FILE * o文件, char * buffer, int count);
#define _1mb (1024 * 1024) //BUG 记录:如果这里的宏定义未加括号保护,则下面 printf 里的计算不正确
void f拆分文件(FILE * o文件, int size)
{
int n拆分尺寸 = size * 10 * _1mb;
int n待写入 = n拆分尺寸;
int n欠写入 = 0;
char * buffer = 0; //BUG 记录:如果此处 写成 char buffer[_1mb]; 则在我机器上出现 函数栈溢出的运行时异常
char * buffer2 = 0;
int n片段序号 = 1;
char s片段文件名[64];
//建立 1mb 的缓存
buffer = (char *)malloc(_1mb);
if(buffer == NULL)
return;
//这里用 if(){...} 块会增加一个缩进和一个大括号嵌套,不利于代码阅读,还是用 goto 吧
_a3:
//创立片段文件
sprintf(s片段文件名, "%d.cf", n片段序号);
FILE * o片段 = fopen(s片段文件名, "wb"); /// BUG 记录:此处打开模式如果写成 “bw”,则会在运行时抛出打开模式错误的异常
//处理欠写入的情况
if(n欠写入 > 0)
{
f全部写入(o片段, buffer2, n欠写入);
n待写入 -= n欠写入;
}
int n已读取 = 0;
//写入片段文件
while(n待写入 > 0)
{
n已读取 = fread(buffer, 1, _1mb, o文件);
if(n已读取 < 1)
break;
if(n待写入 >= n已读取)
n待写入 -= n已读取;
else
{
n欠写入 = n已读取 - n待写入;
n已读取 = n待写入;
n待写入 = 0;
buffer2 = buffer + n已读取;
}
//写入 n已读取 到片段文件
f全部写入(o片段, buffer, n已读取);
}
fflush(o片段);
fclose(o片段);
n片段序号 += 1;
printf("已写入片段文件:%s,大小:%f mb\n", s片段文件名, ((double)(n拆分尺寸 - n待写入)) / _1mb);
//BUG 记录:如果上面对 _1mb 的宏定义未加括号保护(#define _1mb (1024*1024)),则此处计算不正确
n待写入 = n拆分尺寸;
Sleep(1000);
if(n已读取 > 0)
goto _a3;
free(buffer);
printf("一共拆分成 %d 个子文件\n", n片段序号 - 1);
return;
}
void f全部写入(FILE * o文件, char * buffer, int count)
{
int n已写入 = 0;
while(count > 0)
{
n已写入 = fwrite(buffer, 1, count, o文件);
buffer += n已写入;
count -= n已写入;
}
}
粘合器源码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <windows.h>
#define _1mb (1024 * 1024)
void f全部写入(FILE * s读, FILE * s写, char * s缓存);
void main()
{
char * s缓存 = (char *)malloc(_1mb);
if(s缓存 == NULL)
{
printf("创建缓存失败\n");
return;
}
FILE * s写入 = fopen("result.all", "wb");
if(s写入 == NULL)
{
printf("创建写入文件失败\n");
return;
}
int n片段序号 = 1;
_a1:
char s读取文件名[64];
sprintf(s读取文件名, "%d.cf", n片段序号);
FILE * s读取 = fopen(s读取文件名, "rb");
if(s读取 == NULL)
{
printf("片段文件 %s 不存在,停止操作\n", s读取文件名);
goto _a2;
}
f全部写入(s读取, s写入, s缓存);
fclose(s读取);
printf("写入片段 %s \n", s读取文件名);
Sleep(1000);
n片段序号 += 1;
goto _a1;
_a2:
free(s缓存);
fclose(s写入);
printf("已经将所有片段文件粘合成 文件 result.all,请修改扩展名\n");
getchar();getchar();
}
void f全部写入(FILE * o读, FILE * o写, char * s缓存)
{
int n读入 = 0;
while((n读入= fread(s缓存, 1, _1mb, o读)) > 0)
{
char * buffer = s缓存;
while(n读入 > 0)
{
int n已写 = fwrite(buffer, 1, n读入, o写);
n读入 -= n已写;
buffer += n已写;
}
}
fflush(o写);
}
粘合器运行截图:
大家都看到了吧,先拆分成小文件,然后再将这些小文件粘合,最后的大文件就是原来那个(可用)。
欢迎到我的微博上去玩, weibo.com/litingsoft