Ruby'de bir dosyanın satırlarını okuma


238

Bir dosyadan satırları okumak için aşağıdaki kodu kullanmaya çalışıyordum. Ancak bir dosyayı okurken , içeriğin tümü tek bir satırdadır:

line_num=0
File.open('xxx.txt').each do |line|
  print "#{line_num += 1} #{line}"
end

Ancak bu dosya her satırı ayrı ayrı yazdırır.


ruby my_prog.rb < file.txtDosyayı kullanan satır sonu karakterinin ne olduğunu tahmin edemediğim gibi stdin kullanmak zorundayım . Nasıl halledebilirim?


7
line_num = 0Yapmak yerine , each.each_with_indexya da muhtemelen kullanabilirsiniz each.with_index.
Andrew Grimm

@ andrew-grimm teşekkür ederim, daha temiz kod yapar.
çizmek

Satır satır IO'nun neden tercih edildiğini öğrenmek için stackoverflow.com/q/25189262/128421 adresine bakın read.
Tin Man

line.chompHat sonlarını işlemek için kullanın ( @SreenivasanAC'ın izniyle )
Yarin

Yanıtlar:


150

Ben cevabım hem beri satır sonları her türlü işleme konusunda yeni endişeleri kapsar inanıyoruz "\r\n"ve "\r"Linux standardına dönüştürülür "\n"çizgileri ayrıştırma önce.

"\r"EOL karakterini normalle birlikte "\n"ve "\r\n"Windows'dan desteklemek için şunları yapardım:

line_num=0
text=File.open('xxx.txt').read
text.gsub!(/\r\n?/, "\n")
text.each_line do |line|
  print "#{line_num += 1} #{line}"
end

Tabii ki bu çok büyük dosyalar için kötü bir fikir olabilir, çünkü tüm dosyayı belleğe yüklemek anlamına gelir.


Bu normal ifade benim için işe yaramadı. Unix formatı \ n, windows \ r \ n, mac kullanır \ n - .gsub (/ (\ r | \ n) + /, "\ n") tüm durumlarda benim için çalıştı.
Pod

4
/\r?\n/
Pod'un

12
Bu, tüm dosyayı belleğe okuyacaktır, bu da dosyanın ne kadar büyük olduğuna bağlı olarak imkansız olabilir.
eremzeit

1
Bu yöntem çok yüksek verimsizdir, levhalar burada cevap verir stackoverflow.com/a/17415655/228589 en iyi cevaptır. Lütfen bu iki yöntemin uygulandığını doğrulayın.
CantGetANick

1
Bu yakut yol değil. Aşağıdaki cevap doğru davranışı göstermektedir.
Merovex

525

Ruby'nin bunun için bir yöntemi var:

File.readlines('foo').each do |line|

http://ruby-doc.org/core-1.9.3/IO.html#method-c-readlines


bu metod @Olivier L.'den daha yavaştır
HelloWorld

1
@HelloWorld Muhtemelen önceki satırları bellekten silmeleri ve her satıra hafızaya yüklemeleri. Yanlış olabilir, ancak Ruby muhtemelen işleri düzgün yapıyor (böylece büyük dosyalar komut dosyanızın çökmesine neden olmaz).
Starkers

Bununla da kullanabilir misin with_index?
Joshua Pinter

1
Evet, yapabilirsiniz, örneğinFile.readlines(filename).each_with_index { |line, i| puts "#{i}: #{line}" }
wulftone

Bu yöntem daha iyi görünüyor. Çok büyük dosyaları okuyorum ve bu şekilde tüm dosyayı bir kerede belleğe yüklemeye çalışarak uygulamayı çökertmiyor.
Shelby S


18

İlk dosyanızda Mac Classic satır sonları vardır (bu "\r"her zamanki yerine "\n"). Birlikte aç

File.open('foo').each(sep="\r") do |line|

satır sonlarını belirtmek için.


1
Ne yazık ki, en azından bildiğim Python'da evrensel yeni satırlar gibi bir şey yok.
Josh Lee

bir soru daha, ben stdin kullanmak zorunda, ruby ​​my_prog.rb <file.txt gibi, nerede dosya biten char bit kullanır ne varsayalım ... Nasıl halledebilirim?
çizmek

Tüm dosyayı belleğe yüklemeyi tamamlarsanız, Olivier'in yanıtı faydalı görünüyor. Dosyayı tararken yeni satırları tespit etmek biraz daha fazla iş gerektirecektir.
Josh Lee

7

Bunun nedeni her satırdaki bitiş çizgilerinden kaynaklanmaktadır. Sonunda '\ n' veya 'r' bitiş çizgisini silmek için ruby'de chomp yöntemini kullanın.

line_num=0
File.open('xxx.txt').each do |line|
  print "#{line_num += 1} #{line.chomp}"
end

2
Chomp için @SreenivisanAC +1!
Yarin

7

Başlıkları olan dosyalar için aşağıdaki yaklaşımın bir parçasıyım:

File.open(file, "r") do |fh|
    header = fh.readline
    # Process the header
    while(line = fh.gets) != nil
        #do stuff
    end
end

Bu, bir başlık satırını (veya satırlarını) içerik satırlarından farklı şekilde işlemenizi sağlar.


6

nasıl olur ?

myFile=File.open("paths_to_file","r")
while(line=myFile.gets)
 //do stuff with line
end

4

Unutmayın, çalışma zamanında RAM'inizi batabilecek büyük satırlara sahip bir dosyada okuma konusunda endişeleriniz varsa, her zaman dosya parçasını okuyabilirsiniz. Bkz. " Bir dosyayı neden incelemek kötü? ".

File.open('file_path', 'rb') do |io|
  while chunk = io.read(16 * 1024) do
    something_with_the chunk
    # like stream it across a network
    # or write it to another file:
    # other_io.write chunk
  end
end
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.