vote up 1 vote down star

I'm currently converting a Delphi method used for random binary file access into Java. The Delphi procedure uses:

TSingleArray  = Array[0..MAXSIZE] of Single
...
procedure GetLinkValues(const LinkVar: Integer;  const TimePeriod: Integer; var Value: PSingleArray);
...
BlockRead(Fout, Value^, Nlinks*SizeOf(Single));

To read an array of bytes into an array of Single. Is there an equivalent way of doing this in Java without iterating through the array?

I’m currently using

List<Float> l = new ArrayList<Float>();
…
for (int i = 0 ; i < nLinks ; i++ )
l.add( resultsFile.readFloat());

But I’m concerned about speed. Endianness is not a problem.

flag

2 Answers

vote up 2 vote down check

Have you profiled the code and actually found it to be a problem? Something is going to have to loop... are you really sure this is a bottleneck in your code?

Having said all that, you should be able to use a FloatBuffer which I suspect does what you want. Unfortunately Sun's JavaDoc is down, so I can't easily link to or check the documentation at the minute.

To use a FloatBuffer, you'd probably want to:

  • Create a FileChannel associated with the file (e.g. with FileInputStream.getChannel)
  • Create a ByteBuffer
  • Create a FloatBuffer wrapping the ByteBuffer, with ByteBuffer.asFloatBuffer
  • Read into the ByteBuffer with FileChannel.read(byteBuffer)
  • Read from the FloatBuffer

I'm not particularly familiar/comfortable with java.nio, so I hope this is all correct - but it's likely to be pretty fiddly. Your current loop is almost certainly simpler, so I strongly suggest you check the performance of that first! You might want to wrap your current FileInputStream in a BufferedInputStream, btw.

link|flag
Works for me, at least the third time I tried. java.sun.com/javase/6/docs/api/java/nio/… – mmyers Feb 20 '09 at 17:01
Still down for me. I think it must be a net split... – Jon Skeet Feb 20 '09 at 17:02
I think that means that the answer is no. What I was looking for was a way of replicating the pointer operation in Java, filling an array of Simple (float) with bytes as I believe (perhaps incorrectly) that this avoids iteration. Later I can read values using myArray[n] – GrahamA Feb 20 '09 at 17:28
@GrahamA: You can do block copies using a FloatBuffer, which will be efficient - but then the code will be more complicated. Basically you can have efficiency or simplicity, but not both. Have you tested the simple code for speed yet? – Jon Skeet Feb 20 '09 at 17:31
Profiled using System.currentTimeMillis() and a 65Mb file. Reading 27446 records. List<float> 140 Milliseconds ByteBuffer 0 Iteration through he list and byte buffer (after conversion to array) is 16ms. I have tried several different size results files and I’m getting consistent answers. – GrahamA Feb 23 '09 at 11:39
show 1 more comment
vote up 0 vote down

Based on the help provided by Jon the final code looks like this:

    byte[] bt = new byte[nLinks * 4];
    List<Float> l = new ArrayList<Float>();
	if (linkVar != 0 && timePeriod < nPeriods ){
		long p1 = RECORDSIZE*(nNodes*NODEVARS + nLinks*LINKVARS);
		long p2 = RECORDSIZE*(nNodes*NODEVARS + nLinks*(linkVar-1));
		long p3 = offset2 + (timePeriod*p1) + p2;
		resultsFile.seek(p3);

		resultsFile.read( bt, 0, nLinks * 4);
		ByteBuffer bb = ByteBuffer.wrap(bt);
		bb.rewind();
		bb.asFloatBuffer().get(values);
    }
link|flag

Your Answer

Get an OpenID
or
never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.