2010-08-04 13 views
9

Me gustaría dividir un conjunto de bytes grande en fragmentos más pequeños (digamos 64 bytes). Por favor, ayúdame con esto.divide el conjunto en partes más pequeñas

+1

Suena similar a http://stackoverflow.com/questions/3395547/how-to-get-a-sub-array-of-array-in-java-without-copying-data/ –

Respuesta

14

Puede utilizar el método Arrays.copyOfRange (original, de, a)

public static byte[][] divideArray(byte[] source, int chunksize) { 


     byte[][] ret = new byte[(int)Math.ceil(source.length/(double)chunksize)][chunksize]; 

     int start = 0; 

     for(int i = 0; i < ret.length; i++) { 
      ret[i] = Arrays.copyOfRange(source,start, start + chunksize); 
      start += chunksize ; 
     } 

     return ret; 
    } 

o puede utilizar como Max sugirió la System.arraycopy

public static byte[][] divideArray(byte[] source, int chunksize) { 


     byte[][] ret = new byte[(int)Math.ceil(source.length/(double)chunksize)][chunksize]; 

     int start = 0; 

     for(int i = 0; i < ret.length; i++) { 
      if(start + chunksize > source.length) { 
       System.arraycopy(source, start, ret[i], 0, source.length - start); 
      } else { 
       System.arraycopy(source, start, ret[i], 0, chunksize); 
      } 
      start += chunksize ; 
     } 


     return ret; 
    } 
+0

realmente útil para mí. gracias –

+1

Tenga en cuenta que el segundo de estos parece asignar un "demasiado grande" de último fragmento si source.length no es un múltiplo par del tamaño de fragmento ... – rogerdpack

0

Ver Arrays.copyOfRange en busca de ayuda. Podría usar esto en un bucle para dividir su matriz en varios trozos más pequeños.

2

Bueno, System.arraycopy (src, fromPos, dest, toPos, length) generalmente se considera más rápido que Arrays.copyOfRange.

byte[] source = ...read it from somewhere...; 
byte[] newArray = new byte[64]; 
System.arraycopy(source, 0, newArray, 0, 64); 
+4

Esto es incorrecto: no se trata de ser más rápido, 'Arrays. copyOfRange' también asigna un nuevo 'array' mientras' System.arraycopy' solo copia los elementos en otro 'array' pasado como parámetro. Entonces con el segundo guardas la asignación ... es por eso que es más rápido. Si comprueba la definición de 'Array.copyOfRange', verá que invoca' System.arraycopy' .. – Jack

+0

Sí, acaba de verificar, tiene razón. – bezmax

1

tiene dos opciones:

  • System.arraycopy(...)
  • Array.copyOfRange(...)

ambos funcionan de la misma manera pero mientras la primera sólo se logra copiar, segundo está destinado a ser utilizado para asignar el nuevo fragmento al mismo tiempo.

les Benchmarked con un resultado que System.arraycopy es más rápido si logra asignar trozos todos juntos antes de separarse de su matriz, pero ligeramente más lento si se les asigna whle copiar: en este caso se debe utilizar Array.copyOfRange.

+0

Punto de referencia muy interesante dado que Array.copyOfRange() llama a System.arraycopy: http://pastebin.com/SpSyx8Cd – bezmax

0

Esto va a hacer ...

primer método
byte[] source = new byte[2048]; 
    byte[] target = new byte[1024]; 

// fill source with some data... 

    Array.Copy(source, buffer, 1024); 
9

Damian de Vash (el que está utilizando Arrays.copyOfRange()) añade ceros a la final del último trozo si la entrada no es exactamente un múltiplo de chunksize .

Es posible que desee utilizar en su lugar:

public static List<byte[]> divideArray(byte[] source, int chunksize) { 

    List<byte[]> result = new ArrayList<byte[]>(); 
    int start = 0; 
    while (start < source.length) { 
     int end = Math.min(source.length, start + chunksize); 
     result.add(Arrays.copyOfRange(source, start, end)); 
     start += chunksize; 
    } 

    return result; 
} 

y en caso de que sea útil, lo mismo que el uso de ArrayList:

public static List<List<String>> divideList(List<String> source, int chunksize) { 
    List<List<String>> result = new ArrayList<List<String>>(); 
    int start = 0; 
    while (start < source.size()) { 
     int end = Math.min(source.size(), start + chunksize); 
     result.add(source.subList(start, end)); 
     start += chunksize; 
    } 
    return result; 
    } 
3

Si está buscando ahorrar algo de memoria, una ligera modificación La respuesta de Damian Vash ayudaría (en este caso, cualquier trozo restante no tiene asignado un tamaño de bloque de 64 bytes completo, así ...)

private byte[][] splitChunks(byte[] source) 
{ 
    byte[][] ret = new byte[(int)Math.ceil(source.length/(double)CHUNK_SIZE)][]; 
    int start = 0; 
    for(int i = 0; i < ret.length; i++) { 
     if(start + CHUNK_SIZE > source.length) { 
      ret[i] = new byte[source.length-start]; 
      System.arraycopy(source, start, ret[i], 0, source.length - start); 
     } 
     else { 
      ret[i] = new byte[CHUNK_SIZE]; 
      System.arraycopy(source, start, ret[i], 0, CHUNK_SIZE); 
     } 
     start += CHUNK_SIZE ; 
    } 
    return ret; 
} 
Cuestiones relacionadas