问题描述
我知道如何写入文件和读取文件,但除了将整个文件读入内存、操作它和重写整个文件之外,我不知道如何修改文件.对于大文件,这不是很有效率.
I know how to write to a file, and read from a file, but I don't know how to modify a file besides reading the entire file into memory, manipulating it, and rewriting the entire file. For large files this isn't very productive.
我真的不知道追加和写入之间的区别.
I don't really know the difference between append and write.
例如
如果我有一个包含以下内容的文件:
If I have a file containing:
Person1,will,23
Person2,Richard,32
Person3,Mike,44
我如何才能删除包含 Person2 的行?
How would I be able just to delete line containing Person2?
推荐答案
您可以通过多种方式删除一行:
You can delete a line in a several ways:
模拟删除.也就是说,只需用空格覆盖行的内容.以后在读取和处理文件时,忽略这些空行即可.
Simulate deletion. That is, just overwrite line's content with spaces. Later, when you read and process the file, just ignore such empty lines.
优点:这既简单又快速.缺点:这不是真正的数据删除(文件不会缩小),您需要在读取/处理文件时做更多的工作.
Pros: this is easy and fast. Cons: it's not real deletion of data (file doesn't shrink) and you need to do more work when reading/processing the file.
代码:
f = File.new(filename, 'r+')
f.each do |line|
if should_be_deleted(line)
# seek back to the beginning of the line.
f.seek(-line.length, IO::SEEK_CUR)
# overwrite line with spaces and add a newline char
f.write(' ' * (line.length - 1))
f.write("
")
end
end
f.close
File.new(filename).each {|line| p line }
# >> "Person1,will,23
"
# >> "
"
# >> "Person3,Mike,44
"
做真正的删除.这意味着该行将不再存在.所以你必须阅读下一行并用它覆盖当前行.然后对所有后续行重复此操作,直到到达文件末尾.这似乎是一个容易出错的任务(不同长度的行等),所以这里有一个无错误的替代方法:打开临时文件,向其中写入一行(但不包括)要删除的行,跳过您要删除的行想删除,把剩下的写到临时文件中.删除原始文件并重命名临时文件以使用其名称.完成.
Do real deletion. This means that line will no longer exist. So you will have to read next line and overwrite the current line with it. Then repeat this for all following lines until the end of file is reached. This seems to be error prone task (lines of different lengths, etc), so here's an error-free alternative: open temp file, write to it lines up to (but not including) the line you want to delete, skip the line you want to delete, write the rest to the temp file. Delete the original file and rename temporary one to use its name. Done.
虽然这在技术上完全重写了文件,但它确实与您要求的有所不同.该文件不需要完全加载到内存中.一次只需要一行.Ruby 为此提供了一种方法:IO#each_line.
While this is technically a total rewrite of the file, it does differ from what you asked. The file doesn't need to be loaded fully to memory. You need only one line at a time. Ruby provides a method for this: IO#each_line.
优点:没有假设.行被删除.无需更改读取代码.缺点:删除行时需要做更多工作(不仅是代码,还有 IO/CPU 时间).
Pros: No assumptions. Lines get deleted. Reading code needs not to be altered. Cons: lots more work when deleting the line (not only the code, but also IO/CPU time).
@azgult 的答案中有一段说明了这种方法.
There is a snippet that illustrates this approach in @azgult's answer.
这篇关于如何使用 Ruby 删除文本文件中间的数据行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!