我有一个大约1000000行的数据文件,300+ Mb。我想把它转换成一个JSON文件。
JSON.generate和Hash.merge可以帮助生成JSON,但是我需要等待程序生成一个完整的哈希。时间太长了。
我想以增量的方式将JSON写入文件。
这是我的代码:
require 'yajl/json_gem'
my_hash = {}
fd1 = File.open("foo.json", "w")
fd2 = File.open("foo.log")
fd2.each_line do | line |
l = fd2.lineno
remote_addr = line.split(" ")[0]
time_local = line.split("]")[0].split("[")[1]
item = {l => {:remote_addr => remote_addr, :time_local => time_local}}
# {
# 1: {
# remote_addr: "1.2.3.4",
# time_local: ""
# },
# 2: {
# ...
# },
# ...
# }
my_hash.merge!(item)
end
fd2.close
fd1.puts JSON.generate(my_hash)
fd1.close这是我的数据:
// access.log
1.2.3.4 - - [02/Apr/2014:03:23:06 +0800] "GET /index" 200 1 "http://foo" "Mozilla/5.0" "-"有什么想法吗?提前谢谢。
--
编辑:
实际上,我最好像这样转换原始数据:
[
{
id: "1",
remote_addr: "1.2.3.4",
time_local: "02/Apr/2014:03:23:06 +0800"
},
{
...
},
{
...
}
]发布于 2014-04-08 08:51:32
这是基于示例行生成有效JSON输出的基本代码:
require 'json'
lines = [
'1.2.3.4 - - [02/Apr/2014:03:23:06 +0800] "GET /index" 200 1 "http://foo" "Mozilla/5.0" "-"',
'1.2.3.5 - - [03/Apr/2014:03:23:06 +0800] "GET /index" 200 1 "http://foo" "Mozilla/5.0" "-"'
]
lines.each_with_index do |line, l|
puts '{' if l == 0
remote_addr, time_local = /^(\S+) .+ \[(.+)\]/.match(line).captures
print '"%d":{"remote_addr":"%s","time_local":"%s"}' % [l + 1, remote_addr, time_local]
puts ',' if l + 1 < lines.size
end
puts "\n}"
# >> {
# >> "1":{"remote_addr":"1.2.3.4","time_local":"02/Apr/2014:03:23:06 +0800"},
# >> "2":{"remote_addr":"1.2.3.5","time_local":"03/Apr/2014:03:23:06 +0800"}
# >> }您需要将代码转换为读和写文件,或者可能读取单个文件并重定向输出以捕获它。您还需要弄清楚如何确定文件中的行数,以便找到输出逗号的位置。这很容易,而且我知道这里存在堆栈溢出的例子。
在原始代码中,您需要为open使用块表单,而不是将变量分配给变量,然后显式关闭文件;使用块形式的open是Ruby。另外,使用File.foreach逐行读取文件.
发布于 2014-04-08 09:29:34
@theTinMan发布了一个很好的答案,我只想补充一下,对于一个JSON对象列表,一个更通用的解决方案是自己构建这个列表,但是让JSON生成每个条目:
fd1.puts '{'
fd1 = File.open("foo.json", "w")
fd2 = File.open("foo.log")
first_line = true
fd2.each_line do | line |
fd1.puts(',') unless first_line
first_line = false
l = fd2.lineno
remote_addr = line.split(" ")[0]
time_local = line.split("]")[0].split("[")[1]
fd1.print "\"#{l}\": #{JSON.generate(:remote_addr => remote_addr, :time_local => time_local)}"
end
fd1.puts "\n}"https://stackoverflow.com/questions/22930408
复制相似问题