我有一个大约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"
},
{
...
},
{
...
}
]
答案 0 :(得分:1)
这是基于样本行生成有效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"}
# >> }
您需要将代码转换为读取和写入文件,或者读取单个文件并重定向输出以捕获它。您还需要弄清楚如何确定文件中的行数,以便找到输出逗号的位置。这很简单,我知道在Stack Overflow上存在这样做的例子。
在原始代码中,您需要使用open
的块表单,而不是分配给变量然后显式关闭文件;使用open
的块形式是Ruby方式。另外,使用File.foreach
逐行读取文件。
答案 1 :(得分:0)
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}"