删除 C++ 中 ofstream 中的一行
我想删除文件中的行。我知道您可以存储文件的内容(例如在向量中),擦除该行并再次写入。不过感觉很麻烦,而且文件变大的话效率也不是很高。
有人知道更好、更高效、更优雅的方法吗?
I want to erase lines within a file. I know you can store the content of the file (in a vector for example), erase the line and write again. However, it feels very cumbersome, and not very efficient if the file gets bigger.
Anyone knows of a better, more efficient, more elegant way of doing it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在大多数文件系统上,这是除了切换到实际数据库之外的唯一选择。
但是,如果您发现自己处于这种情况(即非常大的文件,中间有插入/删除),请考虑是否可以执行一些操作,例如在文件顶部维护位图,其中每个位代表文件的一行。要“删除”一行,只需翻转相应的位值即可。
On most file-systems, this is the only option you have, short of switching to an actual database.
However, if you find yourself in this situation (i.e. very large files, with inserts/deletes in the middle), consider whether you can do something like maintaining a bitmap at the top of the file, where each bit represents one line of your file. To "delete" a line, simply flip the corresponding bit value.
磁盘文件并没有什么特别神奇的地方。他们仍然喜欢将数据存储在连续的区域(通常称为“块”)。他们没有办法在这些区域中间留下无数据的漏洞。因此,如果您想从这些区域之一的中间“删除”三个字节,则必须通过将该区域中的其他所有内容向后移动三个字节来完成此操作。不,这效率不高。
这就是为什么文本编辑器(必须经常做这种事情)倾向于将尽可能多的文件(如果不是全部)加载到 RAM 中,在 RAM 中移动数据要快得多。它们通常仅在请求时(或定期)将更改写回磁盘。如果您必须进行大量这样的更改,我建议您从他们的书中获取一页并执行类似的操作。
There's nothing particularly magical about disk files. They still like to store their data in contiguous areas (typically called something like "blocks"). They don't have ways of leaving data-free holes in the middle of these areas. So if you want to "remove" three bytes from the middle of one of these areas, something somewhere is going to have to accomplish this by moving everything else in that area back by three bytes. No, it is not efficient.
This is why text editors (which have to do this kind of thing a lot) tend to load as much of the file as possible (if not all of it) into RAM, where moving data around is much faster. They typically only write changes back to disk when requested (or periodically). If you are going to have to make lots of changes like this, I'd suggest taking a page from their book and doing something similar.
BerkeleyDB (dbopen(3)) 有一个名为 DB_RECNO 的访问方法。这允许人们使用任何类型的记录分隔符来操作任意长度的文件。默认使用可变长度记录,并以 Unix 换行符作为分隔符。然后,您可以使用整数索引访问每个“记录”。使用它,您可以从文本文件中删除任意行。这并非特定于 C++,但如果您使用的是大多数 Unix/Linux 系统,则该 API 已经可供您使用。
The BerkeleyDB (dbopen(3)) has an access method called DB_RECNO. This allows one to manipulate files with arbitrary lengths using any sort of record delimiter. The default uses variable-length records with unix newlines as delimiters. You then access each "record" using an integer index. Using this, you can delete arbitrary lines from your text file. This isn't specific to C++, but if you are on most Unix/Linux systems, this API is already available to you.