Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly is a "File Number"?

Tags:

c#

vb.net

vb6

I'm working in some C# code that had earlier been converted over from VB6 and it does lots of file I-O. All over the place I see this:

  fn = VBNET.FileSystem.FreeFile();

...followed by VBNET.FileSystem.FileOpen(), some file I-O, and then VBNET.FileSystem.FileClose() .

The call to FreeFile() generates a "file number", which is required to open the file. But what IS a file number and how do you release it back to the system when you're done with it?

The documentation at http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.filesystem.freefile.aspx doesn't seem to say, but it does say that an exception would be thrown if "more than 255 files are in use", which implies to me that it would be a good idea to release them when I'm done with them.

N.B. - I understand that there are better file-IO libraries to use but this is what we're stuck with until we have resources to rewrite this stuff, so I just want to understand it.

like image 800
user316117 Avatar asked Apr 03 '14 19:04

user316117


2 Answers

Those VB6 commands (FreeFile, FileOpen, FileClose, LOF, etc.) were present at least as far back as QBasic. I expect that the file number was originally an MS-DOS file handle.

A quick google search came up with these links:

  • http://support.microsoft.com/kb/269030 - Maximum file handles in MS-DOS is 255, which may explain that limit. (Not really the subject of the page, but first link that I found.)
  • http://stanislavs.org/helppc/file_handles.html - The INT21 functions listed seem to match up with the old style file commands.

Back in QBasic (if memory serves), the FileOpen command opened the file and reserved the file handle. The FileClose command closed the file and freed the handle.

FreeFile was just a convenience method to get an unused file handle: if you knew that you didn't have (for example) file #1 open, then you could just call OPEN "C:\DOS\RUN" FOR INPUT AS #1 and not bother calling FreeFile. You would still close it with CLOSE #1

I can't remember if that changed in VB6. As Hans Passant mentioned, internally in .NET the file number is now just an index into an array of VB6File objects. FileSystem.vb

like image 114
pmcoltrane Avatar answered Nov 08 '22 19:11

pmcoltrane


In early version of BASIC, pre-objects, when you wanted to do I/O to a file, you needed to tell the interpreter which open file you wanted to use by its number. The runtime had a table of open files, and the file number was basically an index into that table. The concept is similar to a file handle, as you would have used via the Windows API, but every BASIC program had it own set of file numbers.

Normally, the way you would do file I/O would be something like the following:

OPEN #1, "path\to\file"
PRINT #1, "Stuff I want in the file"
CLOSE #1

You would be responsible for keeping tracking of which file numbers you had opened, what files they pointed to, etc.

For simple programs, this isn't a big deal, but when you start to write modular programs, with shared subroutines and external libraries and such, that system becomes unworkable. If you're writing a logging routine, for example, you have to somehow select a file number for your log file that you can guarantee is never being used anywhere else, or bad things would happen.

The FreeFile function is VB's answer to this problem. Calling FreeFile returns the next available slot in the open files list, which you can then be sure no one else is using. In pseudo-code, it would be like doing this in the above code:

I = 0
WHILE ALREADYOPEN(#I) 
  I = I + 1
WEND
OPEN #I, "path\to\file"
PRINT #I, "stuff to go into file"
CLOSE #I

FreeFile basically does the equivalent of the the loop, except it already knows which file numbers are used and which aren't so it can just give you an answer. Otherwise, the I/O works exactly the same: once you have your free file number, you open it, read/write to it, and close it again.

like image 37
Michael Edenfield Avatar answered Nov 08 '22 20:11

Michael Edenfield