【问题标题】:C# compare 2 files contents for matchesC# 比较 2 个文件内容以进行匹配
【发布时间】:2013-09-09 12:28:29
【问题描述】:

我正在尝试找到一种方法来比较 2 个文件中的某些文本,如果找到匹配项,则运行一个进程。

以下是文件示例;

'File A' = 此格式的自动文本列表;

example1
ex2
289 Example
fht_nkka

'File B' = 来自目录搜索的文件名;

example1
test2
test4785

使用我的 2 个示例文件,我想同时搜索它们并找到匹配项。

所以上面的“文件 A”包含“示例 1”,而“示例 1”在“文件 B”中。我想要做的是根据所有匹配创建 'string[] 匹配。有没有简单的方法可以做到这一点?

注意:这些文件并不总是具有相同的行数据或行数。

【问题讨论】:

  • 更新 - 如果需要,我还可以更改“文件 A”的布局,但无论哪种方式,行项目都是相同的
  • 你尝试过什么吗?有代码示例吗?
  • 我是 C# 的初学者,所以还没有尝试过任何东西,因为我不知道该怎么做。我有其他搜索正在其他地方运行,但他们正在寻找静态搜索条件,这个动态的“搜索和运行”过程让我感到难过:S
  • 如果这个项目超出了您的本地解决方案的能力,您可能需要查看Lucene.Net

标签: c# c#-4.0


【解决方案1】:
  1. 在两个文件中的每一个上使用System.IO.File.ReadAllLines() 来创建两个字符串数组。
  2. 创建包含文件名的排序版本的数组以提高搜索性能。为此,您可以使用 LINQ。
  3. 鉴于您的第一个文件具有固定布局,您所需的文件名应始终位于每条记录的第 4 行,因此您可以在第二个数组上使用for 循环以固定增量来读取所需的文件名。
  4. 使用Array.BinarySearch() 快速定位所需文件名是否存在于文件列表(即另一个数组)中。

这是代码的粗略草图:

string[] AllRecs = System.IO.File.ReadAllLines(FIRST_FILE_PATH);
string[] AllFileNames = System.IO.File.ReadAllLines(SECOND_FILE_PATH);
Array.Sort(AllFileNames);

for (int i = 3; i < AllRecs.Length; i += 8) 
{
    if (Array.BinarySearch(AllFileNames, AllRecs(i) + ".exe") >= 0)
        System.Diagnostics.Process.Start(AllRecs(i) + ".exe");

}

【讨论】:

  • 考虑到他是 C# 初学者,这种方法相当复杂
  • 是的,我有点同意,但是他必须从某个地方开始,所以为什么不今天。 :)
  • 排序数组不是最有效的。 HashSet 是,plus 更简单。然后一个简单的包含将产生一个近似恒定时间与 n 平方时间的结果。
  • @dotNET 为什么 i += 8 ?
  • 我认为 i += 8 是文件的结尾。该文件是动态的,可能不仅有 8 行长。每次都会重写,所以开头总是 3 行。同样,如果这使过程更容易,可以删除这 3 行
【解决方案2】:

设法解决这个问题,这是我所做的;

var fileAcontents = File.ReadAllLines(fileA);
var fileBcontents = File.ReadAllLines(fileB);

HashSet<string> hashSet = new HashSet<string>(fileAcontents);
foreach (string i in fileBList)
{
    if (hashSet.Contains(i))
    {
        // <- DO SOMETHING :)
    }
}

【讨论】:

  • 如果您想像比较工具一样比较 2 个文件,这不是一个通用的解决方案。如果fileA 有重复的行,它将不起作用。 HashSet 不能包含重复项。
【解决方案3】:
//Keep in a list of strings with FileA contents 

List<string> linesOfFileA = new List<string>();
string line ;

using (StreamReader sr = new StreamReader(pathToFileA)) 
{
    //read each line of fileA
    line = sr.ReadLine();
    while(line != null)
    {
        linesOfFileA.Add(line) ;
        line = sr.ReadLine();
    }
}
//Now read the contents of FileB

string fileWithoutExtension ;
int posOfExtension ;

using (StreamReader srB = new StreamReader(pathToFileB)) 
{
    //read each line of fileB
    line = sr.ReadLine();
    while(line != null)
    {
        posOfExtension = line.LastIndexOf(".");

        if(posOfExtension < 0)
        {
            fileWithoutExtension = line ;
        }               
        else
        {
            fileWithoutExtension = line.Substring(0,posOfExtension) ;
        }

        //Check to see if the FileA contains file but without Extension
        if(linesOfFileA.Contains(fileWithoutExtension))
        {
            //Store into another list / or execute here
        }
        line = sr.ReadLine();
    }
}

在代码的第一部分中,您跳过了所需的行数,但由于当前显示的格式,它们不会影响您的比较

【讨论】:

  • 好的,所以我已经从 fileB 中删除了扩展名,所以现在文件只是数据行。我创建了基于 fileA 的第一个列表。检查“匹配”并写入 string[] match = 'matches' 的最简单方法是什么?
【解决方案4】:

用文件 A 的内容填充字典对象,然后循环通过文件 B 的内容查询文件 A 的字典对象。如果您有大量数据,字典对象的原因是它的速度。

Dictionary<int, string> FileA = new Dictionary<int, string>();
string sFileAList = dataFileA;

遍历文件 A 的内容并添加到 i 是计数器的 Dict。

int count = 0;
foreach (string s in sFileAList.split('\n')) {
    count++;
    if (count > 3) FileA.Add(i, s);
}

然后在循环文件 B 的内容时进行比较。

foreach (string s in dataFileB.split('\n')) {
    if (FileA.ContainsValue(s)) {
        // Run exe
    }
}

【讨论】:

  • FileB 是什么类型的对象?
  • -1 字典的速度?您的索引对提高速度有何帮助?
  • 我没有。我刚刚添加了索引来填充对象的那部分。原因是因为它是一个哈希表。 stackoverflow.com/questions/301371/…
  • 是的...哈希在 int 上...你想要的是 HashSet&lt;T&gt;
  • 哦,关键。搞混了所以如果我换错了,那可以吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 2021-06-15
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
相关资源
最近更新 更多