将数据从一个文件复制到另一个文件时,首选二进制读写。使用fgets 或getline 等面向行的输入函数读取文件中的所有字符失败的原因有很多。文本输出函数也有类似的缺点(例如,试图写入可打印范围之外的字符或具有 ASCII 替代含义的字符)
使用fread 和fwrite 从二进制模式读取和写入文件并不比使用fgets 和fputs 更难。但是,使用 fread 和 fwrite 可以避免在文本模式下尝试常规文件复制所固有的缺陷,从而确保您获得正确和准确的数据副本。
如果您知道源文件中只包含文本,那么在文本模式下复制它没有任何问题。这只是意味着您将不得不编写另一个函数来处理非文本文件。 (通常您不会看到基于文件内容的不同复制例程)。以二进制形式进行读写消除了所有这些考虑。
以下是filecopy 函数的简短示例,该函数将文件中的所有字节读入缓冲区,然后将缓冲区的内容写入目标文件。 (缓冲读/写通常效率更高,您可以通过调整MAXS 轻松调整缓冲区大小)该函数返回成功复制的字节数,否则返回-1。如果您有任何问题,请查看并告诉我:
#include <stdio.h>
#include <stdlib.h>
#define MAXS 256
int filecopy (char *source, char *dest);
int main (int argc, char **argv) {
if (argc < 3) { /* validate 2 arguments given */
fprintf (stderr, "usage: %s file1 file2\n", argv[0]);
return 1;
}
int filesize = 0;
if ((filesize = filecopy (argv[1], argv[2])) == -1) {
fprintf (stderr, "error: filecopy failed.\n");
return 1;
}
printf ("\n copied '%s' -> '%s' ('%d' bytes)\n\n",
argv[1], argv[2], filesize);
return 0;
}
int filecopy (char *source, char *dest)
{
char *buf = NULL; /* buffer used to read MAXS bytes from file */
size_t nbytes = 0; /* number of bytes read from file */
size_t idx = 0; /* file index (length) */
FILE *fp = fopen (source, "r"); /* stream pointer */
if (!fp) { /* open source for reading */
fprintf (stderr, "error: file open failed '%s'.\n", source);
return -1;
}
/* allocate MAXS size read buf initially */
if (!(buf = calloc (MAXS, sizeof *buf))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
return -1;
}
/* while data read MAXS *buf from file - realloc for next read */
while ((nbytes = fread (buf+idx, sizeof *buf, MAXS, fp)))
{
idx += nbytes; /* update total bytes read */
if (nbytes < MAXS) break; /* end-of-file reached */
/* full read - realloc for next */
void *tmp;
if (!(tmp = realloc (buf, (idx + nbytes) * sizeof *buf))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
buf = tmp;
}
fclose (fp); /* close input stream */
if (!(fp = fopen (dest, "w+b"))) { /* open output stream */
fprintf (stderr, "error: file open failed '%s'.\n", dest);
exit (EXIT_FAILURE);
}
fwrite (buf, sizeof *buf, idx, fp);
fclose (fp); /* close output stream */
free (buf);
return (int)idx;
}
编译
gcc -Wall -Wextra -O3 -o bin/filecopy_simple filecopy_simple.c
输入文件(二进制)
-rw-r--r-- 1 david david 66672 Nov 19 13:17 acarsout2.bin
使用/输出
$ ./bin/filecopy_simple dat/acarsout2.bin dat/acarsout3.bin
copied 'dat/acarsout2.bin' -> 'dat/acarsout3.bin' ('66672' bytes)
验证
$ ls -al acarsout[23]*
-rw-r--r-- 1 david david 66672 Nov 19 13:17 acarsout2.bin
-rw-r--r-- 1 david david 66672 Dec 13 14:51 acarsout3.bin
$ diff dat/acarsout2.bin dat/acarsout3.bin
$