文件迭代失败

时间:2014-03-27 14:02:37

标签: ruby file

我正试图以这种方式迭代文件的每一行:

@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),然后第二行“调用获取”不打印任何内容,实际上从未输入循环。

我做错了吗?

4 个答案:

答案 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)

您需要移除对readlinesgets的通话。 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