C# LINQ学习笔记四:LINQ to OBJECT之操作文件目录
本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5816051.html,记录一下学习过程以备后续查用。
许多文件系统操作实质上是查询,因此非常适合使用LINQ方法。
一、查询具有指定属性或名称的文件
此示例演示如何查找指定目录树中具有指定文件扩展名(例如“.txt”)的所有文件,还演示如何根据创建时间返回树中最新或最旧的文件。
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 查询具有指定属性或名称的文件
- //文件路径
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\";
- //取文件系统快照
- var dir = new DirectoryInfo(path);
- //该方法假定应用程序在指定路径下的所有文件夹都具有搜索权限
- var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
- //创建查询
- var qurey = from file in files
- where file.Extension == ".txt"
- orderby file.Name
- select file;
- //执行查询
- foreach (var file in qurey)
- {
- Console.WriteLine(file.FullName);
- }
- //创建和执行一个新的查询,通过查询旧文件的创建时间作为一个出发点。
- //Last:选择最后一个,因为是按日期升序,所以最新的是指向最后一个。
- var newestFile = (from file in qurey
- orderby file.CreationTime
- select new { file.FullName, file.CreationTime }).Last();
- Console.WriteLine($"\r\nThe newest .txt file is {newestFile.FullName}. Creation time: {newestFile.CreationTime}");
- Console.Read();
- #endregion
- }
- }
运行结果如下:
二、按照扩展名对文件进行分组
此示例演示如何使用LINQ对文件或文件夹列表执行高级分组和排序操作。此外,它还演示如何使用Skip<TSource>和Take<TSource>方法对控制台窗
口中的输出进行分页。
下面的查询演示如何按文件扩展名对指定目录树的内容进行分组。
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 按照扩展名对文件进行分组
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\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);
- #endregion
- }
- /// <summary>
- /// 分页输出
- /// </summary>
- /// <param name="rootLength"></param>
- /// <param name="query"></param>
- private static void PageOutput(int rootLength, IOrderedEnumerable<IGrouping<string, FileInfo>> query)
- {
- //跳出分页循环的标志
- var isAgain = true;
- //控制台输出的高度
- var numLines = Console.WindowHeight - ;
- //遍历分组集合
- foreach (var g in query)
- {
- var currentLine = ;
- do
- {
- Console.Clear();
- Console.WriteLine(string.IsNullOrEmpty(g.Key) ? "[None]" : g.Key);
- //从“currentLine”开始显示“numLines”条数
- var resultPage = g.Skip(currentLine).Take(numLines);
- //执行查询
- foreach (var info in resultPage)
- {
- Console.WriteLine("\t{0}", info.FullName.Substring(rootLength));
- }
- //记录输出行数
- currentLine += numLines;
- Console.WriteLine("点击“任意键”继续,按“End”键退出");
- //给用户选择是否跳出
- var key = Console.ReadKey().Key;
- if (key != ConsoleKey.End) continue;
- isAgain = false;
- break;
- } while (currentLine < g.Count());
- if (!isAgain)
- {
- break;
- }
- }
- }
- }
运行结果如下:
三、查询一组文件夹中的总字节数
此示例演示如何检索指定文件夹及其所有子文件夹中的所有文件所使用的总字节数。
Sum方法添加在select子句中选择的所有项的值。您可以轻松修改此查询以检索指定目录树中的最大或最小文件,方法是调用Min<TSource>或
Max<TSource>方法,而不是Sum。
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 查询一组文件夹中的总字节数
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\";
- 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);
- Console.Read();
- #endregion
- }
- }
运行结果如下:
四、比较两个文件夹中的内容
此示例演示比较两个文件列表的三种方法:
1、查询一个指定两个文件列表是否相同的布尔值。
2、查询用于检索同时位于两个文件夹中的文件的交集。
3、查询用于检索位于一个文件夹中但不在另一个文件夹中的文件的差集。
- /// <summary>
- /// 文件名和字节数比较类
- /// </summary>
- public class FileComparer : IEqualityComparer<FileInfo>
- {
- public bool Equals(FileInfo x, FileInfo y)
- {
- return string.Equals(x.Name, y.Name, StringComparison.CurrentCultureIgnoreCase) && x.Length == y.Length;
- }
- //返回一个比较标准的哈希值。根据IEqualityComparer规则,如果相等,那么哈希值也必须是相等的。
- //因为这里所定义的相等只是一个简单的值相等,而不是引用标识,所以两个或多个对象将产生相同的哈希值是可能的。
- public int GetHashCode(FileInfo obj)
- {
- var s = string.Format("{0}{1}", obj.Name, obj.Length);
- return s.GetHashCode();
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 查询一组文件夹中的总字节数
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\";
- 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);
- Console.Read();
- #endregion
- }
- }
运行结果如下:
此处显示的FileComparer类演示如何将自定义比较器类与标准查询运算符一起使用。该类不是为在实际方案中使用而设计的,它只是使用每个
文件的名称和长度(以字节为单位)来确定每个文件夹的内容是否相同。在实际方案中,应对此比较器进行修改以执行更严格的相等性检查。
五、在目录树中查询最大的文件
此示例演示与文件大小(以字节为单位)相关的五种查询:
1、如何检索最大文件的大小(以字节为单位)。
2、如何检索最小文件的大小(以字节为单位)。
3、如何从指定的根文件夹下的一个或多个文件夹检索FileInfo对象最大或最小文件。
4、如何检索一个序列,如10个最大文件。
下面的示例包含五种不同的查询,这些查询演示如何根据文件大小(以字节为单位)查询和分组文件。可以轻松地修改这些示例,以使查询基
于FileInfo对象的某个其他属性。
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 在目录树中查询最大的文件
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\";
- var dir = new DirectoryInfo(path);
- var files = dir.GetFiles("*.*", SearchOption.AllDirectories);
- var query1 = from file in files
- select file.Length;
- //返回最大文件的大小
- var maxSize = query1.Max();
- Console.WriteLine("The length of the largest file under {0} is {1}", path, maxSize);
- Console.WriteLine();
- //倒序排列
- var query2 = from file in files
- let len = file.Length
- where len >
- 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();
- Console.WriteLine("The smallest file under {0} is {1} with a length of {2} bytes",
- path, smallestFile.FullName, smallestFile.Length);
- Console.WriteLine();
- Console.WriteLine("===== The 10 largest files under {0} are: =====", path);
- //返回前10个最大的文件
- var queryTenLargest = fileInfos.Take();
- foreach (var file in queryTenLargest)
- {
- Console.WriteLine("{0}: {1} bytes", file.FullName, file.Length);
- }
- Console.Read();
- #endregion
- }
- }
运行结果如下:
若要返回一个或多个完整的FileInfo对象,查询必须首先检查数据源中的每个对象,然后按这些对象的Length属性的值排序它们,这样就可以
返回具有最大长度的单个对象或序列。使用 First<TSource>可返回列表中的第一个元素使用 Take<TSource>可返回前n个元素。
六、在目录树中查询重复的文件
有时,多个文件夹中可能存在同名的文件。例如,在Visual Studio安装文件夹中,有多个文件夹包含readme.htm文件。
此示例演示如何在指定的根文件夹中查询重复文件名。
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 在目录树中查询重复的文件示例一
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\";
- 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() >
- select fileGroup).Distinct();
- PageOutput(queryDupNames);
- #endregion
- }
- /// <summary>
- /// 分页输出
- /// </summary>
- /// <typeparam name="TK"></typeparam>
- /// <typeparam name="TV"></typeparam>
- /// <param name="queryDupNames"></param>
- private static void PageOutput<TK, TV>(IEnumerable<IGrouping<TK, TV>> queryDupNames)
- {
- //控制台输出的高度
- var numLines = Console.WindowHeight - ;
- var dupNames = queryDupNames as IGrouping<TK, TV>[] ?? queryDupNames.ToArray();
- foreach (var queryDupName in dupNames)
- {
- //分页开始
- var currentLine = ;
- do
- {
- Console.Clear();
- Console.WriteLine("Filename = {0}", queryDupName.Key.ToString() == string.Empty ? "[none]" : queryDupName.Key.ToString());
- //跳过currentLine行,取numLines行。
- var resultPage = queryDupName.Skip(currentLine).Take(numLines);
- foreach (var fileName in resultPage)
- {
- Console.WriteLine("\t{0}", fileName);
- }
- //增量器记录已显示的行数
- currentLine += numLines;
- //按得有点累,还是让它自动下一页吧。
- Thread.Sleep();
- } while (currentLine < queryDupName.Count());
- }
- }
- }
运行结果如下:
此示例演示如何查询其大小和创建时间也匹配的文件。
- /// <summary>
- /// PortableKey类
- /// </summary>
- public class PortableKey
- {
- public string Name { get; set; }
- public DateTime CreationTime { get; set; }
- public double Length { get; set; }
- }
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 在目录树中查询重复的文件示例二
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\";
- 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() >
- select fileGroup;
- var queryDupNames = queryDupFiles as IGrouping<PortableKey, string>[] ?? queryDupFiles.ToArray();
- var list = queryDupNames.ToList();
- var count = queryDupNames.Count();
- //分页输出
- PageOutput(queryDupNames);
- Console.Read();
- #endregion
- }
- /// <summary>
- /// 分页输出
- /// </summary>
- /// <typeparam name="TK"></typeparam>
- /// <typeparam name="TV"></typeparam>
- /// <param name="queryDupNames"></param>
- private static void PageOutput<TK, TV>(IEnumerable<IGrouping<TK, TV>> queryDupNames)
- {
- //控制台输出的高度
- var numLines = Console.WindowHeight - ;
- var dupNames = queryDupNames as IGrouping<TK, TV>[] ?? queryDupNames.ToArray();
- foreach (var queryDupName in dupNames)
- {
- //分页开始
- var currentLine = ;
- do
- {
- Console.Clear();
- Console.WriteLine("Filename = {0}", queryDupName.Key.ToString() == string.Empty ? "[none]" : queryDupName.Key.ToString());
- //跳过currentLine行,取numLines行。
- var resultPage = queryDupName.Skip(currentLine).Take(numLines);
- foreach (var fileName in resultPage)
- {
- Console.WriteLine("\t{0}", fileName);
- }
- //增量器记录已显示的行数
- currentLine += numLines;
- //按得有点累,还是让它自动下一页吧。
- Thread.Sleep();
- } while (currentLine < queryDupName.Count());
- }
- }
- }
七、在文件夹中查询文件的内容
此示例演示如何查询指定目录树中的所有文件、打开每个文件并检查其内容。 此类技术可用于对目录树的内容创建索引或反向索引。 此示例
虽然执行的是简单的字符串搜索,但是,可使用正则表达式执行更复杂类型的模式匹配。
- class Program
- {
- static void Main(string[] args)
- {
- #region LINQ 在文件夹中查询文件的内容
- const string path = @"C:\Program Files (x86)\Microsoft Visual Studio\2017\";
- 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);
- }
- Console.Read();
- #endregion
- }
- /// <summary>
- /// 读取文件的所有内容
- /// </summary>
- /// <param name="fileName"></param>
- /// <returns></returns>
- static string GetFileConetnt(string fileName)
- {
- //如果我们在快照后已删除该文件,则忽略它,并返回空字符串。
- return File.Exists(fileName) ? File.ReadAllText(fileName) : "";
- }
- }
运行结果如下:
C# LINQ学习笔记四:LINQ to OBJECT之操作文件目录的更多相关文章
- LinQ实战学习笔记(四) LINQ to Object, 常用查询操作符
这一篇介绍了下面的内容: 查询object数组 查询强类型数组 查询泛型字典 查询字符串 SelectMany 索引 Distinct操作符 排序 嵌套查询 分组 组连接 内连接 左外连接 交叉连接 ...
- Entity Framework学习笔记(四)----Linq查询(1)
请注明转载地址:http://www.cnblogs.com/arhat 从本章开始,老魏就介绍一下Entity Framework使用Linq来查询数据,也就是Linq To Entity.其实在E ...
- Linq学习笔记四之linq to sql 的基本操作
首先需要在项目中新增一个 linq to sql 的服务 新增项,数据,LINQ TO sql 类的这个方法 第二步需要一个model类,用作映射 [Table] public class S_ZD ...
- MYSQL初级学习笔记四:查询数据的操作DQL(SELECT基本形式)(26-35)
知识点六:查询数据的操作DQL(SELECT基本形式)(26-35) CREATE DATABASE IF NOT EXISTS cms DEFAULT CHARACTER SET utf8; USE ...
- iView学习笔记(四):Form表单操作
1.后端准备 环境说明 python版本:3.6.6 Django版本:1.11.8 数据库:MariaDB 5.5.60 新建Django项目,在项目中新建app,配置好数据库 2.后端代码(基于C ...
- C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻
前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...
- java之jvm学习笔记四(安全管理器)
java之jvm学习笔记四(安全管理器) 前面已经简述了java的安全模型的两个组成部分(类装载器,class文件校验器),接下来学习的是java安全模型的另外一个重要组成部分安全管理器. 安全管理器 ...
- ES6学习笔记<四> default、rest、Multi-line Strings
default 参数默认值 在实际开发 有时需要给一些参数默认值. 在ES6之前一般都这么处理参数默认值 function add(val_1,val_2){ val_1 = val_1 || 10; ...
- python3.4学习笔记(四) 3.x和2.x的区别,持续更新
python3.4学习笔记(四) 3.x和2.x的区别 在2.x中:print html,3.x中必须改成:print(html) import urllib2ImportError: No modu ...
随机推荐
- 一个故事看懂Linux文件权限管理
前情回顾: 我通过open这个系统调用虫洞来到了内核空间,又在老爷爷的指点下来到了sys_open的地盘,即将开始打开文件的工作. 详情参见:内核地址空间大冒险:系统调用 open系统调用链 我是一个 ...
- vue 鼠标移入移出 列表蒙层展示
<template> <section class="base"> <ul> <li v-for="(item, index) ...
- GNU make doc - 函数总结
$(value variable) 使用variable未展开状态的值 FOO = $(PATH) all: $(warning $(FOO)) $(warning $(value FOO)) #ou ...
- Python学习小记(4)---class
1.名称修改机制 大概是会对形如 __parm 的成员修改为 _classname__spam 9.6. Private Variables “Private” instance variables ...
- openlayers6结合geoserver实现地图矢量瓦片(附源码下载)
内容概览 1.基于openlayers6结合geoserver实现地图矢量瓦片2.源代码demo下载 效果图如下: 实现思路:利用Geoserver发布矢量切片服务,然后openlayers调用矢量瓦 ...
- Linux Samba文件共享服务,安装与案例配置
Samba服务器安装和配置 1:安装Samba服务器软件包 [root@localhost ~]# rpm -qa | grep samba [root@localhost ~]# yum -y in ...
- Charles老版本教程
链接:http://pan.baidu.com/s/1c16PxEo 刮开有奖->密码:dbml 初级篇: 1.1设置代理 1.2参数设置+界面介绍 1.3屏蔽多余数据 1.4请求重发 1.5 ...
- css选择器四大类:基本、组合、属性、伪类
什么是选择器?选择器的作用是通过它可以找到元素,把css样式传递给元素!css选择器主要分为:基本选择器.属性选择器.组合选择器与伪类选择器四个大类! css基本选择器 基本选择器又分为:*通配符.标 ...
- 贪心训练均分纸牌Noip2002
题目链接:https://www.luogu.com.cn/problem/P1031 题目描述 有N堆纸牌,编号分别为 1,2,…,N.每堆上有若干张,但纸牌总数必为N的倍数.可以在任一堆上取若干张 ...
- java基础--------arraylist(动态数组)和linkedlist(双向链表)的区别
arraylist使用数组存储数据,所以这样存储的数据根据索引查询的数据速度快,但是新增或者删除元素时需要设计到位移操作,所以比较慢. linkedlist使用双向链表方式存储数据,每个元素都记录前后 ...