在 C 中将文本附加到文件的开头不起作用
Append a text to a beginning of a file in C does not work
所以伪代码是:
FIle existing = Read whole content of file.
String newcontent = "Blah Blah This is first line" + existing
f.write(newcontent);
实际代码是
void Prepend(char *string, char *file_name)
{
char buf[100];
FILE *fp1, *fp2;
Append(string, "temp_file");
fp1 = fopen(file_name, "a+");
fp2 = fopen("temp_file", "a+");
if (!fp1 && !fp2) {
printf("Unable to open/"
"detect file(s)\n");
exit(1);
}
fprintf(fp2, "\n");
while (!feof(fp1)) {
fgets(buf, sizeof(buf), fp1);
}
rewind(fp2);
while (!feof(fp2)) {
fgets(buf, sizeof(buf), fp2);
}
fclose(fp1);
fclose(fp2);
remove(temp_file);
}
/*-----------------------------------------------------------------------------*/
void Append(char *string, char *file_name)
{
FILE *file = fopen(file_name, "a");
if(file==NULL)
{
printf("Error opening file.");
}
else
{
fputs(string, file);
}
fclose(file);
}
我知道 fseek
maybe 和其他与指针相关的东西有一种方法,但我认为使用“简单方法”并创建一个新的临时文件对我来说会更好更快然后马上删除它。
嗯,也是不行。
这里是一个小例子,只使用两个而不是三个文件。
void prepend(const char *filename, const char *str)
{
// open the orig file (read only)
FILE *orig = fopen(filename, "r");
// open tmp file (read / write)
FILE *tmp = fopen("temp_file", "w+");
// write string into tmp file (prepend)
fwrite(str, 1, strlen(str), tmp);
// file size of orig
fseek(orig, 0L, SEEK_END);
long orig_size = ftell(orig);
rewind(orig); // set pos to 0
// transfer bytes from orig to tmp (append)
char *buf = malloc(orig_size);
fread(buf, 1, orig_size, orig);
fwrite(buf, 1, orig_size, tmp);
free(buf);
// close orig and delete it
fclose(orig);
remove(filename);
// close and rename tmp file as orig
fclose(tmp);
rename("temp_file", filename);
}
注意:为简短起见,不涉及错误检查。
由于您使用的是临时文件,因此不需要辅助缓冲区,只需附加文本,然后将旧文件内容移动到新文件中。
您应该注意的几件事,
if (!fp1 && !fp2)
仅当两个文件都无法打开时才为真,最好单独检查结果,以便我们知道我们失败的地方。您可以将 &&
替换为 ||
,但除非您重新检查文件指针值,否则失败的原因将不明确。
- 看来你从来没有将
fp1
中的数据写入 fp2
我只看到对 fgets()
的调用,然后你将 fp1
读入 buf
您将 fp2
读入 buf
,两次都没有对数据进行任何操作。如果文件大于 100 个字节,最后 100 个或更少字节的数据将存储在 buf 中。
- 这不一定是最糟糕的事情,但最好只打开具有所需权限的文件。打开一个你只需要在 'a+' 模式下读取的文件有点奇怪
- 在创建新文件之前,最好检查一下该名称的文件是否不存在。您最好在系统的临时目录或程序的专用 tmp 目录中创建文件。使用唯一的字符串作为它的名称也是一个好主意。也许像“[my prog]-[原始文件名]-[.tmp]”之类的东西而不是这样一个通用名称。
一个应该有效的方法的简短示例,带有错误检查(不一定是最好的错误检查,但可以让您了解可能发生错误的位置):
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
int Prepend(char *string, char *file_name)
{
FILE *fp1 = NULL, *fp2 = NULL;
struct stat fs;
if (stat("temp_file", &fs) == 0) {
printf("Error, there is already a file named \"temp_file\" in the current working directory\n");
return -1;
}
if ((fp1 = fopen(file_name, "r")) == NULL) {
printf("Error : %s\n", strerror(errno));
printf("Failed to Open file %s\n", file_name);
return -1;
}
if ((fp2 = fopen("temp_file", "w")) == NULL {
printf("Error : %s\n", strerror(errno));
printf("Unable to create Temporary file\n");
fclose(fp1);
return -1;
}
if (fputs("Prepended String\n", fp2) == EOF) {
printf("Failed to write string to file\n");
fclose(fp1);
fclose(fp2);
if (remove("temp_file") != 0)
printf("Error : %s, while removing temp_file\n", strerror(errno));
return -1;
}
int c;
while((c = fgetc(fp1)) != EOF) {
if(fputc(c, fp2) == EOF) {
printf("Error while transfering data from %s to %s\n", file_name, "temp_file");
fclose(fp1);
fclose(fp2);
if (remove("temp_file") != 0)
printf("Error : %s, while removing temp_file\n", strerror(errno));
return -1;
}
}
fclose(fp1);
if (remove(file_name) != 0) {
printf("Error : %s, while removing %s\n", strerror(errno), file_name);
fclose(fp2);
return -1;
}
fclose(fp2);
if (rename("temp_file", file_name) != 0) {
printf("Error : %s, while renaming temp_file\n", strerror(errno));
return -1;
}
return 0;
}
fclose()
也可以 return EOF on error 并设置 errno 来指示错误。但是,对流的任何进一步访问(包括对 fclose() 的另一次调用)都会导致未定义的行为。所以您可以打印错误,但您无能为力。
所以伪代码是:
FIle existing = Read whole content of file.
String newcontent = "Blah Blah This is first line" + existing
f.write(newcontent);
实际代码是
void Prepend(char *string, char *file_name)
{
char buf[100];
FILE *fp1, *fp2;
Append(string, "temp_file");
fp1 = fopen(file_name, "a+");
fp2 = fopen("temp_file", "a+");
if (!fp1 && !fp2) {
printf("Unable to open/"
"detect file(s)\n");
exit(1);
}
fprintf(fp2, "\n");
while (!feof(fp1)) {
fgets(buf, sizeof(buf), fp1);
}
rewind(fp2);
while (!feof(fp2)) {
fgets(buf, sizeof(buf), fp2);
}
fclose(fp1);
fclose(fp2);
remove(temp_file);
}
/*-----------------------------------------------------------------------------*/
void Append(char *string, char *file_name)
{
FILE *file = fopen(file_name, "a");
if(file==NULL)
{
printf("Error opening file.");
}
else
{
fputs(string, file);
}
fclose(file);
}
我知道 fseek
maybe 和其他与指针相关的东西有一种方法,但我认为使用“简单方法”并创建一个新的临时文件对我来说会更好更快然后马上删除它。
嗯,也是不行。
这里是一个小例子,只使用两个而不是三个文件。
void prepend(const char *filename, const char *str)
{
// open the orig file (read only)
FILE *orig = fopen(filename, "r");
// open tmp file (read / write)
FILE *tmp = fopen("temp_file", "w+");
// write string into tmp file (prepend)
fwrite(str, 1, strlen(str), tmp);
// file size of orig
fseek(orig, 0L, SEEK_END);
long orig_size = ftell(orig);
rewind(orig); // set pos to 0
// transfer bytes from orig to tmp (append)
char *buf = malloc(orig_size);
fread(buf, 1, orig_size, orig);
fwrite(buf, 1, orig_size, tmp);
free(buf);
// close orig and delete it
fclose(orig);
remove(filename);
// close and rename tmp file as orig
fclose(tmp);
rename("temp_file", filename);
}
注意:为简短起见,不涉及错误检查。
由于您使用的是临时文件,因此不需要辅助缓冲区,只需附加文本,然后将旧文件内容移动到新文件中。
您应该注意的几件事,
if (!fp1 && !fp2)
仅当两个文件都无法打开时才为真,最好单独检查结果,以便我们知道我们失败的地方。您可以将&&
替换为||
,但除非您重新检查文件指针值,否则失败的原因将不明确。- 看来你从来没有将
fp1
中的数据写入fp2
我只看到对fgets()
的调用,然后你将fp1
读入buf
您将fp2
读入buf
,两次都没有对数据进行任何操作。如果文件大于 100 个字节,最后 100 个或更少字节的数据将存储在 buf 中。 - 这不一定是最糟糕的事情,但最好只打开具有所需权限的文件。打开一个你只需要在 'a+' 模式下读取的文件有点奇怪
- 在创建新文件之前,最好检查一下该名称的文件是否不存在。您最好在系统的临时目录或程序的专用 tmp 目录中创建文件。使用唯一的字符串作为它的名称也是一个好主意。也许像“[my prog]-[原始文件名]-[.tmp]”之类的东西而不是这样一个通用名称。
一个应该有效的方法的简短示例,带有错误检查(不一定是最好的错误检查,但可以让您了解可能发生错误的位置):
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
int Prepend(char *string, char *file_name)
{
FILE *fp1 = NULL, *fp2 = NULL;
struct stat fs;
if (stat("temp_file", &fs) == 0) {
printf("Error, there is already a file named \"temp_file\" in the current working directory\n");
return -1;
}
if ((fp1 = fopen(file_name, "r")) == NULL) {
printf("Error : %s\n", strerror(errno));
printf("Failed to Open file %s\n", file_name);
return -1;
}
if ((fp2 = fopen("temp_file", "w")) == NULL {
printf("Error : %s\n", strerror(errno));
printf("Unable to create Temporary file\n");
fclose(fp1);
return -1;
}
if (fputs("Prepended String\n", fp2) == EOF) {
printf("Failed to write string to file\n");
fclose(fp1);
fclose(fp2);
if (remove("temp_file") != 0)
printf("Error : %s, while removing temp_file\n", strerror(errno));
return -1;
}
int c;
while((c = fgetc(fp1)) != EOF) {
if(fputc(c, fp2) == EOF) {
printf("Error while transfering data from %s to %s\n", file_name, "temp_file");
fclose(fp1);
fclose(fp2);
if (remove("temp_file") != 0)
printf("Error : %s, while removing temp_file\n", strerror(errno));
return -1;
}
}
fclose(fp1);
if (remove(file_name) != 0) {
printf("Error : %s, while removing %s\n", strerror(errno), file_name);
fclose(fp2);
return -1;
}
fclose(fp2);
if (rename("temp_file", file_name) != 0) {
printf("Error : %s, while renaming temp_file\n", strerror(errno));
return -1;
}
return 0;
}
fclose()
也可以 return EOF on error 并设置 errno 来指示错误。但是,对流的任何进一步访问(包括对 fclose() 的另一次调用)都会导致未定义的行为。所以您可以打印错误,但您无能为力。