我已经有了这个问题的解决方案,但似乎非常让我感到困惑和不切实际。
我打算做的是逐行读取文件(由于文件大小,一次性将其加载到内存中是不切实际的),并且如果满足某些条件(例如:该行匹配正则表达式模式,或包含某些关键字,或等于某个字符串)
这是我理想的选择:
void TryGetLineIf(string filePath, Condition condition, out string desiredLine)
{
StreamReader fileReader = new StreamReader(filePath);
string currentLine = "";
while (!fileReader.EndOfStream)
{
currentLine = fileReader.ReadLine();
if (condition)
{
desiredLine = currentLine;
}
}
}
但是,我不知道如何处理condition参数。我能想到的唯一出路是用枚举替换条件,(LineSelectionOptions.IsRegexMatch,LineSelectionOptions.ContainsString ...),向void添加一个额外的参数,并在它之间切换可能的值。我正在使用.NET 2.0,如果这是相关的。
答案 0 :(得分:3)
如果您知道函数的参数,可以使用Func传递一个返回bool的函数
你的方法定义将是这样的
void TryGetLineIf(string filePath, Func<string, bool> condition, out string desiredLine)
if-line将是这样的
if(condition(currentLine)) {
desiredLine = currentLine;
}
并且对方法的调用将是这样的
Func<string, bool> condition = (line) => line.Length > 1;
string desiredLine;
TryGetLineIf("C:\\....file.pdf", condition, out desiredLine)
但是,由于您在2.0中工作,您可能希望使用委托来模拟Func 请参阅此How to simulate a "Func<(Of <(TResult>)>) Delegate" in .NET Framework 2.0?或此Replacing Func with delegates C#
答案 1 :(得分:0)
请原谅格式,因为我在手机上。
无论如何,我认为这是使用yield return
的完美候选者,因为调用者可以决定break
而不想在任何行之后读取文件的其余部分。这样就可以了。此外,呼叫者可以执行链接并进行进一步处理。此外,不需要out
参数。
确保使用using
语句,如果在.NET 2.0中可用,请使用File.ReadLines
方法:它逐行读取,它更简单。一旦我回到家,我会尝试用我提出的建议来编辑我的答案。
public static IEnumerable<string> TryGetLineIf(string filePath, Condition condition
{
StreamReader fileReader = new StreamReader(filePath);
string currentLine = "";
while (!fileReader.EndOfStream)
{
currentLine = fileReader.ReadLine();
if (condition.MeetsCriteria(currentLine))
{
yield return currentLine;
}
}
}
作为最后一点,如果您将委托作为条件而不是另一个答案中建议的类实例传递,则它会更强大。
答案 2 :(得分:0)
@ Gonzalo.-感谢您的回答,我设法在少数情况下使用它。但是现在我在尝试使用Func委托中的更多参数时遇到问题,例如,当尝试检查该行是否与某个正则表达式模式匹配时:
Func<string, string, bool> condition =
(line, pattern) => new Regex(pattern).IsMatch(line)
IEnumerable<string> LinesIWant =
ReturnLineIf("C:\test.txt", condition);
以下是方法:
IEnumerable<string> ReturnLineIf(string filePath, Func<string, string, bool> condition)
{
// (snip)
// How do I specify a pattern when calling the method?
if (condition(currentLine, "This should be the pattern..."))
{
yield return currentLine;
}
}