如何在C语言中读取和覆盖文本文件?

7

我有一个文本文件text.txt,内容如下(为了简单起见):

this is line one
this is line two
this is line three

为了简单起见,我只是尝试将每行的第一个字符设置为'x',所以我的期望结果将是:

xhis is line one
xhis is line two
xhis is line three

我正在打开text.txt文件并尝试覆盖同一文本文件中的每一行,我在while循环中将每一行的第一个字符设置为'x'。我还将变量"line"设置为1,因为如果它在第一行,我希望倒回到文件开头以便在文件开始处进行覆盖而不是在文件结尾处。然后递增line变量以跳过下次迭代的倒回操作,并应该继续覆盖第二和第三行。对于第一行效果很完美。

有人有什么解决方法吗?顺便说一下,我已经在stackoverflow和其他网站上进行了广泛的研究,但没有成功。以下是我的代码以及我的输出:

#include <stdio.h>
#include <stdlib.h>
#define MAX 500

int main() {
    char *buffer = malloc(sizeof(char) * MAX);
    FILE *fp = fopen("text.txt", "r+");
    int line = 1;
    while (fgets(buffer, 500, fp) != NULL) {
            buffer[0] = 'x';
            if (line == 1) {
                    rewind(fp);
                    fprintf(fp, "%s", buffer);
            }
            else {
                    fprintf(fp, "%s", buffer);
            }
            line++;
    }
    free(buffer);
    fclose(fp);
}

输出:

xhis is line one
this is line two
xhis is line two
e
x

2
在读取文件时,您不能覆盖该文件。虽然可以这样做,但会得到乱码数据。您的操作系统是什么?如果是Linux / Unix,请在打开文件后删除该文件 - unlink(“text.txt”); - 然后使用相同的名称打开一个文件,并将修改后的行写入新文件。您将有两个 FILE * 变量。 - Andrew Henle
它必须位于行的开头。 - BLUEPIXY
在原地重写文件是很棘手的。一个鲜为人知但非常重要的事实是,当你已经读到想要开始写入的确切位置时,你必须在开始写入之前调用类似 fseek(fp, 0, SEEK_CUR) 的东西。然后在完成写入后再次调用,在重新开始读取之前。 - Steve Summit
在编程中,始终检查(!=NULL)从malloc()返回的值,以确保操作成功。始终检查(!=NULL)从fopen()返回的值,以确保操作成功。 - user3629249
5个回答

6
long pos = ftell(fp);//Save the current position
while (fgets(buffer, 500, fp) != NULL) {
    buffer[0] = 'x';
    fseek(fp, pos, SEEK_SET);//move to beginning of line
    fprintf(fp, "%s", buffer);
    fflush(fp);
    pos = ftell(fp);//Save the current position
}

1
@NattachaiSuteerapongpan 请查看n1570.pdf中的7.21.5.3 fopen函数p7 - BLUEPIXY
我知道你的评论是2年前回复的,但我刚刚读到了你的答案,对于“fflush()”我不是很清楚。你的代码完全正常,但是我尝试删除“fflush(fp)”并运行代码后,程序陷入无限循环。由于我破坏了程序,它产生了非常奇怪的结果。我真的不知道为什么结果看起来像这样。你能否帮助我解释一下为什么删除fflush会产生这样的结果。 这是文本文件的链接(在执行程序之前和之后)。 https://drive.google.com/drive/folders/0B3cRfiRmMzw6Q01fZ09uX0VOU2c?usp=sharing - Xiao
1
@NattachaiSuteerapongpan 如前面评论中所示,需要调用fflush。如果没有它,它并不总是能正常工作。简单来说,它是缓冲的,因此需要在实际文件中反映出来。 - BLUEPIXY
@BLUEPIXY 非常感谢您的回复 :) 我从您上面提到的链接中得到了很多想法。 - Xiao

3

我建议使用另一个文件来执行这种解决方案。

  1. 读取该行
  2. 将x放在新文件的一行中,并复制该行的其余部分。
  3. 重复此操作,直到遇到EOF(文件结尾)
  4. 删除旧文件
  5. 重命名此新文件

0

试试这个

#include<stdio.h>
#include<stdio.h>
#include<string.h>
int main()
{
    char buffer[500],read[50][50];
    FILE *fp=fopen("text.txt","r+");
    int line =1;
    while(fgets(buffer,500,fp)!=NULL){
        buffer[0]='x';
        printf("\n%d ",line);
        puts(buffer);
        strcat(read[line-1],(const char*)buffer);
        line++;
    }
    fclose(fp);
    FILE *fp1=fopen("text.txt","w");
    rewind(fp1);
    fprintf(fp1,"%s",read);
    return 0;
    }

我在Windows上解决了这个问题


0
// file_overwrite.cpp : main project file.
// File opens and write y value to a file
// again reads same file and re-writes y value to a file

#include "stdafx.h"

using namespace System;

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

int main(int argc, char *argv[])
{
    int x = 19530;

    FILE *fp1 = fopen("D:\\Data\\BUFF.txt","w+");

    if(fp1 == NULL)
        printf("File not opening \n");
        int y=x;
        fprintf(fp1, "%d \n", y);
        fclose(fp1);
        printf("\n file -> open -> write y value and close");


        freopen("D:\\Data\\BUFF.txt", "w", fp1);
        rewind(fp1);
        y=100;
        fprintf(fp1, "%d \n", y);
        printf("\n file -> Reopen -> rewind write y values and close");
        fclose(fp1);

       getch();
       return 0;
}

尽管某些代码片段的用途可能很明显,请在回答问题时考虑使用代码注释或文档引用,以便人们获得额外的背景信息。 - Lepidopteron

0
// overwrite_file.cpp 
// File opens and write y value to a file
// again reads same file and re-writes y value to a file

#include "stdafx.h"

using namespace System;

#include<stdio.h>
#include<stdio.h>
#include<string.h>                //Include appropriate headers
#include <conio.h>
#include<stdlib.h>

int main(int argc, char *argv[])
{
    int x = 19530;                            // Give any value in the limit

    FILE *fp1 = fopen("D:\\Data\\BUFF.txt","w+");   // open file to write

    if(fp1 == NULL)                                 // if the file pointer encounters a null, it may not open neither overwrite 
        printf("File not opening \n");
        int y=x;                                     
        fprintf(fp1, "%d \n", y);                   //print y
        fclose(fp1);
        printf("\n file -> open -> write y value and close");  // close the file after writing the value of y


        freopen("D:\\Data\\BUFF.txt", "w", fp1);            //reopen and rewind file 
        rewind(fp1);
        y=100;                                              // this value of y given within the limits gets printed on the .exe console
        fprintf(fp1, "%d \n", y);
        printf("\n file -> Reopen -> rewind write y values and close");    // rewind write values and close 
        fclose(fp1);

       getch();
       return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接