如何修剪二进制文件的末尾?

问题描述

| 我正在使用以下代码将文本插入文件的任意部分:
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
时,我将用自己的一些数据覆盖现有数据。 当Windows为8时,这非常有用,因为Windows知道增加我的文件大小以容纳新的字节。但是,当我插入的字节少于删除的字节时,文件不会缩小,而将现有字节保留在那里。 例如,如果我的二进制文件
abcdefghijklmnopqrstuvwxyz
,并且我想在
after=5
before=15
中插入
HELLO
,我将得到
abcdeHELLOopqrstuvwxyzvwxyz
,并重复
vwxyz
。我如何缩小文件以便只得到15英镑? 澄清:我知道我可以删除原始文件并写回整个缓冲区,但是我的目标是提高性能,并以这种方式编写插入,因为逐行读取和写入整个文件太慢了。另外,我想保持文件属性完好无损,并且不想在每次插入记录时通过制作一个全新的文件来销毁它们。     

解决方法

        遗憾的是,没有用于设置文件长度的本地VB函数。可能希望使用FileAttr来获取操作系统可以使用的某种文件句柄,但这仅在16位代码中有效。 VBnet建议使用Windows API函数来完成整个工作: CreateFile / CloseHandle打开/关闭文件 GetFileSize以从文件句柄获取大小 SetFilePointer在文件内查找 SetEndOfFile截断文件 我已经基于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
    

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...