简体   繁体   中英

Converting an array of bytes to an array of floats

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.

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 (eg 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.

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);
}

There will always be a loop somewhere - whether it is your own, or internally inside a buffer copy method/operation. The only way of speeding things up beyond that is to find hardware and a compiler that supports vector operations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM