当我尝试逐行读取一个gzip文件到Ruby 1.8.7时,它只读取gzip文件的第一行。这不会发生在我的测试机器上,只发生在我的生产服务器上。
这可能与zlib或Gzipreader有关,但我目前对下一步做什么感到不知所措,任何建议都会很棒。
require 'zlib'
require 'open-uri'
list = Array.new
file = Dir.glob("*").max_by {|f| File.mtime(f)}
File.open(file) do |f|
gz = Zlib::GzipReader.new(f)
#something right here is causing an issue on production system
list = gz.read
gz.close
end
#I need to take the array and push it to redis
list = list.split("\n")
list.shift
list.each do |list|
puts list
puts "\n\n"
end
答案 0 :(得分:2)
首先,如果脚本的工作目录中有其他文件,您可能希望使用'*.gz'
而不是'*'
。
以下是几个解决方案:
require 'zlib'
file = Dir.glob('*').max_by { |f| File.mtime(f) }
fd = File.open(file)
gz = Zlib::GzipReader(fd)
gz.readlines[1..-1].each do |line|
line.chomp!
puts line, "\n\n"
end
你应该不将未经过授权的用户输入传递给Kernel#exec
或类似的函数,因为它可以用来执行任意命令。
在您的情况下,您不处理用户输入。因此,需要对脚本的工作目录进行写访问才能执行此操作。但是,这仍然是不好的做法 - 包含特殊shell字符('
,"
,"$"
等)的文件名可能会导致意外问题。
以下解决方案应该与GzipReader
解决方案一样安全,但通常使用标准库而不是依赖外部程序是一种好习惯。
file = Dir.glob('*').max_by { |f| File.mtime(f) }
IO.popen(['zcat', file]).readlines[1..-1].each do |line|
line.chomp!
puts line, "\n\n"
end
答案 1 :(得分:1)
以下是如何以类似Ruby的方式编写它:
require 'open-uri'
file = Dir.glob("*").max_by { |f| File.mtime(f) }
`zcat #{file}`.split("\n")[1..-1].each do |list|
puts list, "\n\n"
end
以下是它的作用:
zcat
发送命令。each
循环生成的数组。list
传递到块中。原始代码有什么问题?除了以非类似Ruby的方式完成?
Array.new
初始化数组。这不是Java,所以使用[]
除非你需要一些较暗的Array初始化魔法。list
并以多种方式使用{{1}}。这是一个糟糕的主意,特别是当你从非平凡的应用程序转移到大的应用程序时。不要创建“slush”变量,创建有用的命名变量。特别是,当你按照逻辑运行时,不要踩踏它们。 答案 2 :(得分:0)
我根据以下建议找出了解决方案。 我继续向系统提供zcat +最新文件,将其反馈到一个名为output的字符串中。获取字符串输出并将其放入名为list的数组中,以便每个新行分开。这显然是用于登录目的。 再次感谢。
require 'open-uri'
require 'open3'
list = Array.new
file = Dir.glob("*").max_by {|f| File.mtime(f)}
unzip = "zcat " + file
output = `#{unzip}`
list = output
#I need to take the array and push it to redis
list = list.split("\n")
list.shift
list.each do |list|
puts list
puts "\n\n"
end