当从一个文件复制到另一个数据,读,写二进制优选的建议的方法。使用面向行的输入函数(如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
$
** **务必检查能遇到一个错误函数的结果!解引用_null pointer_是未定义的行为。还要注意,你必须“成功”打开文件** iff **。 – Olaf
我在main()中关闭了它们。我认为问题出现在'destination = fopen(name_destination,“w”);' –
'source'和'destination'指针是你的函数的参数,但是你不使用通过这些参数传递的参数值。这不是天生的错误,但是这一点以及你不关闭文件的事实表明你认为调用者会以某种方式通过这些参数从函数接收流指针。它不会,如果调用者认为已经完成,那肯定会产生段错误。 –