2

I am try to do some code using BinaryWriter and Then BinaryReader. When I wanna write I use method Write(). But the problem is that between two lines of Write method there appears a new byte which is in ASCII table in decimal 31 (sometines 24). You can see it on this image:

enter image description here

You can see that byte at index 4 (5th byte) is of ASCII decimal value 31. I didnt insert it there. As you can see 1st 4 bytes are reserved for a number (Int32), next are other data (some text mostly - this is not important now).

As you can see from the code i write: - into 1st line a number 10 - into 2nd line text "This is some text..."

How come came that 5th byte (dec 31) in between??

And this is the code I have:

static void Main(string[] args)
    {           
        //
        //// SEND - RECEIVE:
        //
        SendingData();
        Console.ReadLine();
    }

    private static void SendingData()
    {
        int[] commandNumbers = { 1, 5, 10 }; //10 is for the users (when they send some text)!

        for (int i = 0; i < commandNumbers.Length; i++)
        {
            //convert to byte[]
            byte[] allBytes;
            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    bw.Write(commandNumbers[i]);   //allocates 1st 4 bytes - FOR MAIN COMMANDS!
                    if (commandNumbers[i] == 10)
                        bw.Write("This is some text at command " + commandNumbers[i]); //HERE ON THIS LINE IS MY QUESTION!!!
                }
                allBytes = ms.ToArray();
            }

            //convert back:
            int valueA = 0;
            StringBuilder sb = new StringBuilder();
            foreach (var b in GetData(allBytes).Select((a, b) => new { Value = a, Index = b }))
            {
                if (b.Index == 0) //1st num
                    valueA = BitConverter.ToInt32(b.Value, 0);
                else //other text
                {
                    foreach (byte _byte in b.Value)
                        sb.Append(Convert.ToChar(_byte));
                }
            }

            if (sb.ToString().Length == 0)
                sb.Append("ONLY COMMAND");
            Console.WriteLine("Command = {0} and Text is \"{1}\".", valueA, sb.ToString());
        }
    }

    private static IEnumerable<byte[]> GetData(byte[] data)
    {
        using (MemoryStream ms = new MemoryStream(data))
        {
            using (BinaryReader br = new BinaryReader(ms))
            {
                int j = 0;
                byte[] buffer = new byte[4];
                for (int i = 0; i < data.Length; i++)
                {
                    buffer[j++] = data[i];
                    if (i == 3) //SENDING COMMAND DATA
                    {
                        yield return buffer;
                        buffer = new byte[1];
                        j = 0;
                    }
                    else if (i > 3) //SENDING TEXT
                    {
                        yield return buffer;
                        j = 0;
                    }
                }
            }
        }
    }
1
  • 2
    Side note: You're creating and destroying a writer and stream each time through your loop Commented Sep 2, 2011 at 16:32

6 Answers 6

5

If you look at the documentation for Write(string), you'll see that it writes a length-prefixed string. So the 31 is the number of characters in your string -- perfectly normal.

Sign up to request clarification or add additional context in comments.

2 Comments

:) This is it. Just the point is that I dont want that byte. So it would be better to avoid BinaryWriter method.... the point is I wanna create an application server-client, where will be many possibilities, like chat, new game, join game, ... and 1st bytes (so in Int32) will be reserved for the command, next bytes will be the rest, like text (chat between users).
Perhaps a library like lidgren would be better suited to your needs?
3

You should probably be using Encoding.GetBytes and then write the bytes instead of writing a string

for example

     bw.Write(
          Encoding.UTF8.GetBytes("This is some text at command " + commandNumbers[i])
     );

3 Comments

So no BinaryReader in my code any longer? Do you mind showing me an example? And thx guys for a great and simple answers. It really does writh the Lenght of the whole string into the byte just before string.
@Mitja I clarified what I meant by adding a sample
Thank you very much. I know how to get bytes already. I will show you my new version as soon as its over (soon). The point is to learn how to seperated messages... I will be using this code for Server-Client application. So I have to seperate comamnds from normal text.
2

When a string is written to a binary stream, the first thing it does is write the length of the string. The string "This is some text at command 10" has 31 characters, which is the value you're seeing.

Comments

1

You should check the documentation of methods you use before asking questions about them:

A length-prefixed string represents the string length by prefixing to the string a single byte or word that contains the length of that string. This method first writes the length of the string as a UTF-7 encoded unsigned integer, and then writes that many characters to the stream by using the BinaryWriter instance's current encoding.

;-)

(Though in fact it is an LEB128 and not UTF-7, according to Wikipedia).

Comments

0

The reason this byte is there because you're adding a variable amount of information, so the length is needed. If you were to add two strings, where would you know where the first ended and the second began?

If you really don't want or need that length byte, you can always convert the string to a byte array and use that.

Comments

0

Ok, here is my edited code. I removed BinaryWriter (while BinaryReader is still there!!), and now it works very well - no more extra bytes.

What do you thing? Is there anytihng to do better, to make it run faster? Expecially Im interesting for that foreach loop, which read from another method that is yield return type!!

New Code:

static void Main(string[] args)
    {           
        //
        //// SEND - RECEIVE:
        //
        SendingData();
        Console.ReadLine();
    }

    private static void SendingData()
    {
        int[] commands = { 1, 2, 3 }; 
        // 1 - user text
        // 2 - new game
        // 3 - join game
        // ...

        for (int i = 0; i < commands.Length; i++)
        {
            //convert to byte[]
            byte[] allBytes;
            using (MemoryStream ms = new MemoryStream())
            {
                // 1.st - write a command:
                ms.Write(BitConverter.GetBytes(commands[i]), 0, 4);
                // 2nd - write a text:                                         
                if (commands[i] == 1)
                {
                    //some example text (like that user sends it):
                    string myText = "This is some text at command " + commands[i];
                    byte[] myBytes = Encoding.UTF8.GetBytes(myText);
                    ms.Write(myBytes, 0, myBytes.Length);
                }
                allBytes = ms.ToArray();
            }

            //convert back:
            int valueA = 0;
            StringBuilder sb = new StringBuilder();
            foreach (var b in ReadingData(allBytes).Select((a, b) => new { Value = a, Index = b }))
            {
                if (b.Index == 0)
                {
                    valueA = BitConverter.ToInt32(b.Value, 0);
                }
                else
                {
                    sb.Append(Convert.ToChar(b.Value[0]));
                }
            }

            if (sb.ToString().Length == 0)
                sb.Append("ONLY COMMAND");
            Console.WriteLine("Command = {0} and Text is \"{1}\".", valueA, sb.ToString());
        }            
    }

    private static IEnumerable<byte[]> ReadingData(byte[] data)
    {
        using (MemoryStream ms = new MemoryStream(data))
        {
            using (BinaryReader br = new BinaryReader(ms))
            {
                int j = 0;
                byte[] buffer = new byte[4];
                for (int i = 0; i < data.Length; i++)
                {
                    buffer[j++] = data[i];
                    if (i == 3) //SENDING COMMAND DATA
                    {
                        yield return buffer;
                        buffer = new byte[1];
                        j = 0;
                    }
                    else if (i > 3) //SENDING TEXT
                    {
                        yield return buffer;
                        j = 0;
                    }
                }
            }
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.