搜索
bottom↓
回复: 38

[C#][学习笔记]一个可以存/取HEX文件的类HexFileStream

[复制链接]

出0入296汤圆

发表于 2010-3-21 11:44:54 | 显示全部楼层 |阅读模式

[说在前面的话]

    最近要开发一个类似programmer的软件模块,自然要牵涉到Hex文件的读取和写入,
于是我习惯性的先搜索各大网站,想寻找前人的肩膀,无奈,搜索的结果很出乎我意料,
难道C#程序员都不需要读取Hex文件么?这应该是微软System.IO的一部分吧?
    然而,想当然归想想当然,后来仔细一想,天下文件格式多了去了,微软才不管你
死活呢,要写,估计也是Intel写吧。求人不如求己,于是自己写了一个。
    受水猫启发,单单发一个东西给大家用或者等着喊牛是要挨打的。于是,我决定将
自己的思维过程和开发过程简单的拆解开来,分阶段的接受群众的监督和检查。但不管
怎么说,先放一个能用的HexFileStream类才是王道。


<font color=red>[使用方法]


    1、通过Add reference方法,加入对HexFileStream.dll的引用。

    2、在代码中加入对命名空间的引用:
       using Utilities.IO;

    3、在代码中建立一个HexFileStream
                HexFileStream tStream = null;
                try
                {
                    tStream = new HexFileStream(openFileDialog1.FileName, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite);
                }
                catch (Exception Err)
                {
                    Err.ToString();
                    return;
                }
    4、设置存储器空间的大小——比如你用M128,你就要设置存储器空间大小
       为128 * 1024,当然,如果空间大小是可变的,那么就设置0
       tStream.SetLength(0);

    5、读取所需的数据,并显示出来
       Byte[] tBuffer = new Byte[128 * 1024];
      
       //! 和Stream的用法相同
       tStream.Read(tBuffer, 0, tBuffer.Length);

       //! m_bvExample是一个ByteViewer,ByteViewer是微软提供的一个类,用以将二进制
       //! 数组以Hex字符串的方式显示在窗体上。
       m_bvExample.SetBytes(tBuffer);


[版本说明]

   
    v0.50 由于偷懒,目前版本仅仅支持各类Hex文件的读取,暂不支持写入,也不支持异步读取。
          构造函数目前仅允许使用文件路径来创建HexFileStream,暂不支持使用文件指针。
          构造函数必须指定操作方法为Read或者ReadWrite,否则,任何Read操作都将导致异常。


[相关下载]

    1、点击此处下载HexFileStream.dll ourdev_539960.rar(文件大小:11K) (原文件名:HexFileStream.rar)
    2、点击此处下载测试工程  ourdev_539962.rar(文件大小:61K) (原文件名:HexFileStreamTester.rar)

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入296汤圆

 楼主| 发表于 2010-3-21 11:45:07 | 显示全部楼层

“情况不明的时候,先从必须要做的东西开始入手”

    开发一个较大的项目,由于最终实现的功能可能较为复杂,则在项目的一开始就要求
较为精确的规划,对很多初学者来说,是相当有难度得,也不现实。比较现实的做法是:
<font color=blue>从必须要做的事情入手,然后将遇到的新问题分类,再次找到必须要做的事情,最终完成
大部分工作。

    这种开发方式有其局限性,不过很容易通过经验的积累来弥补这种局限。至于是什么
局限,开发的经验会告诉你。

    废话少说,一个HexFileStream最重要且最先要做的,当然是能够从Hex文件中解码出
我们需要的数据啦。所以,做一个Record类不用犹豫。


Record.h

using System;
using System.Collections.Generic;
using System.Text;

namespace Utilities.IO
{

    //! \name record structure in Intel-Hexadecimal file
    //! @{
    internal abstract class Record
    {
        protected Boolean m_bAvailable = false;

        //! \brief property for check whether this record is available or not.
        public Boolean Available
        {
            get { return m_bAvailable; }
        }


        //! \name record type
        //! @{
        internal enum Type : byte
        {
            DATA_RECORD                     = 0,            //!< data record
            END_OF_FILE_RECORD              = 1,            //!< end of file record
            EXTEND_SEGMENT_ADDRESS_RECORD   = 2,            //!< extend segment address record
            START_SEGMENT_ADDRESS_RECORD    = 3,            //!< start segment address record
            EXTEND_LINEAR_ADDRESS_RECORD    = 4,            //!< extend linear address record
            START_LINEAR_ADDRESS_RECORD     = 5             //!< start linear address record
        }
        //! @}

        //! \brief property for getting record type
        /*! \note Each record has a RECTYP field which specifies the record type of this record.
         *        The RECTYP field is used to interpret the remaining information within the
         *        record. The encoding for all the current record types are:
         *          ’00’ Data Record
         *          ’01’ End of File Record
         *          ’02’ Extended Segment Address Record
         *          ’03’ Start Segment Address Record
         *          ’04’ Extended Linear Address Record
         *          ’05’ Start Linear Address Record
         */
        public abstract Type RecordType
        {
            get;
        }

        /*! \note Each record has a RECLEN field which specifies the number of bytes of
         *        information or data which follows the RECTYP field of the record. Note that
         *        one data byte is represented by two ASCII characters. The maximum value of
         *        the RECLEN field is hexadecimal ’FF’ or 255.
         */
        public abstract Int32 RecordLength
        {
            get;
        }

        /*! \note Each record has a LOAD OFFSET field which specifies the 16-bit starting load
         *        offset of the data bytes, therefore this field is only used for Data Records.
         *        In other records where this field is not used, it should be coded as four
         *        ASCII zero characters (’0000’ or 03030303OH).
         */
        public virtual UInt16 LoadOffset
        {
            get { return 0; }
        }

        /*! \note Each record has a variable length INFO/DATA field, it consists of zero or
         *        more bytes encoded as pairs of hexadecimal digits. The interpretation of
         *        this field depends on the RECTYP field.
         */
        public abstract Byte[] Data
        {
            get;
        }


        //! \brief method to parse record string
        //! \param tHexRecord a record string
        //! \return a reference to a new record object
        public static Record Parse(String tHexRecord)
        {
            //! check input
            if (null == tHexRecord)
            {
                return null;
            }
            
            tHexRecord = tHexRecord.Trim().ToUpper();
            if ("" == tHexRecord)
            {
                return null;
            }

            //! \brief check record head
            if (':' != tHexRecord[0])
            {
                return null;
            }
            if (!IsHexNumber(tHexRecord.Substring(1)))
            {
                return null;
            }

            Int32 tRecordLength = 0;
            Int32 tCheckSUM = 0;
            Int32 tLoadOffSet = 0;
            Byte tRecordType = 0;
            Byte[] tData = null;

            //! try to get record length
            try
            {
                tRecordLength = Int32.Parse(tHexRecord.Substring(1, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            catch (Exception Err)
            {
                Err.ToString();
                return null;
            }
            tCheckSUM += tRecordLength;

            //! check record string length
            if (tHexRecord.Length < (11 + tRecordLength * 2))
            {
                //! incomplete record
                return null;
            }

            //! try to get LoadOffset
            try
            {
                tLoadOffSet = UInt16.Parse(tHexRecord.Substring(3,4), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            catch (Exception Err)
            {
                Err.ToString();
                return null;
            }
            tCheckSUM += tLoadOffSet >> 8;
            tCheckSUM += tLoadOffSet & 0xFF;

            //! try to get record type
            try
            {
                tRecordType = Byte.Parse(tHexRecord.Substring(7, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            catch (Exception Err)
            {
                Err.ToString();
                return null;
            }

            //! check record type value
            if (tRecordType > 5)
            {
                return null;
            }
            else if (
                        ((Type)tRecordType != Type.DATA_RECORD)
                    &&  (tLoadOffSet != 0)
                    )
            {
                //! illegal record loadoffset
                return null;
            }

            tCheckSUM += tRecordType;
            
            //! get data byte
            tData = new Byte[tRecordLength];
            if (null == tData)
            {
                //! failed to allocated memory
                return null;
            }

            //! read all data bytes in a record
            for (Int32 n = 0; n < tData.Length; n++)
            {
                try
                {
                    tData[n] = Byte.Parse(tHexRecord.Substring(9 + n * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
                }
                catch (Exception Err)
                {
                    Err.ToString();
                    return null;
                }
                tCheckSUM += tData[n];
            }

            //! get check sum
            try
            {
                tCheckSUM += Byte.Parse(tHexRecord.Substring(9 + tData.Length * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
            }
            catch (Exception Err)
            {
                Err.ToString();
                return null;
            }
            if (0 != (tCheckSUM & 0xFF))
            {
                //! check sum error
                return null;
            }

            //! \brief check record type
            switch ((Type)tRecordType)
            {
                case Type.DATA_RECORD:                              //!< data record
                    return new DataRecord((UInt16)tLoadOffSet, tData);

                case Type.END_OF_FILE_RECORD:                       //!< EOF record
                    return new EndOfFileRecord();

                case Type.EXTEND_LINEAR_ADDRESS_RECORD:             //!< extend linear address record
                    return new ExtendLinearAddressRecord(tData);   

                case Type.EXTEND_SEGMENT_ADDRESS_RECORD:            //!< extend segment address
                    return new ExtendSegmentAddressRecord(tData);   

                case Type.START_LINEAR_ADDRESS_RECORD:              //!< start linear address record
                    return new StartLinearAddressRecord(tData);     

                case Type.START_SEGMENT_ADDRESS_RECORD:
                    return new StartSegmentAddressRecord(tData);        //!< start segment address

                default:
                    //! brief no such type
                    return null;
            }
            
            return null;
        }

        //! \brief get HEX record String
        public override String ToString()
        {
            StringBuilder tsbHexRecord = new StringBuilder();
            if (m_bAvailable)
            {
                return null;
            }

            UInt32 tCheckSUM = 0;

            //! record head
            tsbHexRecord.Append(':');

            //! record length
            tsbHexRecord.Append(this.RecordLength.ToString("X2"));
            tCheckSUM += (UInt32)RecordLength;

            //! record load offset
            tsbHexRecord.Append(this.LoadOffset.ToString("X4"));
            tCheckSUM += (UInt32)(LoadOffset & 0x00FF);
            tCheckSUM += (UInt32)(LoadOffset >> 8);

            //! record type
            tsbHexRecord.Append(((Byte)this.RecordType).ToString("X2"));
            tCheckSUM += (Byte)RecordType;

            //! record data
            foreach (Byte tItem in Data)
            {
                tsbHexRecord.Append(tItem.ToString("X2"));
                tCheckSUM += tItem;
            }

            //! record check sum
            tsbHexRecord.Append(((Byte)((UInt16)0x100 - (UInt16)(tCheckSUM & 0xFF))).ToString("X2"));

            return tsbHexRecord.ToString();
        }


        //! \brief method for check whecher string only consist of hex value
        static public Boolean IsHexNumber(String tHexString)
        {
            if (null == tHexString)
            {
                return false;
            }

            tHexString = tHexString.Trim().ToUpper();
            if ("" == tHexString)
            {
                return false;
            }

            foreach (Char tSymble in tHexString.ToCharArray())
            {
                if (!Char.IsNumber(tSymble))
                {
                    if ((tSymble < 'A') || (tSymble > 'F'))
                    {
                        return false;
                    }
                }
            }

            return true;
        }

    }
    //! @}

    /*! \note The End of File Record specifies the end of the hexadecimal object
     *        file.
     */
    //! \name the End of File record
    //! @{
    internal class EndOfFileRecord : Record
    {
        //! \brief length always is zero.
        public override int RecordLength
        {
            get { return 0; }
        }


        //! \brief get record type
        public override Record.Type RecordType
        {
            get { return Type.END_OF_FILE_RECORD; }
        }

        //! \brief no data
        public override byte[] Data
        {
            get
            {
                return new Byte[0];
            }
        }
    }
    //! @}

    /*! \note The 32-bit Extended Linear Address Record is used to specify bits
     *        16-31 of the Linear Base Address (LBA), where bits 0-15 of the LBA
     *        are zero. Bits 16-31 of the LBA are referred to as the Upper Linear
     *        Base Address (ULBA). The absolute memory address of a content byte
     *        in a subsequent Data Record is obtained by adding the LBA to an
     *        offset calculated by adding the LOAD OFFSET field of the containing
     *        Data Record to the index of the byte in the Data Record (0, 1, 2,
     *        ... n). This offset addition is done modulo 4G (i.e., 32-bits),
     *        ignoring any carry, so that offset wrap-around loading (from
     *        OFFFFFFFFH to OOOOOOOOOH) results in wrapping around from the end
     *        to the beginning of the 4G linear address defined by the LBA. The
     *        linear address at which a particular byte is loaded is calculated
     *        as:
     *        
     *        (LBA + DRLO + DRI) MOD 4G
     *        
     *        where:
     *        DRLO is the LOAD OFFSET field of a Data Record.
     *        DRI is the data byte index within the Data Record.
     *        
     *        When an Extended Linear Address Record defines the value of LBA,
     *        it may appear anywhere within a 32-bit hexadecimal object file.
     *        This value remains in effect until another Extended Linear Address
     *        Record is encountered. The LBA defaults to zero until an Extended
     *        Linear Address Record is encountered.
     */
    //! \name the Extend Linear Address Record
    //! @{
    internal class ExtendLinearAddressRecord : Record
    {
        private UInt16 m_UpperLinearBaseAddress = 0;
        private Byte[] m_Data = null;

        public ExtendLinearAddressRecord(Byte[] tData)
        {
            if (null == tData)
            {
                return;
            }
            else if (2 != tData.Length)
            {
                return ;
            }

            m_Data = tData;

            try
            {
                Byte[] tTemp = new Byte[2];
                tTemp[0] = tData[1];
                tTemp[1] = tData[0];

                m_UpperLinearBaseAddress = BitConverter.ToUInt16(tTemp, 0);
            }
            catch (Exception Err)
            {
                Err.ToString();
                return;
            }

            m_bAvailable = true;
        }

        //! \brief record data length should always be 2
        public override Int32 RecordLength
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }
                return 2;
            }
        }


        //! \brief get record type
        public override Record.Type RecordType
        {
            get { return Type.EXTEND_LINEAR_ADDRESS_RECORD; }
        }

        //! \brief get data
        public override Byte[] Data
        {
            get
            {
                if (!m_bAvailable)
                {
                    return null;
                }

                return m_Data;
            }
        }

        //! \brief get the Upper Linear Base Address
        public UInt32 UpperLinearBaseAddress
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return ((UInt32)m_UpperLinearBaseAddress) << 16;
            }
        }

    }
    //! @}

    //! \name the Start Segment Address Record
    //! @{
    internal class StartSegmentAddressRecord : Record
    {
        private UInt32 m_StartSegmentAddress = 0;
        private Byte[] m_Data = null;

        public StartSegmentAddressRecord(Byte[] tData)
        {
            if (null == tData)
            {
                return;
            }
            else if (4 != tData.Length)
            {
                return;
            }

            m_Data = tData;

            try
            {
                Byte[] tTemp = new Byte[4];
                tTemp[0] = tData[3];
                tTemp[1] = tData[2];
                tTemp[2] = tData[1];
                tTemp[3] = tData[0];

                m_StartSegmentAddress = BitConverter.ToUInt32(tTemp, 0);
            }
            catch (Exception Err)
            {
                Err.ToString();
            }

            m_bAvailable = true;
        }

        //! \brief always return 4
        public override int RecordLength
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return 4;
            }
        }


        //! \brief get record type
        public override Record.Type RecordType
        {
            get { return Type.START_SEGMENT_ADDRESS_RECORD; }
        }

        //! \brief get data
        public override Byte[] Data
        {
            get
            {
                if (!m_bAvailable)
                {
                    return null;
                }

                return m_Data;
            }
        }

        //! \brief get start segment address
        public UInt32 StartSegmentAddress
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return m_StartSegmentAddress & 0x000FFFFF;
            }
        }

        public UInt16 CS
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return (UInt16)(m_StartSegmentAddress & 0x0000FFFF);
            }
        }

        public UInt16 IP
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return (UInt16)((m_StartSegmentAddress >> 16) & 0x000F);
            }
        }

    }
    //! @}

    /*! \note The Data Record provides a set of hexadecimal digits that represent
     *        the ASCII code for data bytes that make up a portion of a memory image.
     *        The method for calculating the absolute address (linear in the 8-bit
     *        and 32-bit case and segmented in the 16-bit case) for each byte of data
     *        is described in the discussions of the Extended Linear Address Record
     *        and the Extended Segment Address Record.
     */
    //! \name the Data Record
    //! @{
    internal class DataRecord : Record
    {
        private Byte[] m_Data = null;
        private UInt16 m_LoadOffset = 0;

        //! \brief constructor for the Data Record
        public DataRecord(UInt16 tLoadOffset, Byte[] tData)
        {
            if (null == tData)
            {
                return;
            }
            else if (tData.Length > 255)
            {
                return;
            }

            m_Data = tData;
            m_LoadOffset = tLoadOffset;

            m_bAvailable = true;
        }

        //! \brief get record data length
        public override int RecordLength
        {
            get
            {
                if (null == m_Data)
                {
                    return 0;
                }

                return m_Data.Length;
            }
        }

        //! \brief get load offset
        public override UInt16 LoadOffset
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return m_LoadOffset;
            }
        }

        //! \brief get record type
        public override Record.Type RecordType
        {
            get { return Type.DATA_RECORD; }
        }

        //! \brief get record data
        public override Byte[] Data
        {
            get
            {
                if (!m_bAvailable)
                {
                    return null;
                }

                return m_Data;
            }
        }

    }
    //! @}

    /*! \note The 16-bit Extended Segment Address Record is used to specify bits
     *        4-19 of the Segment Base Address (SBA), where bits 0-3 of the SBA
     *        are zero. Bits 4-19 of the SBA are referred to as the Upper Segment
     *        Base Address (USBA). The absolute memory address of a content byte
     *        in a subsequent Data Record is obtained by adding the SBA to an
     *        offset calculated by adding the LOAD OFFSET field of the containing
     *        Data Record to the index of the byte in the Data Record (0, 1, 2,
     *        ... n). This offset addition is done modulo 64K (i.e., 16-bits),
     *        ignoring any carry, so that offset wrap-around loading (from OFFFFH
     *        to OOOOOH) results in wrapping around from the end to the beginning
     *        of the 64K segment defined by the SBA. The address at which a
     *        particular byte is loaded is calculated as:
     *        
     *        SBA + ([DRLO + DRI] MOD 64K)
     *        
     *        where:
     *        DRLO is the LOAD OFFSET field of a Data Record.
     *        DRI is the data byte index within the Data Record.
     *        
     *        When an Extended Segment Address Record defines the value of SBA,
     *        it may appear anywhere within a 16-bit hexadecimal object file. This
     *        value remains in effect until another Extended Segment Address Record
     *        is encountered. The SBA defaults to zero until an Extended Segment
     *        Address Record is encountered.
     */
    //! \name the Extend Segment Address Record
    //! @{
    internal class ExtendSegmentAddressRecord : Record
    {
        private UInt16 m_ExtendSegmentUpperBaseAddress = 0;
        private Byte[] m_Data = null;

        public ExtendSegmentAddressRecord(Byte[] tData)
        {
            if (null == tData)
            {
                return;
            }
            else if (2 != tData.Length)
            {
                return;
            }

            m_Data = tData;

            try
            {
                Byte[] tTemp = new Byte[2];
                tTemp[0] = tData[1];
                tTemp[1] = tData[0];

                m_ExtendSegmentUpperBaseAddress = BitConverter.ToUInt16(tTemp, 0);
            }
            catch (Exception Err)
            {
                Err.ToString();
                return;
            }

            m_bAvailable = true;
        }

        //! \brief always return 2
        public override int RecordLength
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return 2;
            }
        }


        //! \brief get record type
        public override Record.Type RecordType
        {
            get { return Type.EXTEND_SEGMENT_ADDRESS_RECORD; }
        }

        //! \brief get data
        public override Byte[] Data
        {
            get
            {
                if (!m_bAvailable)
                {
                    return null;
                }

                return m_Data;
            }
        }

        //! \brief get extend segment base address
        public UInt32 ExtendSegmentBaseAddress
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return ((UInt32)m_ExtendSegmentUpperBaseAddress) << 4;
            }
        }

    }
    //! @}
   
    /*! \note The Start Linear Address Record is used to specify the execution start
     *        address for the object file. The value given is the 32-bit linear address
     *        for the EIP register. Note that this record only specifies the code
     *        address within the 32-bit linear address space of the 80386. If the code
     *        is to start execution in the real mode of the 80386, then the Start
     *        Segment Address Record should be used instead, since that record specifies
     *        both the CS and IP register contents necessary for real mode.
     */
    //! \name the Start Linear Address Record
    //! @{
    internal class StartLinearAddressRecord : Record
    {
        private UInt32 m_StartLinearAddress = 0;
        private Byte[] m_Data = null;

        public StartLinearAddressRecord(Byte[] tData)
        {
            if (null == tData)
            {
                return;
            }
            else if (4 != tData.Length)
            {
                return;
            }

            m_Data = tData;

            try
            {
                Byte[] tTemp = new Byte[4];
                tTemp[0] = tData[3];
                tTemp[1] = tData[2];
                tTemp[2] = tData[1];
                tTemp[3] = tData[0];

                m_StartLinearAddress = BitConverter.ToUInt32(tTemp, 0);
            }
            catch (Exception Err)
            {
                Err.ToString();
                return ;
            }

            m_bAvailable = true;
        }

        //! \brief always return 4
        public override Int32 RecordLength
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return 4;
            }
        }

        //! \brief get record type
        public override Record.Type RecordType
        {
            get { return Type.START_LINEAR_ADDRESS_RECORD; }
        }

        //! \brief get data
        public override Byte[] Data
        {
            get
            {
                if (!m_bAvailable)
                {
                    return null;
                }

                return m_Data;
            }
        }

        //! \brief get start linear address (EIP)
        public UInt32 StartLinearAddress
        {
            get
            {
                if (!m_bAvailable)
                {
                    return 0;
                }

                return m_StartLinearAddress;
            }
        }

    }
    //! @}
}

出0入296汤圆

 楼主| 发表于 2010-3-21 11:45:19 | 显示全部楼层
To be continue...

出0入296汤圆

 楼主| 发表于 2010-3-21 11:45:30 | 显示全部楼层
To be continue...

出0入134汤圆

发表于 2010-3-21 12:28:46 | 显示全部楼层
呵呵 C#正在学习中   

代码风格很好啊  只是还不习惯全E文  

出0入0汤圆

发表于 2010-3-21 13:25:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-21 13:38:07 | 显示全部楼层
C#~~~~~

出0入0汤圆

发表于 2011-3-22 18:59:26 | 显示全部楼层
mark!!!!!

出0入0汤圆

发表于 2011-5-6 17:28:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-5-9 19:58:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-5 14:44:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-9-5 23:40:13 | 显示全部楼层
学习!

出0入0汤圆

发表于 2011-9-11 15:24:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-10 09:38:18 | 显示全部楼层
谢谢!
正在找这个!

出0入0汤圆

发表于 2011-11-10 09:45:42 | 显示全部楼层
写过vc 6.0下的hex类, 傻孩子的这个支持大于64K的hex文件, 不错, 网上的代码基本只支持小于64K的.

出0入0汤圆

发表于 2011-11-10 10:06:26 | 显示全部楼层
前段时间我也在网上找C#的Hex控件,最后找到一个,还比较好用的。名字叫Be.Windows.Forms.HexBox,功能很全,开源的。网上搜一下就能下载到。
我已经应用到了我的程序中了。如下:

(原文件名:未命名.jpg)

(原文件名:未命名1.jpg)

出0入12汤圆

发表于 2011-11-10 10:09:55 | 显示全部楼层
好东西

出0入0汤圆

发表于 2011-11-10 16:50:23 | 显示全部楼层
好东西

出0入0汤圆

发表于 2012-1-17 21:32:17 | 显示全部楼层
学习了

出0入0汤圆

发表于 2012-1-18 10:15:26 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2012-3-6 01:35:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-5-4 10:31:42 | 显示全部楼层
shandian 发表于 2011-11-10 10:06
前段时间我也在网上找C#的Hex控件,最后找到一个,还比较好用的。名字叫Be.Windows.Forms.HexBox,功能很全 ...

试用了一下,这个控件确实不错,应该做电子的很多地方都可以用。我上传到这里吧

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-5-14 00:06:39 | 显示全部楼层
mark
學習了

出0入0汤圆

发表于 2012-5-14 21:17:47 | 显示全部楼层
學習

出0入0汤圆

发表于 2012-11-3 21:03:23 | 显示全部楼层
有没MFC的呀。

出0入0汤圆

发表于 2012-11-18 15:21:22 | 显示全部楼层
mark~~~~~~~~~~~~~~~~~~

出0入0汤圆

发表于 2012-11-25 10:09:50 | 显示全部楼层
学习了!!

出0入0汤圆

发表于 2012-11-25 16:25:10 来自手机 | 显示全部楼层
谢谢傻孩子大侠,希望您能多写一些关于C#的文章!

出0入0汤圆

发表于 2013-6-28 15:37:13 | 显示全部楼层
学习了,好东西

出0入0汤圆

发表于 2013-7-10 09:30:43 | 显示全部楼层
mark                  

出0入0汤圆

发表于 2013-7-10 10:20:14 | 显示全部楼层
傻孩子的东西不错 .  

出0入0汤圆

发表于 2013-7-20 23:47:43 | 显示全部楼层
这帖太有用报。

出0入0汤圆

发表于 2013-8-20 14:00:12 | 显示全部楼层
文件已经下载不了,楼主能不能再上传一下啊?

出0入0汤圆

发表于 2013-10-7 18:38:39 | 显示全部楼层
不错 16楼的先试试

出0入0汤圆

发表于 2013-10-7 19:04:38 | 显示全部楼层
学习了!

出0入0汤圆

发表于 2013-10-7 21:58:33 | 显示全部楼层
C# HEX文件读写,标记一下。

出0入0汤圆

发表于 2015-4-9 17:43:03 | 显示全部楼层
用附件中的HexFileStreamTester.rar,打开一个数据大小为65684字节(非hex文件本身的大小)的hex文件,显示全部为FF啊
是不是不能显示超过64K的文件?

出0入0汤圆

发表于 2017-8-29 13:38:39 | 显示全部楼层
感谢,让我柳岸花明又一村!

出0入0汤圆

发表于 2018-12-25 12:07:22 | 显示全部楼层
C# hex /HexBox
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 09:52

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表