【问题标题】:Append item to a file before last line in c在c中的最后一行之前将项目附加到文件中
【发布时间】:2010-07-16 07:46:42
【问题描述】:

当新项目添加到文件中时,页脚应更新为当前时间和小时。 这是示例文件格式,

项目1
ITEM2
06/07/2010 10:20:22 //页脚行

“项目”必须附加在现有文件中,位于页脚行之前,并且页脚应使用新值更新。 我必须将变量“item”和“time”保存为字符串。

添加新项目 (ITEM3) 后,文件看起来像,

项目1
项目2
ITEM3
07/07/2010 17:20:12 //已更改页脚

帮助我实现这一目标。

【问题讨论】:

    标签: c file


    【解决方案1】:

    由于页脚行是静态长度...

    找到页脚行的开头,在其上写下新项目,然后换行,然后写出新的页脚。

    (请注意,如果您无法保证始终写入至少足够的总字节数来覆盖现有的页脚,则此过程很危险,但看起来您在这里完全有这种保证。)

    【讨论】:

    • 对静态长度的好调用(假设是,我假设不是),+1。
    • 能否请您提供一个用于查找部分的示例 sn-p?
    • @arun; char footer[] = "00/00/0000 00:00:00\n"; FILE *f = fopen ("myfile", "a+"); fseek(-(sizeof(footer)-1), SEEK_CUR)); fprintf(f, "My next item\n"); fwrite(footer, 1, sizeof(footer)-1, f); fclose(f); sizeof 上的 -1 是为了去除字符串字面量中隐含的空终止符。
    • 我试过你的代码。但是该值仅附加在最后。那是在页脚之后。我尝试调试代码如下: fp = fopen(FILEPATH,"a"); printf("当前位置:%d", ftell(fp)); printf("FSEEK 返回:%d",fseek(fp,-43, SEEK_END)); printf("当前位置:%d", ftell(fp));它打印: Current pos: 0 FSEEK Returns:0 Current pos: 142 // 此值增加等于每次运行的项目。即最后添加的项目。请指导我。谢谢。
    • @arun;是的,对此感到抱歉,请参阅马修斯对我的回答的评论。应该是这样的:char footer[] = "00/00/0000 00:00:00\n"; FILE *f = fopen ("myfile", "r+"); fseek(-(sizeof(footer)-1), SEEK_END)); fprintf(f, "My next item\n"); fwrite(footer, 1, sizeof(footer)-1, f); fclose(f);
    【解决方案2】:

    我的解决方案是fopen,模式为“r+”(读写)。 fseek 从末尾向后,缓冲区长度值得并填充它(再次将光标放在末尾),向后搜索缓冲区以查找最后一个换行符(如果没有,则进一步向后搜索并重复),一旦它有被找到(或者你点击了文件的开头),搜索到文件中的那个位置(你的阅读把它放在了别的地方),然后写你的新项目,然后是一个新的行,然后是一个新的页脚。关闭文件并将其truncate 调整为合适的大小。

    HTH。

    编辑:
    如果页脚总是相同的大小,我肯定会选择 Nicholas 解决方案。

    【讨论】:

    • 谢谢。由于它是静态长度页脚,我将尝试使用 Nicholas 解决方案:)
    • 能否请您提供一个用于 fseek 的示例 sn-p?谢谢。
    • 我不认为a+ 是对的。作为 bluesmoon 的 noted,它应该是 r+docs 表示任何以 'a' 开头的模式都会导致所有写入都被强制结束,无论搜索如何。
    • @Matthew;对..我的错,应该是 r+。搞混了。
    【解决方案3】:

    类似的说明;每当您修改文件时,文件元数据都会更改以更新上次文件写入的确切时间。您始终可以在 Windows 上使用 GetFileTime() 查询该数据。

    【讨论】:

      【解决方案4】:

      这很容易。您只需截断最后一行。

      #include <stdio.h>
      #include <stdlib.h>
      #include <time.h>
      
      #define NEWLINE "new line to append\n"
      
      int main() {
        FILE *file;
        char *line = NULL;
        size_t previous_line_offset = 0, line_offset = 0;
        time_t time_signature;
      
        // open data file
        if((file = fopen("data.txt", "rw+")) == NULL) {
          puts("ERROR: Cannot open the file");
          return 1;
        }
      
        // find last line offset
        while(!feof(file)) {
          int n;
          previous_line_offset = line_offset;
          line_offset = ftell(file);
          getline(&line, &n, file); // NOTE getline is a GNU extension
        }
      
        // append new line
        fseek(file, previous_line_offset, SEEK_SET);
        fputs(NEWLINE, file);
      
        // apend signature
        time(&time_signature);
        fprintf(file, "%s", asctime(localtime(&time_signature)));
      
        // free resources
        fclose(file);
        if(line)
          free(line);
      
        // voila!
        return 0;
      }
      

      【讨论】:

      • 谢谢。我在哪里可以获得 getline()?
      • getline 是一个 GNU 扩展。它仅在 GNU libc 库中可用。在 Visual Studio 上,您可以使用 std::getline(但它是 c++)。
      • 您还有其他不使用任何其他扩展的解决方案吗?谢谢。
      【解决方案5】:

      一个简单(但不是很有效)的算法可能如下所示:

      string content = "";
      string line = "";
      
      // Append every but the last line to content
      while(!eof(file))
      {
          content += line;
          line = readline(file);
      }
      
      content += getNewItem();
      content += generateFooter();
      
      save(content);
      

      【讨论】:

      • 谢谢。实际文件太大,我可能会遇到缓冲区问题或您说的效率较低:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-05
      • 2011-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      相关资源
      最近更新 更多