在C中拆分文件中的二进制文件而不会损坏

时间:2016-04-07 04:03:55

标签: c file io binaryfiles

我有一个作业,我必须使用一个单词文件(.doc),使用文件系统IO代码读取文件将文件分成两半,并将每一半写入二进制模式下的两个单独文件。我编写了下面的代码,它成功运行并生成了两个文件,甚至文件的大小也是原始文件的一半。但是,当我打开word文件时,它们就会被破坏。这适用于.txt文件,但我的教师说它应该适用于.doc和.zip文件,没有文件损坏。我的代码有问题吗?感谢您的帮助,我非常感谢。

#include <stdio.h>

int main (int argc, char **argv)
{
    char *fileName = "1.doc";
    char *buffer = "a";
    int chunk;

    FILE *fd;
    fd = fopen (fileName, "rb");
    if (fd == NULL);
        ferror ("error");
    fseek (fd, 0, SEEK_END);
    chunk = ftell (fd) / 2;
    rewind (fd);                //open file, get size, set chunk = to half the file, rewind back to begining of file

    fread (buffer, chunk, 1, fd);
    fclose (fd);                //read the first half of the file into buffer

    fd = fopen ("1_1.doc", "wb");
    fwrite (buffer, chunk, 1, fd);
    fclose (fd);                //create new file, write the contents of buffer into it

    fd = fopen (fileName, "rb");
    fseek (fd, chunk, SEEK_SET);
    fread (buffer, chunk, 1, fd);
    fclose (fd);                //reopen original file, go to half the file, read the remaining half of the file and store in buffer

    fd = fopen ("1_2.doc", "wb");
    fwrite (buffer, chunk, 1, fd);
    fclose (fd);                //create a new file, write the second half of the file into it

    return 0;

}

我尝试了两种变体

fwrite(buffer, chunk, 1, fd);

fwrite(&buffer, chunk, 1, fd);

2 个答案:

答案 0 :(得分:1)

你有很多问题,主要是你在不分配内存的情况下使用缓冲区,并试图在read-中写入声明的字符串文字 "a"的地址只有记忆。

要解决此问题,您必须:

#include <stdlib.h>
...
    char *buffer = NULL;
...
    chunk = ftell (fd) / 2;

    if ((buffer = malloc (chunk * sizeof *buffer)) == NULL) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

您对ferror的使用不正确,需要FILE *个参数,而不是char *

    fd = fopen (fileName, "rb");
    if (fd == NULL) {
        ferror (fd);
        return 1;
    }

最后,不要忘记释放不再需要时分配的内存:

    free (buffer); /* free allocated memory */

总而言之,您可以执行以下操作:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    char *fileName = "1.doc";
    char *buffer = NULL;
    int chunk;

    FILE *fd;

    /* open file, get size, set chunk = to half the file, 
     * allocate memory, rewind back to begining of file
     */
    fd = fopen (fileName, "rb");
    if (fd == NULL) {
        ferror (fd);
        return 1;
    }
    fseek (fd, 0, SEEK_END);
    chunk = ftell (fd) / 2;

    if ((buffer = malloc (chunk * sizeof *buffer)) == NULL) {
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    rewind (fd);

    /* read the first half of the file into buffer */
    fread (buffer, chunk, 1, fd); /* you should check return of each read */
    fclose (fd);

    /* create new file, write the contents of buffer into it */
    fd = fopen ("1_1.doc", "wb");
    if (fd == NULL) {
        ferror (fd);
        return 1;
    }
    fwrite (buffer, chunk, 1, fd); /* you should check return of each write */
    fclose (fd);

    /* reopen original file, go to half the file, read the 
     * remaining half of the file and store in buffer
     */
    fd = fopen (fileName, "rb");
    if (fd == NULL) {
        ferror (fd);
        return 1;
    }
    fseek (fd, chunk, SEEK_SET);
    fread (buffer, chunk, 1, fd); /* you should check return */
    fclose (fd);

    /* create a new file, write the second half of the file into it */
    fd = fopen ("1_2.doc", "wb");
    if (fd == NULL) {
        ferror (fd);
        return 1;
    }
    fwrite (buffer, chunk, 1, fd); /* check return */
    fclose (fd);

    free (buffer); /* free allocated memory */

    return 0;

}

输入文件

$ cat 1.doc
Mon Feb 29 10:06:59 CST 2016
Mon Feb 29 10:06:59 CST 2016
Mon Feb 29 10:06:59 CST 2016
Mon Feb 29 10:06:59 CST 2016

示例使用/输出文件

$ ./bin/binread

$ l 1*
-rw-r--r-- 1 david david 116 Apr  6 23:17 1.doc
-rw-r--r-- 1 david david  58 Apr  6 23:18 1_1.doc
-rw-r--r-- 1 david david  58 Apr  6 23:18 1_2.doc

$ cat 1_1.doc
Mon Feb 29 10:06:59 CST 2016
Mon Feb 29 10:06:59 CST 2016

如果您有疑问,请告诉我。

答案 1 :(得分:0)

平均而言,你失去了半个字节。

如果文件大小是偶数,那么文件可以分为两个相等的一半。

如果文件大小为奇数,则一个块必须大一个字节。

size_t length = ftell(fd);
size_t chunk1 = length / 2;
size_t chunk2 = length - chunk1;

你真的需要为大块分配空间; buffer不能在不写入其他内存的情况下保存超过2个字节,并且这2个字节可能在只读内存中。