【问题标题】:How to read lines of a file in Ruby如何在 Ruby 中读取文件的行
【发布时间】:2011-08-26 03:45:51
【问题描述】:

我试图使用以下代码从文件中读取行。但是在阅读file时,内容都在一行中:

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

但是这个file 会分别打印每一行。


我必须使用标准输入,比如ruby my_prog.rb < file.txt,我不能假设文件使用的行尾字符是什么。我该如何处理?

【问题讨论】:

标签: ruby line-endings


【解决方案1】:

Ruby 确实有一个方法:

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

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

【讨论】:

  • 这个方法比 @Olivier L 的方法慢。
  • @HelloWorld 可能是因为它正在从内存中删除每一行并将每一行加载到内存中。可能是错误的,但 Ruby 可能会正确处理(因此大文件不会导致脚本崩溃)。
  • 你也可以用with_index这个吗?
  • 是的,你可以,例如File.readlines(filename).each_with_index { |line, i| puts "#{i}: #{line}" }
  • 这种方法似乎更好。我正在读取非常大的文件,这样它就不会因为尝试一次将整个文件加载到内存中而导致应用程序崩溃。
【解决方案2】:
File.foreach(filename).with_index do |line, line_num|
   puts "#{line_num}: #{line}"
end

这将为文件中的每一行执行给定的块,而不会将整个文件拖入内存。请参阅:IO::foreach

【讨论】:

  • 这就是答案 - 惯用的 Ruby 并且不会破坏文件。另见stackoverflow.com/a/5546681/165673
  • 向红宝石众神致敬!
  • 如何进入循环内的第二行?
  • 您必须使用'filename' 而不是filename。还要使用line_num+1 而不是line_num,所以第一行以1 开头,而不是0
  • @Smeterlink filename 是一个包含'xxx.txt' 等字符串的变量。
【解决方案3】:

我相信我的回答涵盖了您对处理任何类型的行尾的新担忧,因为 "\r\n""\r" 在解析行之前都转换为 Linux 标准 "\n"

要支持"\r" EOL 字符以及Windows 中的常规"\n""\r\n",我会这样做:

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

当然,这对于非常大的文件可能不是一个好主意,因为这意味着将整个文件加载到内存中。

【讨论】:

  • 那个正则表达式对我不起作用。 Unix 格式使用 \n,windows \r\n,mac 使用 \n -- .gsub(/(\r|\n)+/,"\n") 在所有情况下都适用于我。
  • 正确的正则表达式应该是 /\r?\n/,它将同时覆盖 \r\n 和 \n 而不会像 Pod 的注释那样组合空行
  • 这会将整个文件读入内存,这可能取决于文件的大小。
  • 这种方法效率非常低,talabes 在这里回答stackoverflow.com/a/17415655/228589 是最好的答案。请验证这两种方法的实现。
  • 这不是红宝石方式。下面的答案显示了正确的行为。
【解决方案4】:

您的第一个文件具有 Mac Classic 行尾(即 "\r" 而不是通常的 "\n")。打开它

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

指定行尾。

【讨论】:

  • 遗憾的是,Python 中没有通用换行符,至少据我所知。
  • 还有一个问题,我必须使用标准输入,例如 ruby​​ my_prog.rb
  • Olivier 的回答似乎很有帮助,如果您可以将整个文件加载到内存中。在扫描文件的同时检测换行符需要更多的工作。
【解决方案5】:

对于具有标题的文件,我偏爱以下方法:

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

这允许您以不同于内容行的方式处理一个(或多个)标题行。

【讨论】:

    【解决方案6】:

    这是因为每一行都有结束线。 使用 ruby​​ 中的 chomp 方法删除末尾的 endline '\n' 或 'r'。

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

    【讨论】:

    • @SreenivasanAC +1 大吃一顿!
    【解决方案7】:

    gets 怎么样?

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

    【讨论】:

      【解决方案8】:

      不要忘记,如果您担心读取的文件可能包含可能会在运行时占用您的 RAM 的大行,您可以随时读取文件。请参阅“Why slurping a file is bad”。

      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
      

      【讨论】:

        猜你喜欢
        • 2019-06-01
        • 1970-01-01
        • 2010-12-02
        • 1970-01-01
        • 2011-03-20
        • 1970-01-01
        • 2015-12-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多