如何在不操作文件中的其余数据的情况下删除文本文件中的字符?

时间:2015-10-21 01:33:03

标签: file text fstream random-access

如何在不操作文件中的其他数据的情况下删除文本文件中的字符?例如, file.txt 1234567,我想删除6所以 file.txt 包含123457而不读取整个文件到内存中。

2 个答案:

答案 0 :(得分:2)

无法做到。如果不处理文件的剩余后缀以缩小差距,则无法删除字符。

大多数主流文件系统的基础数据结构不支持对任意字节范围或单个字节进行常量时间删除。

这不仅仅是文件系统结构的问题。删除字节而不移动任何数据会导致文件块和内存页面之间的错位。这对缓冲,缓存和内存映射有影响。

答案 1 :(得分:0)

问题

如果没有某种方式索引数据流,通常无法将文本作为随机访问数据读取。更重要的是,即使您可以在不写文件其余部分的情况下更改单个字节,也不能删除一个字节,而不会在删除文本后写出剩余的文件。

由于您没有在原始问题中指定语言,因此我将向您介绍一些允许面向行,面向字符和面向字节的文件操作的Ruby方法。这样您就可以将文本视为一系列字符或字节,而不必立即将整个文件粘贴到内存中。

考虑以下Ruby IO methods

之间的区别
  • IO#读
  • IO#readline的
  • IO#readlines方法
  • IO#readbyte
  • IO#readchar

一些实用的解决方案

最简单的解决方案:优化速度而不是内存

一般情况下,只要你有足够的内存,将整个文件用File#read或者用File#readlines创建一个多行数组就会最快,但内存需求会随着内存大小的增加而增长输入文件增长。简而言之,您试图避免使用相当于:

的无限制文件大小的问题
File.read('file') do |f|
  f.delete '6'
end

除非您对磁盘颠簸或内存受限(例如在嵌入式系统中)有合理的期望,否则执行除了篡改文件之外的其他操作可能是过早的优化。您的里程可能会有所不同。

内存受限系统的潜在解决方案

假设它们不是过早优化,您当然可以将以下方法适用于几乎所有语言。我在Ruby中展示它们是为了便于阅读和实验。

面向行的方法

处理多行输入且内存开销很小的一种方法(假设你的文件当然有换行符)是File#readline。例如:

old_file = File.new 'file'
new_file = File.new 'file.new', 'w'

# Delete the string character '6' from each line of input.
while line = old_file.readline do
  new_file.puts line.delete '6'
end 

面向角色的方法

更加内存保守的面向字符的方法可能会使用File#readchar。例如:

old_file = File.new 'file'
new_file = File.new 'file.new', 'w'

# Write each character to the new file unless the character is "6".
while char = old_file.readchar do
  new_file.print(char) unless char == '6'
end