使用 Directory.EnumerateFiles 显示文件名

Posted

技术标签:

【中文标题】使用 Directory.EnumerateFiles 显示文件名【英文标题】:Display filename using Directory.EnumerateFiles 【发布时间】:2020-06-18 01:10:38 【问题描述】:

我正在做一个文件阅读器,它需要以某种格式输出一个新文件。 现在我正在尝试获取构建输出文件所需的所有信息,但我缺少两条信息:文件的日期和文件的名称。对于这两个字段,我计划使用文件的名称,因此对于日期 a 将修剪名称以仅获取日期,因为日期在名称中。

我需要从目录中的每个文件中获取“fct=”之后的值并计算该值加起来的次数,我能够使用正则表达式来做到这一点,但我无法提取文件的名称m in,这样我就可以知道在哪个文件中获取了“fct =”值。 之前我可以使用Directory.Getfilename 做到这一点,但现在我无法使用它,因为我使用的是 EnumerateFiles。

这是输入=文件的示例:

**2020-03-02_TRS.txt**
<dat>FCT=10019,XN=KEY,CN=ROHWEPJQSKAUMDUCFCT=777</dat></logurl>
<dat>XN=KEY,CN=RTU FCT=4515</dat>LBZ=test.sqi</logurl>
<dat>XN=KEY,CN=RT</dat>FCT=10019</logurl>
<dat>XN=KEY,CN=RT</dat>fct=717</logurl>

**2020-03-02_SKU.txt**
<dat>FCT=666,XN=KEY,CN=ROHWEPJQSKAUMDUCFCT=777</dat></logurl>
<dat>XN=KEY,CN=RTU FCT=123</dat>LBZ=test.sqi</logurl>

The output i'm looking for is:
2x 10019 TRS
1x 4515  TRS  
1x 717   TRS 
1x 666   SKU 
1x 123   SKU 

TRS 和 SKU 只是名称的一部分,所以如果我能找到一种方法来找到文件的名称,然后我将能够解析它以只保留 TRS 或 SKU。

这是我的代码:

    class Program


    static void Main(string[] args)
    

        int counter = 0;
        StreamWriter sw = new StreamWriter("C:/LogParser/LogParserV1/test.sql", true);
        char[] delimiters =  '<', ',', '&', ':', ' ', '\\', '\'' ;

        

            Regex regex = new Regex("(?<=FCT=)[0-9]*", RegexOptions.IgnoreCase);

            var fctlist = Directory
                      .EnumerateFiles(@"C:/LogParser/LogParserV1", "*.txt", SearchOption.AllDirectories) 
                      .SelectMany(file => File.ReadLines(file))
                      .SelectMany(line => regex
                      .Matches(line)
                      .Cast<Match>()
                      .Select(match => match.Value))
                      .GroupBy(number => number)
                      .Select(group => $"'group.Count()','group.Key','FCT',");

            foreach (string fctnumber in fctlist)
               Console.WriteLine(fctnumber);
            
            counter++;

            // Suspend the screen.  
            System.Console.ReadLine();
            sw.Close();

        
    

【问题讨论】:

2020-03-02_EXE.txt 还是2020-03-02_SKU.txt 它都有2个文件。 我看到 TRSEXE 文件,我没有看到 SKU 文件。 SKU 来自哪里? 我的错误我更正了感谢您的注意 【参考方案1】:

首先,正则表达式似乎也捕获了ROHWEPJQSKAUMDUCFCT=777 值,根据输出示例,它确实不应该捕获。也许,您需要将其更改为 (?&lt;=[^a-z]FCT=)[0-9]* 之类的内容。

要在输出中保留文件名的一部分,您可以选择一个匿名类并将这部分存储在其字段之一中。这样的事情可能会奏效:

var fctRegex = new Regex("(?<=[^a-z]FCT=)[0-9]*", RegexOptions.IgnoreCase);
//Extracting the last part of a filename with another regular expression
var filenameRegex = new Regex("^.*_([A-Z]+).txt$");
var fctlist = Directory
    .EnumerateFiles(@"C:/LogParser/LogParserV1", "*.txt", SearchOption.AllDirectories)
    .SelectMany(file => File.ReadLines(file)
        .SelectMany(line => fctRegex.Matches(line).Cast<Match>())
        //define an anonymous class with two fields
        .Select(match => new
            
            //one to store a filename 
            Filename = filenameRegex.Match(Path.GetFileName(file)).Groups[1].Value,
            //second to store a value
            match.Value
            )
    )
    //group by both filename and value
    //if you don't need to group the same value across similar files,
    //consider grouping before selecting an anonymous class.
    .GroupBy(v => v)
    //I assumed that you need your results sorted
    //feel free to remove it if you don't
    .OrderByDescending(g => g.Count())
    .ThenByDescending(g => int.Parse(g.Key.Value)); 

foreach (var fct in fctlist)
    Console.WriteLine($"fct.Count()x fct.Key.Value fct.Key.Filename");

稍后,您可以以类似的方式添加日期:

.Select(match => new
     
          Filedate = //some parsing here

【讨论】:

【参考方案2】:

这是另一种解决方案:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication159

    class Program
    
        const string FOLDER = @"c:\temp\test\";
        static void Main(string[] args)
        
            string patternData = "<dat>(?'data1'[^<]+)</dat>(?'data2'[^<]+)?</logurl>";
            string patternAttribute = @"(?'key'\w+)=(?'value'\w+)";
            string[] filenames = Directory.GetFiles(FOLDER, "*.txt");
            foreach (string filename in filenames)
            
                Dictionary<string, int> dict = new Dictionary<string, int>();
                StreamReader reader = new StreamReader(filename);
                string line = "";
                while ((line = reader.ReadLine()) != null)
                
                    Match matchData = Regex.Match(line, patternData);
                    if (matchData.Success)
                    
                        string data = string.Join(",", new string [] matchData.Groups["data1"].Value, matchData.Groups["data2"].Value).ToUpper();

                        Dictionary<string,string> dictAttributes = Regex.Matches(data, patternAttribute)
                            .Cast<Match>().GroupBy(x => x.Groups["key"].Value, y => y.Groups["value"].Value)
                            .ToDictionary(x => x.Key, y => y.FirstOrDefault());
                        if (dictAttributes.ContainsKey("FCT"))
                        
                            string value = dictAttributes["FCT"];
                            if (dict.ContainsKey(value))
                            
                                dict[value]++;
                            
                            else
                            
                                dict.Add(value, 1);
                            
                        

                    

                
                foreach (KeyValuePair<string, int> key in dict)
                
                    string file = filename.Substring(0,filename.LastIndexOf("\\"));
                    file = file.Substring(file.LastIndexOf(".") + 1);
                    Console.WriteLine("0x 1\t\t2", key.Value, key.Key, file);
                
            
            Console.ReadLine();
         
    

【讨论】:

以上是关于使用 Directory.EnumerateFiles 显示文件名的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)