使用动态缓冲区?Java

4
在Java中,我有一个方法。
public int getNextFrame( byte[] buff )

这段代码从一个文件中读取内容到缓冲区,并返回读取的字节数。我正在读取一个.MJPEG文件,它有一个5字节的值,比如“07939”,后面跟着相应数量的jpeg数据。

问题在于JPEG字节大小可能会超过缓冲区的容量。我找不到一个简洁的解决方案来分配内存。我的目标是不为每个图像创建一个新的缓冲区。我尝试了直接使用ByteBuffer,以便可以使用其array()方法直接访问底层缓冲区,但是ByteBuffer不会动态扩展。

我应该返回参数的引用吗?像这样:

public ByteBuffer getNextFrame( ByteBuffer ref )

我该如何找到已读取的字节数?谢谢。

4个回答

1

java.io.ByteArrayOutputStream 是一个围绕字节数组的包装器,并根据需要扩大它。也许这是你可以使用的东西。

编辑:
要重用,只需调用reset()并重新开始...


诀窍在于使其可重用。 ;) 但是你可以创建自己的可重用代码。 - Peter Lawrey
1
你可以重复使用 ByteArrayOutputStream,只需调用 reset() 方法即可... - Boris
然而,toByteArray() 仍然会复制结果,这可能是不希望的。 - Peter Lawrey
你可以扩展ByteArrayOutputStream以直接获取缓冲区,这是类的一个定义部分,只是受保护的。如果需要,你必须在其上自行同步,并记住这是完整的数组,包括尚未写入的字节。但如果内存使用/性能很重要,这是可以处理的。你也会在其他方法中遇到类似的限制。 - Boris
好的。所以java.io.ByteArrayOutputStream会动态增长;为了避免使用toByteArray(),这会复制缓冲区,我需要扩展该类。感谢您的建议!比我预期的要多得多(我是新手)--令人印象深刻。 - LJWolfe

1

只需读取所需的字节数。不要使用read(buffer),而是使用read(buffer,0,size)。如果有更多的字节,只需丢弃它们,因为JPG已经损坏了。


0

编辑:

分配一个byte[]比从文件或套接字读取要快得多,除非你的系统微秒成本很高,否则我会感到惊讶它会有太大的区别。

读取64 KB文件所需的时间约为10毫秒(除非文件在内存中)

分配64 KB byte[]所需的时间约为0.001毫秒,可能更快。


你可以使用Apache IO的IOBuffer,但是这会非常昂贵。

你也可以使用ByteBuffer,position()会告诉你读取了多少数据。

如果你不知道缓冲区的大小,并且你有一个64位的JVM,你可以创建一个大的直接缓冲区。只有在使用时才会分配内存(按页)。好处是你可以分配1GB,但如果你只需要4KB,那么可能只会使用4KB。直接缓冲区不支持array(),但是你可以使用它的其他方法从ByteBuffer中读取。

另一种解决方案是使用AtomicReference<byte[]>,被调用的方法可以根据需要增加大小,但如果足够大,则会重用以前的缓冲区。


-1
在高级API中实现这一点的常规方法是让用户提供一个OutputStream并用您的数据填充它(可以是ByteArrayOutputStream或完全不同的内容),或者返回一个InputStream,用户可以读取以获取数据(这将动态加载文件的正确部分,并在完成时停止)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接