如何让Ruby代码批量读取含多专辑信息的TXT文件?
解决Ruby批量读取多专辑TXT文件的问题
原代码的核心问题
- 重复IO操作:反复调用
IO.readlines会多次读取整个文件,既低效又无法追踪读取位置。 - 硬编码行号:固定从指定行读取单专辑信息,无法连续解析后续专辑。
- 逻辑混乱:
get_track和get_tracks的职责重叠,导致歌曲重复读取,无法正确对应专辑的歌曲数量。
重构后的解决方案
我们可以一次性读取文件所有内容到内存,用索引追踪读取位置,逐段解析每个专辑,直到文件内容处理完毕。
完整重构代码
# 读取单个专辑的信息,接收文件行数组和当前索引(引用传递,用于更新读取位置) def read_single_album(lines, index_ref) # 读取专辑基础信息 artist = lines[index_ref].strip index_ref[0] += 1 album_name = lines[index_ref].strip index_ref[0] += 1 genre_id = lines[index_ref].strip.to_i index_ref[0] += 1 track_count = lines[index_ref].strip.to_i index_ref[0] += 1 # 读取对应数量的歌曲 tracks = [] track_count.times do track_name = lines[index_ref].strip index_ref[0] += 1 track_path = lines[index_ref].strip index_ref[0] += 1 tracks << Track.new(track_name, track_path) end # 创建并返回专辑对象 Album.new(album_name, artist, genre_id, tracks) end # 批量读取文件中所有专辑 def read_all_albums(file_path) # 一次性读取所有行,过滤空行(避免文件末尾空行干扰) lines = File.readlines(file_path).reject { |line| line.strip.empty? } index = [0] # 用数组实现引用传递,在子方法中更新索引 albums = [] # 循环读取直到所有行处理完毕 while index[0] < lines.size albums << read_single_album(lines, index) end albums end
代码说明
- 一次性读取文件:用
File.readlines一次性把所有内容读入数组,避免重复IO操作,同时过滤空行防止解析错误。 - 索引追踪读取位置:用数组
index实现引用传递(Ruby中整数是值传递,数组是引用传递),在读取单个专辑时动态更新索引,确保下一次读取从下一个专辑的起始行开始。 - 逐段解析专辑:
- 先读取专辑的4行基础信息(艺术家、专辑名、流派、歌曲数)。
- 根据歌曲数读取对应数量的歌曲(每首歌占两行:歌名+路径)。
- 创建
Track和Album对象,加入结果数组。
- 无硬编码行号:所有读取位置通过索引动态计算,完全兼容单专辑和多专辑的TXT文件。
使用示例
# 读取多专辑文件并处理 albums = read_all_albums("multi_albums.txt") albums.each do |album| puts "艺术家: #{album.artist}" puts "专辑名: #{album.title}" puts "流派编号: #{album.genre}" puts "歌曲列表:" album.tracks.each do |track| puts " - #{track.name}: #{track.location}" end puts "-------------------------" end
适配原代码的Track/Album类
假设你的Track和Album类定义如下(如果原类结构不同,只需调整read_single_album中创建对象的参数即可):
class Track attr_reader :name, :location def initialize(name, location) @name = name @location = location end end class Album attr_reader :title, :artist, :genre, :tracks def initialize(title, artist, genre, tracks) @title = title @artist = artist @genre = genre @tracks = tracks end end
内容的提问来源于stack exchange,提问作者user14397428
相关产品推荐
相关产品推荐

