【问题标题】:Read latest line from CSV file从 CSV 文件中读取最新行
【发布时间】:2018-02-19 07:34:35
【问题描述】:

我有一个 CSV 文件,我需要从中读取所有值。但仅限于最新的最后一行。但我不知道该怎么做。

我现在正在使用流式阅读器,但它会循环遍历整个 CSV 文件,该文件可能非常大。

我需要读取两个不同的 csv 文件(标题相同但位置不同)。

但是如何编辑此代码以仅从最后一行读取?我四处寻找,但找不到与我相同的东西。

这就是我现在的做法:

using (var reader = new StreamReader(path))
            {
                var headerLine = reader.ReadLine();
                var headerValues = headerLine.Split(',');
                var serialNumber = headerValues[66];

                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    var values = line.Split(',');

                    if (values[0] != "Index")
                    {
                        var analyseReport = new AnalyseReport();
                        analyseReport.SerialNumber = serialNumber;

                        foreach (var item in headerValues)
                        {
                            var headerName = item.Trim();
                            var index = Array.IndexOf(headerValues, item);

                            switch (headerName)
                            {
                                case "Index":
                                    analyseReport.Index = Convert.ToInt32(values[index].Trim());
                                    break;

                                case "Time":
                                    analyseReport.TimeStamp = Convert.ToDateTime(values[index].Trim());
                                    break;

                                case "Reading No":
                                    analyseReport.ReadingNo = Convert.ToInt32(values[index].Trim());
                                    break;
                                case "Duration":
                                    analyseReport.Duration = values[index].Trim();
                                    break;

                                case "Type":
                                    analyseReport.Type = values[index].Trim();
                                    break;

                                case "Units":
                                    analyseReport.Units = values[index].Trim();
                                    break;

                                default:
                                    break;
                            }
                        }

                        analyseReportList.Add(analyseReport);

                    }
                }
                return analyseReportList;
            }

【问题讨论】:

标签: c# csv


【解决方案1】:

如果您没有固定长度的行,但可以确定行长度的上限,则可以使用启发式方法来提高读取最后一行的效率。

基本上要做的是将文件流的当前位置从末尾移动到n字节,然后读取直到到达最后一行。

private string ReadLastLine(string fileName, int maximumLineLength)
{
    string lastLine = string.Empty;

    using(Stream s = File.OpenRead(path))
    {
        s.Seek(-maximumLineLength, SeekOrigin.End);

        using(StreamReader sr = new StreamReader(s))
        {
            string line;

            while((line = sr.ReadLine()) != null)
            {
                lastLine = line;
            }
        }
    }

    return lastLine;
}

对于 1.8 MB 的 CSV,它比 File.ReadLines 方法快大约 100-200 倍。无论如何,以更复杂的代码为代价。

备注:虽然你可以使用这个方法来优化读取最后一行,如果真的是瓶颈,请使用该方法如果可能的话,Tim Schmelter 的版本更清晰、更干净。请记住第二条优化规则:“暂时不要这样做。”

此外,要确定行的最大长度,您必须小心并考虑字符编码。而不是高估而不是低估行长。

【讨论】:

    【解决方案2】:

    你可以使用File.ReadLines(path).Last():

    string headerLine = File.ReadLines(path).First();
    string lastLine = File.ReadLines(path).Last();
    // ... (no loop)
    

    这些是 LINQ 方法,因此您需要添加 using System.Linq;

    【讨论】:

    • 但这不会仍然读取所有行,这是 OP 试图避免的吗?
    • @PaulKertscher:你无法避免这种情况,但他不会(像目前一样)处理所有行,他会保持代码简洁易读。 Enumerable.First 只读取第一行,Last 将“读取”所有行但不对它们做任何事情,它只返回最后一行。
    • 谢谢,我试试看。
    • @AndreasPettersson:请记住,您应该使用ReadLines 而不是ReadAllLines。后者确实将所有行读入内存。
    • @Evk:您可以尝试我尚未测试过的 Jon Skeets 方法。我怀疑它是否会使您的代码更具可读性:stackoverflow.com/a/452945/284240 我也怀疑这是否是 OP 真正想要的。他只是想避免处理循环中的所有行。
    猜你喜欢
    • 2014-12-10
    • 2021-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    相关资源
    最近更新 更多