简体   繁体   English

C ++在文件中的特定点插入一行

[英]C++ Inserting a line at specific point in file

I have a text file that contains the high scores of a game in this format: 我有一个文本文件,其中包含这种格式的游戏的高分:

Name Score
Name Score
Name Score

With the file ordered in descending order on score. 文件按分数降序排列。

I want to insert a new name and its corresponding score in the right place in the file so that it remains ordered correctly. 我想在文件的正确位置插入一个新名称及其对应的分数,以使其顺序正确。 Any suggestions how to do this would be greatly appreciated! 任何建议如何做到这一点将不胜感激!

For Example, given the following file: 例如,给定以下文件:

Edward 100
David 90
Sarah 80
Alice 60

And I want to add. 我想补充。

Name = Jodi
Score = 70

To the file, so the new file reads: 对于文件,因此新文件显示为:

Edward 100
David 90
Sarah 80
Jodi 70
Alice 60

Thanks 谢谢

At the moment I have the following code: 目前,我有以下代码:

string playerName = pPlayer->GetName();
int playerScore = pPlayer->GetScore();

std::ofstream score("scores.txt", std::ios_base::app | std::ios_base::out);

score << "\n" << playerName << " " << playerScore;

Which just adds the name to the end of the file. 只是将名称添加到文件末尾。 I considered reading in the whole file ordering it then Over righting the old file. 我考虑阅读整个文件,然后按顺序整理旧文件。 But I don't want to do this because it could take ages if the file got large. 但是我不想这样做,因为如果文件很大,可能要花一些时间。

There are a few different ways to do this. 有几种不同的方法可以做到这一点。 The one that is simplest to implement is one that reads the entire file into a vector, inserts the new value and writes out the new file. 最容易实现的一种方法是将整个文件读入向量,插入新值并写出新文件。

The second option is to read the file until you find the right place, "mark" where that is in the file (using for example istream::tellg() ), then read all the following elements into a vector, update the new record, and write back out the once beyond that. 第二种选择是读取文件,直到找到正确的位置,在文件中找到正确的位置(例如使用istream::tellg() ),然后将以下所有元素读取到向量中,更新新记录,然后重新写出一次。

A third option is to just keep the list unordered in the file, and sort the information when you read it. 第三种选择是仅使列表在文件中保持无序,并在阅读时对信息进行排序。 That way, you can just append to the end, saving on writing the file over and over again. 这样,您可以追加到末尾,从而省去了一次又一次地写入文件的麻烦。

In reality, I suspect that writing a VERY large file will still be quick enough to make little or no difference at all. 实际上,我怀疑编写一个非常大的文件仍然足够快,几乎没有差别。 Modern hard drives will write many megabytes per second, and you only have some dozens of bytes per line, so you need to have milions of lines in your file before it makes any difference at all. 现代硬盘驱动器每秒将写入许多兆字节,并且每行只有几十个字节,因此您需要在文件中包含数百万行,才能完全不起作用。 For example, I just copied some large files amounting to 132MB on my machine, and the compined time to read and write 132mb came to 1.2s. 例如,我刚刚在计算机上复制了一些大文件,总计132MB,读写132mb的时间总计为1.2s。 If each of your records are 26 bytes, that's 50 million "scores". 如果您的每个记录都是26字节,则为5,000万个“分数”。

If you carefully define a type to represent your data record: 如果您仔细定义一个类型来表示您的数据记录:

struct Record { 
    std::string name; int score; 
    friend std::istream& operator>>(std::istream& is, Record& r)       { return is >> r.name         >> r.score; }
    friend std::ostream& operator<<(std::ostream& os, Record const& r) { return os << r.name << "\t" << r.score; }

    bool operator<(Record const& other) const {
        return other.score < score;
    }
};

Note that it knows how to 请注意,它知道如何

  • read a record from a stream 从流中读取记录
  • write it back to a stream 写回流
  • compare records by score 按分数比较记录

Then, C++ algorithms are your friend once again: 然后,C ++算法再次成为您的朋友:

int main()
{
    std::ifstream ifs("input.txt");
    std::vector<Record> const insert { Record { "Jodi", 70 } };

    std::merge(
            std::istream_iterator<Record>(ifs), {}, 
            insert.begin(), insert.end(),
            std::ostream_iterator<Record>(std::cout, "\n"));
}

See it Live On Coliru 在Coliru上实时观看

How does it behave depends on file system. 它的行为取决于文件系统。 There is no solution for general. 没有通用的解决方案。 But I don't think there is a real-life filesystem where you can do such things. 但是我认为没有现实的文件系统可以执行此类操作。

Thing about how would file look on disk before and after such operation. 关于这种操作前后文件在磁盘上的外观如何。 File is one big block on disk. 文件是磁盘上的一大块。 So rewriting is action that need to be done. 因此,重写是需要执行的操作。

There could be a solution if you are open on some different approaches. 如果您对某些不同的方法持开放态度,可能会有解决方案。 Think about this file like about memory. 像存储一样考虑该文件。 How would you do this if it weren't on disk? 如果它不在磁盘上,您将如何处理? Which data structure you could use inside an array (we could fink about file as about an array)? 您可以在数组内使用哪种数据结构(我们可以将文件视为数组)?

If you don't want to create your own, use sth, which is done. 如果您不想创建自己的文件,请使用sth,这可以完成。 Personally I would use database for such task. 我个人将数据库用于此类任务。 It is just what you want. 这就是您想要的。 You can insert data and then get it sorted and it works fast. 您可以插入数据,然后对其进行排序,并且可以快速运行。 It is optimized to work in such environment like hard drive. 它经过优化,可在硬盘等环境中工作。 If you want to have it on file you can use SQLite . 如果您希望将其归档,则可以使用SQLite

One way is to load the file and then rewrite it having included the new data: 一种方法是加载文件,然后在包含新数据的情况下重写它:

1) You have to load the file in a structure using C++ file handling API (or any that you might think it is better). 1)您必须使用C ++文件处理API(或您认为更好的任何文件)将文件加载到结构中。

2) Data will be, because of being loaded sequentially, sorted in the structure.You must then add the node (your new data) you want in the structure in an order that it remains sorted. 2)由于将按顺序加载数据,因此将在结构中对数据进行排序。然后,必须按顺序将想要添加的节点(您的新数据)添加到结构中。

3) Finally, rewrite your file from the structure. 3)最后,从结构中重写文件。

For your case, you could maybe use an std::vector . 对于您的情况,您可以使用std::vector You can open the file and load all of its lines into that vector. 您可以打开文件并将其所有行加载到该向量中。 You can isolate data by doing string manipulation. 您可以通过执行字符串操作来隔离数据。 Then, put your data in the structure, in order that it remains sorted. 然后,将您的数据放入结构中,以使其保持排序状态。 You can, for example, split a line and then take the score part, parse it as int and make your comparisons with the new data score. 例如,您可以分割一条线,然后取分数部分,将其解析为int并与新数据分数进行比较。 After that, the structure contains your data state. 之后,该结构包含您的数据状态。 Open the file and rewrite it line by line. 打开文件并逐行重写。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM