[C#] Read hex data and parse to listBox

gooby pls
Decennium
Joined
Mar 22, 2008
Messages
830
Reaction score
177
I want to load a file and parse the item IDs located inside that file to a listBox. The IDs are separated from each other by 807 bytes. In between each ID there is information about each of the items.

This is how I am loading the file:
Code:
            int itemSectionStart = 0x00000008;
            int itemSectionEnd = 0x002e11ec;

            FileStream fstream = new FileStream("C:\\Users\\xxx\\Desktop\\xxx\\xxx\\xxx.cfg", FileMode.Open);
            BinaryReader breader = new BinaryReader(fstream);
            long length = fstream.Length;

            breader.BaseStream.Position = itemSectionStart;
            byte[] itemSection = breader.ReadBytes(itemSectionEnd);

Now I need to parse the IDs to a listBox.
First ID is at 0x00000008 and it's HEX value is "01", second ID is at 0x00000330 and it's HEX value is "02", third ID is at 0x00000658 and it's HEX value is "03", etc...
 
There's a couple of different ways to go about this, but to simply add to your current code:
Code:
using (MemoryStream ms = new MemoryStream(itemSection, false))
{
    using (BinaryReader br = new BinaryReader(ms))
    {
        //List<FileObject> objs = new List<FileObject>();

        // If your parsing is correct, you won't trigger end of
        // stream reading exceptions.
        while (br.BaseStream.Position < br.BaseStream.Length)
        {
            // Make a new object to hold the entry data.
            // FileObject obj = new FileObject();

            // read all the data about the item
            //obj.id = br.ReadByte();
            // < read all other fields into an object for saving>

            // Save the current object to the list for processing after
            // all have been parsed.
            //objs.Add(obj);

            // At this point, you are now at the next item,
            // the loop will take you through all the objects.
        }

        // now you can loop through all the objects and add the
        // id and object reference to your listbox.
    }
}

The FileObject type would be a class you add that contained all the fields for each item in the file. It's ok if you have "unknown fields", either make them bytes and read each byte individually in a loop, or make the unknown fields byte arrays and call ReadBytes instead.

Also, if itemSectionEnd is the end position in the file, you only want to read "itemSectionEnd - itemSectionStart" bytes. Right now, you are reading 8 extra bytes, which would cause a parsing error in the example I showed.

Lastly, if you are doing this in a non-GUI thread, you will need to use Invoke to make sure you don't cause any GUI exceptions.

The alternative method would be to not call your first "breader.ReadBytes" function and instead start parsing from there in the same way my "br" parsing logic went, except you'd make sure the position is "< itemSectionEnd" rather than the length of the stream.
 
Finally accomplished what I was looking for!
Here is the approach I took to make it work: (Might not be pretty, but it works!)

Code:
    private string hex2dec(string hexString)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(long.Parse(hexString, System.Globalization.NumberStyles.HexNumber));
        return sb.ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        int numRecords = 3737;
        int itemSectionStart = 0x00000008;
        int itemSectionEnd = 0x002e11ec;

        using (FileStream str = File.OpenRead("C:\\Users\\xxx\\Desktop\\xxx\\xxx\\xxx.dec"))
        {
            BinaryReader breader = new BinaryReader(str);
            breader.BaseStream.Position = itemSectionStart;
            byte[] itemSection = breader.ReadBytes(itemSectionEnd);

            int j = 0;
            int k = j++;
            for (int i = 0; i < numRecords; i++)
            {
                string id = BitConverter.ToString(itemSection, 808 * k++, 7);
                string[] strArrayID = id.Split(new char[] { '-' });
                string reversedID = strArrayID[6] + strArrayID[5] + strArrayID[4] + strArrayID[3] + strArrayID[2] + strArrayID[1] + strArrayID[0];
                listBox1.Items.Add(this.hex2dec(reversedID));
            }
        }
    }
 
Why on Earth are you using BitConverter.ToString, then converting that string to the equivalent decimal value...? I don't understand why you're reading an entire section into a byte array, either. There was no point in the extra overhead of creating a BinaryReader if you're only going to use it once. You also don't want to hardcode the file location, nor the number of items. Anyways, ignoring the hardcoded filename and offsets, here's how your code should look. Please learn from it instead of just copy-pasting it.

Code:
private void button1_Click(object sender, EventArgs e)
{
	int numRecords = 3737;	// Get rid of this!  Calculate the number of items.
	int itemSectionStart = 0x00000008;	// Is this always 8?  I'm guessing that it's probably preceeded by a chunk (section) identifier.
	int itemSectionEnd = 0x002e11ec;	// If it is, then this doesn't need to be hardcoded, either.  We really needed more info to help you properly, but oh well.

	var file = File.OpenRead("C:\\Users\\xxx\\Desktop\\xxx\\xxx\\xxx.dec");	// Eww...
	var reader = new BinaryReader(file);
	reader.BaseStream.Seek(itemSectionStart, SeekOrigin.Begin);	// Alternatively, use reader.ReadInt64() to skip 8 bytes.

	// Why did you have j and k here?  Both were completely useless.
	for (int i = 0; i < numRecords; i++)
	{
 		var id = reader.ReadUInt64();
		reader.BaseStream.Seek(800, SeekOrigin.Current);	// You'd probably want to read all of the other item information here, instead.
		
		listBox1.Items.Add(id.ToString());
	}
}
 
Last edited:
Item ID starts at 0x00000008 exactly, it is 7 bytes long and the next item ID begins 808 bytes after the previous item ID.
Code:
            string itemID = BitConverter.ToString(itemSection, 808 * index, 7);
            string[] strArrayID = itemID.Split(new char[] { '-' });
            string reversedID = strArrayID[6] + strArrayID[5] + strArrayID[4] + strArrayID[3] + strArrayID[2] + strArrayID[1] + strArrayID[0];
this returns the item ID in correct HEX format, ready to be converted into Decimal form.
 
That turns it into a string, ready for you to convert it again... Why you're turning it into a hex string in the first place, I do not know. It's completely unnecessary when you can just read it exactly how you need it. 7 bytes is a bit of an odd length for a numeric value. Is it usually followed by a 0? If so, it's 8 bytes. If not, just read in 8 bytes and mask the value to get rid of the byte you don't need. It's gonna be a hell of a lot cheaper than what you're doing, and makes far more sense.
 
Back