f# - 处理大型文本文件?

标签 f#

我需要导入一个大文本文件 (55MB) (525000 * 25) 并操作数据并产生一些输出。像往常一样,我开始使用 f# Interactive 进行探索,并且得到了一些非常奇怪的行为。

这个文件太大还是我的代码错误?

第一个测试是导入并简单地计算一列的总和(不是最终目标,而是第一个测试):

let calctest =
let reader = new StreamReader(path)
let csv = reader.ReadToEnd()    
csv.Split([|'\n'|])
|> Seq.skip 1
|> Seq.map (fun line -> line.Split([|','|]))
|> Seq.filter (fun a -> a.[11] = "M")
|> Seq.map (fun values -> float(values.[14]))

正如预期的那样,这会在类型检查和交互中产生一个浮点序列。如果我知道添加:

|> Seq.sum

类型检查有效,并表示该函数应该返回一个 float ,但如果我在交互式模式下运行它,则会收到此错误:

System.IndexOutOfRangeException: Index was outside the bounds of the array

然后我再次删除了最后一行,并认为我查看了文本文件中 float 的 seq:

let writetest = 
let str = calctest |> Seq.map (fun i -> i.ToString())
System.IO.File.WriteAllLines("test.txt", str )

同样,这通过了类型检查,但在交互中抛出错误。

标准 StreamReader 无法处理那么多数据吗?或者我在某个地方出错了?我应该使用与 Streamreader 不同的函数吗? 谢谢。

最佳答案

Seq 是惰性的,这意味着只有当您添加 Seq.sum 时,所有映射和过滤才会真正完成,这就是为什么您看不到添加该行之前出错。您确定所有行上都有 15 列吗?应该是这个问题

我建议您使用 CSV Type Provider而不是仅仅执行 string.Split,这样您就可以确保不会出现意外的 IndexOutOfRangeException,并且您将正确处理 , 转义。

此外,您通过调用 reader.ReadToEnd() 将整个 csv 文件读入内存,如果您将 Cache 参数设置为 false,CsvProvider 支持流式传输。对于 55MB 的文件来说这不是问题,但如果您有更大的文件,则可能会出现问题

关于f# - 处理大型文本文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19361281/

相关文章:

winforms - 在 F# 中使用 Windows 窗体的面向对象的 "Hello world"

f# - 使用不区分大小写的比较从集合中减去记录

ubuntu - 如何让 F# 与 Mono 一起工作?

function - 类型和功能

loops - F# 创建具有多个函数的单个循环

.net - 带有嵌套聚合的Elasticsearch NEST客户端

azure - Azure 是否支持构建 F# 3.0/VS2012 项目?

f# - 如何避免在 F# 中双重包装到 Some

.net - 执行 F# 脚本

f# - 如何将 F# 中的模块导入限制在本地范围内?