读取/制作文本文件的备份

时间:2013-09-25 08:41:20

标签: c file file-io

我有以下代码尝试读取文本文件,进行备份,并将读取文件字符串传递给进一步的处理例程。我所看到的行为是非常意外的。

01: rewind(PPLFile);
02: fseek(PPLFile, 0, SEEK_END);
03: unsigned long fsize = ftell(PPLFile);
04: char *string = (char*)calloc(fsize + 1, sizeof(char));
05: rewind(PPLFile);
06: fread(string, sizeof(char), fsize, PPLFile);

07: FILE* PPLBackup;
08: char* fileSuffix = ".backup";
09: char* PPLBackupLocation = (char*)calloc(strlen(basePath) + strlen(fileSuffix) + 1, sizeof(char));
10: strcpy(PPLBackupLocation, basePath);
11: strcat(PPLBackupLocation, fileSuffix);
12: PPLBackup = fopen(PPLBackupLocation, "w");
13: fprintf(PPLBackup, fileContent);
14: fclose(PPLBackup);
15: free(PPLBackupLocation);

先前已使用*PPLFilew+标记打开了文件句柄a+,具体取决于最初编写该文件的代码中的某些情况。

我认为这个概念非常简单:

  1. 将指针移到文件末尾并检测其位置以建立文件大小(以字节为单位)
  2. 创建字节大小的空字符串加一(对于空终止符)
  3. 将整个文件内容倒回并读入字符串,直至感知文件大小
  4. 创建备份文件名和文件指针
  5. 将从原始文件读取的整个字符串写入新的备份文件。
  6. 关闭备份文件并继续处理读取字符串
  7. 有两个令人不安的症状:

    1. 包含原始文件的* char字符串有更多的零(文本文件中有数千个〜= 20MB),因此最后一个非零值可能是距离结尾的3000个字节。看似比原始文件小。
    2. 在编写备份文件时,生成的文件比原始文件少了,原始文件的看似随机的额外样本附加到末尾,再次是几千字节。
    3. 很简单,到底是怎么回事?

4 个答案:

答案 0 :(得分:2)

为什么你用fread()阅读并用fprintf()而不是fwrite()写?你使用fprintf()的方式,你受到文件中第一个%符号的摆布(格式字符串漏洞)。

此外,请确保两个文件都以相同模式打开(文本模式与二进制模式)。通常,fread()/ fwrite()倾向于与二进制模式一起使用。

答案 1 :(得分:2)

这一行不太好:

13: fprintf(PPLBackup, fileContent);

如果文件包含%s之类的字符序列,那么fprintf将在堆栈中查找其他数据。

您应该使用fwrite代替:

13: fwrite(fileContent, fsize, 1, PPLBackup);

或者至少这样做:

13: fprintf(PPLBackup, "%s", fileContent);

答案 2 :(得分:0)

这个完整的程序适用于Linux。它有Klas的改动。注意我必须使用fsize作为全局因为传递要复制的文件的char *内容如果稍后strlen'd则会破坏 - 原因很明显

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

unsigned long fsize=0L;

char *get_file(FILE *PPLFile) {
    rewind(PPLFile);
    fseek(PPLFile, 0, SEEK_END);
    fsize = ftell(PPLFile);
    char *string = (char*)calloc(fsize + 1, sizeof(char));
    rewind(PPLFile);
    fread(string, sizeof(char), fsize, PPLFile);
    return string;
}

void write_file(char *basePath, char *fileContent) {
 FILE* PPLBackup;
 char* fileSuffix = ".backup";
 char* PPLBackupLocation = (char*)calloc(strlen(basePath) + strlen(fileSuffix) + 1, sizeof(char));
 strcpy(PPLBackupLocation, basePath);
 strcat(PPLBackupLocation, fileSuffix);
 PPLBackup = fopen(PPLBackupLocation, "w");
 fwrite(fileContent, fsize, 1, PPLBackup);
 fclose(PPLBackup);
 free(PPLBackupLocation);
}

答案 3 :(得分:0)

多个问题

  1. 正如@KlasLindbäck&amp; amp; @Medinoc,请勿使用fprintf()fwrite()要好得多。

  2. @KlasLindbäck说,确保在二进制模式下打开两个文件读写。如fopen(PPLBackupLocation, "wb")

  3. 应评估fread()的返回值,如果好,则用于fwrite()

  4. calloc(fsize + 1, sizeof(char))无需添加1.