1

BinaryWriter と Then BinaryReader を使用してコードを実行しようとしています。書きたいときは、メソッド Write() を使用します。しかし、問題は、Write メソッドの 2 行の間に、10 進数の 31 (24 の場合もある) の ASCII テーブルにある新しいバイトが現れることです。この画像でそれを見ることができます:

ここに画像の説明を入力

インデックス 4 のバイト (5 番目のバイト) が ASCII 10 進値 31 であることがわかります。そこには挿入しませんでした。ご覧のとおり、最初の 4 バイトは数値 (Int32) 用に予約されており、次は他のデータです (主に一部のテキスト - これは重要ではありません)。

コードからわかるように、私は次のように書いています。

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 インスタンスの現在のエンコーディングを使用して、その数の文字をストリームに書き込みます。

;-)

(ウィキペディアによると、実際には UTF-7 ではなくLEB128ですが)。

于 2011-09-02T16:38:22.750 に答える
0

このバイトが存在する理由は、可変量の情報を追加しているため、長さが必要だからです。2 つの文字列を追加するとしたら、最初の文字列がどこで終わり、2 番目の文字列がどこで始まったかはどこでわかりますか?

その長さのバイトが本当に必要ない、または必要ない場合は、いつでも文字列をバイト配列に変換して使用できます。

于 2011-09-02T17:20:58.690 に答える
0

わかりました、これが私の編集されたコードです。BinaryWriter を削除しましたが (BinaryReader はまだあります!!)、今では非常にうまく機能します - 余分なバイトはもうありません。

あなたは何をしますか?より速く実行するために、より良いことはありますか? 特に、yield 戻り値の型である別のメソッドから読み取る foreach ループが興味深いです!!

新しいコード:

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 に答える