1

我正在文本文件(也包括 XML)中搜索字符串。这是我首先想到的:

using (StreamReader sr = File.OpenText(fileName))
{
    string s = String.Empty;
    while ((s = sr.ReadLine()) != null)
    {
        if (s.Contains("mySpecialString"))
            return true;
    }
}

return false;

我想逐行阅读以尽量减少使用的 RAM 量。找到字符串后,它应该中止操作。我不将它作为 XML 处理的原因是因为它必须被解析并且还会在必要时消耗更多的内存。

另一个简单的实现是

bool found = File.ReadAllText(path).Contains("mySpecialString") ? true : false;

但这会将完整的文件读入内存,这不是我想要的。另一方面,它可能会提高性能。

另一个是这个

foreach (string line in File.ReadLines(path))
{
    if (line.Contains("mySpecialString"))
    {
        return true;
    }
}
return false;

但是其中哪一个(或您的另一个?)的内存效率更高?

4

3 回答 3

3

您可以使用带有 的查询File.ReadLines,因此它只读取所需的行数,以满足您的查询。该Any()方法将在遇到包含您的字符串的行时停止。

return File.ReadLines(fileName).Any(line => line.Contains("mySpecialString"));
于 2015-05-06T13:38:55.240 回答
2

我也更喜欢接受的答案。也许我在这里对事物进行了微优化,但您已经要求一种内存有效的方法。还要考虑到您正在搜索的文本也可能包含换行符'\r''\n'或者"\r\n",理论上一个大文件可能包含单行,这否定了ReadLines.

所以你可以使用这个方法:

public static bool FileContainsString(string path, string str, bool caseSensitive = true)
{
     if(String.IsNullOrEmpty(str))
        return false;

    using (var stream = new StreamReader(path))
    while (!stream.EndOfStream)
    {
        bool stringFound = true;
        for (int i = 0; i < str.Length; i++)
        {
            char strChar = caseSensitive ? str[i] : Char.ToUpperInvariant(str[i]);
            char fileChar = caseSensitive ? (char)stream.Read() : Char.ToUpperInvariant((char)stream.Read());
            if (strChar != fileChar)
            {
                stringFound = false;
                break; // break for-loop, start again with first character at next position
            }
        }
        if (stringFound) 
            return true;
    }
    return false;
}

bool containsString = FileContainsString(path, "mySpecialString", false); // ignore case if desired

请注意,这可能是最有效的方法,并且隐藏在一个也可读的方法中。但它有一个缺点,实现对文化敏感的比较是不可行的,因为它只查看单个字符而不是子字符串。

因此,您必须牢记一些可能遇到问题的边缘情况,例如著名的土耳其语 i 示例代理对

于 2015-05-06T14:16:25.453 回答
1

我认为您的两个解决方案都是相同的。阅读 MSDN:https ://msdn.microsoft.com/en-us/library/dd383503%28v=vs.110%29.aspx

它说:“ReadLines 和 ReadAllLines 方法的区别如下:使用 ReadLines 时,您可以在返回整个集合之前开始枚举字符串集合”

同一篇文章还建议应将 ReadLines 与 LINQ to Objects 结合使用。

于 2015-05-06T13:40:46.230 回答