2014-03-27 51 views
0

我想重复一个文件的每一行是这样的:文件迭代失败

@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 ([email protected]_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

不要在拆分后使用'inspect'查看数组。而是使用'join('')'。 –

回答

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或者文件类的方法来自动close文件块退出时。这保留了系统资源。
  • 而不是使用openreadlines,这是不可扩展的,如果您需要知道有多少条目,则逐行迭代文件。 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连接所需的代码。这更容易,并经过战斗测试。

0

@dump_users.readlines.size使文件指针前进到文件末尾。尝试删除该行。

2

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

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 ([email protected]_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 
+0

现在正在运行测试,thx为此!我没有意识到gets和readline的内部工作 – JBoy