2009-02-20 12 views
5

¿Cuál es la forma más eficiente de poner tantos bytes como sea posible desde un ByteBuffer bbuf_src en otro ByteBuffer bbuf_dest (así como saber cuántos bytes se transfirieron)? Estoy intentando bbuf_dest.put(bbuf_src) pero parece querer lanzar una BufferOverflowException y no puedo obtener los javadocs de Sun en este momento (problemas de red) cuando los necesito. > :(arghtransfiriendo bytes de un ByteBuffer a otro


edición:. Darnit, @ enfoque (uso put() de la matriz respaldo de bbuf_src) de Richard no funcionará si bbuf_src es un búfer de sólo lectura, ya que no se puede obtener acceso a esa matriz. ¿Qué puedo hacer yo en ese caso ???

+0

Creo que debe dividir esto en dos preguntas. – GEOCHET

+0

la otra mitad ha sido reubicada aquí: http://stackoverflow.com/questions/570218/downloading-sun-javadocs-mirror-websites –

Respuesta

1

bien, me he adaptado @ respuesta de Richard:

public static int transferAsMuchAsPossible(
        ByteBuffer bbuf_dest, ByteBuffer bbuf_src) 
{ 
    int nTransfer = Math.min(bbuf_dest.remaining(), bbuf_src.remaining()); 
    if (nTransfer > 0) 
    { 
    bbuf_dest.put(bbuf_src.array(), 
        bbuf_src.arrayOffset()+bbuf_src.position(), 
        nTransfer); 
    bbuf_src.position(bbuf_src.position()+nTransfer); 
    } 
    return nTransfer; 
} 

y una prueba para asegurarse de que funciona:

public static boolean transferTest() 
{ 
    ByteBuffer bb1 = ByteBuffer.allocate(256); 
    ByteBuffer bb2 = ByteBuffer.allocate(50); 
    for (int i = 0; i < 100; ++i) 
    { 
     bb1.put((byte)i); 
    } 
    bb1.flip(); 
    bb1.position(5); 
    ByteBuffer bb1a = bb1.slice(); 
    bb1a.position(2); 
    // bb3 includes the 5-100 range 
    bb2.put((byte)77); 
    // something to see this works when bb2 isn't empty 
    int n = transferAsMuchAsPossible(bb2, bb1a); 
    boolean itWorked = (n == 49); 

    if (bb1a.position() != 51) 
     itWorked = false; 
    if (bb2.position() != 50) 
     itWorked = false; 
    bb2.rewind(); 
    if (bb2.get() != 77) 
     itWorked = false; 
    for (int i = 0; i < 49; ++i) 
    { 
     if (bb2.get() != i+7) 
     { 
      itWorked = false; 
      break; 
     } 
    } 
    return itWorked; 
} 
1

Usted recibe la BufferOverflowException porque su bbuf_dest no es lo suficientemente grande.

Usted tendrá que utilizar bbuf_dest.remaining() para averiguar el número máximo de bytes que puede transferir desde bbuf_src:

int maxTransfer = Math.min(bbuf_dest.remaining(), bbuf_src.remaining()); 
bbuf_dest.put(bbuf_src.array(), 0, maxTransfer); 
+0

Ah. Eso es útil. Creo que sé qué hacer ahora. Gracias. Pero tenga en cuenta que su respuesta no funcionará si bbuf_src es un buffer de vista para otro buffer. Creo que puedo adaptarlo sin embargo. –

+0

(o si la posición de bbuf_src es> 0) –

+0

... y también tengo que actualizar la posición de bbuf_src. –

8

Como usted ha descubierto, obteniendo la matriz respaldo no siempre funciona (falla para los búferes de solo lectura, los búferes directos y los búferes de archivos mapeados en memoria). La mejor alternativa es duplicar el buffer de origen y establecer un nuevo límite para la cantidad de datos que desea transferir:

int maxTransfer = Math.min(bbuf_dest.remaining(), bbuf_src.remaining()); 
// use a duplicated buffer so we don't disrupt the limit of the original buffer 
ByteBuffer bbuf_tmp = bbuf_src.duplicate(); 
bbuf_tmp.limit (bbuf_tmp.position() + maxTransfer); 
bbuf_dest.put (bbuf_tmp); 

// now discard the data we've copied from the original source (optional) 
bbuf_src.position(bbuf_src.position() + maxTransfer); 
+0

Pero Oracle dice que el límite debe ser "no más grande que la capacidad del búfer". Duplicar un buffer duplicará su capacidad, ¿no es así? –

Cuestiones relacionadas