4

フラットな.txtファイル(100行未満の小さなファイル)内にいくつかのデータチャンクを格納するスクリプトを作成しようとしています。

とにかく、私は事実上、ファイル内に他のすべてを残したまま、その行の新しい値で単一の一致する行を更新しようとしていますが、ファイル全体を置き換えるのではなく、1行だけを変更する方法を完全に理解することはできません。

これまでの私のコードは次のとおりです。

# get file contents as array.
array_of_lines = File.open( "textfile.txt", "r" ).readlines.map( &:chomp )

line_start = "123456:"    # unique identifier
new_string = "somestring" # a new string to be put after the line_start indentifier.

# cycle through array finding the one to be updated/replaced with a new line.
# the line we're looking for is in format 123456:some old value

# delete the line matching the line_start key
array_of_lines.delete_if( |line| line_start =~ line )

# write new string into the array.
array_of_lines.push( "#{line_start}:#{new_string}" )

# write array contents back to file, replacing all previous content in the process
File.open( "textfile.txt", "w" ) do |f|
    array_of_lines.each do |line|
        f.puts line
    end
end

textfile.txt内容は常に次の形式で構成されます。

unique_id:string_of_text

ここでunique_id、スクリプトによって生成された使用中のアプリデータを照合して、更新するテキストの行を特定できます。

私がやろうとしていることを行うためのより良い方法はありますか?

ファイル全体をメモリに読み込んで、そのファイルの1行を更新するためだけにすべてをループするのは、少し非効率的なようです。

4

1 に答える 1

4

書き込んでいる新しいデータが古いデータと同じ長さでない限り、やりたいことを行うことはできません。

長さが異なる場合は、変更後のファイル内のすべてのバイトを移動する必要があります。ファイルデータの移動には、常にすべての書き換えが含まれます(変更の時点から)。その場合、ファイルが非常に小さいので、ファイル全体を書き直したほうがよいでしょう。

置換データが同じ長さの場合は、を使用IO.seekしてファイルポインターを適切な場所に配置し、を使用writeして置換データを入力できます。

それでもファイル全体を書き直したくないが、代わりにデータを移動するだけの場合(置換の長さが異なる場合)、seek正しい場所に移動し、writeその時点からファイルの最後まですべてを移動する必要があります。置換が短い場合はFile.truncate、ファイルのサイズを変更するために呼び出す必要もあります。

于 2012-07-14T22:46:18.267 に答える