Click here to Skip to main content
Click here to Skip to main content
Go to top

ViewFile and Head Tools

, 23 Jun 2014
Rate this:
Please Sign up or sign in to vote.
This article presents two tools, ViewFile and Head, that provide a dump of the contents of a file

Introduction [toc]

This article presents two tools, ViewFile and Head, that produce byte-oriented dumps of the contents of files.

Often, during the development process, it is useful to know the contents of one or more files in a format that is not the one provided by default by the operating system. For example, a .txt file displayed by Notepad; an .exe file by the execution of the file, or a .png file by an image viewer. Rather, the display desired is a byte-ordered display.

Table of Contents

The symbol [toc] returns the reader to the top of the Table of Contents.

ViewFile ViewFile [toc]

The ViewFile tool is a straight-forward file dump facility. On its initial execution, ViewFile accepts the name of an input file when the user clicks on the Browse button.

ViewFile Start

When the user has provided the name of the input file, ViewFile displays the file's contents in its display area. ViewFile is not reentrant, so, as soon as the input file name has been obtained, the Browse button is disabled and removed from the display.

Default File View

Note that, in this case, the file whose contents are being displayed is a BitMap file (recognized not only by its name, but also by its file signature - BM). For a good source of file signatures see Gary Kessler's File Signatures Table [^].

The user may scroll up and down through the file contents using the vertical scroll bar to the right of the window.

The user may choose to:

  • Change the left-hand format from hexadecimal to decimal.
  • Cause the display to stay on top of all other windows on the desktop.
  • Replace, on the right-hand side, spaces by the characters "<sp>". This is useful when the number of space characters on the right is not immediately apparent.

ViewFile displays the number of bytes in the file and the number of display lines for the file.

Head Head [toc]

Head was named after the unix head command. It performs in much the same manner as ViewFile except that, like its unix cousin, it displays only the first 160 bytes of the file. For this reason, there is no scroll bar.

After the user has provided the name of the input file, Head displays the file's contents in its display area. Like ViewFile, Head is not reentrant, so, as soon as the input file name has been obtained, the Browse button is disabled and removed from the display.

Default Head

As with ViewFile, the user may choose to:

  • Change the left-hand format from hexadecimal to decimal.
  • Cause the display to stay on top of all other windows on the desktop.
  • Replace, on the right-hand side, spaces by the characters "<sp>". This is useful when the number of space characters on the right is not immediately apparent.

Head displays the number of bytes in the file.

Implementation [toc]

With the exception of scroll bar handling, ViewFile and Head share much in common.

  1. Initialize the GUI.
  2. Hide all GUI elements except the input file elements and the Exit button.
  3. Wait for the user to specify an input file.
  4. When specified and the input file can be processed:
    1. Show all GUI elements.
    2. Hide input file Browse buttton.
    3. Prepare the view.
    4. Display the view.

Preparing the View [toc]

The most complex method of both ViewFile and Head is the prepare_file_view method.

    // ***************************************** prepare_file_view

    string prepare_file_view ( int  start_at )
        {
        int       bytes_read = 0;
        int       count = 0;

        left_side_sb.Length = 0;
        right_side_sb.Length = 0;
        view_sb.Length = 0;

        start_at *= BYTES_PER_LINE;
        read_file_bytes (     start_at,
                              buffer.Length,
                          ref bytes_read );

        for ( int i = 0; ( i < bytes_read ); i++ )
            {
            if ( hexadecimal )
                {
                left_side_sb.AppendFormat ( "{0:X2}  ", 
                                            buffer [ i ] );
                }
            else
                {
                left_side_sb.AppendFormat ( "{0,3:D} ", 
                                            buffer [ i ] );
                }

            if ( ( buffer [ i ] == 
                       ( byte ) Ascii.Control_Codes.ASCII_SP ) && 
                   use_SP )
                {
                right_side_sb.Append ( "<SP>" );
                }
            else if ( buffer [ i ] <= 
                      ( byte ) Ascii.Control_Codes.ASCII_DEL )
                {
                right_side_sb.Append ( Ascii.Code_Names [ 
                                                 buffer [ i ] ] );
                }
            else
                {
                int  int_value = ( int ) buffer [ i ];
                int  div_value = int_value / 100 ;

                right_side_sb.AppendFormat ( "<{0:D1}", 
                                             div_value );
                int_value = int_value % 100 ;
                div_value = int_value / 10 ;
                int_value = int_value % 10;
                right_side_sb.AppendFormat ( "{0:D1}{1:D1}>", 
                                             div_value, 
                                             int_value );
                }

            count++;

            if ( ( count == BYTES_PER_LINE ) ||
                 ( i == ( bytes_read - 1 ) ) )
                {
                if ( i == ( bytes_read - 1 ) )
                    {
                    for ( int j = count; 
                              ( j < BYTES_PER_LINE ); 
                              j++ )
                        {
                        left_side_sb.Append ( "    " );
                        }
                    }

                view_sb.AppendFormat ( 
                                "{0}| {1,10:D} | {2}",
                                left_side_sb.ToString ( ),
                                start_at,
                                right_side_sb.ToString ( ) );

                if ( i < ( buffer.Length - 1 ) )
                    {
                    view_sb.Append ( Environment.NewLine );
                    }

                count = 0;
                left_side_sb.Length = 0;
                right_side_sb.Length = 0;
                start_at += BYTES_PER_LINE;
                }
            }

        return ( view_sb.ToString ( ) );
        }
  

prepare_file_view uses three StringBuilder [^] objects, declared at the class level (declaring the StringBuilders at the class level avoids the cost of repeated setups). One StringBuilder collects the contents of the left-hand side of the view; another, the right-hand side of the view; and the third collects the view itself. Because the StringBuilder class does not have a Clear method (in .Net Framework 3.5), whenever an empty StringBuilder is desired, its Length property is set to zero.

Vertical Scroll Bar [toc]

ViewFile provides an instance of the VScroll Class [^] to support navigation within the view's RichTextBox [^]. Although a RichTextBox may have its own vertical scroll bar, it is somewhat more difficult to program PageUp, PageDown, Home, End, UpArrow, and DownArrow than with an independent scroll bar.

Two event handlers support the vertical scroll bar: vertical_VSB_Scroll and file_view_RTB_KeyDown

vertical_VSB_Scroll is the "standard" event handler for the VScroll Scroll event. Any movement of the scroll box triggers the event.

    // *************************************** vertical_VSB_Scroll

    void vertical_VSB_Scroll ( Object          sender,
                               ScrollEventArgs e )
        {

        if ( initialized )
            {
            current_VSB = e.NewValue;
            view = prepare_file_view ( current_VSB );
            if ( view.Length > 0 )
                {
                display_file_view ( );
                }
            }
        }
  

file_view_RTB_KeyDown is triggerred by any keyboard key press. It extends the vertical_VSB_Scroll handler by adding keyboard events to process the PageUp, PageDown, Home, End, UpArrow, and DownArrow key presses.

    // ************************************* file_view_RTB_KeyDown

    void file_view_RTB_KeyDown ( object       sender, 
                                 KeyEventArgs e )
        {
        int   old_current_VSB = vertical_VSB.Value;
        bool  refresh = true;

        e.Handled = true;

        switch ( e.KeyCode )
            {
            case Keys.PageDown:
            case Keys.Down:
            case Keys.End:
                refresh = ( vertical_VSB.Value <
                            ( vertical_VSB.Maximum - 
                             LINES_PER_VIEW - 1 ) );
                break;

            case Keys.PageUp:
            case Keys.Up:
            case Keys.Home:
                refresh = ( vertical_VSB.Value > 0 );
                break;

            default:
                refresh = false;
                break;
            }

        if ( !refresh )
            {
            return;
            }

        if ( e.KeyCode == Keys.PageDown )
            {
            current_VSB = 
                Math.Min ( vertical_VSB.Value + LINES_PER_VIEW,
                           ( vertical_VSB.Maximum - 
                             LINES_PER_VIEW - 1 ) );
            }
        else if ( e.KeyCode == Keys.Down )
            {
            current_VSB = 
                Math.Min ( vertical_VSB.Value + 1,
                           ( vertical_VSB.Maximum - 
                             LINES_PER_VIEW - 1 ) );
            }
        else if ( e.KeyCode == Keys.PageUp )
            {
            current_VSB = 
                Math.Max ( vertical_VSB.Value - LINES_PER_VIEW,
                           0 );
            }
        else if ( e.KeyCode == Keys.Up )
            {
            current_VSB = Math.Max ( vertical_VSB.Value - 1, 0 );
            }
        else if ( e.KeyCode == Keys.Home )
            {
            current_VSB = 0;
            }
        else if ( e.KeyCode == Keys.End )
            {
            current_VSB = 
                vertical_VSB.Maximum - LINES_PER_VIEW - 1;
            }
        else
            {
            refresh = false;
            }

        if ( !refresh )
            {
            return;
            }

        if ( old_current_VSB != current_VSB )
            {
            vertical_VSB.Value = current_VSB;
            view = prepare_file_view ( current_VSB );
            if ( view.Length > 0 )
                {
                display_file_view ( );
                }
            }
        }
  

Installing [toc]

When either ViewFile or Head is rebuilt, a Post Build Event [^] script is executed. This script creates the Deploy directory and copies files into it. These files will be used later by the setup script that controls the execution of Inno Setup [^]. Inno Setup is a free installer for Windows programs that I have been using for decades. The setup script for each tool is located in the solution directory. The actual setup executable is found in

  ...\Deploy\<tool-name>\Deploy\setup\setup_FW.exe
  

Whenever I create a new solution, I add a .iss script file from an earlier solution and modify it to meet the new solution's needs.

To install either of these tools, execute the setup_FW.exe in the appropriate ...Deploy\setup directory.

Conclusion [toc]

This article has presented two tools that provide the ability to obtain byte-oriented displays of files.

References [toc]

Development Environment [toc]

The ViewFile and Head tools were developed in the following environment:

      Microsoft Windows 7 Professional SP1
Microsoft Visual Studio 2008 Professional SP1
      Microsoft .Net Framework Version 3.5 SP1
      Microsoft Visual C# 2008

History [toc]

ViewFile V1.1
Head V1.2
06/23/2014 Original Article

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

gggustafson
Software Developer (Senior)
United States United States
I started programming more than 42 years ago using AutoCoder and RPG (note no suffixing numbers). Programs and data were entered using punched cards. Turnaround between submitting a job for compilation and execution was about 3 hours. So much for the "good old days!" Today, I particularly enjoy programming real-time software. I consider myself capable in WinForms, Mobile Apps, and C# although there are occasions that I yearn to return to C and the Win32 API.

Comments and Discussions

 
GeneralMy vote of 5 PinprofessionalEmre Ataseven23-Jun-14 22:40 
GeneralRe: My vote of 5 Pinprofessionalgggustafson24-Jun-14 4:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 23 Jun 2014
Article Copyright 2014 by gggustafson
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid