2010-08-04 12 views
9

Vorrei dividere un array di byte di grandi dimensioni in blocchi più piccoli (ad esempio 64 byte). Per favore aiutami con questo.divide la matrice in parti più piccole

+1

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

risposta

14

È possibile utilizzare il metodo Arrays.copyOfRange (originale, da, 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; 
    } 

Oppure si può usare come Max ha suggerito lo 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

sono davvero utili per me. grazie –

+1

Attenzione che il secondo di questi sembra allocare un "troppo grande" dell'ultimo chunk se source.length non è un multiplo pari del chunksize ... – rogerdpack

0

Vedere Arrays.copyOfRange per chiedere aiuto. È possibile utilizzare questo in un ciclo per dividere l'array in diversi blocchi più piccoli.

2

Bene, System.arraycopy (src, fromPos, dest, toPos, length) è generalmente considerato più veloce di Arrays.copyOfRange.

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

Questo non è corretto: non è questione di essere più veloce, 'Arrays. copyOfRange' assegna anche un nuovo 'array' mentre' System.arraycopy' copia gli elementi in un altro 'array' passato come parametro. Quindi con il secondo si salva l'allocazione .. ecco perché è più veloce. Se controlli la definizione di 'Array.copyOfRange' vedrai che richiama' System.arraycopy' .. – Jack

+0

Yup, appena controllato, hai ragione. – bezmax

1

si hanno due scelte:

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

entrambi funzionano allo stesso modo, ma mentre prima gestisce unica copia, secondo è destinato a essere utilizzato per allocare il nuovo blocco allo stesso tempo.

li ho benchmark con un risultato che System.arraycopy è più veloce se si riesce a allocare blocchi tutti insieme prima di dividere la matrice, ma leggermente più lento se li si alloca whle si copia: in questo caso si dovrebbe usare Array.copyOfRange.

+0

Benchmark molto interessante dato che Array.copyOfRange() chiama System.arraycopy: http://pastebin.com/SpSyx8Cd – bezmax

0

Questo farà ...

primo metodo
byte[] source = new byte[2048]; 
    byte[] target = new byte[1024]; 

// fill source with some data... 

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

Damiano Vash (quella che utilizza Arrays.copyOfRange()) aggiunge zeri a fine dell'ultimo pezzo se l'ingresso non è esattamente un multiplo di chunksize .

Si potrebbe desiderare di utilizzare questo, invece:

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

e nel caso in cui è utile, la stessa cosa usando di 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

Se siete alla ricerca risparmiare un po 'di memoria, una leggera modifica al La risposta di Damian Vash sarebbe di aiuto (in questo caso ogni chunk rimanente non viene allocata una dimensione completa di 64 byte, pure ...)

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; 
} 
Problemi correlati