8

ByteBuffer offers asFloatBuffer() function. However, there is no equivalent FloatBuffer.asByteBuffer()

I am trying to do:

float[] array = ...
try( ByteChannel channel = Files.newByteChannel( path, WRITE, CREATE, TRUNCATE_EXISTING ) ) {
    channel.write (FloatBuffer.wrap (array) .asByteBuffer());
}

Is there a way of efficiently doing this, or do I have to resort to allocating a ByteBuffer as in:

ByteBuffer buffer = ByteBuffer.allocate( array.length * 4 );
buffer .asFloatBuffer() .put (array);
channel.write (buffer);
Aleksandr Dubinsky
  • 22,436
  • 15
  • 82
  • 99
  • Does this answer suit to you? http://stackoverflow.com/questions/7298997/convert-from-floatbuffer-to-byte – ServerSideCat Dec 15 '14 at 20:14
  • @ServerSideCat He is already doing what that answers says to do. – markbernard Dec 15 '14 at 20:29
  • 1
    You are correct. There is no other way to do it. – markbernard Dec 15 '14 at 20:30
  • I actually wasted a lot of time trying to figure out how to do this seemingly simple task. Being a C programmer, I was pretty shocked to realize there's no easy way to do it without a for loop. The only alternative I found was starting with a `ByteBuffer`, and then creating my array (e.g. float[]) as a view into the `ByteBuffer`, e.g. `bb.asFloatBuffer`. That's the price you pay for abstraction. – orodbhen Jul 22 '17 at 12:43

1 Answers1

1

For a HeapFloatBuffer, ie created by FloatBuffer.allocate or FloatBuffer.wrap, there is no easy solution. A custom class extending ByteBuffer needs to be written.

For direct buffers in HotSpot 8, this will work in the trivial case:

FloatBuffer floatBuffer = ByteBuffer.allocateDirect (...).asFloatBuffer();
ByteBuffer byteBuffer = (ByteBuffer) ((sun.nio.ch.DirectBuffer)floatBuffer).attachment();

For other situations, use the following. Note that this class is declared in package java.nio. This also probably will only work in HotSpot 8.

package java.nio;

/**
 *
 * @author Aleksandr Dubinsky
 */
public class BufferUtils {

      public static ByteBuffer
    asByteBuffer (FloatBuffer floatBuffer) {

            if (floatBuffer instanceof DirectFloatBufferU)
            {
                DirectFloatBufferU buffer = (DirectFloatBufferU) floatBuffer;
                return (ByteBuffer) new DirectByteBuffer (buffer.address(), floatBuffer.capacity() * Float.BYTES, buffer)
                                            .position (floatBuffer.position() * Float.BYTES)
                                            .limit (floatBuffer.limit() * Float.BYTES);
            }
            else if (floatBuffer instanceof DirectFloatBufferS)
            {
                DirectFloatBufferS buffer = (DirectFloatBufferS) floatBuffer;
                return (ByteBuffer) new DirectByteBuffer (buffer.address(), floatBuffer.capacity() * Float.BYTES, buffer)
                                            .position (floatBuffer.position() * Float.BYTES)
                                            .limit (floatBuffer.limit() * Float.BYTES);
            }
            else if (floatBuffer instanceof ByteBufferAsFloatBufferB)
            {
                ByteBufferAsFloatBufferB buffer = (ByteBufferAsFloatBufferB)floatBuffer;
                return (ByteBuffer) ((ByteBuffer) buffer.bb
                                                        .duplicate()
                                                        .position (buffer.offset)
                                                        .limit (buffer.offset + buffer.capacity() * Float.BYTES))
                                                        .slice()
                                                        .position (buffer.position() * Float.SIZE)
                                                        .limit (buffer.limit() * Float.BYTES);
            }
            else if (floatBuffer instanceof ByteBufferAsFloatBufferL)
            {
                ByteBufferAsFloatBufferL buffer = (ByteBufferAsFloatBufferL)floatBuffer;
                return (ByteBuffer) ((ByteBuffer) buffer.bb
                                                        .duplicate()
                                                        .position (buffer.offset)
                                                        .limit (buffer.offset + buffer.capacity() * Float.BYTES))
                                                        .slice()
                                                        .position (buffer.position() * Float.SIZE)
                                                        .limit (buffer.limit() * Float.BYTES);
            }
            else
                throw new IllegalArgumentException ("Unsupported implementing class " + floatBuffer.getClass().getName());
        }

}
Aleksandr Dubinsky
  • 22,436
  • 15
  • 82
  • 99
  • 1
    hm, since FloatBuffer is only a view and when you can create the BB first, you could use `ByteBuffer bb = ByteBuffer,allocate(); FloatBuffer fb = bb.asFloatBuffer();`, they share the same backing. – eckes Jan 21 '15 at 23:14
  • @eckes The question assumes you've lost the reference to the original ByteBuffer. – Aleksandr Dubinsky Jan 22 '15 at 15:20