【问题标题】:split file in c error get buffer in readfile在c错误中拆分文件在readfile中获取缓冲区
【发布时间】:2012-07-28 14:57:19
【问题描述】:

我编写了一个程序来在 Ubuntu 中用 C 语言分割文件。 在读取文件中获取缓冲区时出现错误。 这是我的代码。

    int split(char *filename, unsigned long part) {
        FILE *fp;
        char *buffer;
        size_t result; // bytes read
        off_t fileSize;

        fp = fopen(filename, "rb");
        if (fp == NULL) {
            fprintf(stderr, "Cannot Open %s", filename);
            exit(2);
        }
    // Get Size
        fileSize = get_file_size(filename);
    // Buffer
        buffer = (char*) malloc(sizeof(char) * (fileSize + 1));
        if (buffer == NULL) {
            fputs("Memory error", stderr);
            fclose(fp);
            return 1;
        }
    // Copy file into buffer
    //char buffers[11];
        result = fread(buffer, 1, fileSize, fp);
        buffer[fileSize] = '\0';

        if (result != fileSize) {
            fputs("Reading error", stderr);
            return 1;
        }

    // Split file
        off_t partSize = fileSize / part;
    // Last Part
        off_t lastPartSize = fileSize - partSize * part;
        unsigned long i;
        unsigned long j;
        // create part 1 to n-1
        for (j = 0; j < part; j++) {
            char partName[255];
            char *content;
            char partNumber[3];
            // Content of file part
    //      for (i = j; i < partSize * (j + 1); i++) {
    //
    //      }
            content = (char*) malloc(sizeof(char) * partSize);
            content = copychar(buffer, j + i, partSize + i);
            i += partSize;
            //copy name
            strcpy(partName, filename);
            // part Number
            sprintf(partNumber, "%d", j);
            // file name with .part1 2 3 4 ....
            strcat(partName, ".part");
            strcat(partName, partNumber);
            // Write to file
            writeFile(partName, content);
            free(content);
        }
    // last part
    char *content;
    content = (char*) malloc(sizeof(char) * (fileSize - partSize * (part - 1)));
    content = copychar(buffer, (part - 1) * partSize + 1, fileSize);
    char lastPartNumber[3];
    char lastPartName[255];
    sprintf(lastPartNumber, "%d", part);
    strcpy(lastPartName, filename);
    strcat(lastPartName, ".part");
    strcat(lastPartName, lastPartNumber);
    writeFile(lastPartName, content);
    free(content);

    free(buffer);
    fclose(fp);
    return 0;    
}

这里是从头到尾的函数copychar

char *copychar(char* buffer, unsigned long start, unsigned long end) {
    if (start >= end)
        return NULL;
    char *result;
    result = (char*) malloc(sizeof(char) * (end - start) + 1);
    unsigned long i;
    for (i = start; i <= end; i++)
        result[i] = buffer[i];
    result[end] = '\0';
    return result;
}

这里是获取文件大小的函数

off_t get_file_size(char *filename) {
    struct stat st;
    if (stat(filename, &st) == 0)
        return st.st_size;
    fprintf(stderr, "Cannot determine size of %s: %s\n", filename);
    return -1;
}

这里是写文件的函数

    int writeFile(char* filename, char*buffer) {
    if (buffer == NULL || filename == NULL)
        return 1;
    FILE *file;
    file = fopen(filename, "wb");
    fwrite(buffer, sizeof(char), sizeof(buffer) + 1, file);
    fclose(file);
    return 0;
}

当我测试时,我使用了 29MB 的文件 test 并且它被转储了。 我调试它返回 fileSize true 但是当缓冲区中的 readfile 从文件中获取时它只返回 135 个字符并且当使用 copychar 时它会出错。

    Breakpoint 1, 0x0000000000400a0b in copychar (buffer=0x7ffff5e3a010 "!<arch>\ndebian-binary   1342169369  0     0     100644  4         `\n2.0\ncontrol.tar.gz  1342169369  0     0     100644  4557      `\n\037\213\b", start=4154703576, end=4164450461) at final.c:43

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400a0b in copychar (buffer=0x7ffff5e3a010 "!<arch>\ndebian-binary   1342169369  0     0     100644  4         `\n2.0\ncontrol.tar.gz  1342169369  0     0     100644  4557      `\n\037\213\b", start=4154703576, end=4164450461) at final.c:43

程序以 SIGSEGV 信号终止,分段错误。 该程序已不存在。

我不知道如何在拆分时将缓冲区分成部分以写入部分。 感谢提前!

【问题讨论】:

  • 什么是i?在copychar 中写出开始值和结束值,并弄清楚为什么它们不是你想要的。 sizeof(buffer) 也没有按照您的预期进行。而且您正在泄漏大量内存。 (你根本不需要 copychar,整个程序中的一个 malloc 就足够了。)
  • 您应该避免将整个文件读入 RAM,因为当您拆分非常大的文件时,这可能会导致问题。
  • @Mat i 是变量,用于数组结果从缓冲区复制字符从头到尾
  • 这是作业吗?有一些工具可以拆分文件...
  • @spedau:你忘了初始化它。启用警告。

标签: c file file-io split


【解决方案1】:

您可能已经注意到,将文件复制到 1 个大块中是非常不切实际的。这不是必需的。

在最简单的层面上,您可以像这样逐字节复制文件

while( ( ch = fgetc(source) ) != EOF ) {
   fputc(ch, target);
}

这会起作用,但会很慢。最好分块复制,如下所示:

 unsigned char buf[4096];
 size_t size;
 while( (size = fread(buf, 1, sizeof(buf), fpRead) ) > 0) {
     fwrite(buf, 1, size, fpWrite);
 }

请注意,生成的代码要简单得多,并且不包含动态内存分配。

当然,您仍然需要添加拆分逻辑,但这可以通过跟踪写入的字节数并在实际写入之前打开一个新的写入文件来完成。

编辑:如何处理多部分方面 - 示意性地,您仍然需要对一些特殊情况进行额外检查,并测试不同系统调用的结果

 unsigned char buf[4096];
 size_t size;
 size_t partsize = 100000; // asssuming you want to write 100k parts.
 size_t stilltobewritten = partsize; // bytes remaining to be written in current part
 size_t chunksize = sizeof(buf); // first time around we read full buffersize
 while( (size = fread(buf, 1, chunksize, fpRead) ) > 0) {
     fwrite(buf, 1, size, fpWrite);
     stilltobewritten -= size; // subtract bytes written from saldo
     if (stilltobewritten == 0) {
         // part is complete, close this part and open next
         fclose(fpWrite);
         fpWrite = fopen(nextpart,"wb");
         // and reinit variables
         stilltobewritten = partsize;
         chunksize = sizeof(buf);
     } else {
         // prep next round on present file - just the special case of the last block
         // to handle
         chunksize = (stilltobewritten > sizeof(buf)) ? sizeof(buf) : stilltobewritten;
     }
 }

和编辑 2:文件部分名称也可以更简单:

 sprintf(partName, "%s.part%d",file, j);

【讨论】:

  • 如果你想分成 10 个部分(他做了,但 ihmo 没有多大意义),你需要文件的大小。
  • @KarolyHorvath 确实 - 我会调整我的答案。
【解决方案2】:

关于原始代码,copychar 中的startend 存在一些混淆。首先,您可能指的是 malloc 中的 sizeof(char) * (end - start + 1) 而不是 sizeof(char) * (end - start) + 1,其次,您要从原始缓冲区 (for (i = start; i &lt;= end; i++)) 复制 end-start+1 符号,然后用 '\0' 覆盖最后一个符号,这可能不是预期的行为。

【讨论】:

  • sizeof(char) 总是 1,所以这并不重要。
  • @KarolyHorvath 我同意这不太可能导致任何错误,但是有了这样的假设,为什么还要打扰 sizeof(char) 呢? :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-12
  • 1970-01-01
相关资源
最近更新 更多