【问题标题】:Why does InputStreamReader giving me U-FFFD? How can I fix it?为什么 InputStreamReader 给我 U-FFFD?我该如何解决?
【发布时间】:2021-05-27 18:37:12
【问题描述】:

我正在尝试从蓝牙设备接收数据,预计该格式为:

00 FE 80 01 01 A0 0A B0 0B C0 0C D0 0D E0 0E F0 0F 00 01 02 03 04 05 06 07 08 09
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25
26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41
42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D
5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 FF FF 68 FF

我希望它在接收后转换为十进制,应该是这样的:

   0 254 128 1 1 160 10 176 11 192 12 208 13 224 14 240 15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
   16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 
   48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 
   80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 
   109 110 111 112 113 255 255 104 255

但是,我实际收到的是这种形式:

�����F���t?���������������������������������������������

如果我尝试将其转换为十六进制:

FFFD FFFD FFFD FFFD FFFD 46 06 FFFD FFFD FFFD 01 74 3F FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD 
FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD 
FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD FFFD

如果是十进制,我会得到这些:

65533 65533 65533 65533 65533 70 6 65533 65533 65533 1 116 63 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533 65533

这是使用 InputStreamReader 和 BufferedReader 读取数据的代码部分(我从 library 获得):

override fun openMessageStream(): Flowable<String> {
    checkNotClosed()
    return Flowable.create({ emitter ->
        val reader = BufferedReader(InputStreamReader(inputStream, charset))
        while (!emitter.isCancelled && !closed.get()) {
            synchronized(inputStream) {
                try {
                    val receivedString = reader.readLine()
                    if (!TextUtils.isEmpty(receivedString)) {
                        emitter.onNext(receivedString)
                    }
                } catch (e: Exception) {
                    if (!emitter.isCancelled && !closed.get()) {
                        emitter.onError(e)
                    }
                }
            }
        }
        emitter.onComplete()
    }, BackpressureStrategy.BUFFER)
}

我尝试了其他建议来更改 InputStreamReader 中使用的字符集。我已经尝试了in this documentation 列出的所有字符集,但仍然没有解决问题。

如何正确读取数据?在处理来自流阅读器的传入数据时,我应该更改哪一部分?

编辑:

我现在可以使用下面的代码并按照 Andy 的建议接收正确的值。现在我可以继续扫描开始位和结束位并获取其间的数据。我知道这段代码效率不高,我是 Java 新手,所以我非常感谢任何让这段代码变得更好的建议。

   override fun openMessageStream(): Flowable<String> {
    checkNotClosed()
        return Flowable.create({ emitter ->
            val reader = BufferedInputStream(inputStream)
            while (!emitter.isCancelled && !closed.get()) {
                synchronized(inputStream) {
                    try {
                        val receivedString = reader.read()
                        if (!TextUtils.isEmpty(receivedString.toString())) {
                            emitter.onNext(receivedString.toString())
                        }
                    } catch (e: Exception) {
                        if (!emitter.isCancelled && !closed.get()) {
                            emitter.onError(e)
                        }
                    }
                }
            }
            emitter.onComplete()
        }, BackpressureStrategy.BUFFER)
    }

【问题讨论】:

  • I am trying to receive data from bluetooth device which is expected to be in this format: 不会。发送方肯定不会发送十六进制的数据。而且也不是十进制。发送者发送的是字节。字节只有八位。现在由您决定如何显示这些位表示的值。如果你愿意,你可以用十六进制表示法或十进制表示。如果您想接收完好无损/未更改的字节,请不要使用阅读器,因为它是用于接收安迪告诉您的文本。

标签: java android kotlin bluetooth inputstreamreader


【解决方案1】:

您似乎不是在读取 二进制 数据,但您正在尝试将其作为特定字符集中的字符串读取。

FFFD 是一个替换字符,基本上是说“输入数据无法在这个字符集中解释”。

将其读取为二进制。不要使用InputStreamReader,而是将InputStream 包装在BufferedInputStream 中,然后一次读取一个块的字节。

不过,您似乎想返回 String:我无法评论您应该做什么,或者如果您真正需要的话,如何将您的字节转换为字符串。

【讨论】:

  • 谢谢你的回答,我会试试的。我实际上需要将其作为字节返回以进行进一步处理。
  • 我现在能够获得正确的数据。我用我的代码中的更改编辑了我的帖子。我认为它虽然效率不高。
猜你喜欢
  • 2020-09-14
  • 1970-01-01
  • 2019-01-14
相关资源
最近更新 更多