例程以递归方式搜索目录层次结构中的文件以查找目标字符串。它可以搜索几乎任何类型的文件,即使它不包含 Windows 理解的文本。例如,它可以搜索 DLL 和可执行文件以查看它们是否恰好包含字符串。
下面的代码中显示的ListFiles 方法完成了大部分工作。
// Add the files in this directory's subtree
// that match the pattern to the ListBox.
private void ListFiles(ListBox lst, string pattern,
DirectoryInfo dir_info, string target)
{
// Get the files in this directory.
FileInfo[] fs_infos = dir_info.GetFiles(pattern);
foreach (FileInfo fs_info in fs_infos)
{
if (target.Length == 0)
{
lstResults.Items.Add(fs_info.FullName);
}
else
{
string txt = File.ReadAllText(fs_info.FullName);
if (txt.IndexOf(target, StringComparison.OrdinalIgnoreCase) >= 0)
{
lstResults.Items.Add(fs_info.FullName);
}
}
}
// Search subdirectories.
DirectoryInfo[] subdirs = dir_info.GetDirectories();
foreach (DirectoryInfo subdir in subdirs)
{
ListFiles(lst, pattern, subdir, target);
}
}
ListFiles将DirectoryInfo作为参数,表示搜索应从哪里开始。它使用该对象的GetFiles方法获取与文件模式匹配的文件列表。如果没有要查找的目标字符串,程序只会将文件添加到结果列表中。
如果有目标字符串,程序将使用File.ReadAllText将文件的内容读入字符串。如果目标在字符串中,程序将文件添加到列表中。程序使用IndexOf方法而不是Contains,因此它可以使用OrdinalIgnoreCase参数在查找匹配项时忽略大小写。
搜索完此目录中的文件后,程序使用DirectoryInfo对象的GetDirectories方法获取其子目录的列表。程序递归调用ListFiles来搜索每个子目录。
这就是搜索代码的全部内容,但程序还做了一件更有趣的事情。启动时,它使用以下代码来确定是否从“发送到”菜单执行。
// If we launched from the Send To menu,
// use the argument as our directory.
private void Form1_Load(object sender, EventArgs e)
{
if (System.Environment.GetCommandLineArgs().Length > 1)
{
txtDirectory.Text = System.Environment.GetCommandLineArgs()[1];
txtTarget.Focus();
}
}
此代码检查程序的命令行参数。第一个参数始终是执行程序的名称。如果有第二个参数,则它应该是拖到可执行文件上或通过“发送到”菜单发送到程序的目录的名称。如果有第二个参数,程序会将其放在“目录”文本框中。
为了方便使用此程序,我将其添加到“发送到”菜单中。然后我可以右键单击目录,打开“发送到”菜单(在 Windows 11 中更难),然后选择此程序以使其搜索目录。有关向“发送到”菜单添加项目的更多信息,请参阅向“发送到”菜单添加项目。
结果并不像文件资源管理器的搜索那样花哨。您无法按文件日期、大小、作者、评级或任何其他您永远不想在搜索中使用的内容进行搜索。如果您愿意,您可以添加这些功能。
但是,这个程序可以搜索任何类型的文件。它甚至比 Windows 搜索还要快得多。
查看结果: