使用 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个文件。
我看到 TRS
和 EXE
文件,我没有看到 SKU
文件。 SKU
来自哪里?
我的错误我更正了感谢您的注意
【参考方案1】:
首先,正则表达式似乎也捕获了ROHWEPJQSKAUMDUCFCT=777
值,根据输出示例,它确实不应该捕获。也许,您需要将其更改为 (?<=[^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有三种方式(不使用,动态使用,静态使用,默认是动态使用)