[armedbear-devel] is there a good method to read/write java byte arrays?
Alessio Stalla
alessiostalla at gmail.com
Wed Mar 17 16:04:31 UTC 2010
On Wed, Mar 17, 2010 at 12:06 AM, David Kirkman <dkirkman at ucsd.edu> wrote:
> Does anybody know of a good way to serialize lisp objects into
> java byte arrays? I've got a method that almost works, but if anybody
> has a better/canonical way of doing this I'd love to know!
>
> I've been trying to use cl-store, outputting to a stream I create with
> sys::%make-byte-array-output-stream, and then getting the byte array with
> sys::%get-output-stream-bytes. I've only been using abcl for a few days,
> and I found those functions by grepping through the sources, so I apologize
> if I'm inviting trouble by messing around with functions you never meant users
> to play with.
>
> Anyway, the output works fine. But I can't find the equivalent of
> sys::%make-byte-array-output-stream to create an input stream, so I
> attempted to make my own
>
> (defun make-byte-array-input-stream (bytes)
> (let ((bis (jnew (jconstructor "java.io.ByteArrayInputStream" "[B") bytes)))
> (jnew
> (jconstructor "org.armedbear.lisp.Stream" "java.io.InputStream") bis)))
>
> This almost seems to work, but if I try to use it I get a java
> exception and a (very long) java stack trace. I put a copy of
> the stack trace at the end of this message. Here is an
> expression which will produce the problem in abcl-18.1
>
> (let ((outbytes (with-open-stream
> (stream (sys::%make-byte-array-output-stream))
> (write-byte 101 stream)
> (sys::%get-output-stream-bytes stream))))
> ;; now open the byte array as an input stream
> (with-open-stream
> (stream (make-byte-array-input-stream outbytes))
> ;; all works fine until here
> (read-byte stream)))
>
> I don't need to read the stream, asking for the element type of the input
> stream is enough to cause trouble ...
>
> (let ((outbytes (with-open-stream
> (stream (sys::%make-byte-array-output-stream))
> (write-byte 101 stream)
> (sys::%get-output-stream-bytes stream))))
> (with-open-stream
> (stream (make-byte-array-input-stream outbytes))
> (stream-element-type stream)))
>
>
> I can fix the problem and make my code work, but I have to change Stream.java
> to make it work. I added
>
> elementType = UNSIGNED_BYTE_8;
>
> to the initAsBinaryInputStream(InputStream in) method. I did this because
> the stack trace suggested that the problem was stream_element_type.execute()
> was returning null.
>
> Anyway, that fixes the problem, and I'm happily serializing/deserializing
> lisp objects to a Berkeley DB ... so I guess I'm happy! But I don't know how
> rational that fix is, because I don't really know how Stream is supposed to
> work. I suspect that my 'fix' probably breaks something else that I'm just not
> using yet.
>
> Any ideas?
I wrote sys::%make-byte-array-output-stream in order to make the
runtime compiler capable of generating bytecode without using
temporary files; it wasn't meant to be used by the ABCL user, and as
such it's not very polished (for example, the type of a
byte-array-output-stream is simply STREAM). In any case, it's defined
in the ByteArrayOutputStream Java class, and as you correctly noted,
it explicitly sets the element type to (unsigned-byte 8). As a quick
and dirty solution, you could more or less copy-paste that class and
replace "output" with "input" :) (as well as update Autoload.java to
make ABCL know of the new primitives).
We should probably polish it a bit and release it as an extension.
Alessio
> Thanks,
>
> -david k.
>
> Here's the first few lines of the stack trace ...
>
> CL-USER(2): Debugger invoked on condition of type SIMPLE-TYPE-ERROR:
> java.lang.NullPointerException
> at org.armedbear.lisp.Primitives$49.execute(Primitives.java:795)
> at org.armedbear.lisp.Symbol.execute(Symbol.java:781)
> at org.armedbear.lisp.LispThread.execute(LispThread.java:579)
> at org.armedbear.lisp.print_8.execute(print.lisp:127)
> at org.armedbear.lisp.Symbol.execute(Symbol.java:781)
> at org.armedbear.lisp.LispThread.execute(LispThread.java:579)
> at org.armedbear.lisp.print_14.execute(print.lisp:279)
>
> ... (and it ends with)
>
> at org.armedbear.lisp.AutoloadedFunctionProxy.execute(AutoloadedFunctionProxy.java:139)
> at org.armedbear.lisp.Symbol.execute(Symbol.java:760)
> at org.armedbear.lisp.LispThread.execute(LispThread.java:546)
> at org.armedbear.lisp.top_level_51.execute(top-level.lisp:415)
> at org.armedbear.lisp.AutoloadedFunctionProxy.execute(AutoloadedFunctionProxy.java:139)
> at org.armedbear.lisp.LispThread.execute(LispThread.java:546)
> at org.armedbear.lisp.Interpreter.run(Interpreter.java:310)
> at org.armedbear.lisp.Main$1.run(Main.java:50)
> at java.lang.Thread.run(Thread.java:613)
> READ-BYTE: unsupported element type
> Debugger invoked on condition of type ERROR:
> Caught java.lang.NullPointerException.
> Restarts:
> 0: TOP-LEVEL Return to top level.
>
> _______________________________________________
> armedbear-devel mailing list
> armedbear-devel at common-lisp.net
> http://common-lisp.net/cgi-bin/mailman/listinfo/armedbear-devel
>
More information about the armedbear-devel
mailing list