有效地从大型csv文件中读取最后一行

时间:2016-08-28 02:26:46

标签: csv f#

给定一个大的csv文件,是否可以以合理有效的方式读取最后一行?我有以下python函数,做得很好。想知道是否有相应的F#解决方案。

def readCsvLines(fp):
    with open(fp, "rb") as f:
        first = f.readline()
        second = f.readline()
        f.seek(-2, 2)              # jump to the second last byte
        while f.read(1) != "\n":   # until EOL is found...
            f.seek(-2, 1)          # jump back the read byte plus one more
        last = f.readline()
    return first, second, last

[编辑] 我仍然不确定如何找出跳回到最后一行的足够字节,以便我可以检测行尾字符并返回下一行。根据csv(有数千个),-100L可能不是正确的跳回量。

open System.IO

let f = File.Open("someFile.txt", FileMode.Open)
f.Seek(-100L, SeekOrigin.End) |> ignore
let s = new StreamReader(f)

while s.Read() <> 10 do
    ignore

let ln = s.ReadLine()

1 个答案:

答案 0 :(得分:3)

这似乎有效,假设文件是​​ASCII或UTF-7,单个换行符分隔行,文件以换行符结束。

虽然这不是真正惯用的F#,但非常强制性。

let lastLine (path) =
    use strm = new System.IO.FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 2048, FileOptions.RandomAccess)
    strm.Seek(-2L, SeekOrigin.End) |> ignore
    while (strm.ReadByte() <> 0xa) do
        strm.Seek(-2L, SeekOrigin.Current) |> ignore    

    use br = new BinaryReader(strm, System.Text.Encoding.UTF7)
    br.ReadChars(int (strm.Length - strm.Position) - 1) // Remove the newline at the end of the file  
    |> System.String