Techioz Blog

ファイルを一行ずつ読み込みます、 または 行区切りとして

概要

ファイルを一行ずつ処理したい。ただし、これらのファイルの行区切り文字は異なります: ““、” ” または ” “。どれを使用しているのか、どの種類の OS なのかはわかりません。

解決策は 2 つあります。

ただし、ファイルが大きい場合、2 番目の解決策は適切ではありません。参考資料を参照してください。他にRubyの慣用的で効率的な解決策はありますか?

解決策

最初に行区切り文字を決定することをお勧めします。 「」に遭遇するまでは文字を読むことでそれができると思っていました。 ” または “” (またはファイルの最後に到達した場合、” ” を行区切り文字として使用します)。文字 ” の場合、 ” が見つかった場合は、それが区切り文字であると仮定します。” の場合は、” が見つかったので、次の文字を読み取ろうとします。読み取れた場合は ” “、 私は返す” 「」を区切り文字として使用します。” はファイルの最後の文字であるか、その後に ” 以外の文字が続きます。 “、 私は返す”“を区切り文字として使用します。

def separator(fname)
  f = File.open(fname)
  enum = f.each_char
  c = enum.next
  loop do
    case c[/\r|\n/]
    when "\n" then break
    when "\r"
      c << "\n" if enum.peek=="\n"
      break
    end
    c = enum.next
  end
  c[0][/\r|\n/] ? c : "\n"
end

次に、ファイルを 1 行ずつ処理します

def process(fname)
  sep = separator(fname)
  IO.foreach(fname, sep) { |line| puts line }
end

変換してないよ」” または ” ” に ” 」と書かれていますが、もちろんそれは簡単に行うことができます。書き込み用にファイルを開き、プロセス中に各行を読み取り、デフォルトの行区切り文字を使用して出力ファイルに書き込むだけです。

試してみましょう (わかりやすくするために、セパレータによって返される値を示します)。

fname = "temp"

IO.write(fname, "slash n line 1\nslash n line 2\n")
  #=> 30 
separator(fname)                                    
  #=> "\n" 
process(fname)
  # slash n line 1
  # slash n line 2

IO.write(fname, "slash r line 1\rslash r line 2\r", )
  #=> 30 
separator(fname)
  #=> "\r" 
process(fname)
  # slash r line 1
  # slash r line 2

IO.write(fname, "slash r slash n line 1\r\nslash r slash n line 2\r\n")
  #=> 48 
separator(fname)
  #=> "\r\n" 
process(fname)
  # slash r slash n line 1
  # slash r slash n line 2