我正在使用<fstream>
读取文件,并且该文件包含以下行:
Name=Cecil
Age=34
Born=London
//etc.
为了举例说明,我想将34
分配给变量int age
。这意味着我必须找到以Age
开头的行,然后在等号后提取值34
。
稍后我想在程序中更改此值,并将其替换为文件,因此34
将成为例如35
,所以我必须再次找到此特定部分文件并写在那里。
这似乎是一项基本任务,但到目前为止我找不到任何好的例子。也许最好将我的数据存储为JSON或XML,并为此目的使用库?
答案 0 :(得分:2)
这是基本需求,但不是基本实现,因为文件只是字节流而没有结构。这意味着您需要实现一些算法来解释/解析写入的数据。您应该知道,您无法删除文件中的内容,也无法插入;我的意思是没有单一的操作可以解决这个问题,并且在你的情况下会出现问题,因为如果你想用34替换34,那么信息的长度是不同的,你想要删除一个char(不可能)和替换另一个(这是可能的);将103替换为103时的原因相同。这就是为什么数据库适用于:让您轻松管理结构化信息。
好的,这并不意味着这是不可能的,因为数据库使用文件。也许,首先,您可以:读取所有文件并将其解析为内存中的结构化数据,然后管理该数据,并在需要时将数据写入新文件中。当然,如果您有太多数据,这不是一个严肃的实现。
答案 1 :(得分:1)
这只是一些一般性的推理,作为答案的答案“也许它会更好......”:
任何简单的实现都会有点脆弱,但是如果您对输入文件有很好的控制,并且可能存在数据损坏的风险并不会给您带来太多麻烦(即损坏程度低且易于恢复/修复),你甚至可以通过更换字符串来逃避,搜索“Age = 34 \ n”并将其替换为“Age = 35 \ n”(如果文件中只有单个Age行,否则你需要先找到正确的人)。 ..首先将整个文件读入内存,然后在替换后将其写回。
使用JSON将为您提供更多的结构安全性(没有机会意外更改“CarnAge = 34”而不是“Age = 34”),但JSON仍然可以在纯文本编辑器中编辑(如果你足够小心) )。此外,JSON是与Web服务交换数据的非常流行的方式。这段也适用于XML,虽然在纯文本编辑方面我认为JSON对于非程序员来说更容易学习。所以“ini”会这样做,但我仍然喜欢JSON。
最后,如果这更严重,考虑一些数据库会很有意义。这些是经过验证的解决方案,可以非常有效地存储/修改/获取数据,使用文件I / O比使用简单的读/写整个文件更高效(DB正在以允许他们通过覆盖部分内容来修改内容的方式处理文件,通过保留周围的储备空间并具有完全重构某些文件的一部分的机制)。此外,大多数数据库都是ACID,因此可以“免费”为您的应用添加额外的稳健性。您无法以纯文本格式编辑数据(但您仍然可以在某个工作表中准备数据,并通过某些数据库管理器工具导入它们。)
为什么要避免一些常见的数据库 - 我能想到的 - 的唯一原因是:1)性能(在特殊情况下,优秀的程序员将胜过专业的数据库引擎,但大多数时候它不值得付出巨大的努力), 2)项目太小/教程,所以虽然集成例如“sqlite”并不困难,但只需读取整个文件并替换字符串就更简单了。但是,例如我使用U ++框架编写我的C ++项目,因此添加SQL将是轻而易举的几行,没有大麻烦......
答案 2 :(得分:0)
由于您的数据看起来像键值对,所以这是一种面向对象的方式:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct DATA
{
struct PAIR
{
string m_szComponentSeparator;
string m_szKey;
string m_szValue;
PAIR()
{
m_szComponentSeparator = "=";
}
void Read(ifstream &_inFile)
{
string szLine;
_inFile >> szLine;
size_t pos = szLine.find(m_szComponentSeparator);
m_szKey = szLine.substr(0, pos);
m_szValue = szLine.substr(pos + 1);
}
void Write(ofstream &_outFile)
{
_outFile << m_szKey << m_szComponentSeparator << m_szValue << endl;
}
int To_int()
{
return atoi(m_szValue.c_str());
}
void SetAs_int(int _iValue)
{
char szBuf[32] = {0};
snprintf(szBuf, sizeof(szBuf), "%d", _iValue);
m_szValue = szBuf;
}
};
PAIR m_stName;
PAIR m_stAge;
PAIR m_stBorn;
void Read(string _szFilepath)
{
ifstream inFile(_szFilepath.c_str());
m_stName.Read(inFile);
m_stAge.Read(inFile);
m_stBorn.Read(inFile);
}
void Write(string _szFilepath)
{
ofstream outFile(_szFilepath.c_str());
m_stName.Write(outFile);
m_stAge.Write(outFile);
m_stBorn.Write(outFile);
}
void Print()
{
cout << m_stName.m_szKey << m_stName.m_szComponentSeparator << m_stName.m_szValue << endl;
cout << m_stAge.m_szKey << m_stAge.m_szComponentSeparator << m_stAge.m_szValue << endl;
cout << m_stBorn.m_szKey << m_stBorn.m_szComponentSeparator << m_stBorn.m_szValue << endl;
}
};
int main()
{
string szInputFile = "in.txt";
string szOutputFile = "out.txt";
DATA oData;
oData.Read(szInputFile);
oData.Print();
int age = oData.m_stAge.To_int();
age = 35;
oData.m_stAge.SetAs_int(age);
cout << "after modification:" << endl;
oData.Print();
oData.Write(szOutputFile);
return 0;
}
//Output:
Name=Cecil
Age=34
Born=London
after modification
Name=Cecil
Age=35
Born=London
答案 3 :(得分:0)
尝试这个
ifstream ifs("e:\\file.txt");
vector<string> file;
string temp;
while(getline(ifs, temp))
{
if(temp.compare(0,4,"Age=")==0)
temp.replace(0, sizeof("Age=125"),"Age=125");
file.push_back(temp);
}
ifs.close();
ofstream ofs("e:\\file.txt");
for(auto begin = file.begin(), end = file.end(); begin!=end; begin++)
ofs << *begin << endl;
ofs.close();