文件迭代失败



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

@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(,然后第二行"callinggets"不打印任何内容,并且实际上从未进入循环。

我做错什么了吗?

当您调用@dump_users.readlines时,您正在将位置推进到文件的末尾。迭代前调用@dump_users.rewind

您所做的工作存在一些问题。我会像这样写未经测试的代码:

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接口所需的代码。它更容易,而且经过战斗考验。

@dump_users.readlines.size将文件指针推进到文件的末尾。试着去掉那条线。

您需要删除对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

相关内容

  • 没有找到相关文章

最新更新