我正试图以这种方式迭代文件的每一行:
@dump_users=File.open("#{@tmp_dir}path_to_file.txt","r")
puts "about to open file #{@dump_users.path} with size #{@dump_users.readlines.size}"
puts "calling gets: #{@dump_users.gets}"
while (user_line=@dump_users.gets) do
arr=user_line.split("\t")
puts "About to add user: #{arr.inspect}"
query="INSERT INTO users VALUES (%s,\"%s\")" % [arr.at(0),arr.at(1).chop]
puts "Added users: #{arr.inspect}"
@db_3.execute(query)
end
第一行puts
行打印正确的路径和文件的行数(362),然后第二行“调用获取”不打印任何内容,实际上从未输入循环。
我做错了吗?
答案 0 :(得分:2)
当您致电@dump_users.readlines
时,您需要将该位置推进到文件末尾。在迭代之前调用@dump_users.rewind
。
答案 1 :(得分:1)
您正在做的事情存在一些问题。我把它写成这个未经测试的代码:
require 'sequel'
DB = Sequel.connect(@dsn)
path_to_file = File.join(@tmp_dir, "path_to_file.txt")
puts %Q[About to open "#{ path_to_file }"]
File.foreach(path_to_file) do |user_line|
arr = user_line.split("\t")
puts "Adding user: #{arr.join(' ') }"
DB[:users].insert(fname: arr[0], lname: arr[1])
end
open
,而是从不关闭文件,使用带有Ruby的IO或File类方法的块在块退出时自动close
文件。这样可以保留系统资源。如果您需要知道有多少条目,而不是使用open
而不是可扩展的readlines
,则逐行遍历文件。 foreach
几乎(如果没有那么快)readlines
并且如果您正在处理的文件变成数百GB,则不会打开代码占用所有空间尺寸。例如,您可以对文件进行简单的飞行前检查,以查看需要使用的行数:
lines_in_file = 0
File.foreach('file_to_read') { lines_in_file += 1 }
puts "There are #{ lines_in_file } lines."
如果您在插入之前需要查看每一行,请使用比inspect
更能控制的内容,例如简单的String format
行:
puts 'Adding user: %s %s' % [arr[0], arr[1]]
inspect
对于调试很有用,但在生产代码中却没有用,所以不要养成这种习惯。
不要将值插入数据库查询"插入"串。决不。永远。如果该文件遭到入侵或来自未知/不安全的来源,这就是SQL注入攻击的直接途径。相反,您至少应该使用占位符。但是,更好的方法是使用良好的ORM,如Sequel,并让它处理生成与DBM接口所需的代码。它更容易,经过实战考验。
答案 2 :(得分:0)
@dump_users.readlines.size
将文件指针前进到文件末尾。尝试删除该行。
答案 3 :(得分:0)
您需要移除对readlines
和gets
的通话。 readlines
将文件指针前进到文件结尾,然后gets
没有任何内容可读,并返回nil:
@dump_users=File.open("#{@tmp_dir}path_to_file.txt","r")
# puts "about to open file #{@dump_users.path} with size #{@dump_users.readlines.size}"
# puts "calling gets: #{@dump_users.gets}"
while (user_line=@dump_users.gets) do
arr=user_line.split("\t")
puts "About to add user: #{arr.inspect}"
query="INSERT INTO users VALUES (%s,\"%s\")" % [arr.at(0),arr.at(1).chop]
puts "Added users: #{arr.inspect}"
@db_3.execute(query)
end