You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何从Stream对象获取字符串 解决蓝牙数据文本显示问题

问题根因

你现在的写法不可能正确展示设备传输的真实内容。
numBytesRead是int类型,它存储的仅仅是本次循环从流中读取到的字节总个数,不是流承载的实际业务数据。对它调用ToString()最终只会在界面上输出一个数字——比如本次读了32个字节就显示"32",和对端发来的文本内容没有任何关系。
你代码里真正存了流原始数据的是名为bytes的字节数组,要展示文本,必须把这个字节数组按照和对端约定好的字符编码转成字符串才行。

现有代码的潜在问题

你参考的是本地固定长度文件流的读取写法,直接套在蓝牙通信流上会出问题:

  • 蓝牙是流式通信,input.Length绝大多数场景拿不到准确的待读数据长度,部分实现下甚至会直接抛出“不支持该操作”的异常,上来就根据这个值初始化字节数组,很容易触发崩溃或者读不全数据
  • 循环读取时没有处理Read返回0的场景:如果Read返回0,代表对端已经主动断开了流连接,不做判断的话循环会一直跑下去触发死循环。
修正实现

首先要和蓝牙对端确认传输文本使用的字符编码,通用消费级设备大多用UTF8,老旧嵌入式设备可能用ASCII、GB2312等编码,编码不匹配会出现乱码。
可参考如下修正后的代码:

BluetoothSocket source_device = mysocket.Accept();
output = source_device.OutputStream;
input = source_device.InputStream;

// 用动态列表缓存读到的字节,不依赖流的Length属性
List<byte> buffer = new List<byte>();
byte[] readTmp = new byte[1024]; // 单次读取缓冲区大小,可根据实际传输数据量调整

while (input.IsDataAvailable())
{
    int readCount = input.Read(readTmp, 0, readTmp.Length);
    if (readCount == 0)
    {
        // 对端断开连接,跳出循环
        break;
    }
    // 追加本次读到的有效字节到缓存
    buffer.AddRange(readTmp.Take(readCount));
}

// 按约定编码转字符串,以下以UTF8为例,可根据实际协议替换
string receivedText = System.Text.Encoding.UTF8.GetString(buffer.ToArray());

// 安卓平台若在子线程执行流读取,必须切回主线程更新UI
RunOnUiThread(() => {
    _data.Text = receivedText;
});
补充说明

如果你的场景是设备持续分批次上报数据,不要等IsDataAvailable为false才转码,要提前和对端约定好帧分隔规则(比如固定帧头帧尾、特殊字符分隔、固定长度等),每凑齐一帧完整数据就转码展示,避免出现粘包、半包导致的乱码或者内容缺失。

内容的提问来源于stack exchange,提问作者TechGeek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 23:12:33