1

我尝试使用 BinaryWriter 然后 BinaryReader 做一些代码。当我想写时,我使用方法 Write()。但问题是在两行 Write 方法之间出现了一个新字节,它在十进制 31(sometines 24)的 ASCII 表中。你可以在这张图片上看到它:

在此处输入图像描述

您可以看到索引 4 处的字节(第 5 个字节)是 ASCII 十进制值 31。我没有将它插入那里。如您所见,前 4 个字节是为数字(Int32)保留的,接下来是其他数据(主要是一些文本 - 现在这不重要)。

正如您从我编写的代码中看到的那样: - 在第一行输入一个数字 10 - 在第二行文本中“这是一些文本......”

中间的第 5 个字节(12 月 31 日)怎么来的?

这是我的代码:

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;
                    }
                }
            }
        }
    }
4

6 回答 6

5

如果您查看 的文档Write(string),您会看到它写入了一个以长度为前缀的字符串。所以 31 是字符串中的字符数——完全正常。

于 2011-09-02T16:34:24.170 回答
3

您可能应该使用Encoding.GetBytes然后写入字节而不是写入字符串

例如

     bw.Write(
          Encoding.UTF8.GetBytes("This is some text at command " + commandNumbers[i])
     );
于 2011-09-02T16:36:05.333 回答
2

当一个字符串被写入二进制流时,它做的第一件事就是写入字符串的长度。字符串“This is some text at command 10”有 31 个字符,这是您看到的值。

于 2011-09-02T16:32:53.213 回答
1

在询问有关它们的问题之前,您应该检查您使用的方法的文档:

以长度为前缀的字符串通过在字符串前面加上一个包含该字符串长度的单个字节或单词来表示字符串长度。此方法首先将字符串的长度写入为 UTF-7 编码的无符号整数,然后使用 BinaryWriter 实例的当前编码将那么多字符写入流。

;-)

(虽然事实上它是一个LEB128而不是 UTF-7,根据维基百科)。

于 2011-09-02T16:38:22.750 回答
0

这个字节存在的原因是因为您要添加可变数量的信息,因此需要长度。如果你要添加两个字符串,你会在哪里知道第一个结束和第二个开始的地方?

如果您真的不想要或不需要那个长度字节,您可以随时将字符串转换为字节数组并使用它。

于 2011-09-02T17:20:58.690 回答
0

好的,这是我编辑的代码。我删除了 BinaryWriter(而 BinaryReader 仍然存在!!),现在它工作得很好 - 没有更多的额外字节。

你有什么事吗?有什么可以做得更好,让它跑得更快吗?特别是我对那个 foreach 循环很感兴趣,它从另一个方法中读取,它是 yield return 类型!

新代码:

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;
                    }
                }
            }
        }
    }
于 2011-09-02T17:32:27.970 回答