gpt4 book ai didi

java - 创建吞吐量有限的 OutputStream

转载 作者:行者123 更新时间:2023-12-04 05:25:30 26 4
gpt4 key购买 nike

我正在通过 USB 连接将数据从我的 Java 应用程序推送到另一端的 Arduino。

Arduino 只能在其末尾缓冲 64 字节的数据,因此我必须限制从我的 Java 应用程序的每个“gulp”中发送多少字节(多余的字节将丢失)。当 Arduino 代码准备好接收更多字节时,它会发送一个简单的 ping 线路。

所以,我扩展了 BufferedOutputStream在一个类(class)ArduinoBufferedOutputStream ,它包装了实际的输出流。从 Java 应用程序的不同部分将任意数量的字节写入流(使用 write(byte b) ),并且流偶尔为 flush编。

我需要(我猜)是覆盖BufferedOutputStream s flush 方法,这样在接收到来自 Arduino 的 ping 之前,它不会发送超过 64 个字节,此时流应该发送 64 个更多字节(或更少)。

     static class ArduinoBufferedOutputStream extends BufferedOutputStream {

public static final int WIRE_CAPACITY = 25;
private byte[] waiting = new byte[0];
private int onWire = 0;

public ArduinoBufferedOutputStream(final OutputStream wrapped) throws IOException {
super(wrapped, 500);
}

public void ping() {
this.onWire = 0;
this.flush();
}

@Override
public void flush() throws IOException {
if (this.onWire >= WIRE_CAPACITY) {
return; // we're exceeding capacity, don't to anything before the next ping
}
if (this.count > WIRE_CAPACITY) {
this.waiting = new byte[this.count - WIRE_CAPACITY];
System.arraycopy(this.buf, WIRE_CAPACITY, waiting, 0, this.count - WIRE_CAPACITY);
this.buf = Arrays.copyOfRange(this.buf, 0, WIRE_CAPACITY);
this.count = WIRE_CAPACITY;
} else {
this.waiting = new byte[0];
}
onWire += this.count;
super.flush();
if (this.waiting.length > 0) {
System.arraycopy(this.waiting, 0, this.buf, 0, Math.min(this.waiting.length, WIRE_CAPACITY));
this.count = Math.min(this.waiting.length, WIRE_CAPACITY);
}
}
}

但是,这不能正常工作。如果缓冲区包含超过 WIRE_CAPACITY,则字节丢失字节,如以下测试用例所示:
@Test
public void testStream() throws IOException {
final ArduinoBufferedOutputStream stream = new ArduinoDisplayOutputStream.ArduinoBufferedOutputStream(System.out);
stream.write("This is a very, very long string, which must be made even longer to demonstrate the problem".getBytes());
stream.flush();
stream.ping();
stream.ping();
stream.ping();
stream.ping();
stream.ping();
stream.ping();
stream.ping();
stream.ping();
stream.ping();
}

打印以下字符串: This is a very, very long string, which must be ma ,而我显然希望打印整个字符串。

谁能看到我在这里做错了什么?
或者更好的是,有人知道现有的图书馆可以满足我的要求吗?

最佳答案

诚然,我对 Arduino 没有任何经验,但我在处理 Java 输出/输入流方面有很多经验。对此持保留态度,因为我无法在真正的 Arduino 设备上实际测试它,但如果我处于你的情况,这就是我会做的。

我怀疑你调用 stream.write("This is a very, very long string, which must be made even longer to demonstrate the problem".getBytes());实际上是缓冲整个字符串。当您随后调用 stream.flush() ,所有字符串数据都被一次性“写入”到 Arduino 设备。我怀疑这是因为您正在调用 BufferedOutputStream大小为 500 字节的 super 构造函数。首先,我会尝试将其减少到 64 字节。但是,我怀疑这也可能无法解决问题,因为 BufferedOutputStream不知道什么时候打电话ping .

我想你会想要同时覆盖 writeflush . flush 背后的理念,根据 Java 规范,是 flush应该强制任何未写入的缓冲字节写入底层流:

http://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#flush ()

我也可能只是扩展plain-ole OutputStream并自己做任何缓冲。我会覆盖 write方法一次缓冲最多 64 字节的数据。如果 64 字节空间不够,请调用 super.write()在填充的 64 字节缓冲区上,然后调用 super.flush()然后 ping() ,在缓冲/写入更多数据之前。在 while 循环中重复此过程,直到您的缓冲区有足够的空间来容纳输入数据的剩余部分。然后覆盖 flush写入任何没有完全填满底层 64 字节缓冲区的数据(因此实际上并没有被之前对 super.write() 的调用写入)。

这样,如果您调用 write如果数据过多,您的类(class)将写入底层流,直到最多保留 64 字节,然后您对 flush 的调用将确保最后几个字节实际写入 Arduino。归根结底,您还将获得完全符合 Java 的 OutputStream实现,这也很好。

编辑

我使用 64 字节只是因为您说您的 Arduino 一次可以处理这么多字节。当然,如果需要的话可以减少,我只是为了方便使用“64”。

关于java - 创建吞吐量有限的 OutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13240945/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com