C# 将大型.txt文件与值数组进行比较

C# 将大型.txt文件与值数组进行比较,c#,wpf,file-io,C#,Wpf,File Io,您好,我正在尝试将一个相当大的文本文件(大约100k行)与一个1000到14000个值的数组进行比较。这样做的目的是,用户有一个值的文本文件,每行1个值,数组包含的信息片段可能与每行匹配,也可能与每行不匹配。文本文件中的每一行都是唯一的,数组中的每一项都是唯一的 例如文本文件结构:] 数组(单元格)将包含每行的第一个单词,但可能包含文本文件中的所有或任何匹配项,例如,它将包含单词“Is”,但不包含行的其余部分。我需要它来保留整行并将其写入新路径中的新文件 我曾尝试使用文件流和标准流读写器,但进行

您好,我正在尝试将一个相当大的文本文件(大约100k行)与一个1000到14000个值的数组进行比较。这样做的目的是,用户有一个值的文本文件,每行1个值,数组包含的信息片段可能与每行匹配,也可能与每行不匹配。文本文件中的每一行都是唯一的,数组中的每一项都是唯一的

例如文本文件结构:]

数组(单元格)将包含每行的第一个单词,但可能包含文本文件中的所有或任何匹配项,例如,它将包含单词“Is”,但不包含行的其余部分。我需要它来保留整行并将其写入新路径中的新文件

我曾尝试使用文件流和标准流读写器,但进行比较并将数组中“以”项开始的行写入新的txt文件大约需要50秒

有没有人对我如何加快速度有什么建议,我在网上浏览了一下,但似乎找不到任何有用的东西

public static void CopyActiveFiles(List<string> files, string targetLocation, OutfitCell[] activeCells)
        {
            string tempFile = Path.Combine(Path.GetTempPath(), "tempPermit.txt");
            try
            {
                foreach (string file in files)
                {

                    File.SetAttributes(file, FileAttributes.Normal);
                    using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        using (BufferedStream bs = new BufferedStream(fs))
                        {
                            using (StreamReader sr = new StreamReader(bs))
                            {
                                using (var writer = File.CreateText(tempFile))
                                {
                                    string line;
                                    while ((line = sr.ReadLine()) != null)
                                    {
                                            foreach (var activeCell in activeCells)
                                            {
                                                if (line.StartsWith(activeCell.Name))
                                                {

                                                    writer.WriteLine(line);
                                                }
                                            }

                                    }
                                }
                            }
                        }
                    }

                    File.SetAttributes(tempFile, FileAttributes.Normal);
                    File.Copy(tempFile, Path.Combine(targetLocation, Path.GetFileName(file)));
publicstaticvoidcopyactivefiles(列表文件、字符串targetLocation、oughtCell[]activeCells)
{
字符串tempFile=Path.Combine(Path.GetTempPath(),“tempPermit.txt”);
尝试
{
foreach(文件中的字符串文件)
{
SetAttributes(File,FileAttributes.Normal);
使用(FileStream fs=File.Open(File,FileMode.Open,FileAccess.Read,FileShare.ReadWrite))
{
使用(BufferedStream bs=新的BufferedStream(fs))
{
使用(StreamReader sr=新StreamReader(bs))
{
使用(var writer=File.CreateText(tempFile))
{
弦线;
而((line=sr.ReadLine())!=null)
{
foreach(activeCells中的var activeCell)
{
if(line.StartsWith(activeCell.Name))
{
writer.WriteLine(行);
}
}
}
}
}
}
}
SetAttributes(tempFile,FileAttributes.Normal);
Copy(tempFile,Path.Combine(targetLocation,Path.GetFileName(File));

我将把事情分成2-3个函数。调用函数、文件函数和线程工作函数

    public static void CopyActiveFiles(List<string> files, string targetLocation, OutfitCell[] activeCells)
    {
        foreach (string file in files)
        {
            CheckFile(file, activeCells);
        }
    }

    private static void CheckFile(string file, OutfitCell[] activeCells)
    {
        // Thread call
        // declare some thread safe collection.
        // var lines = File.ReadLines(file).Skip(<index>).Take(<count>);
        // Use a variant of the above line to grab a section of lines from the file to then ship out to threads.
    }
publicstaticvoidcopyactivefiles(列表文件、字符串targetLocation、oughtCell[]activeCells)
{
foreach(文件中的字符串文件)
{
检查文件(文件,活动单元格);
}
}
私有静态无效检查文件(字符串文件,OutfightCell[]activeCells)
{
//线程调用
//声明一些线程安全集合。
//var lines=File.ReadLines(File.Skip().Take();
//使用上述行的变体从文件中获取一部分行,然后发送到线程。
}


该链接将帮助您计算文件中的行数。这对于将文件划分为块非常有用。需要进行数学运算。可能会使用y项循环x次,最后一个块的大小为z。

我会将其分解为2-3个函数。调用函数、文件函数和线程工作函数离子

    public static void CopyActiveFiles(List<string> files, string targetLocation, OutfitCell[] activeCells)
    {
        foreach (string file in files)
        {
            CheckFile(file, activeCells);
        }
    }

    private static void CheckFile(string file, OutfitCell[] activeCells)
    {
        // Thread call
        // declare some thread safe collection.
        // var lines = File.ReadLines(file).Skip(<index>).Take(<count>);
        // Use a variant of the above line to grab a section of lines from the file to then ship out to threads.
    }
publicstaticvoidcopyactivefiles(列表文件、字符串targetLocation、oughtCell[]activeCells)
{
foreach(文件中的字符串文件)
{
检查文件(文件,活动单元格);
}
}
私有静态无效检查文件(字符串文件,OutfightCell[]activeCells)
{
//线程调用
//声明一些线程安全集合。
//var lines=File.ReadLines(File.Skip().Take();
//使用上述行的变体从文件中获取一部分行,然后发送到线程。
}

该链接将帮助您计算文件中的行数。这有助于将文件划分为多个块。需要进行数学运算。可能需要使用y项循环x次,最后一个块的大小为z。

我创建了一个大文件(133k行)从cmudict words文件中,仅使用长度超过两个字符的单词,并在每行末尾添加70个随机ASCII字符。我还将单词存储在另一个文件中,并将其中1000到14000个单词拉入名为
值的
列表中

使用
ToLookup
,我将
值按前两个字符分组,并将行与相应的子组进行比较。我还取出了
BufferedStream
,因为各种博客显示它并没有提高阅读性能,在这种情况下会降低阅读速度

根据“我的数据”运行代码大约需要14.7秒来创建结果文件。运行查找代码大约需要0.2秒。使用3个字符进行索引可以将代码缩短一半到0.1秒,从而使速度提高150倍以上。将
值限制在10000以上需要137秒,将时间缩短到0.267秒,从而使速度提高超过150倍加速500倍(具有3个字符索引)

您可以使用从
activeCells
创建

var values = activeCells.Select(a => a.Name).ToList();
然后使用以下代码:

var possibles = values.ToLookup(v => v.Substring(0, 2));
using (FileStream fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
    using (StreamReader sr = new StreamReader(fs)) {
        using (var writer = File.CreateText(tempFile)) {
            while (!sr.EndOfStream) {
                var line = sr.ReadLine();
                var index = line.Substring(0, 2);
                foreach (var value in possibles[index]) {
                    if (line.StartsWith(value)) {
                        writer.WriteLine(line);
                    }
                }
            }
        }
    }
}
我从cmudict words文件创建了一个大文件(133k行),只使用超过两个字符长的单词,并在每行末尾添加70个随机ASCII字符。我还存储了单词