关于BinaryWriter或者BinaryReader中的编码和流字节序问题

本文探讨TCP/IP文件传输过程,包括文件名和大小的传送,重点在于BinaryWriter和BinaryReader在处理编码和字节序问题上的细节。字符串长度采用7bit编码,确保最高位无效,参考了mscorlib.dll中的相关代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


关于TCP/IP传送文件过程:

1. 传送文件名(有长度前缀的字符串);  2. 传送文件大小(INT64类型); 3. 传送具体内容;

其中所谓有长度前缀的字符串,就是在发送字符串之前先发送字符串的长度,收发两端都会有对长度的处理函数。而这个长度是以7bit编码的,也就是说长度数据中改到每一个字节中最高位无效。具体可参见解析了mscorlib.dll库中的System.IO.BinaryWriter的成员函数的代码,如下所示:


public virtual unsafe void Write(string value)
{
    if (value == null)
    {
        throw new ArgumentNullException("value");
    }
    int byteCount = this._encoding.GetByteCount(value);
    this.Write7BitEncodedInt(byteCount);
    if (this._largeByteBuffer == null)
    {
        this._largeByteBuffer = new byte[0x100];
        this._maxChars = 0x100 / this._encoding.GetMaxByteCount(1);
    }
    if (byteCount <= 0x100)
    {
        this._encoding.GetBytes(value, 0, value.Length, this._largeByteBuffer, 0);
        this.OutStream.Write(this._largeByteBuffer, 0, byteCount);
    }
    else
    {
        int num4;
        int num2 = 0;
        for (int i = value.Length; i > 0; i -= num4)
        {
            num4 = (i > this._maxChars) ? this._maxChars : i;
            fixed (char* str = ((char*) value))
            {
                int num5;
                char* chPtr = str;
                fixed (byte* numRef = this._largeByteBuffer)
                {
                    num5 = this._encoder.GetBytes(chPtr + num2, num4, numRef, 0x100, num4 == i);
                    str = null;
                }
                this.OutStream.Write(this._largeByteBuffer, 0, num5);
                num2 += num4;
            }
        }
    }
}
protected void Write7BitEncodedInt(int value)
{
    uint num = (uint) value;
    while (num >= 0x80)
    {
        this.Write((byte) (num | 0x80));
        num = num >> 7;
    }
    this.Write((byte) num);
}

第二步中的发送文件大小是按先发送低字节再发送高字节为顺序的,对应的解析该文件大小的函数可以是BinaryReader.ReadInt64()或BinaryReader.ReadInt32()等,其读入过程反过来,即先读入低字节再读入高字节。

测试代码如下:

using System;
using System.Collections.Generic;
using System.Text;

using System.IO;

namespace TestBinaryReaderClass_ReadString
{
    class Program
    {
        static void Main(string[] args)
        {
            string path = System.IO.Directory.GetCurrentDirectory() + "\\123.txt";
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
            BinaryReader br = new BinaryReader(fs);
            char cha;
            int num;
            double doub;
            string str;
            try
            {
                    byte[] bAll = br.ReadBytes(2000);
                    br.Close();fs.Close();
                    foreach (byte b0 in bAll)
                        Console.Write(b0.ToString() + " ");
                    Console.Write("\n\n");
                    foreach (byte b0 in bAll)
                        Console.Write(((char)b0).ToString() + " ");
                    Console.Write("\n\n");

                    fs = new FileStream(path, FileMode.Open, FileAccess.Read);
                    br = new BinaryReader(fs);
                    cha = br.ReadChar();
                    num = br.ReadInt32();
                    doub = br.ReadDouble();
                    Console.WriteLine("{0},0x{1},{2}\n", cha, num.ToString("X"), doub);
                    byte[] b = BitConverter.GetBytes(doub);
                    foreach ( byte b0 in b)
                        Console.Write(b0.ToString() + " ");
                    Console.Write("\n\n");

                    str = br.ReadString();
                    Console.WriteLine("{0},{1},{2},{3}\n", cha, num, doub, str);
            }
            catch (EndOfStreamException e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine("已经读到末尾");
            }
            finally
            {
                Console.ReadKey();
            }
        }
    }
}
其中123.txt已事先写入 其中不能解析为ASCII码的一个黑色方块是0x0a(换行符),而不是可以看见的中文换行(0x0d 0x0a或者\r\n),这个是我在UltraEdit中手动修改的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值