KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub

Q68026: Unexpected Results Using DOS TYPE to Display RANDOM File

Article: Q68026
Product(s): See article
Version(s): 1.00 1.01 1.02 2.00 2.01 3.00 4.00 4.00b 4.50
Operating System(s): MS-DOS
Keyword(s): ENDUSER | SR# S901119-101 B_BASICCOM B_GWBasicI | mspl13_basic
Last Modified: 9-JAN-1991

When you display the contents of a BASIC RANDOM or BINARY access file
with DOS's TYPE command, you may see unexpected or extra characters
(as in example 1 below) and/or the file may appear truncated (as in
example 2). This is because the TYPE command is designed to only
display ASCII text files. Using the TYPE command on a non-ASCII file
will produce output that resembles a corrupted or invalid file, but is
actually valid binary numeric information readable from certain
programs.

This behavior of the DOS TYPE command occurs for binary numeric data
stored files created in most Microsoft BASICs:

1. Microsoft QuickBASIC versions 1.00, 1.01, 1.02, 2.00, 2.01, 3.00,
   4.00, 4.00b, 4.50 for MS-DOS (BINARY access was introduced in
   QuickBASIC 4.00 and later).

2. Microsoft BASIC Compiler versions 6.00 and 6.00b for MS OS/2 and
   MS-DOS.

3. Microsoft BASIC Professional Development System (PDS) versions 7.00
   and 7.10 for MS-DOS and MS OS/2.

4. Microsoft GW-BASIC Interpreter versions 3.20, 3.22, 3.23 for
   MS-DOS (RANDOM access supported, but not BINARY access).

If extra text, which you did not write, appears in a file opened with
RANDOM access, then you may be mistakenly writing a record size
smaller than the RANDOM record buffer size you specified in your OPEN
statement. (See example 1 below.)

When you OPEN a file with RANDOM or BINARY access, PUT writes a
numeric (INTEGER, LONG, CURRENCY, SINGLE, or DOUBLE) variable with a
bit-by-bit representation. For instance, if you PUT the INTEGER 35 to
a RANDOM file, the DOS TYPE command will not display 35, but will
instead display an ASCII representation of the 2 bytes that make up
the integer variable:

                                         Byte 1        Byte 2
                                         ------        ------

   Binary integer representation of 35:  00000000      00100011
   Decimal value of byte:                0             35
   ASCII Character representation:       NULL (blank)  #

Because an INTEGER variable is stored in 2 bytes in two's complement
signed binary integer format, DOS's TYPE command will display the
INTEGER 35 as an ASCII blank followed by the ASCII # character.

Thus, byte values from 0 to 255 will be displayed by DOS's TYPE
command as control characters (ASCII 0 through 31), normal text (ASCII
32 through 127), and line draw, symbolic, and foreign alphabetic
characters (extended ASCII 128 through 255).

Also, if DOS's TYPE command encounters any binary byte value equal to
26, the output will be truncated at that point because TYPE treats 26
(or CTRL+Z) as an end-of-file marker for ASCII text files.

Code Examples
=============

The sample programs below apply to Microsoft QuickBASIC versions 4.00,
4.00b, and 4.50 for MS-DOS; to Microsoft BASIC Compiler versions 6.00
and 6.00b for MS-DOS and MS OS/2; and to Microsoft BASIC Professional
Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS
OS/2. (Earlier BASIC versions do not support the TYPE...END TYPE
statement, or the new third argument for the PUT statement syntax,
which is used in the examples below.)

Example 1:
---------

Below is an example of how extra characters will appear in your RANDOM
access file if you mistakenly write a record size smaller than the
record buffer size you specified in your OPEN statement.

When you OPEN a RANDOM access file, the PUT statement writes only as
many characters as are in the variable being PUT. If the record length
you specified in your OPEN statement exceeds the number of characters
that you PUT, then PUT does not fill out the remainder of the record
or clear the remaining information that was previously on the disk.
This location may contain unpredictable data from an old file that was
deleted. (To avoid this problem, make sure to PUT records of a size
equal to the OPEN statement's record buffer length, and don't leave
records or portions of records unwritten.)

     TYPE FileOutput
          TextString AS STRING * 50
     END TYPE
     DIM FileVar(3) AS FileOutput
     FileVar(0).TextString = "Hello World"
     FileVar(1).TextString = "Hello Again"
     F$ = "TESTFILE.DAT"
     OPEN F$ FOR RANDOM AS #1 LEN = 70
     PUT 1, 1, FileVar(0)
     PUT 1, 2, FileVar(1)
     GET 1, 1, FileVar(2)
     GET 1, 2, FileVar(3)
     CLOSE #1
     PRINT FileVar(2).TextString        'Prints correct information
     PRINT FileVar(3).TextString        'Prints correct information
     SHELL "TYPE TESTFILE.DAT"          'May show extra characters
     'Extra characters will appear in positions 51-70.

Also, the following example demonstrates how you can apparently
receive extra characters in a variable.

     TYPE FileIO1
          TextString AS STRING * 50
     END TYPE
     TYPE FileIO2
          TextString AS STRING * 70
     END TYPE
     DIM FileVar1 AS FileIO1
     DIM FileVar2 AS FileIO2
     FileVar1.TextString = "Hello From 1"
     OPEN "TESTFILE.DAT" FOR RANDOM AS #1 LEN = 70
     PUT 1, 1, FileVar1
     PUT 1, 2, FileVar1
     GET 1, 1, FileVar2
     PRINT FileVar2           ' May contain extra characters
     CLOSE #1

Example 2:
---------

DOS's TYPE command will print the contents of a file to the screen
until it reads an end-of-file (EOF) marker, a byte value equal to 26.
(But in the File Allocation Table on disk, MS-DOS itself keeps track
of the exact length of the file, instead of using CTRL+Z to mark the
end of file.)

It is possible for a byte value equal to 26 to correctly occur in your
random access file without your realization. An example of this
follows. (This example requires QuickBASIC 4.00b or later, where a
2-byte string length is written to disk in front of variable-length
strings written as the third argument of the PUT statement.)

   FileName$ = "TESTFILE.DAT"
   OPEN FileName$ FOR RANDOM AS #1 LEN = 80
   FOR I = 1 TO 5
      READ L$
      'L$ = LEFT$(L$+SPACE$(80), 78)   'Gets rid of extra characters
      PUT 1,,L$
   NEXT I
   CLOSE #1
   SHELL "TYPE TESTFILE.DAT"
   DATA "This line is fine"
   DATA "This line is also fine"
   DATA "This line is 26 characters"
   DATA "This line won't be printed by TYPE"
   DATA "neither will this line"

The results will be:

   ##This line is fine***********************************
   ##This line is also fine******************************

Note: ## refers to the 2-byte string length; * refers to a possible
extra character.

The third through fifth lines are not printed because QuickBASIC
includes a 2-byte integer, which stores the length of the string,
before each variable length string. Because the third line is 26
characters long, QuickBASIC stores a CHR$(26) before the third line.
The DOS command TYPE then interprets the CHR$(26) as an EOF marker.

Note that even though DOS's TYPE command did not display all of your
file, you can still GET all the information in the file.

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.