Getting Past the 2 Gb File Limit

VB6 has its little bugs and quirks; we have all learnt to program around them. In recent times, it's become necessary to work with extremely large files, some that may break the 2 Gb barrier that VB has. So, to start, look closer at the VB 6 IDE and why you have this barrier.

When working in the IDE, any numbers that are entered are limited to a Long variable type. Actually, as far I've found, the IDE uses Longs for most numeric storage within the projects that you write.

Okay, so what's the problem with Longs? Well, by definition they are a signed 4-byte variable, in hex &H7FFFFFFF, with a lower limit of -2,147,483,648 and an upper limit of 2,147,483,647 (2 Gb). &H80000000 stores the sign of the value. Even when you enter values in Hex, they are stored in a Long.

Working with random access files, you quite often use a Long to store the filesize and current position, completely unaware that if the file you access is just one byte over the 2 Gb size, you can cause our application to corrupt the file when writing to it.

Unfortunately, there is no quick fix for this. To get around the problem, you need to write your own file handling module, one that uses windows APIs to open, read, write, and close any file.

Note: C++ apparently has a similar problem; the process described here can be exactly duplicated into C++. Simple code is included in C++. The first inspection of VB .NET does not seem to suffer with the same IDE restrictions, but for the interest of it, a VB .NET module is also included. The methods described here can be used on any Win32 Language IDE that has a 2 Gb file limit.

The first API you will look at is CreateFile:

Declaration

CreateFile ({FileName} as String, {Access} as (uInt32), _
   {ShareMode} as (uInt32), {Security} as Any, _
   {Disposition} as (uInt32), {Attributes} as (uInt32), _
   {TemplateFile} as (uInt32)) as (uInt32)

When you look at it the first time, it looks very intimidating, but there's not much to it. CreateFile is used to open files, existing or new.

  • {FileName}: The file to be opened, including full path name.
  • {Access}: Read and/or write access requirement.
  • {ShareMode}: Share mode for file access.
  • {Security}: Security Access. (You don't use this for this module, although you can add it according to your needs.)
  • {Disposition}: Opening method. In other words: Create new, open existing.
  • {Attributes}: Additional file attributes. (Again unused here, but you can add according to your needs.)
  • {TemplateFile}: File handle of a template file when creating a new file. (Again unused here, but you can add according to your needs.)
  • {Returns}: The file handle of the opened file.

Before using CreateFile and a few other APIs. you need to define a few variables, namely:

VB6

Const MOVEFILE_REPLACE_EXISTING = &H1
Const FILE_ATTRIBUTE_TEMPORARY  = &H100
Const FILE_BEGIN       = 0
Const FILE_SHARE_READ  = &H1
Const FILE_SHARE_WRITE = &H2
Const CREATE_NEW    = 1
Const CREATE_ALWAYS = 2
Const OPEN_EXISTING = 3
Const OPEN_ALLWAYS  = 4
Const GENERIC_READ  = &H80000000
Const GENERIC_WRITE = &H40000000

VB .NET

Const MOVEFILE_REPLACE_EXISTING As Short    = &H1s
Const FILE_ATTRIBUTE_TEMPORARY  As Short    = &H100s
Const FILE_BEGIN                As Short    = 0
Const FILE_SHARE_READ           As Short    = &H1s
Const FILE_SHARE_WRITE          As Short    = &H2s
Const CREATE_NEW                As Short    = 1
Const CREATE_ALWAYS             As Short    = 2
Const OPEN_EXISTING             As Short    = 3
Const OPEN_ALLWAYS              As Short    = 4
Const GENERIC_READ              As Integer  = &H80000000
Const GENERIC_WRITE             As Integer  = &H40000000

And then, you need to define the function.

VB6

Private Declare Function CreateFile Lib "kernel32" _
   Alias "CreateFileA" (ByVal lpFileName As String, _
   ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _
   ByVal lpSecurityAttributes As Any, _
   ByVal dwCreationDisposition As Long, _
   ByVal dwFlagsAndAttributes As Long, _
   ByVal hTemplateFile As Long) As Long

VB .NET

Private Declare Function CreateFile Lib "kernel32" _
   Alias "CreateFileA" (ByVal lpFileName As String, _
   ByVal dwDesiredAccess As uInteger, _
   ByVal dwShareMode As uInteger, _
   ByVal lpSecurityAttributes  As Integer, _
   ByVal dwCreationDisposition As uInteger, _
   ByVal dwFlagsAndAttributes  As uInteger, _
   ByVal hTemplateFile As uInteger) As uInteger

In C++, there is no need to define the API function.

Later in the article, you will start writing your modules; but, for now, you will look at the individual usages.

FileHandle = CreateFile(FileName, GENERIC_READ Or GENERIC_WRITE, _
   FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, OPEN_EXISTING, 0, 0)

VB .NET

FileHandle = CreateFile(FileName, GENERIC_READ Or GENERIC_WRITE, _
   FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)

C++

HANDLE FileHandle = CreateFile(Filename, GENERIC_READ|GENERIC_WRITE,
                               FILE_SHARE_READ|FILE_SHARE_WRITE, 
                               NULL, OPEN_EXISTING, 0&, 0&);
Note: When using CreateFile with the OPEN_EXISTING option, and the file does not exist, CreateFile returns an error. Take care in using the CREATE_ALWAYS option for Disposition; this will completely erase the named file, and create a new 0-byte file. CREATE_NEW will return a error if the named file exists.

The next API you will look at is GetFileSize. This API simply returns the current size of the opened file.

Declaration

GetFileSize ({FileHandle} as (uInt32), _
   { FileSizeHigh } as (uInt32)) as (uInt32)
  • {FileHandle}: File Handle of the opened file
  • {FileSizeHigh}: Returns the high 32bits of the file size
  • {Returns}: The Low 32bits of the file size

Definition

VB6

Private Declare Function GetFileSize Lib "kernel32" _
   (ByVal hFile As Long, lpFileSizeHigh As Long) As Long

VB .NET

Private Declare Function GetFileSize Lib "kernel32" _
   (ByVal hFile As uInteger, lpFileSizeHigh As uInteger) As uInteger

Usage

VB6 and VB .NET

FileSizeL = GetFileSize (FileNumber, FileSizeH)

C++

DWORD FileSizeL = GetFileSize (FileNumber, FileSizeH);

Next, you look at SetFilePointer. This API is used to set the current position in the open file. This function is very important because any reads or writes to the file do not automatically forward the file position.

Declaration

SetFilePointer ({FileHandle} as (uInt32), _
   { FilePosLow } as (uInt32), { FilePosHigh } as (uInt32), _
   {MoveMethod} as (uInt32)) as (uInt32)
  • {FileHandle}: File Handle of the opened file
  • {FilePosLow}: The Low 32bits of the file pos
  • {FilePosHigh}: The High 32bits of the file pos
  • {MoveMethod}: The Method to use when setting a new position
  • {Returns}: Error Code

Definition

VB6

Private Declare Function SetFilePointer Lib "kernel32" _
   (ByVal hFile As Long, ByVal lDistanceToMove As Long, _
   lpDistanceToMoveHigh As Long, ByVal dwMoveMethod As Long) As Long

VB .NET

Private Declare Function SetFilePointer Lib "kernel32" _
   (ByVal hFile As uInteger, ByVal lDistanceToMove As uInteger, _
    lpDistanceToMoveHigh As uInteger, _
    ByVal dwMoveMethod As Integer) As Integer

Usage

VB6 and VB .NET

Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)

C++

SetFilePointer (FileNumber, PosL, PosH, FILE_BEGIN);

On the next page, you will start writing some of your own functions in your module using the above three APIs. Also, you look at how to get your upper and lower 32-bit variables to use in the APIs.

Getting Past the 2 Gb File Limit

Having gotten a basic understanding of the previous three APIs, you now can look at making the first few sub routines in your VB6 Module. But, there's one problem: The API's expect the Low and High 32-bit values in unsigned format. Also, the APIs return unsigned values. So, the first thing you have to do is decide on a variable type that you can use to store values higher than 2 Gb. After some serious thought, I decided to use a Currency type (64-bit scaled integer) this gives you a 922,337gig upper file limit, way bigger that the largest hard drive available today.

Now that you have your Currency type to hold the file size and position info, you need two functions to convert them to and from the signed 32-bit variables.

VB6

Private Sub Size2Long(ByVal FileSize As Currency, _
   ByRef LongLow As Long, ByRef LongHigh As Long)
'&HFFFFFFFF unsigned = 4294967295
Dim Cutoff As Currency
Cutoff = 2147483647
Cutoff = Cutoff + 2147483647
Cutoff = Cutoff + 1
LongHigh = 0
Do Until FileSize < Cutoff
   LongHigh = LongHigh + 1
   FileSize = FileSize - Cutoff
Loop
If FileSize > 2147483647 Then
   LongLow = -CLng(Cutoff - (FileSize - 1))
Else
   LongLow = CLng(FileSize)
End If
End Sub

Look closer at what you are doing: Cutoff is a temporary, Currency type, variable that you use to hold the value of an unsigned 32-bit variable. Because VB6 uses Longs to store numbers in the IDE, you have to work around it a little by adding the biggest positive number possible (2147483647) repetitively until you get your wanted number. (2147483647 + 2147483647 + 1 = 4294967295). This looks a bit like it could be done easier, but there is no other method in the VB6 IDE.

Next, you work out the higher 32 bits. This code looks like it could be done with a simple division, but you have the problem of the IDE using longs. So, rather than running the risk of the IDE using a long somewhere in the calculations (tests have returned varied results where the division is often 1 out on certain file sizes), you may find a division method that will give the correct value every time, but for now this method will suffice.

With your max filesize being 922,337 Gb, the highest value that LongHigh will hold is 2147630, way below the Max positive value that a Long can hold. This means that you do not need to monitor it. Something to note: If the filesize is smaller than 4 Gb, the Do loop does not execute. Between 4 and 8 Gb the Do loop executes once; between 8 and 12 Gb, it executes twice. Som using this loop will have a very minor effect on performance.

Next, take the remainder and decide whether it needs the Sign bit of the long to hold a value (&H80000000). If it's smaller than 2147483648 (&H80000000 Unsigned), you can pass the value directly to your Long (LongLow); if not, you have to convert the value to the hex equivalent in Signed 32bit.

Now, you need to look at converting two Long values into one Currency value.

VB6

Private Sub Long2Size(ByVal LongLow As Long, _
                      ByVal LongHigh As Long, _
                      ByRef FileSize As Currency)
Dim Cutoff As Currency
Cutoff   = 2147483647
Cutoff   = Cutoff + 2147483647
Cutoff   = Cutoff + 1
FileSize = Cutoff * LongHigh
If LongLow < 0 Then
   FileSize = FileSize + (Cutoff + (LongLow + 1))
Else
   FileSize = FileSize + LongLow
End If
End Sub

Here, you are doing pretty much the same calculations, except that you are rebuilding the Currency value from two Long values. The multiplication here does not give any erroneous results, but note that the currency type variable must be listed first; otherwise, VB will try to use a Long type variable to temporally store the result. (This is one of the minor issues in VB6. When doing calculations, VB uses the same variable type of your first variable in the calculation and not the variable type of the destination variable. This has been documented on several sites so I'm not going too much into it.)

Without a clear understanding of variable types and limits in C++, I'm unable to duplicate these functions in C++. VB .NET, on the other hand, has opened up the available variables, giving yu signed and unsigned 8-bit, 16b-it, 32-bit, and 640bit variables. By using these newly available variables, your two functions now are very easy to code.

VB6

Private Sub Size2Long(ByVal FileSize As uLong, _
                      ByRef LongLow As uInteger, _
                      ByRef LongHigh As uInteger)
'&HFFFFFFFF unsigned = 4294967295
LongHigh = (FileSize And &HFFFFFFFF00000000) / &H100000000
LongLow  =  FileSize And &HFFFFFFFF
End Sub

VB .NET

Private Sub Long2Size(ByVal LongLow As uInteger, _
                      ByVal LongHigh As uInteger, _
                      ByRef FileSize As uLong)
FileSize = (LongHigh * &H100000000) Or LongLow
End Sub

These two functions are very straightforward in VB .NET because you now have the ability to use unsigned variables. Also, VB .NET does not have the IDE restrictions of VB6.

Now, having prepared your conversion functions, you can start with your API functions. The first one you will write is the Filesize API function. That's because the Openfile function will use the Filesize function to return the filesize upon opening the file (a value-added feature that the standard Open does not have).

VB6

Public Sub API_FileSize(ByVal FileNumber As Long, _
                        ByRef FileSize As Currency)
Dim FileSizeL As Long
Dim FileSizeH As Long
FileSizeH = 0
FileSizeL = GetFileSize(FileNumber, FileSizeH)
Long2Size FileSizeL, FileSizeH, FileSize
End Sub

VB .NET

Public Sub API_FileSize(ByVal FileNumber As UInteger, _
                        ByRef FileSize As ULong)
Dim FileSizeL As UInteger
Dim FileSizeH As UInteger
FileSizeH = 0
FileSizeL = GetFileSize(FileNumber, FileSizeH)
Long2Size(FileSizeL, FileSizeH, FileSize)
End Sub

In this function, you passed the API GetFileSize the file number (not to be confused with the file number used in the Open command), and it returns the filesize of the open file, in two 32-bit variables. You then pass these two variables to one of your functions, Long2Size, to get a single variable with the real file size.

Next, you will do your new Openfile function. As mentioned, this function has the added benefit of returning the filesize when you open the file. Also, there is no need to find a free file number because the function will return a unique Windows Handle for the file; you can use this to call the File Handle or the File number.

VB6

Public Sub API_OpenFile(ByVal FileName As String, _
                        ByRef FileNumber As Long, _
                        ByRef FileSize As Currency)
Dim FileH As Long
Dim Ret As Long
On Error Resume Next
FileH = CreateFile(FileName, GENERIC_READ Or GENERIC_WRITE, _
                   FILE_SHARE_READ Or FILE_SHARE_WRITE, 0&, _
                   OPEN_ALLWAYS, 0, 0)
If Err.Number > 0 Then
   Err.Clear
   FileNumber = -1
Else
   FileNumber = FileH
   Ret = SetFilePointer(FileH, 0, 0, FILE_BEGIN)
   API_FileSize FileH, FileSize
End If
On Error GoTo 0
End Sub

VB .NET

Public Sub API_OpenFile(ByVal FileName As String, _
                        ByRef FileNumber As UInteger, _
                        ByRef FileSize As ULong)
Dim FileH As UInteger
Dim Ret   As UInteger
On Error Resume Next
FileH = CreateFile(FileName, GENERIC_READ Or GENERIC_WRITE, _
                   FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, _
                   OPEN_ALLWAYS, 0, 0)
If Err.Number > 0 Then
   Err.Clear()
   FileNumber = 0
Else
   FileNumber = FileH
   Ret = SetFilePointer(FileH, 0, 0, FILE_BEGIN)
   API_FileSize(FileH, FileSize)
End If
On Error GoTo 0
End Sub

Here, you enable error trapping for the CreateFile API because, if there is a problem opening a file the API Errors out, and you need to trap it and react to it. At the moment, you simply reply that the file open was unsuccessful, but you can expand the function to include codes for failure reasons.

You then set the file position to zero so that your first read starts at the beginning of the file. This is not vital, but I felt it is warranted for those "just-in-case" scenarios. Next, you call the API_FileSize function with the File Handle you got from the CreateFile API. When the function ends, you now have a File Handle for the requested file and the file size.

On the next page, you look at reading and writing blocks of data to and from the file. Also, you find another added benefit of using API's—the ability to trim the filesize down.

Getting Past the 2 Gb File Limit

So now, you have your file handle to an open file and you want to read and write from it. The first API you will look at is the ReadFile API.
This API is, as its name suggests, used to read data blocks from the file. You pass it the File Handle you got when opening the file, an empty Buffer (or UDT), and how many bytes you want to read into the buffer. If successful, it will return the data in the buffer and how many bytes were read.

Declaration

ReadFile ({FileHandle} as (uInt32), { Buffer } as (Any), _
   { BytesToRead } as (uInt32), { ByteRead} as (uInt32) , _
   { OverLap } as (Any)) as (uInt32)
  • {FileHandle}: File Handle of the opened file
  • {Buffer}: Buffer to hold incoming data block
  • {BytesToRead}: Requested number of bytes
  • {ByteRead}: Bytes read from the file
  • {OverLap}: Overlap info used for Asynchronous data transfers
  • {Returns}: Error code

Definition

VB6

Private Declare Function ReadFile Lib "kernel32" _
   (ByVal hFile As Long, ByRef lpBuffer As Any, _
    ByVal nNumberOfBytesToRead As Long, _
    ByRef lpNumberOfBytesRead As Long, _
    ByVal lpOverlapped As Any) As Long

VB .NET

Private Declare Function ReadFile Lib "kernel32" _
   (ByVal hFile As uInteger, ByRef lpBuffer As Byte(), _
    ByVal nNumberOfBytesToRead As uInteger, _
    ByRef lpNumberOfBytesRead As uInteger, _
    ByVal lpOverlapped As Integer) As uInteger

Usage

VB6 and VB .NET

Ret = ReadFile(FileNumber, Data(0), BlockSize, SizeRead, 0&)

C++

BOOL Ret = ReadFile (FileNumber, Buffer, BlockSize, SizeRead, Null)

After having read all the data from your file, you will want to update some of it or add to it, so now you need to look at the WriteFile API. Again, as the name suggests, this API is used to write data to the file. You pass it the File Handle, a full buffer, and the number of bytes to write. If successful, it will return the number of bytes written.

Declaration

WriteFile ({FileHandle} as (uInt32), { Buffer } as (Any), _
   { BytesToWrite } as (uInt32), { ByteWriten} as (uInt32), _
   { OverLap } as (Any)) as (uInt32)
  • {FileHandle}: File Handle of the opened file
  • {Buffer}: Buffer to hold data block to be written
  • {BytesToWrite}: Number of bytes in buffer
  • {ByteWriten}: Bytes written from the file
  • {OverLap}: Overlap info used for asynchronous data transfers
  • {Returns}: Error code

Definition

VB6

Private Declare Function WriteFile Lib "kernel32" _
   (ByVal hFile As Long, ByVal lpBuffer As Any, _
    ByVal nNumberOfBytesToWrite As Long, _
    ByRef lpNumberOfBytesWriten As Long, _
    ByVal lpOverlapped As Any) As Long

VB .NET

Private Declare Function WriteFile Lib "kernel32" _
   (ByVal hFile As uInteger, ByVal lpBuffer As Byte(), _
    ByVal nNumberOfBytesToWrite As uInteger, _
    ByRef lpNumberOfBytesWriten As uInteger, _
    ByVal lpOverlapped As Integer) As uInteger

Usage

VB6 and VB .NET

Ret = WriteFile(FileNumber, Data(0), BlockSize, SizeWrit, 0&)

C++

BOOL Ret = WriteFile (FileNumber, Buffer, BlockSize, SizeWrit, Null)

Now, you are ready to write your two most important functions, API_ReadFile and API_WriteFile. These two are essentially the heart of your module.

VB6

Public Sub API_ReadFile(ByVal FileNumber As Long, _
                        ByVal Position As Currency, _
                        ByRef BlockSize As Long, _
                        ByRef Data() As Byte)
Dim PosL As Long
Dim PosH As Long
Dim SizeRead As Long
Dim Ret As Long
Size2Long Position, PosL, PosH
Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)
Ret = ReadFile(FileNumber, Data(0), BlockSize, SizeRead, 0&)
BlockSize = SizeRead
End Sub

VB .NET

Public Sub API_ReadFile(ByVal FileNumber As uInteger, _
                        ByVal Position As uLong, _
                        ByRef BlockSize As uInteger, _
                        ByRef Data() As Byte)
Dim PosL As uInteger
Dim PosH As uInteger
Dim SizeRead As uInteger
Dim Ret As uInteger
Size2Long(Position, PosL, PosH)
Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)
Ret = ReadFile(FileNumber, Data(0), BlockSize, SizeRead, 0)
BlockSize = SizeRead
End Sub

This function works much like the standard Read # command. You pass the function the file handle you got when opening the file, the byte position you want to start our read from, the size of the data block you require, and a buffer. For the buffer, you use an array of bytes because this seems to be the best method to ensure that any type of data can be read and written with it.

You use your conversion function to split the position info into the two 32-bit variables needed for the SetFilePointer API. Set the location in your file and then call your ReadFile API. And, for when you read at the end of the file, you pass the number of bytes that have been read.

The Write function is very similar to the Read function, with the exception that you call the WriteFile API.

VB6

Public Sub API_WriteFile(ByVal FileNumber As Long, _
                         ByVal Position As Currency, _
                         ByRef BlockSize As Long, _
                         ByRef Data() As Byte)
Dim PosL     As Long
Dim PosH     As Long
Dim SizeWrit As Long
Dim Ret      As Long
Size2Long Position, PosL, PosH
Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)
Ret = WriteFile(FileNumber, Data(0), BlockSize, SizeWrit, 0&)
BlockSize = SizeWrit
End Sub

VB .NET

Public Sub API_WriteFile(ByVal FileNumber As uInteger, _
                         ByVal Position As uLong, _
                         ByRef BlockSize As uInteger, _
                         ByRef Data() As Byte)
Dim PosL As uInteger
Dim PosH As uInteger
Dim SizeWrit As uInteger
Dim Ret As uInteger
Size2Long(Position, PosL, PosH)
Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)
Ret = WriteFile(FileNumber, Data(0), BlockSize, SizeWrit, 0)
BlockSize = SizeWrit
End Sub

What you will look into now is something that is not available in the standard IDE. You are going to write a module that you can use to trim the filesize down. How, you may ask? Windows gives us a bonus API, SetEndOfFile. So, take a look at it.

Declaration

SetEndOfFile ({FileHandle} as (uInt32)) as (uInt32)
  • {FileHandle}: File handle of the opened file
  • {Returns}: Error code

Definition

VB6

Private Declare Function SetEndOfFile Lib "kernel32" _
   (ByVal hFile As Long) As Long

VB.Net

Private Declare Function SetEndOfFile Lib "kernel32" _
   (ByVal hFile As uInteger) As uInteger

Usage

VB6 and VB .NET

Ret = SetEndOfFile (FileNumber)

C++

BOOL Ret = SetEndOfFile (FileNumber)

As simple as this API looks, it's very powerful. And, you must use it with caution. Now, look at the function you write to use it.

VB6

Public Sub API_SetEndOfFile(ByVal FileNumber As Long, _
                            ByVal Position As Currency)
Dim PosL As Long
Dim PosH As Long
Dim Ret  As Long
Size2Long Position, PosL, PosH
Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)
Ret = SetEndOfFile (FileNumber)
End Sub

VB .NET

Public Sub API_ SetEndOfFile(ByVal FileNumber As uInteger, _
                             ByVal Position As uLong)
Dim PosL As uInteger
Dim PosH As uInteger
Dim Ret  As uInteger
Size2Long(Position, PosL, PosH)
Ret = SetFilePointer(FileNumber, PosL, PosH, FILE_BEGIN)
Ret = SetEndOfFile(FileNumber)
End Sub

Everything in this function is what you know already. You set the file position as per usual, and then use SetEndOfFile to set the new end of file marker.

It is only polite to close a file when you're done with it; otherwise, you cannot use it in any other application. So, here's how to close the file with APIs. It's simple; you call the CloseHandle API. Why is it not called CloseFile? Well, when you opened the file, you got a Windows handle for the file. So, a CloseFile API would essentially do the same as CloseHandle. Take a look.

Declaration

CloseHandle ({ObjectHandle} as (uInt32)) as (uInt32)
  • {ObjectHandle}: Handle of any object
  • {Returns}: Error code

Definition

VB6

Private Declare Function CloseHandle Lib "kernel32" _
   (ByVal hObject As Long) As Long

VB .NET

Private Declare Function CloseHandle Lib "kernel32" _
   (ByVal hObject As uInteger) As uInteger

Usage

VB6 and VB .NET

Ret = CloseHandle (FileNumber)

C++

BOOL Ret = CloseHandle (FileNumber)

This API can be used to close any object that has a Windows handle, but it must be used with caution. If you use it to close forms, you may get unexpected errors. Always be wary about using the right file handle. Look now at the function.

VB6

Public Sub API_CloseFile(ByVal FileNumber As Long)
Dim Ret As Long
Ret = CloseHandle(FileNumber)
End Sub

VB .NET

Public Sub API_CloseFile(ByVal FileNumber As uInteger)
Dim Ret As uInteger
Ret = CloseHandle(FileNumber)
End Sub

Wow. Now you have all the functions required to write an application to use APIs to open, read, write, and close a file. The functions are easy to use, and can be used to replace the standard commands in most applications.

In the downloads, I've included a VB6 Project that uses this API module: Hex Editor. This is a small application that you can use to edit files at the raw data level.

Enjoy and happy programming.



About the Author

Richard Newcombe

Richard Newcombe has been involved in computers since the time of the Commodore 64. Today, he has excelled in programming, and designs. Richard is in his mid 30's and, if or when you looking for him look no further than his computer. Always willing to help and give advice where he can in regard to computer related subjects. At present he is working as a .NET 2008 Software Developer for Syncrony Web Services, South Africa.

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Packaged application development teams frequently operate with limited testing environments due to time and labor constraints. By virtualizing the entire application stack, packaged application development teams can deliver business results faster, at higher quality, and with lower risk.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds