Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/213.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用Java读取串行信息_Java_Android_Python - Fatal编程技术网

用Java读取串行信息

用Java读取串行信息,java,android,python,Java,Android,Python,我正在移植一个已经用Python开发的Android应用程序。在Python程序中,有一行我正试图完全理解: self.comfd = Serial(...) # from the pySerial API .... self.buffer = list(struct.unpack('192H', self.comfd.read(384))) 据我所知,self.comfd.read(384)正在读取384字节,unpack('192H')正在从该数据中解压192个未签名的短消息。这是否正确

我正在移植一个已经用Python开发的Android应用程序。在Python程序中,有一行我正试图完全理解:

self.comfd = Serial(...) # from the pySerial API
....
self.buffer  = list(struct.unpack('192H', self.comfd.read(384)))
据我所知,
self.comfd.read(384)
正在读取384字节,
unpack('192H')
正在从该数据中解压192个未签名的短消息。这是否正确

现在在Java中,我已经能够使用

SerialPort device = SerialPort(file, baud, flags);
InputStream in = device.getInputStream(); 
我的问题是,现在我有了输入流,如何像Python程序那样创建无符号的短裤

我尝试过的(没有产生正确的值):

byte[]buffer=新字节[384];
in.read(缓冲区);
ByteBuffer bb=ByteBuffer.allocate(2);
对于(int i=0;i
我做错了什么?谢谢你的帮助

编辑:我合并了Jason C的答案,而且我循环错误。通过将其更改为

for(int i=0;i
解决了我的问题。

您可以使用字符(在Java中是一个16位无符号值),例如:

使用bb.order()设置big-vs.little-endian

您也可以不使用ByteBuffer将2个字节打包成一个int(假定为小endian)。字节在Java中是有符号的,因此您必须在移位之前将字节转换为无符号值,您可以通过将其临时存储在一个短值(或int或任何足以容纳0-255的大值)中来实现:

short b0=(缓冲区[0]&255);//技巧转换为无符号
短b1=(缓冲区[1]&255);

int val=b0 |(b1Java没有无符号的数字(
char
是16位无符号的,但它不是一个数字,
char
的数学运算将始终导致对
int
的隐式强制转换)

如果将2个字节的无符号数据读入
short
,并希望看到0-65535(而不是-32768-32767)范围内的值,则必须使用可以包含该范围内值的类型

对于16位
short
的情况,下一个较大的值是32位
int

short signed = ...;
int unsigned = signed & 0xFFFF;
假设
signed
的值为
0xFFFF
,则会发生以下情况:

short signed = -1; // FFFF on byte level
表达式
signed&0xFFFF
包含一个
short
和一个
int
0xFFFF
是一个文本整数类型的数字,当在Java源代码中找到它时,它被认为是
int
。您可以通过将其更改为
0xFFFF
来将其设置为
long
(如果要将无符号的
int
转换为
long
,则需要该参数)

由于
&
运算符在一个公共类型中需要两边,因此Java将静默地转换较小的类型

int stillSigned = (int) signed; // hidden step
它仍将具有完全相同的值-1,因为在查看它时,这是以前的无符号值,但它在bytelevel上更改为
0xFFFFFFFF

现在应用位操作以删除所有添加的
FF
s

int unsigned = stillSigned & 0xFFFF;
最后在字节级上得到
0x0000FFFF
,最后可以看到65535的值

由于正好有16位值,所以可以使用
char
并将其强制转换为
int

char value = ...;
int unsigned = value;
但上述方法适用于任何无符号转换:
byteValue&0xFF
shortValue&0xFFFF
intValue&0xffffff


接下来应该做的事情是不要使用简单的
InputStream
来执行

SerialPort device = SerialPort(file, baud, flags);
InputStream in = device.getInputStream(); 
byte[] buffer = new byte[384];
in.read(buffer);
原因是不能保证读取缓冲区中所需的所有字节。如果流已完成,它将返回已读取的字节数或
-1
。手动编写确保缓冲区已满的代码很麻烦,但有一个简单的解决方案:

DataInputStream
具有非常好的功能,您可以使用:

SerialPort device = SerialPort(file, baud, flags);
DataInputStream in = new DataInputStream(device.getInputStream());
int unsignedShort = in.readUnsignedShort();
字节[]
数据中获取不同数字的另一种方法是使用
ByteBuffer
,因为它提供了类似
.getShort()


我已经更新了这个答案,我以前的答案不是最好的。请注意,DataInputStream假设大端字节顺序,并且这是不能更改的。这是正确的。例如,这样做会有所帮助。或者使用
字节缓冲
方式并指定正确的
字节顺序
char value = ...;
int unsigned = value;
SerialPort device = SerialPort(file, baud, flags);
InputStream in = device.getInputStream(); 
byte[] buffer = new byte[384];
in.read(buffer);
SerialPort device = SerialPort(file, baud, flags);
DataInputStream in = new DataInputStream(device.getInputStream());
byte[] buffer = new byte[384];
in.readFully(buffer);
SerialPort device = SerialPort(file, baud, flags);
DataInputStream in = new DataInputStream(device.getInputStream());
int unsignedShort = in.readUnsignedShort();
SerialPort device = SerialPort(file, baud, flags);
DataInputStream in = new DataInputStream(device.getInputStream());
byte[] buffer = new byte[384];
in.readFully(buffer);
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer);
while (byteBuffer.hasRemaining()) {
    int unsigned = byteBuffer.getChar();
    System.out.println(unsigned);
}