System.IO 的新特性和性能改进

  • Jonathan Allen
  • 朱永光

2009 年 10 月 15 日

话题:.NET语言 & 开发架构

微软打算为核心的System.IO功能提供一些简单却极受欢迎的性能改进。包括读写文本文件的便捷方法,快速地列举目录,对内存映射文件的支持。

第一个改进是,替换 File.ReadAllLines 这个原有的便捷方法。对于小文件而言,这是一个很好用的函数,但随着文件大小增大就会出现问题。根本的缺陷在于,ReadAllLines 会暂停程序的运行直到整个文件都被读到字符串数组中。

替代的方法是 File.ReadLines,其返回一个字符串枚举器。这种用延迟模式来读取文件方式,犹如使用低级的流对象一样。也为 File.WriteAllLines 和 File.AppendAllLines 提供了新的重载,两者可以接受枚举器而非数组作为参数。

DirectoryInfo.GetFiles 具有同样的数组问题,不过它们还带来了更为严重的问题。在获取文件列表的时候,Win32 API 也同时会返回诸如大小和最后编辑日期这样的基本信息。不幸的是,这些信息被.NET 遗弃了,而由 FileInfo 对象来保存这些信息。所以,在程序开始遍历这些文件的时候,假设为了确定目录的总大小,就必须逐一重新查询文件系统。这就是一个经典的 1+N 优化问题。DirectoryInfo.GetFiles 和新的 DirectoryInfo.EnumerateFiles 都修复了这个问题。

另外一个针对.NET 的重要的性能改进是,对内存映射文件的支持。内存映射文件是把一块内存连接到一个文件的操作系统特性。一旦连接起来,你就能读写文件的任意部分,就像它已经不再是非托管内存数组了。操作系统会处理一些重要的细节问题,如把文件的不同部分分页到内存上,并在需要的时候从内存里提取出来。内存映射文件让应用程序可以操作非常庞大的文件,甚至上 G 的文件也可高效地处理。

另外,对于底层文件 I/O,内存映射文件提供了强大的方法来与进程通信。如果两个应用程序打开了同一个内存映射文件,那么某个应用程序做出的改变会立即反映给另外一个应用程序。

尽管名称如此,内存映射文件并不需要一个真正的文件。它们可以是一些纯粹的内存对象,只要不用于后备存储。在应用程序内,这个潜在好处,特别适合于解决跨进程通信的问题。

查看英文原文:New Features and Performance Improvements for System.IO

.NET语言 & 开发架构