none
Byte Array (write size and Read) RRS feed

  • Question

  • I am writing some content to a binary file. one item is an image, so converting image in to a byte array and writing it as below.

     BinaryWriter bw = (BinaryWriter)writer;

     WritePropertyTag(property); //IMAGE_TAG 

    bw.Write((short)(sizeofshort + imagedata.Length + (writesize ? sizeofshort : 0)));

     if (writesize)   

     { bw.Write((short)(imagedata.Length)); }     

    bw.Write(imagedata);

        

    and reads it back with the below code:

    short datasize = binReaderIn.ReadInt16();

    byte[] data = new byte[datasize];   

    binReaderIn.Read(data, 0, datasize);   

    Image img = (Bitmap)((new ImageConverter()).ConvertFrom(data));

    The above code works very well if the byte array is relatively smaller (Short numbers).

    When we want to store larger images (with approx byte array size 25k) it fails. I tried using long and int instead of short in the above code blocks and read with ReadInt32() or ReadInt64() method, but not getting the right byte array size as stored.

    No error observed while writing but while reading the array size back, getting a wrong value.

    Please help. Thanks.

    Thursday, February 13, 2020 1:07 PM

All replies

  • 25K would easily fit into a short so that isn't the issue. But looking at your writing code I don't understand all that sizeofshort + stuff. What is that supposed to be writing? If you want to store an arbitrary byte array in a stream then write the size of the array first (as an Int32) and then the byte array next. To read you do the reverse, read the length as an Int32, allocate the array and then read the bytes. Something like this.

    void WriteArray ( BinaryWriter writer, byte[] data ) 
    {
       //Write length first
       writer.Write(data.Length);
    
       //Write array
       writer.Write(data, 0, data.Length);
    }
    
    byte[] ReadArray ( BinaryReader reader )
    {
       //Read the length
       var len = reader.ReadInt32();
    
       //Should probably validate length
       return reader.ReadBytes(len);
    }
    The assumption here is that everything you're writing before that array is being properly read on the other side. You can confirm this by checking that the offset at the point you start writing the array is the same offset at the point you start reading the array. If they are different then naturally you'll be reading the wrong data. This has nothing to do with read/write of the array but the code that precedes it.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, February 13, 2020 3:14 PM
    Moderator
  • Thanks for your quick response.

    The size of the byte array is not 25K its 250K. I tried the way you suggested and for some reason still I am not getting the right data size back while reading.

    As I mentioned for smaller byte array the below works fine.

    internal static byte sizeofshort = 2;

    internal void WritePropertyBinary(SkPropertiesType property, byte[] data, bool writesize)        {            BinaryWriter bw = (BinaryWriter)writer;            WritePropertyTag(property); bw.Write((short)(sizeofshort + data.Length + (writesize ? sizeofshort : 0)));            if (writesize)            {                bw.Write((short)(data.Length));            }            bw.Write(data);        }

    We are writing many other parameters also to this file, once we find the IMAGE_TAG while reading the binary file, we will read the data size (reader.Readint16()) and it gives the short value back as saved. This is not happening when we write as Int. Badly need help here!

    Thursday, February 13, 2020 5:26 PM
  • 250K requires an int then. There really is no reason to use a short. An int will give you arrays of up 2GB in size. If you really, really need to conserve space then you could use a compressed int but I wouldn't go that route unless you have to.

    "we will read the data size (reader.Readint16()) and it gives the short value back as saved"

    You need to read/write that data as an Int32 and your problem should go away. A short isn't sufficient for anything above 32K so any data size above that would be wrong. Remove the cast to short on the write/read.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, February 13, 2020 6:14 PM
    Moderator
  • Another thread has been started for this same issue in another forum:

    Write size of a byte array (C#)
    https://social.msdn.microsoft.com/Forums/vstudio/en-US/ecbc411c-0fd4-4df9-94cc-0a1dc2d6aaa5/write-size-of-a-byte-array-c?forum=winforms

    The threads should be merged.

    - Wayne

    Thursday, February 13, 2020 7:01 PM
  • I tried saving it as int and retrieved using ReadInt32(), but still getting wrong size.

    BinaryWriter bw = (BinaryWriter)writer;            WritePropertyTag(property);   
             
    bw.Write((int)(4 + data.Length + (writesize ? 4 : 0))); 
    //4 is the size of integer, I really don't know why this statement is required, but in short case its working fine.            
    if (writesize)            
    {                
       bw.Write((int)(data.Length));            
    }            
    bw.Write(data);

    Friday, February 14, 2020 11:56 AM
  • Your code still isn't lining up with what I posted. You cannot conditionally write the length of the array because the reader could would not know whether to read or not. Tell you what, replace everything after that comment about the size of an int with a call to the method I gave you to write the array out. Then replace the corresponding call in your reader with the code I gave to read the array. Then run it and see if it works. 

    If it doesn't work then you have a mismatch between the offsets that the reader is using vs writer. Run your code again and record (in the debugger, console window, etc) the offset where you started writing the length of the array. Then run your reader code against that data and check the offset where you're starting to read the array. If they don't line up your issue is with the reader code prior to the array.

    Also, I don't understand the line of code before the writing of the array. It reads like this - take the length of the array and add 4 to it, then add another 4 if writesize is set. What exactly does this value represent? It'll either be array length + 4 (if writesize is false) or array length + 8. You are already writing the array length out in the next write so there is no benefit here. I don't understand the 4/8 thing. It's almost like you're trying to write out the size of a pointer but that isn't the correct code for this type of thing. It also wouldn't really matter in the case of this binary file. So unless you need it I'd recommend you just remove that reading/writing code.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, February 14, 2020 2:41 PM
    Moderator
  • Show us the code that WRITES, and show us the code that READS.  You're doing one of them wrong.  By the way, how will the reader know whether "writesize" was specified at write time?  If it doesn't know that, then it can't recreate the data.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Monday, February 17, 2020 12:41 AM