// VisorHexadecimal.cs
// Versión 1.0
// Fecha: 7-Enero-2003
// Juan Manuel Cueva Lovelle
// Ilustra el manejo de archivos

using System;
using System.IO;

namespace Archivos
{

    /// <summary>
    /// Visualiza ficheros en formato Hexadecimal
    /// </summary>
    public class VisorHexadecimal
    {
        protected FileInfo fichero;

        public VisorHexadecimal(string nombre)
        {
            fichero = new FileInfo(nombre);
            if (!fichero.Exists)
            {
                Console.WriteLine("Error: Fichero {0} no encontrado", nombre);
                Environment.Exit(1);
            }
        }

        public void VerInfo ()
        {
           Console.WriteLine("Nombre : {0}", fichero.Name);
           Console.WriteLine("Extensión : {0}", fichero.Extension);
           Console.WriteLine("Nombre completo: {0}", fichero.FullName);
           Console.WriteLine("Directorio padre: {0}", fichero.DirectoryName);
           Console.WriteLine("Fecha creación: {0}", fichero.CreationTime);
           Console.WriteLine("Fecha último acceso: {0}", fichero.LastAccessTime);
           Console.WriteLine("Fecha última modificación: {0}", fichero.LastWriteTime);
           Console.WriteLine("Atributos: {0}", fichero.Attributes.ToString("F"));
           Console.WriteLine("Tamaño: {0}", fichero.Length);
       }
        public void VerContenido()
        {
            using (FileStream contenido = fichero.OpenRead())
            {
                if (fichero.Length==0)
                    Console.WriteLine("Archivo vacio");                
                else
                {
                    byte[] bytesLeidos = new byte[16];
                    long nBytesLeidos = contenido.Read(bytesLeidos, 0, 16);

                    while (nBytesLeidos!=0)
                    {
                        // Mostramos posición en el fichero del primer byte de la línea
                        Console.Write("\n{0:X8}:", contenido.Position-16);

                        // Mostramos línea de bytes
                        for (int i=0; i<nBytesLeidos; i++)
                            Console.Write(" {0:X2}", bytesLeidos[i]);

                        //  Separamos los bytes de sus respectivos caracteres asegurando que siempre
                        // se mantenga el mismo espaciado entre ellos
                        for (int i=0; i<16-nBytesLeidos; i++)
                            Console.Write("   ");
                        Console.Write(" | ");

                        //  Mostramos caracteres de los bytes de la línea.
                        //Los no imprimibles se muestran como un carácter de punt (‘.’)    
                        for(int i=0; i<nBytesLeidos; i++)
                        {
                            char carácterActual = (char) bytesLeidos[i];
                            if (Char.IsControl(carácterActual))
                                Console.Write('.');
                            else
                                Console.Write(carácterActual);
                        }
                        nBytesLeidos = contenido.Read(bytesLeidos, 0, 16);
                        Console.WriteLine();
                    }
                }
            }
        }
        /// <summary>
        /// Prueba unitaria de la clase VisorHexadecimal
        /// </summary>
        /// <param name="args">archivo a visualizar</param>
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Console.WriteLine("Formato de uso:");
                Console.WriteLine("\n\t VisorHexadecimal <archivo>");
                Environment.Exit(1);
            }

            VisorHexadecimal f = new VisorHexadecimal(args[0]);

            f.VerInfo();

            //Espera una tecla
            Console.ReadLine();

            f.VerContenido();
            //Espera una tecla
            Console.ReadLine();

        }
    }
}