我在寻找一个文本文件中的字符串(也包括XML)。 这是我首先想到:
using (StreamReader sr = File.OpenText(fileName))
{
string s = String.Empty;
while ((s = sr.ReadLine()) != null)
{
if (s.Contains("mySpecialString"))
return true;
}
}
return false;
我想逐行读出,以尽量减少内存使用量。 当字符串已经发现它应该退出操作。 我之所以不处理它作为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;
但他们中的哪一个(或者你另外一个?)是更多的内存效率?
您可以使用查询File.ReadLines
,所以它需要,以满足您的查询只读取尽可能多的行。 在Any()
当它击中包含您的串线法将停止。
return File.ReadLines(fileName).Any(line => line.Contains("mySpecialString"));
我也喜欢接受的答案。 也许我在这里很微opimizing事情,但你已经问了内存使用效率的方法。 还要考虑您正在搜索的文本还可以包含像新行字符'\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
请注意,这可能是最有效的方法,并隐藏在也可读的方法。 但它有一个缺点,这是不可行的实现文化敏感比较,因为它着眼于单个字符,而不是在子。
所以,你必须保持一些边缘情况记在这里你可以遇到的问题,如著名的土耳其我例子或代理对 。
我想无论您的解决方案都是一样的。 阅读在MSDN: https://msdn.microsoft.com/en-us/library/dd383503%28v=vs.110%29.aspx
在那里,它说:“方法不同为readlines方法和ReadAllLines如下:当您使用readlines方法,你可以返回整个集合之前开始枚举字符串的集合”
同一篇文章也表明readlines方法应与LINQ到对象一起使用。
文章来源: read a text file and search for string in memory efficient way (and abort when found)