我使用以下代码将文本插入文件的任意部分:
Dim prebuffer() As Byte
Dim postbuffer() As Byte
Dim number As Integer
number = FreeFile
Open file For Binary Access Read Write Lock Read Write As number
ReDim prebuffer(after - 2)
ReDim postbuffer(LOF(number) - before)
Get number, 1, prebuffer
Get number, before, postbuffer
Seek number, 1
Put number, , prebuffer
Put number, , value
Put number, , postbuffer
Close number
after
和before
是从先前对Seek(number)
的调用中检索到的长片。当after
等于before
时,我只想插入数据而不删除任何数据。但是当after
小于before
时,我会用我自己的一些数据覆盖现有数据。
这在(before - after) <= Len(value)
时效果很好,因为Windows知道增加文件大小以容纳新字节。但是,当我插入的字节少于我删除的字节时,文件不会缩小,并在那里留下现有的字节。
例如,如果我的二进制文件是abcdefghijklmnopqrstuvwxyz
,并且我想在HELLO
和after=5
中插入before=15
,我会abcdeHELLOopqrstuvwxyzvwxyz
vwxyz
重复。如何缩小文件以便我只获得abcdeHELLOopqrstuvwxyz
?
答案 0 :(得分:0)
遗憾的是,没有用于设置文件长度的本地VB函数。有人可能希望使用FileAttr来获取操作系统可以使用的某种文件句柄,但这仅在16位代码中有效。
VBnet建议使用Windows API函数来完成整个工作:
我已经基于VBnet示例编写了一些简单的代码:
Option Explicit
'' constants for CreateFile
Private Const OPEN_ALWAYS As Long = 4, GENERIC_WRITE As Long = &H40000000, GENERIC_READ As Long = &H80000000, FILE_ATTRIBUTE_NORMAL As Long = &H80, INVALID_HANDLE_VALUE As Long = -1
'' constants for SetFilePointer
Private Const FILE_BEGIN As Long = 0, INVALID_SET_FILE_POINTER As Long = -1
'' kernel32 functions needed
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function GetFileSize Lib "kernel32" (ByVal hfile As Long, lpFileSizeHigh As Long) As Long
Private Declare Function SetFilePointer Lib "kernel32" (ByVal hfile As Long, ByVal lDistanceToMove As Long, lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long
Private Declare Function SetEndOfFile Lib "kernel32" (ByVal hfile As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hfile As Long) As Long
Sub truncatefile(filename As String, ByVal size As Currency)
Dim hfile As Long
Dim dwFileSizeLow As Long
Dim dwFileSizeHigh As Long
Dim ret As Long
'' open the file
hfile = CreateFile(filename, _
GENERIC_WRITE Or GENERIC_READ, _
0&, ByVal 0&, _
OPEN_ALWAYS, _
FILE_ATTRIBUTE_NORMAL, _
0&)
Debug.Assert (hfile <> INVALID_HANDLE_VALUE) '' make sure file opened OK
'' optional: get the current file length
dwFileSizeLow = GetFileSize(hfile, dwFileSizeHigh)
Debug.Assert (dwFileSizeLow >= 0 And dwFileSizeHigh = 0) '' TODO: handle 2GB and higher
Debug.Print "Old file size: " & dwFileSizeLow
'' split length into DWORDs (TODO: handle 2GB and higher)
dwFileSizeLow = size
dwFileSizeHigh = 0
'' seek to the desired file length
ret = SetFilePointer(hfile, dwFileSizeLow, dwFileSizeHigh, FILE_BEGIN)
Debug.Assert ret <> INVALID_SET_FILE_POINTER
'' set this as the length of the file
ret = SetEndOfFile(hfile)
Debug.Assert (ret <> 0)
'' close the file handle
Debug.Assert CloseHandle(hfile) <> 0
End Sub