Hey I'm working on an app that uses Paho mqtt
嘿,我正在开发一个使用Paho mqtt的应用程序
Now I'm trying to cast the contents of a couple of objects to byte arrays so I can send them to the broker. There are a couple of different objects that all adhere to a abstract class, but the one I started with contains a double[]
现在我正在尝试将几个对象的内容转换为字节数组,以便将它们发送给代理。有几个不同的对象都遵循抽象类,但我开始使用的是一个double []
Here's the function I'm trying to implement:
这是我正在尝试实现的功能:
@Override
public byte[] getBytes() {
return Arrays.stream(driveVector).map(d -> Double.valueOf(d).byteValue()).toArray();
}
I thought this would work, but I get an error that the return value is a double[]
我认为这会工作,但我得到一个错误,返回值是双[]
I think I either don't understand the map method or I'm goin about this all wrong in general (I looked at the ByteBuffer class, but it seems like a pain to implement this with it)
我想我要么不理解map方法,要么我总是把这个都搞错了(我看了一下ByteBuffer类,但用它来实现它似乎很痛苦)
Thanks in advance
提前致谢
4 个解决方案
#1
1
You can use ByteBuffer for it:
您可以使用ByteBuffer:
double[] doubles = new double[] {1,2,3,4,5};
ByteBuffer buffer = ByteBuffer.allocate(doubles.length * Double.BYTES);
Arrays.stream(doubles).forEach(buffer::putDouble);
buffer.array();
#2
2
You can't cast a double[]
to a byte[]
for the fundamental reason that they are unrelated types, and you can only cast between related types.
由于它们是不相关的类型的基本原因,您不能将double []转换为byte [],并且只能在相关类型之间进行转换。
Casts in Java, unlike, say, C++, don't actually create a new object: they are merely a way to the compiler "I know more about the type of this object than you; trust me." For example, you might know that a variable of type Object
actually holds a reference to a String
, something which the compiler cannot know; in that case, you can cast the reference.
与C ++不同,Java中的强制转换实际上并不创建新对象:它们只是编译器的一种方式“我比你更了解这个对象的类型;相信我。”例如,您可能知道Object类型的变量实际上包含对String的引用,这是编译器无法知道的;在这种情况下,您可以转换引用。
You can, however, construct a new array:
但是,您可以构造一个新数组:
byte[] output = new byte[input.length];
for (int j = 0; j < input.length; j++) {
output[j] = (byte) input[j];
}
There is no way to do this with streams. Or rather, there is, in that you could crowbar this code into a stream operation on a Stream<double[]>
, say; but involving streams like that clearly adds no benefit.
使用流无法做到这一点。或者更确切地说,你可以将这段代码扼流到Stream
#3
0
Java Streams is not the right tool here, especially not since there is no ByteStream
in Java.
Java Streams不是正确的工具,特别是因为Java中没有ByteStream。
Your method can be implemented as a simple for
loop.
您的方法可以实现为简单的for循环。
@Override
public byte[] getBytes() {
byte[] arr = new byte[driveVector.length];
for (int i = 0; i < arr.length; i++)
arr[i] = (byte) driveVector[i];
return arr;
}
#4
0
In my MQTT application I read a single double value and post that to the broker. However, there is no real difference between a single and an array of doubles. The client needs to know the array length, while with a single value it always knows there is one.
在我的MQTT应用程序中,我读取了一个double值并将其发布到代理。但是,单个和双数组之间没有真正的区别。客户端需要知道数组长度,而使用单个值时,它总是知道有一个。
I'm confident that you can adapt my code to writing multiple values, adapt the toMessage
to write multiple double
values.
我相信你可以调整我的代码来编写多个值,调整toMessage来编写多个double值。
public abstract class SensorMonitor {
protected final MqttAsyncClient client;
protected final String topic;
protected final Logger logger = Logger.getLogger(getClass().getName());
private final ByteArrayOutputStream byteOut = new ByteArrayOutputStream(8);
private final DataOutputStream dataOut = new DataOutputStream(byteOut);
public SensorMonitor(MqttAsyncClient mqttClient, String topic) {
this.client = mqttClient;
this.topic = topic;
}
public void start(ScheduledExecutorService service) {
service.scheduleWithFixedDelay(this::publish, 0, 30, TimeUnit.SECONDS);
}
protected void publish() {
try {
MqttMessage message = toMessage(readNewValue());
client.publish(topic, message);
} catch (MqttException | IOException e) {
logger.log(Level.SEVERE, "Could not publish message", e);
}
}
private MqttMessage toMessage(double value) throws IOException {
byteOut.reset();
dataOut.writeDouble(value);
return new MqttMessage(byteOut.toByteArray());
}
protected abstract double readNewValue();
}
The DataOutputStream.writeDouble
uses Double.doubleToLongBits
to create a IEEE 754 floating-point "double format" bit layout.
DataOutputStream.writeDouble使用Double.doubleToLongBits创建IEEE 754浮点“双格式”位布局。
In my case I could pre-alloc and reuse the byteOut
output stream as I knew upfront the needed size of the byte[]
.
在我的情况下,我可以预先分配和重用byteOut输出流,因为我事先知道byte []所需的大小。
#1
1
You can use ByteBuffer for it:
您可以使用ByteBuffer:
double[] doubles = new double[] {1,2,3,4,5};
ByteBuffer buffer = ByteBuffer.allocate(doubles.length * Double.BYTES);
Arrays.stream(doubles).forEach(buffer::putDouble);
buffer.array();
#2
2
You can't cast a double[]
to a byte[]
for the fundamental reason that they are unrelated types, and you can only cast between related types.
由于它们是不相关的类型的基本原因,您不能将double []转换为byte [],并且只能在相关类型之间进行转换。
Casts in Java, unlike, say, C++, don't actually create a new object: they are merely a way to the compiler "I know more about the type of this object than you; trust me." For example, you might know that a variable of type Object
actually holds a reference to a String
, something which the compiler cannot know; in that case, you can cast the reference.
与C ++不同,Java中的强制转换实际上并不创建新对象:它们只是编译器的一种方式“我比你更了解这个对象的类型;相信我。”例如,您可能知道Object类型的变量实际上包含对String的引用,这是编译器无法知道的;在这种情况下,您可以转换引用。
You can, however, construct a new array:
但是,您可以构造一个新数组:
byte[] output = new byte[input.length];
for (int j = 0; j < input.length; j++) {
output[j] = (byte) input[j];
}
There is no way to do this with streams. Or rather, there is, in that you could crowbar this code into a stream operation on a Stream<double[]>
, say; but involving streams like that clearly adds no benefit.
使用流无法做到这一点。或者更确切地说,你可以将这段代码扼流到Stream
#3
0
Java Streams is not the right tool here, especially not since there is no ByteStream
in Java.
Java Streams不是正确的工具,特别是因为Java中没有ByteStream。
Your method can be implemented as a simple for
loop.
您的方法可以实现为简单的for循环。
@Override
public byte[] getBytes() {
byte[] arr = new byte[driveVector.length];
for (int i = 0; i < arr.length; i++)
arr[i] = (byte) driveVector[i];
return arr;
}
#4
0
In my MQTT application I read a single double value and post that to the broker. However, there is no real difference between a single and an array of doubles. The client needs to know the array length, while with a single value it always knows there is one.
在我的MQTT应用程序中,我读取了一个double值并将其发布到代理。但是,单个和双数组之间没有真正的区别。客户端需要知道数组长度,而使用单个值时,它总是知道有一个。
I'm confident that you can adapt my code to writing multiple values, adapt the toMessage
to write multiple double
values.
我相信你可以调整我的代码来编写多个值,调整toMessage来编写多个double值。
public abstract class SensorMonitor {
protected final MqttAsyncClient client;
protected final String topic;
protected final Logger logger = Logger.getLogger(getClass().getName());
private final ByteArrayOutputStream byteOut = new ByteArrayOutputStream(8);
private final DataOutputStream dataOut = new DataOutputStream(byteOut);
public SensorMonitor(MqttAsyncClient mqttClient, String topic) {
this.client = mqttClient;
this.topic = topic;
}
public void start(ScheduledExecutorService service) {
service.scheduleWithFixedDelay(this::publish, 0, 30, TimeUnit.SECONDS);
}
protected void publish() {
try {
MqttMessage message = toMessage(readNewValue());
client.publish(topic, message);
} catch (MqttException | IOException e) {
logger.log(Level.SEVERE, "Could not publish message", e);
}
}
private MqttMessage toMessage(double value) throws IOException {
byteOut.reset();
dataOut.writeDouble(value);
return new MqttMessage(byteOut.toByteArray());
}
protected abstract double readNewValue();
}
The DataOutputStream.writeDouble
uses Double.doubleToLongBits
to create a IEEE 754 floating-point "double format" bit layout.
DataOutputStream.writeDouble使用Double.doubleToLongBits创建IEEE 754浮点“双格式”位布局。
In my case I could pre-alloc and reuse the byteOut
output stream as I knew upfront the needed size of the byte[]
.
在我的情况下,我可以预先分配和重用byteOut输出流,因为我事先知道byte []所需的大小。