繁体   English   中英

如何一次读取和写入超过25000条记录/行到文本文件中?

[英]How to read and write more then 25000 records/lines into text file at a time?

我正在使用Web套接字将我的应用程序与股票市场实时数据提供者连接 因此,当市场存在且套接字打开时,它会在一分钟内给我近45000条线路。 我一次逐行反序列化,然后将该行写入文本文件,并读取文本文件并删除第一行文本文件。 因此,使用套接字处理另一个进程会变慢 那么请你能帮助我,我应该如何快速地完成这个过程,就像一分钟近25000行。

string filePath = @"D:\Aggregate_Minute_AAPL.txt";
var records = (from line in File.ReadLines(filePath).AsParallel()                    
               select line);
    List<string> str = records.ToList();
    str.ForEach(x =>
    {
         string result = x;
         result = result.TrimStart('[').TrimEnd(']');
         var jsonString = Newtonsoft.Json.JsonConvert.DeserializeObject<List<LiveAMData>>(x);
         foreach (var item in jsonString)
         {
             string value = "";
             string dirPath = @"D:\COMB1\MinuteAggregates";
             string[] fileNames = null;
             fileNames = System.IO.Directory.GetFiles(dirPath, item.sym+"_*.txt", System.IO.SearchOption.AllDirectories);
             if(fileNames.Length > 0)
             {
                 string _fileName = fileNames[0];
                 var lineList = System.IO.File.ReadAllLines(_fileName).ToList();
                 lineList.RemoveAt(0);
                 var _item = lineList[lineList.Count - 1];
                 if (!_item.Contains(item.sym))
                 {
                      lineList.RemoveAt(lineList.Count - 1);
                 }
                 System.IO.File.WriteAllLines((_fileName), lineList.ToArray());
                 value = $"{item.sym},{item.s},{item.o},{item.h},{item.c},{item.l},{item.v}{Environment.NewLine}";
                 using (System.IO.StreamWriter sw = System.IO.File.AppendText(_fileName))
                 {
                      sw.Write(value);
                 }
              }
          }
 });

如何快速制作流程,如果应用程序执行此操作则需要将近3000到4000个符号。 如果没有任何进程,则每分钟执行25000行。 那么如何使用所有这些代码增加行执行时间/进程?

首先,你需要清理你的代码以获得更多的可见性,我做了一个快速的重构,这就是我得到的

const string FilePath = @"D:\Aggregate_Minute_AAPL.txt";

class SomeClass
{
    public string Sym { get; set; }
    public string Other { get; set; }
}

private void Something() {
    File
        .ReadLines(FilePath)
        .AsParallel()
        .Select(x => x.TrimStart('[').TrimEnd(']'))
        .Select(JsonConvert.DeserializeObject<List<SomeClass>>)
        .ForAll(WriteRecord);
}

private const string DirPath = @"D:\COMB1\MinuteAggregates";
private const string Separator = @",";

private void WriteRecord(List<SomeClass> data)
{
    foreach (var item in data)
    {
        var fileNames = Directory
            .GetFiles(DirPath, item.Sym+"_*.txt", SearchOption.AllDirectories);
        foreach (var fileName in fileNames)
        {
            var fileLines = File.ReadAllLines(fileName)
                .Skip(1).ToList();
            var lastLine = fileLines.Last();
            if (!lastLine.Contains(item.Sym))
            {
                fileLines.RemoveAt(fileLines.Count - 1);
            }
            fileLines.Add(
                new StringBuilder()
                    .Append(item.Sym)
                    .Append(Separator)
                    .Append(item.Other)
                    .Append(Environment.NewLine)
                    .ToString()
            );
            File.WriteAllLines(fileName, fileLines);
        }
    }
}

从这里应该更容易使用List.AsParallel来检查代码如何以及使用什么参数更快。

也:

  • 您正在打开写入文件两次
  • 删除也有些昂贵,在索引0中更多(但是,如果元素很少,这可能没有多大区别
  • if(fileNames.Length > 0)没用,请使用for,如果列表为空,那么他将只是跳过
  • 您可以尝试使用StringBuilder而不是字符串插值

我希望这些提示可以帮助您改善时间! 而且我没有忘记一些事情。

编辑


我们的目录中有近10,000个文件。 因此,当进程正在运行时,它会传递一个错误,即进程无法访问该文件,因为它正由另一个进程使用

那么,您的流程行中是否有可能存在重复的文件名?

如果是这种情况,您可以尝试一种简单的方法,在几毫秒后重试,类似于

private const int SleepMillis = 5;
private const int MaxRetries = 3;

public void WriteFile(string fileName, string[] fileLines, int retries = 0)
{
    try
    {
        File.WriteAllLines(fileName, fileLines);
    }
    catch(Exception e) //Catch the special type if you can
    {
        if (retries >= MaxRetries)
        {
            Console.WriteLine("Too many tries with no success");
            throw; // rethrow exception
        }
        Thread.Sleep(SleepMillis);
        WriteFile(fileName, fileLines, ++retries); // try again
    }
}

我试图保持简单,但有一些注释: - 如果你可以使你的方法异步 ,它可以通过改变Task.Delay的睡眠来改善 ,但你需要知道并理解异步如何工作 - 如果碰撞发生了很多,那么你应该尝试另一种方法,比如带有信号量的并发映射

第二次编辑


在实际情况中,我连接到websocket并在每分钟接收70,000到1个lac记录,之后我用实时流数据分叉这些记录并存储在它自己的文件中。 当我将我们的概念应用于11,000个文件时,这会变慢

这是一个难题,据我所知,你说的是每秒1166条记录,在这个尺寸下,小细节可能成为大瓶颈。

在那个阶段,我认为考虑其他解决方案更好,它可能是磁盘的I / O,可能是很多线程,或者太少,网络......

您应该首先分析应用程序以检查应用程序在该区域花费更多时间的重点,使用了多少资源? 你有多少资源? 内存,处理器,垃圾收集器,网络如何? 你有SSD吗?

你需要清楚地看到什么在减慢你的速度,这样你就可以直接攻击它,它将取决于很多东西,这将很难帮助那部分:(。

大量的工具用于配置文件c#应用程序 ,以及许多方法来解决这个问题(在几个服务器上传播费用,使用像redis这样的东西来快速保存数据,一些事件存储使你可以使用事件....

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM