65.9K
CodeProject 正在变化。 阅读更多。
Home

访问 NTFS 卷上的文件备用数据流

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (47投票s)

2002 年 8 月 1 日

CPOL

4分钟阅读

viewsIcon

522036

downloadIcon

5406

一对用于封装访问 NTFS 备用数据流的类。

引言

自 NT 3.1 起,NTFS 文件系统就支持文件的多个数据流。一直以来,都没有内置的支持来查看或操作这些附加流,但 Windows API 函数通过特殊的语法支持它们:Filename.ext:StreamName。即使是 Win9x 机器也可以访问它们有权访问的任何 NTFS 卷上的文件的备用数据流,例如,通过映射驱动器。由于 Scripting.FileSystemObject 和许多其他库在后台调用 CreateFile API,因此即使是脚本也能相当容易地访问备用流(尽管枚举现有流一直很棘手)。

然而,在 .NET 中,似乎有人决定添加一些对文件名格式的检查。如果您尝试在备用流上打开 FileStream,您将收到“Path Format not supported”异常。我一直未能找到 CLR 中任何提供备用数据流支持的类,因此我决定自己编写。

更新

我最初在 2002 年编写了这段代码,目标是 .NET Framework v1。现在看这段代码,它似乎相当混乱,并且存在注释中提到的几个错误和问题。此后,我已为 .NET v3.5 完全重写了代码,并(希望)修复了这些错误。

新代码与原始版本不兼容。但是,我包含了一个示例兼容性包装器,它将旧 API 映射到新 API。您可以在下载的“other/Compatibility wrapper”文件夹下找到这些文件。

已修复的错误/问题

  • 代码现在使用 FileSystemInfo 类而不是 FileInfo 类。这允许您访问附加到文件夹和文件的备用数据流。(由 Dan Elebash 建议。)
  • 代码现在使用 SafeFileHandle 而不是 IntPtr 作为文件句柄。(由 Moomansun 建议。)
  • 代码现在兼容 64 位。(由 John SMith 5634552745 报告。)
  • 代码现在在枚举流后正确调用 BackupRead,并将 bAbort 参数设置为 true。(由 scooter_jsm 报告。)
  • 读取文件流所需的全局内存分配数量已减少。(由 scooter_jsm 建议。)
  • v2.1ValidateStreamName 现在接受包含 ASCII 码在 1 到 31 之间的字符的流名称。(由 Andy Missico 报告。)
  • v2.1:代码现在将尝试将标准 IO 错误映射到等效的 .NET Exception 类型。(由 Andy Missico 建议。)

使用类

AlternateDataStreamInfo 类代表单个流的详细信息,并提供创建、打开或删除该流的方法。

静态 FileSystem 类提供了用于检索文件流列表、检索文件的特定流、确定流是否存在以及删除特定流的方法。

FileSystem 类上的所有方法都提供接受路径或 FileSystemInfo 对象的重载。接受 FileSystemInfo 对象的重载也可以作为扩展方法调用。

示例

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using Trinet.Core.IO.Ntfs;

...

FileInfo file = new FileInfo(path);

// List the additional streams for a file:
foreach (AlternateDataStreamInfo s in file.ListAlternateDataStreams())
{
    Console.WriteLine("{0} - {1} bytes", s.Name, s.Size);
}

// Read the "Zone.Identifier" stream, if it exists:
if (file.AlternateDataStreamExists("Zone.Identifier"))
{
    Console.WriteLine("Found zone identifier stream:");
    
    AlternateDataStreamInfo s = 
       file.GetAlternateDataStream("Zone.Identifier",
                                   FileMode.Open);
    using (TextReader reader = s.OpenText())
    {
        Console.WriteLine(reader.ReadToEnd());
    }
    
    // Delete the stream:
    s.Delete();
}
else
{
    Console.WriteLine("No zone identifier stream found.");
}

// Alternative method to delete the stream:
file.DeleteAlternateDataStream("Zone.Identifier");

包含的文件

  • Trinet.Core.IO.Ntfs 文件夹包含源代码。
  • doc 文件夹包含文档和 FxCop 项目。
  • bin 文件夹包含已编译的程序集。
  • other 文件夹包含兼容性包装器,以及一个用于递归删除给定路径中所有文件的“Zone.Identifier”流的示例。

参考文献

如果您想了解有关 NTFS 编程的更多信息,或我基于此编写的 C++ 代码,请参阅 Dino Esposito 在 2000 年 3 月的 MSDN 文章:http://msdn.microsoft.com/en-us/library/ms810604.aspx [^]。

历史

  • v1 - 2002 年 8 月 1 日 - 初始发布,目标为 .NET 1.0。
  • v2 - 2008 年 9 月 16 日 - 重写以支持 .NET 3.5;主要更改包括
    • FileInfo 替换为 FileSystemInfo
    • IntPtr 替换为 SafeFileHandle
    • 使 P/Invoke 调用兼容 64 位。
    • 使代码在枚举流后中止 BackupRead 操作。
    • 减少了所需的全局内存分配数量。
  • v2.1 - 2010 年 7 月 28 日 - 由 Andy Missico 建议的微小修复
    • 更改 ValidateStreamName 以接受包含 ASCII 码在 1 到 31 之间的字符的流名称(请参阅 msdn.microsoft.com/en-us/library/aa365247)。
    • 添加了将标准 IO 错误映射到正确 .NET 异常的功能。
  • v2.2 - 2016 年 8 月 15 日 - 修复了 Member 12683101 报告的错误,即零长度的备用流阻止了后续流的枚举。
© . All rights reserved.