【问题标题】:Reading specific files in different subfolders for same line of text C#为同一行文本C#读取不同子文件夹中的特定文件
【发布时间】:2018-08-21 14:14:19
【问题描述】:

我目前正在创建一个简短的控制台应用程序来读取多个子文件夹中的特定文件。该文件在所有目录中都具有相同的名称,因此将它们全部移动到一个目录并重命名它们将是一个巨大的麻烦(这些文件中有超过 365 个。它们每天都会自动创建一个新名称,并返回一些年)。但是,它们都在同一个主文件夹下。

我已经调查过Read all files in directory sub folders。我知道我能够搜索每个单独的子文件夹并查看所有文件(我能够在我的 foreach 语句中找到的每个文件的控制台中显示他们的 fileName

到目前为止的代码:

static void Main(string[] args)
{
    string readLine = string.Empty;
    var dir = new DirectoryInfo(@"C:\MotherDir\");
    // foreach loop to go through each subfolder to find FileINeed.txt
    foreach (var file in dir.EnumerateFiles("FileINeed.txt", SearchOption.AllDirectories))
    {
        //I get an error here: "System.IO.FileNotFoundException: 'Could not file file-'"
        using (StreamReader sr = new StreamReader(file.ToString()))   //this is using the wrong directory, not the one set previously (var dir)
        {
            while (!sr.EndOfStream)
            {
                readLine = sr.ReadLine();

                ProcessFiles(file.ToString());
            }
        }
    }

    Console.WriteLine("Finished.");
    Console.ReadKey(); //Gets pause at the end of the program
}

// Method to pass files through in order to search for specific string
static fileEntry ProcessFiles(string fileName)
{
    fileEntry inputFiles = new fileEntry();

    string fileString = string.Empty;
    string readLine;
    using (StreamReader sr = new StreamReader(fileName))
    {
        while (!sr.EndOfStream)
        {
            readLine = sr.ReadLine();

            if (readLine.Length < 1)
            {
            }

            if (readLine.Contains("RUN DATE: "))
            {
                Console.Write("RUN DATE:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("1234567"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("7654321"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("1346785"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("2589632"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
            if (readLine.Contains("12587412"))
            {
                Console.Write("Found this:    ");
                Console.WriteLine(readLine);
            }
        }
    }

    inputFiles.FileName = fileString;
    return inputFiles; 
}


public class fileEntry
{
    //stores file names and datetimes
    public string FileName { get; set; }

    public DateTime FileDate { get; set; }
}

对于寻找特定字符串的糟糕的 if 语句,我深表歉意,我试图使用 switch/case 语句但无法使其工作。

如果它找到其中一个字符串,我只需要将它输出到控制台窗口(我知道我正在尝试输出整个readLine)。该程序的目的是查看这些字符串是否存在于正在处理的文件中。

我对 C# 还很陌生,这是我从头开始编写的第一个有价值的程序之一。所以我为我仍在学习的糟糕的编码实践(如果有的话)道歉!如果您有任何建议或帮助,我们将不胜感激!如果我需要澄清任何事情,请告诉我!

提前谢谢你!

【问题讨论】:

  • @Archer ,请参阅代码中的 cmets。我目前在using (StreamReader sr = new StreamReader(file.ToString()) 上遇到错误。到目前为止,我的文件没有得到处理。
  • 是的,谢谢 - 我看到并删除了我的评论。如果您在代码之外解释问题所在可能会更好,但至少它在那里:)

标签: c#


【解决方案1】:

您在那里不必要地使用 StreamReader,您应该将其传递给您的 ProcessFiles(不是 file.ToString() 而是 file.FullName,它是文件的全名和路径 - 其他是 FileInfo 对象):

// foreach loop to go through each subfolder to find FileINeed.txt
foreach (var file in dir.EnumerateFiles("FileINeed.txt", SearchOption.AllDirectories))
{
    //I get an error here: "System.IO.FileNotFoundException: 'Could not file file-'"
            ProcessFiles(file.FullName);
}

注意:难以理解 ProcessFiles 的用途。即:为什么在作为新类处理时返回文件?您已经将它们放在您第一次获取列表的位置。

注意 2:顺便说一句,使用 dir.EnumerateFiles 或 dir.GetFiles 是比使用 Directory.GetFiles 更好的选择,特别是如果您还想过滤其他文件属性,例如(CreationDate、ModificationDate ...)。

另一个示例:

void Main()
{
    string[] searches = { "RUN DATE: ", "1234567", "7654321", "1346785", "2589632", "12587412"};

    var dir = new DirectoryInfo(@"C:\MotherDir\");
    var files = from fi in dir.GetFiles("FileINeed.txt", SearchOption.AllDirectories)
                let content = File.ReadAllText(fi.FullName)
                // sample filter
                // where fi.CreationTime >= DateTime.Now.AddDays(-3)
                where searches.Any(c => content.Contains(c))
                select fi;

    foreach (var file in files)
    {
        Console.WriteLine(file.FullName);
    }           
}

【讨论】:

  • 这很棒!谢谢!我不知道FullName 是一个财产。 - ProcessFiles 是为完全不同且更高级的程序编写的。我只是拿了它,把它掏空,只保留我认为我需要的东西。我为方法的创建包括了fileEntry 类。我想我不清楚您在Note 中提出的问题。根据Note2:,我不是已经在使用dir.EnumerateFiles,还是我不明白什么?
  • @Symon,不,您使用的是 dir.EnumerateFiles,这是正确的。我的意思是,如果您改为尝试使用 Directory.GetFiles,那么您将只返回一个包含 FullName 的字符串 []。在现实生活中,通常这样的搜索也会添加一些条件,例如 where file.CreationDate > DateTime.Today.AddDays(-3)。
  • @Symon,在注释中我问你为什么要返回一个新的 FileEntry,将其 FileName 属性设置为空字符串(在我看来完全没有目的)。
  • @Symon,我将尝试编写一个实际示例(认为您搜索的文件是小文本文件,这样做不会损害内存 - 坚持下去需要 5-10 分钟的时间来编写) .
  • @Symon,是的,没必要,因为您已经知道文件名。刚刚添加了一个示例,该示例返回一个 IEnumerable,其中至少包含一个搜索字符串。
【解决方案2】:

跳出来的错误是您打开每个文件并将文件内容传递给ProcessFiles,它实际上需要一个文件名,而不是文件内容。尝试将main() 方法更改为此...

static void Main(string[] args)
{
    // this gets all matching files in a string array...
    string[] allfiles = Directory.GetFiles(@"C:\MotherDir\", "FileINeed.txt", SearchOption.AllDirectories);

    // parse the string array and call ProcessFiles for each one...
    foreach (var file in allfiles)
    {
        ProcessFiles(file);
    }

    Console.WriteLine("Finished.");
    Console.ReadKey(); //Gets pause at the end of the program
}

【讨论】:

  • 将此作为另一个答案!谢谢您的意见。非常感谢!
  • 没问题。但是,您只能标记一个答案,因此除非您认为这是一个更合适的答案,否则您应该再次标记前一个答案。您的电话 - 很乐意提供帮助 :)
  • 啊。那我的坏!我仍然习惯于标记问题的答案。谢谢!让大家知道您的解决方案也有效!
【解决方案3】:

dir.EnumerateFiles 返回一个FileInfo 对象。使用 file.FullName 属性获取完全限定的路径名​​。

【讨论】:

    【解决方案4】:

    我觉得是你用的

    file.ToString()
    

    我不确定它会返回什么。要从 FileInfo 获取 Stream,您需要使用

    file.OpenText()
    

    所以你的失败代码将是

    using (StreamReader sr = file.OpenText())
    

    您的 ProcessFiles 可以使用 FileInfo 而不是字符串,然后您会得到这个

    static fileEntry ProcessFiles(FileInfo file)
    

    如果您想从 FileInfo 获取文件的完整路径,您可以使用

    Path.Combine(file.DirectoryName, file.Name)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多