C# 使用linq比较两个文本文件?
我在一个文件夹中有4个文本文件和一个pattern.txt来比较这些文本文件..在pattern.txt中我有 我需要将这个文本文件与这四个文本文件进行比较,如果这些模式与该文本文件中的任何一行匹配,我必须将这些行写入另一个日志文件…我已经使用linq读取了这些文件..我需要比较这些文件并将其写入带有行号的文本文件..这是我的代码C# 使用linq比较两个文本文件?,c#,linq,C#,Linq,我在一个文件夹中有4个文本文件和一个pattern.txt来比较这些文本文件..在pattern.txt中我有 我需要将这个文本文件与这四个文本文件进行比较,如果这些模式与该文本文件中的任何一行匹配,我必须将这些行写入另一个日志文件…我已经使用linq读取了这些文件..我需要比较这些文件并将其写入带有行号的文本文件..这是我的代码 var foldercontent = Directory.GetFiles(pathA) .Select(filename
var foldercontent = Directory.GetFiles(pathA)
.Select(filename => File.ReadAllText(filename))
.Aggregate(new StringBuilder(),
(sb, s) => sb.Append(s).Append(Environment.NewLine),
sb => sb.ToString());
var pattern = File.ReadAllLines(pathB).Aggregate(new StringBuilder(),
(sb, s) => sb.Append(s).Append(Environment.NewLine),
sb => sb.ToString());
using (var dest = File.AppendText(Path.Combine(_logFolderPath, "log.txt")))
{
//dest.WriteLine("LineNo : " + counter.ToString() + " : " + "" + line);
}
编辑
我已经使用c来比较两个文本文件,但我需要在linq中使用它
while ((line = file.ReadLine()) != null)
{
if (line.IndexOf(line2, StringComparison.CurrentCultureIgnoreCase) != -1)
{
dest.WriteLine("LineNo : " + counter.ToString() + " : " + " " + line.TrimStart());
}
counter++;
}
file.BaseStream.Seek(0, SeekOrigin.Begin);
counter = 1;
可能有一个更简单的解决方案,但如果您真的想使用LINQ,这至少是可行的:
var foldercontent = Directory.GetFiles(pathA)
.Select(filename => new
{
Filename = filename,
Lines = File.ReadAllLines(filename)
})
.SelectMany(file => file.Lines.Select((line, idx) => new
{
LineNumber = idx + 1,
Text = line,
FileName = file.Filename
}));
var pattern = File.ReadAllLines(pathB);
var result = from fileLine in foldercontent
where pattern.Any(p => fileLine.Text.IndexOf(p, StringComparison.CurrentCultureIgnoreCase) != -1)
select fileLine;
foreach (var match in result)
{
System.Diagnostics.Debug.WriteLine("File: {0} LineNo: {1}: Text: {2}", match.FileName, match.LineNumber, match.Text);
}
或者,如果您愿意,您可以将其组合到一个LINQ查询中,但我认为这不太可读:
var result = from fileLine in (Directory.GetFiles(pathA)
.Select(filename => new
{
Filename = filename,
Lines = File.ReadAllLines(filename)
})
.SelectMany(file => file.Lines.Select((line, idx) => new
{
LineNumber = idx + 1,
Text = line,
FileName = file.Filename
})))
where File.ReadAllLines(pathB).Any(p => fileLine.Text.IndexOf(p, StringComparison.CurrentCultureIgnoreCase) != -1)
select fileLine;
因为我是linq爱好者,有时会在不合适的时候使用工具,所以我同意@juharr关于在这种情况下使用grep或类似的工具,这里有一个可能的版本供您使用
static IEnumerable<string> CreateMatchesLog(string patternFilePath, string pathToSearch)
{
string logTemplate = "File {0}, Line: {1}, Pattern: {2}";
DirectoryInfo di = new DirectoryInfo(pathToSearch);
var patternlines = File.ReadAllLines(patternFilePath);
var fileslines = di.EnumerateFiles().Select(fi => File.ReadAllLines(fi.FullName).Select((line, i) => new {fi.FullName, line, i}));
return from filelines in fileslines
from pattern in patternlines
from fileline in filelines
where fileline.line.Contains(pattern)
select String.Format(logTemplate, fileline.FullName, fileline.i + 1, pattern);
}
我在StreamWriter中将append设置为true,因为我假设您不希望在每次运行程序时丢失文件的内容
它看起来相当低效,没有测试这方面,但它使用linq和lambdas的wazoo 你需要存储匹配行来自哪个文件吗?@Matt Ellen:我需要将匹配行存储在另一个文本中file@bala3569:是的,但是在日志文件中,你需要存储匹配行来自哪个其他文件吗?@Matt Ellen:dint明白你的意思。你可以考虑使用grep而不是为此编写程序。如果我这样给它,意味着如果有n个匹配项var result1=string.Join,,result.Selectx=>x.ToString.ToArray,它将写入n次;结果{dest.WriteLineresult1;}中的foreach变量匹配我不完全理解您的意思。我的LINQ查询提供所有文件的所有匹配行。你不会得到双倍的行数。是的,它给出的正确,但它正在为n个匹配项写n次。对我来说,它每匹配一行写一次
static IEnumerable<string> CreateMatchesLog(string patternFilePath, string pathToSearch)
{
string logTemplate = "File {0}, Line: {1}, Pattern: {2}";
DirectoryInfo di = new DirectoryInfo(pathToSearch);
var patternlines = File.ReadAllLines(patternFilePath);
var fileslines = di.EnumerateFiles().Select(fi => File.ReadAllLines(fi.FullName).Select((line, i) => new {fi.FullName, line, i}));
return from filelines in fileslines
from pattern in patternlines
from fileline in filelines
where fileline.line.Contains(pattern)
select String.Format(logTemplate, fileline.FullName, fileline.i + 1, pattern);
}
using (StreamWriter sw = new StreamWriter("log.txt", true))
{
foreach (var log in CreateMatchesLog("pattern.txt", @"c:\test"))
{
sw.WriteLine(log);
}
}