How to read lines of a file in Ruby
我试图使用以下代码从文件中读取行。 但是在阅读文件时,内容都在一行中:
1 2 3 4
| line_num=0
File.open('xxx.txt').each do |line|
print"#{line_num += 1} #{line}"
end |
但是这个文件分别打印每一行。
我必须使用stdin,比如ruby my_prog.rb < file.txt,我不能假设文件使用的行尾字符是什么。 我该怎么处理?
-
您可以使用each.each_with_index或可能使用each.with_index,而不是line_num = 0。
-
@ andrew-grimm谢谢你,它使代码更清晰。
-
请参阅stackoverflow.com/q/25189262/128421,了解为什么逐行IO优于使用read。
-
使用line.chomp来处理行结尾(@SreenivasanAC提供)
-
可能的重复什么是在Ruby中读取文件的所有常用方法?
-
我建议阅读stackoverflow.com/questions/25189262/why-is-slurping-a-file-bad
Ruby确实有一个方法:
1
| File.readlines('foo').each do |line| |
http://ruby-doc.org/core-1.9.3/IO.html#method-c-readlines
-
这种方法比@Olivier L.的方法更慢
-
那个过早的优化怎么样?它读得更好,如果我没有弄错,它不会优化。最佳方法是这里讨论的方法,因为它不需要首先将整个文件读入内存。 ruby-doc.org/core-2.0/IO.html#method-c-foreach
-
我认为@Barry指的是接受的答案 - 而不是这个答案
-
@HelloWorld可能是因为它从内存中删除了每一行并在每行中加载到内存中。可能是错的,但Ruby可能正常做事(因此大文件不会导致脚本崩溃)。
-
这看起来是正确的答案。
-
你也可以用with_index吗?
-
是的,你可以,例如, File.readlines(filename).each_with_index { |line, i| puts"#{i}: #{line}" }
-
这种方法似乎更好。我正在读取非常大的文件,这样它不会通过尝试立即将整个文件加载到内存中而使应用程序崩溃。
-
@HelloWorld只有当你将整个文件同时放入内存时,否则这个文件会更快或者是唯一一个没有崩溃的文件。在只有1 GB RAM的系统上尝试1 GB文件中的每种方法。
1 2 3
| File.foreach(filename).with_index do |line, line_num|
puts"#{line_num}: #{line}"
end |
这将为文件中的每一行执行给定的块,而不会将整个文件压入内存。请参阅:IO :: foreach。
-
我不敢相信这不是正确的答案。
-
这就是答案 - 惯用的Ruby并没有玷污文件。另请参见stackoverflow.com/a/5546681/165673
-
所有人都欢呼红宝石众神!
-
如何进入循环内的第二行?
我相信我的答案涵盖了处理任何类型的行结尾的新问题,因为在解析行之前"
"和"
"都转换为Linux标准"
"。
要支持"
" EOL字符以及来自Windows的常规"
"和"
",以下是我要做的事情:
1 2 3 4 5 6 7 8 9
| line_num=0
text=File.open('xxx.txt').read
text.gsub!(/
?/,"
")
text.each_line do |line|
print"#{line_num += 1} #{line}"
end |
当然,这对于非常大的文件来说可能是一个坏主意,因为这意味着将整个文件加载到内存中。
-
那个正则表达式对我不起作用。 Unix格式使用 n,windows r n,mac使用 n - .gsub(/( r | | n)+ /," n")适用于所有情况。
-
正确的正则表达式应该是/
?
/,它将覆盖 r n和 n而不组合空行,因为Pod的注释会做
-
这会将整个文件读入内存,这可能是不可能的,具体取决于文件的大小。
-
我想而不是text = File.open('xxx.txt')。你想要File.read('xxx.txt')。否则你需要关闭文件?
-
这种方法非常低效,talabes在这里回答stackoverflow.com/a/17415655/228589是最好的答案。请验证这两种方法的实现。
-
@AntoineToulme不,ruby会在gc时自动关闭文件。真正的一点是我们应该使用乔纳森的答案。
-
这不是红宝石的方式。下面的答案显示了正确的行为。
您的第一个文件具有Mac Classic行结尾(即"
"而不是通常的"
")。打开它
1 2
| File.open('foo').each(sep="
") do |line| |
指定行结尾。
-
哦,我以为Ruby会处理它......
-
可悲的是,至少在我所知道的情况下,没有像Python中的通用新行那样。
-
还有一个问题,我必须使用stdin,比如ruby my_prog.rb
-
如果你把整个文件加载到内存中,Olivier的答案似乎很有帮助。在扫描文件的同时检测换行还需要更多的工作。
-
好的,谢谢!
怎么样?
1 2 3 4
| myFile=File.open("paths_to_file","r")
while(line=myFile.gets)
//do stuff with line
end |
这是因为每行的终结线。
使用ruby中的chomp方法删除末尾的' n'或'r'。
1 2 3 4
| line_num=0
File.open('xxx.txt').each do |line|
print"#{line_num += 1} #{line.chomp}"
end |
-
@SreenivisanAC +1 for chomp!
对于具有标题的文件,我对以下方法不满意:
1 2 3 4 5 6 7
| File.open(file,"r") do |fh|
header = fh.readline
# Process the header
while(line = fh.gets) != nil
#do stuff
end
end |
这允许您以不同于内容行的方式处理标题行(或多行)。
不要忘记,如果您担心在文件中读取可能会在运行期间淹没RAM的大行,您可以随时读取文件。请参阅"为什么啜饮文件很糟糕"。
1 2 3 4 5 6 7 8
| 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 |