检查文件中是否存在字符串

8
我有以下一段代码,它打开一个文本文件并读取文件中的所有行并将其存储到字符串数组中。
然后检查字符串是否存在于该数组中。但是我面临的问题是,每当找到一个字符串时,它总是显示“存在匹配项”以及“不存在匹配项”。 有什么办法可以解决这个问题吗?
请检查以下代码:
using (StreamReader sr = File.OpenText(path))
{
    string[] lines = File.ReadAllLines(path);
    for (int x = 0; x < lines.Length - 1; x++)
    {
        if (domain == lines[x])
        {
            sr.Close();
            MessageBox.Show("there is a match");
        }
    }
    if (sr != null)
    {
        sr.Close();
        MessageBox.Show("there is no match");
    }
}
8个回答

24
Sounds overly complex, no reason to check by line or anything if you want to know if a string is present in a file. You can replace all of your code simply with :
if(File.ReadAllText(path).Contains(domain))
{
    MessageBox.Show("There is a match");
}

5
我建议设置一个标志并按如下方式检查它...
using (StreamReader sr = File.OpenText(path))
{
    string[] lines = File.ReadAllLines(path);
    bool isMatch = false;
    for (int x = 0; x < lines.Length - 1; x++)
    {
        if (domain == lines[x])
        {
            sr.Close();
            MessageBox.Show("there is a match");
            isMatch = true;
        }
    }
    if (!isMatch)
    {
        sr.Close();
        MessageBox.Show("there is no match");
    }
}

Good Luck!


你打开了文件两次,却从未使用第一个流。string[] lines = File.ReadAllLines(path) 是制作奶酪的地方,没有使用StreamReader。 - HackSlash

3
实际上你不需要将整个文件读入内存。有一个File.ReadLines方法,允许您逐行枚举文件行,而无需读取整个文件。您可以创建以下方法:
private bool DomainExists(string domain)
{
    foreach(string line in File.ReadLines(path))
        if (domain == line)
            return true; // and stop reading lines

    return false;
}

使用这种方法的示例:

if (DomainExists(domain))
    MessageBox.Show("there is a match");
else
    MessageBox.Show("there is no match");

此外,有两点需要注意——如果您使用File.ReadAllLines读取行(它会在内部创建读取器),则不需要StreamReader。只需检查一下——您甚至没有在任何地方使用sr变量。另外一个注意事项是,如果您将流包装在using块中,则无需手动关闭流。在这种情况下,流将自动被处理和关闭。

1

由于已接受的答案未解决原问题,这里提供一个简短而精悍的基于LINQ的版本:

private static bool TextFoundInFile(string fileName, string text)
{
    // If the line contains the text, FirstOrDefault will return it. 
    // Null means we reached the end without finding it.
    return File.ReadLines(fileName).FirstOrDefault(x => x.Contains(text)) is not null;
}

这种方法的好处是,它在找到值时立即返回true。仅当未找到文本时才会读取整个文件。如果您正在处理通常包含搜索内容的大型文件,则可以提高性能。

也许使用 Any 会是更好的选择?File.ReadLines(fileName).Any(x => x.Contains(text)) - rasputino
@rasputino,FirstOrDefault 可以更快:https://dev59.com/4Gsy5IYBdhLWcg3wvgr7 - HackSlash
1
正如您可以在该帖子中查看的那样,根据环境,Any()可能更快,或者FirstOrDefault()可能更快。但对于这种特定情况(读取文件),它们大多相同,并且Any()提供了更好的语法。只是出于好奇,我刚刚检查了多个300MB文件,Any()需要3.9秒,而FirstOrDefault()需要4.5秒。 - rasputino

0

最简单的方法:

string content = File.ReadAllText(path);
if (content.IndexOf(domain) > -1)
{
   // domain exists
}
else
{
   // domain does not exist
}

现在来分析你的代码:

首先,你创建了一个StreamReader实例,但是后面没有使用它。

其次,如果文件中出现多个域名怎么办?在你的代码中会出现多个“有匹配项”的情况。

using (StreamReader sr = File.OpenText(path)) // you can remove this line
{
    string[] lines = File.ReadAllLines(path); // as you are not using it here
    for (int x = 0; x < lines.Length - 1; x++)
    {
        if (domain == lines[x])
        {
            sr.Close();
            MessageBox.Show("there is a match");
            hasMatch = true;
            break; // exit loop if found
        }
    }

    if (!hasMatch)
    {
        // there is no match
    }

    if (sr != null) // you dont need this if you remove it from the beginning of the code
    {
        sr.Close();
        MessageBox.Show("there is no match");
    }
}

0

你可以尝试这个:


首先,您需要创建一个接收字符串类型数组的方法,然后将该数组转换为字符串,接着我们从txt文件中读取所有文本,使用Contains方法来判断我们发送的文本是否存在于txt文件中,并验证其真假性。希望这能对您有所帮助。
        public static void TextValidation(string[] val){
            //Path of your file
            string path = "/Users/Desktop/YourFile.txt";
            //Array to string
            string b = string.Join(",",val);
            //Validate if exists
            if(File.ReadAllText(path).Contains(b)){
                Console.WriteLine("found");
                // Do something if the data is found
            }else{
                Console.WriteLine("Not found");
            }
        }

欢迎来到StackOverflow!能否解释一下这个方法是如何解决问题的呢?谢谢! - Quality Catalyst

-1
你可以尝试这段代码:
 using (StreamReader sr = File.OpenText(path))
                        {
                            string[] lines = File.ReadAllLines(path);
                            for (int x = 0; x < lines.Length - 1; x++)
                            {
                                if (lines[x].Contains(domain, StringComparison.InvariantCultureIgnoreCase)
                                {
                                    sr.Close();
                                    MessageBox.Show("there is a match");
                                }
                            }
                            if (sr != null)
                            {
                                sr.Close();
                                MessageBox.Show("there is no match");
                            }
                        }

即使找到匹配项,仍将显示“没有匹配项”对话框。如果您想突出显示string.Contains()的使用,我会澄清答案。 - chwarr

-1

尝试使用try catch:

string x;

string log = @"C:\Users\Log.txt";

string ruta = @"C:\Users\x.txt";

if (File.Exists(ruta))
{                    
    try
    {
        x = File.ReadAllText(ruta);  
    }
    catch (Exception ex)
    {
        File.AppendAllText(ruta, "Something");
        File.AppendAllText(log, Environment.NewLine + DateTime.Now.ToString() + ": The file not contain a string. " + ex.Message);
    }
}

请解释你的回答。 - Andre Hofmeister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接