将大型 .text 文件与值数组进行比较
Compare large .txt file against array of values
美好的一天,我正在尝试将一个相当大的文本文件(大约 10 万行)与一个包含 1000 到 14000 个值的数组进行比较。这样做的目的是用户有一个值的文本文件,每行 1 个,并且该数组包含可能与每行匹配或不匹配的信息片段。文本文件中的每一行都是唯一的,数组中的每一项都是唯一的。
例如文本文件结构:]1
数组 (outfitCell) 将包含每行的第一个单词,但可能包含文本文件中的全部或 none 部分匹配项,例如,它将包含单词 "Is" 但不会包含该行的其余部分。我需要它来保留整行并将其写入新路径中的新文件。
我曾尝试使用文件流和标准流 reader 和编写器,但是需要大约 50 秒来进行比较并写出 "start with" 数组中的项目的行到一个新的 txt 文件中。
有没有人对我如何使它更快有任何建议,我在网上看过但似乎找不到任何有用的东西。
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)));
我会把事情分解成 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.
}
https://www.nimaara.com/counting-lines-of-a-text-file/
link 将帮助您计算文件中的行数。这对于将文件分成块很有用。数学将是必需的。可能循环 x 次,要计算 y 个项目,最后一个块的大小为 z。
我从 cmudict 单词文件创建了一个大文件(133k 行),只使用超过两个字符的单词,并在每行末尾添加 70 个随机 ASCII 字符。我还将单词存储在另一个文件中,并将其中的 1000 到 14,000 个提取到名为 values
.
的 List<string>
中
使用 ToLookup
,我按前两个字符对 values
进行分组,然后将行与适当的子组进行比较。我还删除了 BufferedStream
,因为各种博客表明它不会提高阅读性能,在这种情况下会减慢速度。
运行 你根据我的数据编写的代码用了大约 14.7 秒来创建结果文件。 运行 查找代码用了大约 0.2 秒。使用 3 个字符进行索引可将时间减半至 0.1 秒,加速超过 150 倍。将 values
大小限制为超过 10,000 将时间从 137 秒降至 0.267 秒,加速超过 500 倍(使用 3 个字符索引)。
您可以使用
从 activeCells
创建 values
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);
}
}
}
}
}
}
美好的一天,我正在尝试将一个相当大的文本文件(大约 10 万行)与一个包含 1000 到 14000 个值的数组进行比较。这样做的目的是用户有一个值的文本文件,每行 1 个,并且该数组包含可能与每行匹配或不匹配的信息片段。文本文件中的每一行都是唯一的,数组中的每一项都是唯一的。
例如文本文件结构:
数组 (outfitCell) 将包含每行的第一个单词,但可能包含文本文件中的全部或 none 部分匹配项,例如,它将包含单词 "Is" 但不会包含该行的其余部分。我需要它来保留整行并将其写入新路径中的新文件。
我曾尝试使用文件流和标准流 reader 和编写器,但是需要大约 50 秒来进行比较并写出 "start with" 数组中的项目的行到一个新的 txt 文件中。
有没有人对我如何使它更快有任何建议,我在网上看过但似乎找不到任何有用的东西。
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)));
我会把事情分解成 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.
}
https://www.nimaara.com/counting-lines-of-a-text-file/
link 将帮助您计算文件中的行数。这对于将文件分成块很有用。数学将是必需的。可能循环 x 次,要计算 y 个项目,最后一个块的大小为 z。
我从 cmudict 单词文件创建了一个大文件(133k 行),只使用超过两个字符的单词,并在每行末尾添加 70 个随机 ASCII 字符。我还将单词存储在另一个文件中,并将其中的 1000 到 14,000 个提取到名为 values
.
List<string>
中
使用 ToLookup
,我按前两个字符对 values
进行分组,然后将行与适当的子组进行比较。我还删除了 BufferedStream
,因为各种博客表明它不会提高阅读性能,在这种情况下会减慢速度。
运行 你根据我的数据编写的代码用了大约 14.7 秒来创建结果文件。 运行 查找代码用了大约 0.2 秒。使用 3 个字符进行索引可将时间减半至 0.1 秒,加速超过 150 倍。将 values
大小限制为超过 10,000 将时间从 137 秒降至 0.267 秒,加速超过 500 倍(使用 3 个字符索引)。
您可以使用
从activeCells
创建 values
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);
}
}
}
}
}
}