我目前正在使用极大的固定宽度文件,有时超过一百万行。我编写了一个可以根据一组参数写入文件的方法,但我认为必须有一种更有效的方法来实现这一点。我正在使用的当前代码是:
def self.writefiles(file_name, positions, update_value)
@file_name = file_name
@positions = positions.to_i
@update_value = update_value
line_number = 0
@file_contents = File.open(@file_name, 'r').readlines
while line_number < @file_contents.length
@read_file_contents = @file_contents[line_number]
@read_file_contents[@positions] = @update_value
@file_contents[line_number] = @read_file_contents
line_number += 1
end
write_over_file = File.new(@file_name, 'w')
line_number = 0
while line_number < @file_contents.length
write_over_file.write @file_contents[line_number]
line_number += 1
end
write_over_file.close
end
例如,如果文件中的位置25表明它是原始文件,则该值将设置为“O”,如果我想替换该值,我将使用ClassName.writefiles(filename,140,“X” )改变每一行的这个位置。任何有助于提高此方法效率的帮助都将非常感激!
由于
答案 0 :(得分:1)
如果它是固定宽度的文件,您可以打开文件进行读/写,并使用搜索移动到要写入的数据的开头,并且只写入您正在更改的数据而不是整行。这可能比重写整个文件以替换一个字段更有效。
这是一个粗略的例子。它读取最后一个字段(10,20,30),将其递增1,并将其写回:
tha_file (每行10个字符,包括换行符)
12 3 x 10
23 4 x 20
78 9 x 30
<强> seeker.rb 强>
#!/usr/bin/env ruby
fh=open("tha_file", "r+")
$RECORD_WIDTH=10
$POS=8
$FIELD_WIDTH=2
# seek to first field
fh.seek($POS - 1, IO::SEEK_CUR)
while !fh.eof?
cur_val=fh.read($FIELD_WIDTH).to_i
puts "read #{cur_val}"
fh.seek(-1 * $FIELD_WIDTH, IO::SEEK_CUR)
cur_val = cur_val + 1
fh.write(cur_val)
puts "wrote #{cur_val}"
# Move to start of next field in the middle of next record
fh.seek($RECORD_WIDTH - $FIELD_WIDTH, IO::SEEK_CUR)
end
答案 1 :(得分:0)
#!/usr/bin/ruby
# replace_at_pos.rb
pos, char, infile, outfile = $*
pos = pos.to_i
File.open(outfile, 'w') do |f|
File.foreach(infile) do |line|
line[pos] = char
f.puts line
end
end
并将其用作:
replace_at_pos.rb 140 X inputfile.txt outputfile.txt
要替换值集,可以使用哈希:
replace = {
100 => 'a',
155 => 'c',
151 => 't'
}
. . .
replace.each do |k, v|
line[k] = v
end
答案 2 :(得分:0)
通过重新编写程序一次读取一行文件(当前正在将整个文件读入内存),您肯定会节省一些时间和相当多的内存。然后,您可以在循环中写入文件的备份副本,然后在末尾重命名该文件。这样的事情。
def self.writefiles2(file_name, positions, update_value)
@file_name = file_name
@new_file = file_name + ".bak"
@positions = positions.to_i
@update_value = update_value
line_number = 0
reader = File.open(@file_name, 'r')
writer = File.open(@new_file, 'w')
while (line = reader.gets() and not line.nil? )
line[@positions] = @update_value
writer.puts(line)
end
reader.close
writer.close
# Rename the file
end
这当然需要在重命名元素周围进行一些错误处理,这可能会导致输入数据丢失。