Discussion:
Module resource as seekable byte channel?
Mark Raynsford
2018-02-04 13:31:45 UTC
Permalink
Hello.

I'm working on a problem that would seem to require accessing a
(large) resource included inside a module in random manner. More
specifically, I have some large audio resources inside a module and
need to be able to get something analogous to a SeekableByteChannel
for a given resource so that I can stream the audio and seek
forwards/backwards.

I could unpack the resources to the filesystem, but I'd prefer not to
do this (because that would then mean I'm using double the amount of
storage).

Is there some way to get access to a module resource as a
SeekableByteChannel in the standard library?

--
Mark Raynsford | http://www.io7m.com
Alan Bateman
2018-02-04 20:41:48 UTC
Permalink
Post by Mark Raynsford
Hello.
I'm working on a problem that would seem to require accessing a
(large) resource included inside a module in random manner. More
specifically, I have some large audio resources inside a module and
need to be able to get something analogous to a SeekableByteChannel
for a given resource so that I can stream the audio and seek
forwards/backwards.
I could unpack the resources to the filesystem, but I'd prefer not to
do this (because that would then mean I'm using double the amount of
storage).
Is there some way to get access to a module resource as a
SeekableByteChannel in the standard library?
The only support for random access is in the ModuleReader API where the
read method returns a ByteBuffer containing the resource. This is very
efficient for resources in modules that are linked into the runtime
image as it's essentially a slice of a memory mapped region. It's not
efficient for modules that are packaged as JAR files as random access
poses challenges there (esp. when entries in JAR file are compressed).

-Alan
Mark Raynsford
2018-02-05 17:08:06 UTC
Permalink
On 2018-02-04T20:41:48 +0000
Post by Alan Bateman
The only support for random access is in the ModuleReader API where the
read method returns a ByteBuffer containing the resource. This is very
efficient for resources in modules that are linked into the runtime
image as it's essentially a slice of a memory mapped region. It's not
efficient for modules that are packaged as JAR files as random access
poses challenges there (esp. when entries in JAR file are compressed).
OK, thanks, that's what I suspected.

I decided I could probably get away with simply being able to restart
streams rather than seeking backwards. Implementing this turned out to
be as trivial as opening the resource twice yielding streams A and B,
playing from stream A until EOF, and then playing from stream B (whilst
opening stream C in the background to act as the new stream A when B
reaches EOF). It uses a constant amount of storage (the fixed-size read
buffer per-stream) and doesn't seem to consume any extra file
descriptors (because the JVM is obviously just reading bytes from a
ZipEntry that it already has open behind the scenes).

--
Mark Raynsford | http://www.io7m.com

Loading...