首先通过两种方法得到文件的大小,字节为单位,根据这个大小使用malloc分配固定的空间buffer,二进制流读入文件,把二进制流写入buffer中,buffer输出写入到新的文件。
源文件1.txt,输出文件1.txt.txt
环境为Ubuntu 16.04,gcc
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
//get file size
int file_size(char *filename)
{
struct stat statbuf;
stat(filename, &statbuf);
int size = statbuf.st_size;
printf("the size of file %s is : %d byte\n", filename, size);
return size;
}
long file_size2(FILE *file)
{
/* 获取文件大小 */
fseek (file, 0, SEEK_END);
long lSize;
lSize = ftell (file);
rewind (file);//point back to the begin
printf("the size of file is : %ld byte\n", lSize);
return lSize;
}
//inputName: 1.txt -> outputName:1.txt.txt
void initOutname(char *filename)
{
int nameLen = strlen(filename), suffixLen = 0;
char *first = strrchr(filename, '.');
if (first == NULL) return ;
strcat(filename, first);
}
int main(int argc, char *argv[])
{
char *buffer = NULL;
char filename[100];
if(argc == 1){
strcpy(filename, "1.txt");
}else if(argc == 2){
strcpy(filename, argv[1]);
}else {
printf("parameter ERROR!\n");
return -1;
}
int len = file_size(filename);
FILE *file = fopen(filename, "rb");
if (!file)
{
printf("%s: can not open %s\n", __func__, filename);
return -1;
}
long llen = file_size2(file);
//len bytes
buffer = malloc(llen);
// printf("%ld\n", sizeof(char));
if(NULL != buffer)
{
printf("success\n");
}
else
{
printf("the file is too large to load!\n");
return -1;
}
/* 将文件拷贝到buffer中 */
size_t result = fread (buffer, 1, llen, file);
if (result != llen)
{
printf("fread ERROR\n");
return -1;
}
printf("%ld\n", result);
printf("%s\n", buffer);
initOutname(filename);
FILE *fileOut = fopen(filename, "w+");
if (!fileOut)
{
printf("%s: can not open %s\n", __func__, filename);
return -1;
}
result = fwrite(buffer, 1, llen, fileOut);
if (result != llen)
{
printf("%s: can not write %s\n", __func__, filename);
return -1;
}
fclose (fileOut);
fclose (file);
free(buffer);
return 0;
}
在测试大文件(5G)大小时候,第一种方法测出只有1G,第二种方法比较准确,原因还未知,读者知道的麻烦告诉下~
ant@antBox:/workfile$ ./test /media/sf_share/16.04.vdi
the size of file /media/sf_share/16.04.vdi is : 1075838976 byte
the size of file is : 5370806272 byte
success
第一种方法是一次性申请读入文件大小的内存空间buffer,一次性写入buffer,再输出到文件中,但文件特别大时候,malloc时候就失败了,解决方法是申请固定size大小的buffer,得到文件的大小len,每次写入size字节的内容,更新len为len-size,刚开始判断len<size,如果是的话则写入len大小。最终退出循环时,len减为0
更新后的代码使用第二种文件大小得到方法,代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 32768
#include <sys/stat.h>
//inputName: 1.txt -> outputName:1.txt.txt
void initOutname(char *filename)
{
int nameLen = strlen(filename), suffixLen = 0;
char *first = strrchr(filename, '.');
if (first == NULL) return ;
strcat(filename, first);
}
long file_size2(FILE *file)
{
/* 获取文件大小 */
fseek (file, 0, SEEK_END);
long lSize;
lSize = ftell (file);
rewind (file);//point back to the begin
printf("the size of file is : %ld byte\n", lSize);
return lSize;
}
int main(int argc, char *argv[])
{
char *buffer = NULL;
char filename[100];
if(argc == 1)
{
strcpy(filename, "1.txt");
}
else if(argc == 2)
{
strcpy(filename, argv[1]);
}
else
{
printf("parameter ERROR!\n");
return -1;
}
FILE *file = fopen(filename, "rb");
if (!file)
{
printf("%s: can not open %s\n", __func__, filename);
return -1;
}
initOutname(filename);
FILE *fileOut = fopen(filename, "w");
fclose (fileOut);
fileOut = fopen(filename, "a+");
if (!fileOut)
{
printf("%s: can not open %s\n", __func__, filename);
return -1;
}
buffer = malloc(MAXSIZE);
if(NULL != buffer)
{
printf("success\n");
}
else
{
printf("%s the file is too large to load!\n", __func__);
return -1;
}
/* 将文件拷贝到buffer中 */
int bytes_read = 0;
int onceSize = MAXSIZE;
int len = file_size2(file);
for(; len > 0; len -= onceSize)
{
if(len < MAXSIZE) onceSize = len;
fread (buffer, 1, onceSize, file);
fwrite(buffer, 1, onceSize, fileOut);
}
fclose (fileOut);
fclose (file);
free(buffer);
return 0;
}
其中打开输出文件方式先使用w目的是新建并清空之前的文件内容,再用二进制追加a+的方式打开。
判断生成的文件和源文件的sha224的值:
ant@antBox:/workfile/SHA$ ./sha sha224 ../1.txt
File('../1.txt'): a069a467f410fae0559382f1e45ec9a850e1e26472eac466588291c7
ant@antBox:/workfile/SHA$ ./sha sha224 ../1.txt.txt
File('../1.txt.txt'): a069a467f410fae0559382f1e45ec9a850e1e26472eac466588291c7
其中读入再写入有一种简单的写法,思想和图片一样。读入了byte_read字节,那么就写入byte_read字节到文件中。
// int onceSize = MAXSIZE;
// int len = file_size2(file);
// for(; len > 0; len -= onceSize)
// {
// if(len < MAXSIZE) onceSize = len;
// fread (buffer, 1, onceSize, file);
// fwrite(buffer, 1, onceSize, fileOut);
// }
while(bytes_read=fread (buffer, 1, MAXSIZE, file))
fwrite(buffer, 1, bytes_read, fileOut);