【问题标题】:How to update data at a particular line in a file?如何更新文件中特定行的数据?
【发布时间】:2015-08-29 21:12:30
【问题描述】:

考虑我有以下文件(“testt.txt”)

abc
123
def
456
ghi
789
jkl
114

现在,如果我想更新名称 ghi 旁边的数字(即 789), 我该怎么做?

下面的代码无疑可以帮助我快速到达那里,但是如何快速更新呢?

#include<iostream>
#include<fstream>
#include<string>

using namespace std;

int main() 
{
    int counter = 0;
    string my_string;
    int change = 000;
    ifstream file ( "testt.txt" );

    while(!file.eof())
    {
        counter = counter + 1;
        getline(file, my_string, '\n');
        if (my_string == "ghi") 
        {
            ofstream ofile ( "testt.txt" );
            for (int i = 0; i < counter + 1; i++)
            {
                //reached line required i.e. 789
                //how to process here?
            }
            ofile.close();
            break;
        }
    }
    cout << counter << endl;
    file.close();
    return 0;
}

显然这里的计数器是5对应“ghi”, 所以 counter + 1 将指向值789。怎么改成000

------------已解决-----------最终代码-----

 #include<iostream>
 #include<fstream>
 #include<string>
 #include <cstdio>

using namespace std;

int main() 
{
string x;
ifstream file ( "testt.txt" );
ofstream ofile ( "test2.txt" );
while (!file.eof())
{
    getline(file,x);
    if (x == "789")
    {
        ofile << "000" << endl;
    }
    else
        ofile << x << endl;
}
file.close();
ofile.close();
remove("testt.txt");
return 0;
}

输出(“test2.txt”)

abc
123
def
456
ghi
000
jkl
114

【问题讨论】:

  • 考虑使用数据库,因为使用简单的文件访问这些操作往往很复杂。无论如何,您处理问题的方式归结为“读取数据”,“修改数据”,“写入数据”,这很麻烦但可能。您究竟在哪一步遇到了问题?
  • 你可以看到,它是用for循环写的,还有什么不用数据库也能用的方法??我的意思是将更新的数据写入新文件并删除旧文件..
  • @bikrathor 如果您拥有所有某些固定的数据位置,这是可能的。查看std::basic_ostream::seekp() 方法。

标签: c++ file iostream file-handling


【解决方案1】:

如果您使用ifstream 打开文件进行读取,然后使用ofstream 进行写入,ofstream 将无法工作或覆盖文件 - 我不确定哪个选项是正确的,但也不是你想要的。

所以使用std::fstream打开一个文件进行读写:

fstream file ( "testt.txt" );

到了合适的地方后,使用seekp方法在读取流后启用写入(通常不使用seekp,但失败时很难找到错误),如标准要求:

if (my_string == "ghi") 
{
    file.seekp(file.tellg());
    ...
    break;
}

修改文件时,您必须将现有字节替换为新字节。准确写入 3 个字节很重要,因此值 789 会被正确覆盖。所以你可能想检查范围:

if (change < 0 || change > 999)
    abort(); // or recover from the error gracefully

并在写入之前设置输出字段的宽度:

file << setw(3) << change;

如果您的代码从写回切换到读取,请使用file.seekg(file.tellp()) 确保其正常工作。

【讨论】:

    【解决方案2】:

    这样做通常并不容易,因为文件系统不会按行存储文件,而是按字节序列存储文件。因此,如果您将其中包含 4 个字符的行替换为包含 5 个字符的行,您将覆盖下一行中的某些内容。您必须将文件读入内存,然后从更改的行开始重新写入所有内容。

    这是一种可怕的方法,因为它非常慢,如果您可以通过不使用文本文件来存储此类信息来避免这种情况,那么您应该这样做。我通常建议使用sqlite 之类的东西,如果您需要将数据存储在感觉像表格的东西中,则存在所有相关语言的库;对于其他类型的数据,除了关系数据库之外还有其他方法,但这取决于您要实际存储的内容。

    【讨论】:

    • “没有办法做到这一点......”这根本不是真的。
    • @πάνταῥεῖ:是的,我什至描述了它是如何可能的......好吧,我走了,编辑我的答案。
    • 不是真的,就回答 OP 的原始问题而言。
    • @πάνταῥεῖ:这取决于您将什么视为“原始问题”,甚至更多取决于您是否将“原始问题”视为相关概念-您知道,一切都在流动:-D 否,实际上,OP 询问如何更改该行,我的回答是“写下新行和所有行”,老实说,我相信这回答了他的问题。我回答的“没办法做到这一点”的开头来自 OP 询问“有没有办法快速做到这一点”,一般来说,如果他的文件持续到千兆字节,则没有。
    • 认真对待 OP 想要在代码中实现的目标,并向他们展示如何实现。如果您认为这是一个 XY 问题,请将其扩展为您的答案中的评论或附加说明。
    猜你喜欢
    • 2013-02-21
    • 2011-08-30
    • 1970-01-01
    • 2017-11-17
    • 2014-08-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 1970-01-01
    相关资源
    最近更新 更多