Ruby中如何低成本获取调用文件的总行数?
Ruby 获取调用文件总行数的低成本方案
Ruby没有内置直接获取文件总行数的API,但可以通过缓存+高效行统计的方式实现低成本需求,完美适配你的调试工具场景:
核心实现思路
直接每次读取文件统计行数确实开销大,但同一个文件在调试过程中不会频繁变动,用缓存存储已统计过的文件行数,就能避免重复IO操作。同时用高效的行统计方法,减少内存占用。
基础缓存版实现
# 模块级缓存,存储文件路径对应的总行数 @@line_count_cache = {} def get_total_lines(file_path) # 优先返回缓存结果 return @@line_count_cache[file_path] if @@line_count_cache.key?(file_path) # 用File.foreach逐行统计,不加载整个文件到内存 line_count = 0 File.foreach(file_path) { line_count += 1 } # 写入缓存 @@line_count_cache[file_path] = line_count line_count rescue Errno::ENOENT, Errno::EACCES # 处理文件不存在或无权限的异常,返回nil nil end
结合你的调试代码使用
把这个方法和你现有获取行号的代码结合,就能输出3/122格式的内容:
loc = caller_locations(1, 1).first current_line = loc.lineno total_lines = get_total_lines(loc.path) # 输出结果,兼容文件无法读取的情况 puts total_lines ? "#{current_line}/#{total_lines}" : current_line.to_s
进阶:支持文件更新的缓存版
如果调试过程中需要实时获取修改后的文件行数,可以在缓存中同时存储文件的修改时间,每次调用时检查文件是否更新:
@@line_count_cache = {} def get_total_lines(file_path) if @@line_count_cache.key?(file_path) cached_count, cached_mtime = @@line_count_cache[file_path] return cached_count if File.mtime(file_path) == cached_mtime end line_count = 0 File.foreach(file_path) { line_count += 1 } @@line_count_cache[file_path] = [line_count, File.mtime(file_path)] line_count rescue Errno::ENOENT, Errno::EACCES nil end
为什么用File.foreach?
相比File.read(file_path).lines.size,File.foreach会逐行读取文件并立即处理,不会把整个文件内容加载到内存,对于大文件来说内存友好得多,统计效率也更高。
内容的提问来源于stack exchange,提问作者tscheingeld
相关产品推荐
相关产品推荐

