C#(99):LINQ to Objects(2)
2021-03-05 16:26
标签:嵌套 exists 扩展名 文件 示例 需要 byte read 快照 许多文件系统操作实质上是查询,因此非常适合使用 LINQ 方法。 本部分中的查询是非破坏性查询。 它们不用于更改原始文件或文件夹的内容。 这遵循了查询不应引起任何副作用这条规则。 通常,修改源数据的任何代码(包括执行创建/更新/删除运算符的查询)应与只查询数据的代码分开。 实例1、如何查询具有指定属性或名称的文件 此示例演示如何查找指定目录树中具有指定文件扩展名(例如“.txt”)的所有文件,还演示如何根据创建时间返回树中最新或最旧的文件。 实例2、如何按照扩展名对文件进行分组 此示例演示如何使用 LINQ 对文件或文件夹列表执行高级分组和排序操作。此外,它还演示如何使用 Skip 下面的查询演示如何按文件扩展名对指定目录树的内容进行分组。 图中执行结果可能与您的不一样。 此程序的输出可能会很长,具体取决于本地文件系统的细节以及 path 的设置。为了使您可以查看所有结果,此示例还演示如何按页查看结果。这些方法可应用于 Windows 和 Web 应用程序。 请注意,由于代码将对组中的项进行分页,因此需要嵌套的 foreach 循环。此外,还会使用某他某个逻辑来计算列表中的当前位置,以及使用户可以停止分页并退出程序。在这种特定情况下,将针对原始查询的缓存结果运行分页查询。 实例3、如何查询一组文件夹中的总字节数 此示例演示如何检索指定文件夹及其所有子文件夹中的所有文件所使用的总字节数。 Sum 方法添加在 select 子句中选择的所有项的值。您可以轻松修改此查询以检索指定目录树中的最大或最小文件,方法是调用 Min 如果您只需要统计特定目录树中的字节数,则可以更高效地实现此目的,而无需创建 LINQ 查询,因为该查询会引发创建列表集合作为数据源的系统开销。随着查询复杂度的增加,或者当您必须对同一数据源运行多个查询时,LINQ 方法的有用性也会随之增加。 实例4、如何比较两个文件夹中的内容 此示例演示比较两个文件列表的三种方法: (1)查询一个指定两个文件列表是否相同的布尔值; (2)查询用于检索同时位于两个文件夹中的文件的交集; (3)查询用于检索位于一个文件夹中但不在另一个文件夹中的文件的差集; 【注意】 可以修改上述这些方法以便对任意类型的对象序列进行比较。 此处显示的 FileComparer 类演示如何将自定义比较器类与标准查询运算符一起使用。该类不是为在实际方案中使用而设计的。它只是使用每个文件的名称和长度(以字节为单位)来确定每个文件夹的内容是否相同。在实际方案中,应对此比较器进行修改以执行更严格的相等性检查。 实例5、如何在目录树中查询最大的文件 此示例演示与文件大小(以字节为单位)相关的五种查询: (1)如何检索最大文件的大小(以字节为单位); (2)如何检索最小文件的大小(以字节为单位); (3)如何从指定的根文件夹下的一个或多个文件夹检索 FileInfo 对象最大或最小文件; (4)如何检索一个序列,如 10 个最大文件。 下面的示例包含五种不同的查询,这些查询演示如何根据文件大小(以字节为单位)查询和分组文件。可以轻松地修改这些示例,以使查询基于 FileInfo 对象的某个其他属性。 若要返回一个或多个完整的 FileInfo 对象,查询必须首先检查数据源中的每个对象,然后按这些对象的 Length 属性的值排序它们。然后查询可以返回具有最大长度的单个对象或序列。使用 First 实例6、如何在目录树中查询重复的文件 有时,多个文件夹中可能存在同名的文件。例如,在 Visual Studio 安装文件夹中,有多个文件夹包含 readme.htm 文件。此示例演示如何在指定的根文件夹中查询这样的重复文件名。第二个示例演示如何查询其大小和创建时间也匹配的文件。 第一个查询使用一个简单的键确定是否匹配;这会找到同名但内容可能不同的文件。第二个查询使用复合键并根据 FileInfo 对象的三个属性来确定是否匹配。此查询非常类似于查找同名且内容类似或相同的文件。 实例7、如何在文件夹中查询文件的内容 此示例演示如何查询指定目录树中的所有文件、打开每个文件并检查其内容。 此类技术可用于对目录树的内容创建索引或反向索引。 此示例中执行的是简单的字符串搜索。 但是,可使用正则表达式执行更复杂类型的模式匹配。 C#(99):LINQ to Objects(2) 标签:嵌套 exists 扩展名 文件 示例 需要 byte read 快照 原文地址:https://www.cnblogs.com/springsnow/p/12894028.html五、LINQ 和字符串
1、LINQ 和文件目录
//该查询将所有生产的完整路径。txt文件指定的文件夹包括子文件夹下。
const string path = @"C:\Program Files (x86)\Microsoft Visual Studio 14.0\";
//取文件系统快照
var dir = new DirectoryInfo(path);
//该方法假定应用程序在指定路径下的所有文件夹都具有搜索权限。
var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
//创建查询
var fileQuery = from file in files
where file.Extension == ".html"
orderby file.Name
select file;
//执行查询
foreach (var file in fileQuery)
{
Console.WriteLine(file.FullName);
}
//创建和执行一个新的查询,通过查询旧文件的创建时间作为一个出发点
//Last:选最后一个,因为是按日期升序,所以最新的是指最后一个
var newestFile = (from file in fileQuery
orderby file.CreationTime
select new { file.FullName, file.CreationTime }).Last();
Console.WriteLine(
$"\r\nThe newest .txt file is {newestFile.FullName}. Creation time: {newestFile.CreationTime}");
const string path = @"C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7";
//“path”的长度,后续用于在输出时去掉“path”这段前缀
var trimLength = path.Length;
//取文件系统快照
var dir = new DirectoryInfo(path);
//该方法假定应用程序在指定路径下的所有文件夹都具有搜索权限。
var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
//创建查询
var query = from file in files
group file by file.Extension.ToLower() into fileGroup
orderby fileGroup.Key
select fileGroup;
//一次显示一组。如果列表实体的行数大于控制台窗口中的行数,则分页输出。
PageOutput(trimLength, query);
private static void PageOutput(int rootLength, IOrderedEnumerable
const string path = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC#";
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
var query = from file in files
select file.Length;
//缓存结果,以避免多次访问文件系统
var fileLengths = query as long[] ?? query.ToArray();
//返回最大文件的大小
var largestLength = fileLengths.Max();
//返回指定文件夹下的所有文件中的总字节数
var totalBytes = fileLengths.Sum();
Console.WriteLine();
Console.WriteLine("There are {0} bytes in {1} files under {2}",
totalBytes, files.Count(), path);
Console.WriteLine("The largest files is {0} bytes.", largestLength);
//创建两个带比较的文件夹
const string path1 = @"E:\Test1";
const string path2 = @"E:\Test2";
var dir1 = new DirectoryInfo(path1);
var dir2 = new DirectoryInfo(path2);
//取文件快照
var files1 = dir1.GetFiles("*.*", SearchOption.AllDirectories);
var files2 = dir2.GetFiles("*.*", SearchOption.AllDirectories);
//自定义文件比较器
var comparer = new FileComparer();
//该查询确定两个文件夹包含相同的文件列表,基于自定义文件比较器。查询立即执行,因为它返回一个bool。
var areIdentical = files1.SequenceEqual(files2, comparer);
Console.WriteLine(areIdentical == true ? "the two folders are the same" : "The two folders are not the same");
//交集:找相同的文件
var queryCommonFiles = files1.Intersect(files2, comparer);
var commonFiles = queryCommonFiles as FileInfo[] ?? queryCommonFiles.ToArray();
if (commonFiles.Any())
{
Console.WriteLine("The following files are in both folders:");
foreach (var v in commonFiles)
{
Console.WriteLine(v.FullName);
}
}
else
{
Console.WriteLine("There are no common files in the two folders.");
}
//差集:对比两个文件夹的差异
var diffQuery = files1.Except(files2, comparer);
Console.WriteLine("The following files are in list1 but not list2:");
foreach (var v in diffQuery)
{
Console.WriteLine(v.FullName);
}
//该实现定义了一个非常简单的两个 FileInfo 对象之间的比较。它只比较文件的名称和它们字节数的长度
public class FileComparer : IEqualityComparer
const string path = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC#";
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
var query = from file in files
select file.Length;
//返回最大文件的大小
var maxSize = query.Max();
Console.WriteLine("The length of the largest file under {0} is {1}",
path, maxSize);
//倒序排列
var query2 = from file in files
let len = file.Length
where len > 0
orderby len descending
select file;
var fileInfos = query2 as FileInfo[] ?? query2.ToArray();
//倒序排列的第一个就是最大的文件
var longestFile = fileInfos.First();
//倒序排列的第一个就是最小的文件
var smallestFile = fileInfos.Last();
Console.WriteLine("The largest file under {0} is {1} with a length of {2} bytes",
path, longestFile.FullName, longestFile.Length);
Console.WriteLine("The smallest file under {0} is {1} with a length of {2} bytes",
path, smallestFile.FullName, smallestFile.Length);
Console.WriteLine("===== The 10 largest files under {0} are: =====", path);
//返回前10个最大的文件
var queryTenLargest = fileInfos.Take(10);
foreach (var v in queryTenLargest)
{
Console.WriteLine("{0}: {1} bytes", v.FullName, v.Length);
}
static void Main(string[] args)
{
QueryDuplicates();
//QueryDuplicates2();
Console.ReadKey();
}
static void QueryDuplicates()
{
const string path = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0";
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
var charsToSkip = path.Length;
var queryDupNames = (from file in files
group file.FullName.Substring(charsToSkip) by file.Name into fileGroup
where fileGroup.Count() > 1
select fileGroup).Distinct();
PageOutputstring, string>(queryDupNames);
}
private static void QueryDuplicates2()
{
const string path = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0";
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
//路径的长度
var charsToSkip = path.Length;
//注意一个复合键的使用。三个属性都匹配的文件属于同一组。
//匿名类型也可以用于复合键,但不能跨越方法边界。
var queryDupFiles = from file in files
group file.FullName.Substring(charsToSkip) by
new PortableKey() { Name = file.Name, CreationTime = file.CreationTime, Length = file.Length }
into fileGroup
where fileGroup.Count() > 1
select fileGroup;
var queryDupNames = queryDupFiles as IGrouping
const string path = @"C:\Program Files (x86)\Microsoft Visual Studio 12.0";
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
//待匹配的字符串
const string searchTerm = @"Visual Studio";
//搜索每个文件的内容。
//您也可以使用正则表达式替换 Contains 方法
var queryMatchingFiles = from file in files
where file.Extension == ".html"
let content = GetFileConetnt(file.FullName)
where content.Contains(searchTerm)
select file.FullName;
//执行查询
Console.WriteLine("The term \"{0}\" was found in:", searchTerm);
foreach (var filename in queryMatchingFiles)
{
Console.WriteLine(filename);
}
///
文章标题:C#(99):LINQ to Objects(2)
文章链接:http://soscw.com/index.php/essay/60516.html