【问题标题】:Ruby Program not reading all lines in filesRuby程序没有读取文件中的所有行
【发布时间】:2016-05-22 18:27:07
【问题描述】:

我是 ruby​​ 新手,并且有以下代码读取文件,然后将符号用“|”分隔登录到 Struc 数据类型的不同属性:

Song = Struct.new(:title, :name, :length)
song_file = File.new("songdata.txt")
songs = []

song_file.each_line do |line|
    file, length, name, title = line.chomp.split(/\s*\|\s*/)
    songs << Song.new(title, name, length)
end

p songs

文件 songdata.txt 包含以下 txt:

/jazz/j00132.mp3  | 3:45 | Fats     Waller     | Ain't Misbehavin'
/jazz/j00319.mp3  | 2:58 | Louis    Armstrong  | Wonderful World
/bgrass/bg0732.mp3| 4:09 | Strength in Numbers | Texas Red

但是,当我去打印数组歌曲时,它只包含文本文件的第一行。关于为什么会这样的任何想法?

【问题讨论】:

  • 我在我的机器上运行了这个确切的代码和这个确切的输入文件,但是得到了所有三行。你确定它行为不端?你有什么版本的红宝石?
  • 您确定这是您使用的输入吗?适合我。
  • 2.3.0 - 是的,说其他索引为零
  • 你们的txt文件都用什么?
  • 该代码看起来不错。一定是发生了其他事情。

标签: ruby io


【解决方案1】:

问题应该与行尾有关。 Ruby 似乎可以很好地处理 Windows 和 Unix 行尾,但是当您将文件的行尾更改为 OSX(SublimeText 中的“Mac OS 9”)时,它只会读取第一行。

songdata.txt 的行尾更改为 Unix 或 Windows。

【讨论】:

  • 感谢您 - 当我通过 TextEdit 创建文件时,它不起作用。但是当我使用 TextWrangler 创建文件时它起作用了,因为它的默认值是 Unix
【解决方案2】:

看起来问题是由于行尾引起的。我发布此内容只是为了向您展示如何在此用例中使用 map。它还使用 __END__DATA 在单个 ruby​​ 脚本中混合 ruby​​ 代码和测试数据。适合测试这种情况。

Song = Struct.new(:title, :name, :length)
song_file = DATA

songs = song_file.each_line.map do |line|
    file, length, name, title = line.chomp.split(/\s*\|\s*/)
    Song.new(title, name, length)
end

p songs.size
__END__
/jazz/j00132.mp3  | 3:45 | Fats     Waller     | Ain't Misbehavin'
/jazz/j00319.mp3  | 2:58 | Louis    Armstrong  | Wonderful World
/bgrass/bg0732.mp3| 4:09 | Strength in Numbers | Texas Red

通过使用map,您可以避免在迭代文件之前定义空数组。

【讨论】:

    【解决方案3】:

    试试这个

    arr = []
    File.open('songdata.txt', 'r') do |song_file|
        song_file.each_line do |detail|
          arr =  detail.split(' | ')
          title = arr[0].split(/\s*\|\s*/)
          length = arr[1]
          artist = arr[2]
          name = arr[3]
          #now you can do anything as per requirement
        end
    end
    

    【讨论】:

      【解决方案4】:

      正如之前针对类似问题所说,您可能不应该自己进行解析,而应该使用 CSV 库为您完成解析。 CSV = 逗号分隔值,但支持逗号以外的分隔符,并且管道很常见。

      Ruby 有一个内置的 CSV 库,使用它,您可以将您的方法和 CSV 方法的结果与以下代码进行比较:

      #!/usr/bin/env ruby
      
      Song = Struct.new(:title, :name, :length)
      SONG_FILESPEC = 'songdata.txt'
      
      def read_records_regex  # OP's original approach
        songs = []
        File.new(SONG_FILESPEC).each_line do |line|
            file, length, name, title = line.chomp.split(/\s*\|\s*/)
            songs << Song.new(title, name, length)
        end
        songs
      end
      
      require 'csv'
      def read_records_csv  # alternate CSV approach
        songs = []
        CSV.foreach(SONG_FILESPEC, col_sep: '|') do |fields|
          fields.map!(&:strip)
          file, length, name, title = fields
          songs << Song.new(title, name, length)
        end
        songs
      end
      
      puts read_records_regex
      puts '-' * 79
      puts read_records_csv
      

      输出:

      #<struct Song title="Ain't Misbehavin'", name="Fats     Waller", length="3:45">
      #<struct Song title="Wonderful World", name="Louis    Armstrong", length="2:58">
      #<struct Song title="Texas Red", name="Strength in Numbers", length="4:09">
      -------------------------------------------------------------------------------
      #<struct Song title="Ain't Misbehavin'", name="Fats     Waller", length="3:45">
      #<struct Song title="Wonderful World", name="Louis    Armstrong", length="2:58">
      #<struct Song title="Texas Red", name="Strength in Numbers", length="4:09">
      

      请注意,如果要丢弃数据文件,则可能不应包含空格。

      有些 CSV gem 比 Ruby 的内置支持更复杂,但这种情况很简单,Ruby 就可以了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-04-19
        • 1970-01-01
        • 2013-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多