VisualBasic.Net 2003实现NTFS文件
附加数据流的读写类
中国人民解放军91515部队 贾文博(海南三亚 572016)
摘要:NTFS是Microsoft公司开发的一种有着良好安全性和稳定性的高性能文件系统,NTFS的文件或文件夹中附加多个额外的数据流,但是其访问一直没有很好的解决办法,本文使用VB2003实现NTFS文件附加数据流的读写类,提供.Net框架下NTFS文件附加数据流的完整解决方案。
关键词:VB.Net NTFS 数据流 类
1 导言
NTFS(New Technology File System)是Microsoft公司开发的一种有着良好安全性和稳定性的高性能文件系统,广泛用于WindowsNT、Windows2000、WindowsXP、Windows2003等操作系统中。为了使NTFS能访问Macintosh文件服务器的HFS(Hierarchical File System),Microsoft在NTFS中引入了交换数据流ADS(Alternate Data Streams),并提供了访问ADS的命令方式和编程API(Application Programming Interface)。这种机制允许在一个基于NTFS的文件或文件夹中附加多个额外的数据流,但其中只有一个是主数据流(Main Data Stream),其余为附加数据流,每个数据流都可以看作一个独立的文件,其内容可以是任何数据或程序代码,并能通过相应的接口访问,这种访问包括读写和执行。(图1.1)
图1.1
MSDN中已经演示了一种使用C++的MFC访问NTFS文件附加数据流的方法,由于对数据流的访问需要借助API函数,因此到目前为止,尚未有VB.Net程序能够完整地解决操作数据流的问题,为了跨越API与VB.Net的鸿沟,特写了此类访问NTFS文件附加数据流,提供.Net框架下文件附加数据流的完整解决方案。
2 设计方案
NTFS文件附加数据流的访问类,应具有如下功能:
2.1 读取/写入文件的特定数据流、获取其文件流FileStream(流文件名已知)
对流文件访问需要已知流文件的完整文件名,其完整文件名为:
主文件名:流文件名
声明如下:
Dim sFileStreamName As String = FileName & “:” & sStreamName
相对于.Net,获取文件名后我们需要借助于API函数CreateFile()创建流文件的操作句柄,然后串接到FileStream类进行数据的读取,其关键代码如下:
声明CreateFile函数:
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA"
(ByVal lpFileName As String, ByVal dwDesiredAccess As Integer, ByVal dwShareMode As Integer,
ByVal lpSecurityAttributes As Integer, ByVal dwCreationDisposition As Integer,
ByVal dwFlagsAndAttributes As Integer, ByVal hTemplateFile As Integer) As Integer
获得文件操作句柄:
Dim hfile As Integer ‘定义文件操作句柄
Dim tmpfilename As String = sFileStreamName ‘传递完整流文件名
hfile = CreateFile(tmpfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
由文件操作句柄串接至FileStream类:
Dim sFile As New FileStream(IntPtr.op_Explicit(hfile), FileAccess.ReadWrite)
其中IntPtr.op_Explicit()函数功能是把API文件操作句柄Integer类型转换为.Net文件操作句柄IntPtr类型。串接之后按照.Net下二进制数据的读取方法操作即可。
对文件写入特定数据流方法与读取特定数据流大体相同,把操作属性改为Write即可。(本文后附完整类代码,可参照实现)
2.2 枚举文件所有附加数据流名称
对所有附加数据流名称的枚举需要借助API函数BackupRead()和BackupSeek(),具体功能请查阅《Windows API参考手册完全版》,该函数主要用来在磁带机上读取备份。
Function ReadNTFSStreamsName() As String()
Dim returnNames() As String
'获取文件操作句柄
Dim tmpfilename As String = _str_sfilename ‘待枚举流文件名的NTFS文件
Dim hfile As Integer = CreateFile(tmpfilename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)
Try
Dim Sid As New WIN32_STREAM_ID ‘定义流文件头部的格式,此结构后面介绍
Dim dwStreamHeaderSize As Integer = Marshal.SizeOf(Sid) ‘获得占用字节大小
Dim lpContext = 0
Dim bContinue As Boolean = True ‘执行成功标志
Dim num As Integer = -1 ‘附加数据流总数
Dim sum As Integer
‘循环读取文件数据流名称,直到全部读取完毕
While (bContinue)
Dim lRead As Integer = 0
bContinue = BackupRead(hfile, Sid, dwStreamHeaderSize, lRead, False, False, lpContext)
If (bContinue AndAlso lRead = dwStreamHeaderSize) Then
sum += 1
If (Sid.dwStreamNameSize > 0) Then
num += 1
lRead = 0
‘获得数据流名称地址
Dim pName As Int32 = Marshal.AllocHGlobal(Sid.dwStreamNameSize).ToInt32
Try
bContinue = BackupRead(hfile, pName, Sid.dwStreamNameSize, lRead, False, False, lpContext)
Dim bName(Sid.dwStreamNameSize - 1) As Char
‘传递地址数据到字符数组bName