我正在尝试在Rails中读取上传文件的每一行。
file_data = params[:files]
if file_data.respond_to?(:read)
file_data.read.gsub( /\n/, "\r\n" ).split("\r\n").each do |line|
inputUsers.push(line.strip)
end
elsif file_data.respond_to?(:path)
File.read(file_data.path).gsub( /\n/, "\r\n" ).split("\r\n").each do |line|
inputUsers.push(line.strip)
end
如果上传的文件包含Windows和Unix编码的混合,可能是由于从多个位置复制,Rails没有正确分隔文件的每一行,有时会返回两行作为一行。
该应用程序托管在Linux机器上。此外,该文件是从Google文档电子表格列中复制的。
这个问题有什么解决方案吗?
编辑:
未分隔成新行的行的十六进制代码如下所示:
636f 6d0d 0a4e 6968
答案 0 :(得分:2)
以下是我如何做到这一点。首先,测试一些代码:
SAMPLE_TEXT = [
"now\ris\r\nthe\ntime\n",
"for all good men\n"
]
def read_file(data)
data.each do |li|
[ *li.split(/[\r\n]+/) ].each do |l|
yield l
end
end
end
read_file(SAMPLE_TEXT) do |li|
puts li
end
哪个输出:
now
is
the
time
for all good men
神奇发生在[ *li.split(/[\r\n]+/) ]
。打破它:
li.split(/[\r\n]+/)
导致该行在返回,换行和其组合上被拆分。如果一行有多个代码,那么代码会吞噬空行,所以如果有可能你会收到那些你需要更复杂的模式,/[\r\n]{1,2}/
虽然未经测试,但应该有效。*li.split(/[\r\n]+/)
使用“splat”运算符*
,它表示将以下数组分解为其组成元素。当您不确定是否将单个元素或数组传递给方法时,这是获取数组的便捷方法。 [*li.split(/[\r\n]+/)]
获取返回的组件并将其转回单个数组。修改处理文件的方法很简单:
def read_file(fname)
File.foreach(fname) do |li|
[ *li.split(/[\r\n]+/) ].each do |l|
yield l
end
end
end
以与上一个示例中相同的方式调用它:
read_file('path/to/file') do |li|
puts li
end
您要使用foreach
的原因是它会逐行读取,这比使用read
或readlines
诋毁文件的内存效率要高得多其中一次将整个文件读入内存。 foreach
也非常快,因此在使用它时不会受到速度限制。因此,read
- 类型方法几乎没有优势,使用foreach
具有很大优势。
答案 1 :(得分:1)
您将\n
替换为\r\n
,这在解析Windows文件时会出现问题。现在\r\n
变为\r\r\n
。
最好是替换Unix行结束格式,然后拆分\n
:
file_data.read.gsub( /\n/, "\r\n" ).split("\r\n").each do |line|
变为:
file_data.read.gsub( /\r\n/, "\n" ).split("\n").each do |line|
答案 2 :(得分:0)
尝试内置方法:
File.readlines('foo').each do |line|
或者:
File.open('foo').read.gsub(/\r\n?/, "\n").each_line do |line|