java - 为什么我的 InputStream 保留旧值?

标签 java android inputstream

我正在向红外接收器发送一个红外信号,该信号通过 BT 模块传递到 Android 应用程序的 InputStream。每次我按下发射器上的按钮时,我都会发送 100 个 bytes 然后我希望进入 InputStream (有没有办法在没有异常时处理异常100 字节,因为数据包已损坏?)。

这是我读取 InputStream 并将值放入 byte[] 缓冲区 的代码:

 public int read(final InputStream input, final byte[] buffer) throws IOException {
        int remaining = buffer.length;
        try {
            Thread.sleep(100); // Not sure if this helps anything, just a desperate move
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (remaining > 0) {
            final int location = buffer.length - remaining;
            final int count = input.read(buffer, location, remaining);
            if (count == -1) { // EOF
                break;
            }
            remaining -= count;
        }
        return buffer.length - remaining;
    }

它有几次工作正常,但在某些时候,通常是在第 4 次尝试之后,我得到的是没有第一个字节的那些提到的字节。似乎包在某个时候已损坏并且仅发送了 99 个字节,然后随后发送了下一个字节,导致将一个字节放入先前的缓冲区并丢失了第一个字节。

但是有趣的是,数据包总是 100 字节,并且它们不是虚拟的(零值)。

这些值是加速度计坐标(并不重要)。

示例正确值:

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

示例不正确的值(第一个字节丢失也可能发生,但在这种情况下,开头多了一个字节):

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

知道怎么解决吗?请注意,如果这有助于找到解决方案,我不会在不到 3 秒内两次发送 2 个字节包。

最佳答案

InputStream 是一个非常底层的 API,您几乎不想直接使用它。在这种情况下,最适合您目的的包装器是 DataInputStream,它有一个 readFully。似乎是你想要的方法;代码更简单、更短。

public void read(final InputStream input, final byte[] buffer) throws IOException, EOFException {
  DataInputStream dataStream = new DataInputStream(input);
  dataStream.readFully(buffer, 0, buffer.length);
}

如果这不起作用,那么我怀疑问题出在 IR 本身的数据流上。


如果您需要从流中读取超时(在数据包损坏的情况下),则不建议使用此方法,因为它会阻塞,正如您已经注意到的那样。在这种情况下,我建议阅读此问题中的信息:Is it possible to read from a InputStream with a timeout?

关于java - 为什么我的 InputStream 保留旧值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32288524/

相关文章:

php - 使用 Android Volley 将数组发布到 PHP

android - 如何将 MultiAutoCompleteTextView 中的结果设置为来自 Web 源而不是静态或数据库结果?

java - 如何在Java中读取这样的输入?

java - 如何使用Java直接使用字符集对字节数组进行编码/解码/转码

java - 如何测试菜单

java - 将终端输出输入java

java - 为什么我得到 java.io.IOException : Stream Closed? (java 7)

java - 我可以在不设置环境变量的情况下使用 Maven 吗?

java - 使用 OkHttp3 WebSocket 和 Retrofit 持续跟踪 Android 设备位置

java - 了解生成线程的类上的线程和同步