2010-08-04 26 views
9

Ich möchte ein großes Byte-Array in kleinere Stücke teilen (sagen wir 64 Bytes). Bitte hilf mir dabei.Array in kleinere Teile teilen

+1

Klingt ähnlich wie http://stackoverflow.com/questions/3395547/how-to-get-a-sub-array-of-array-in-java-without-copying-data/ –

Antwort

14

können Sie die Methode Arrays.copyOfRange verwenden (Original, von, bis)

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

Oder Sie können verwenden, wie Max das 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

es wirklich hilfreich für mich. danke –

+1

Vorsicht, die zweite scheint einen "zu großen" letzten Chunk zuzuordnen, wenn source.length kein gerades Vielfaches der Chunksize ist ... – rogerdpack

0

vorgeschlagen Siehe Arrays.copyOfRange um Hilfe. Sie können dies in einer Schleife verwenden, um Ihr Array in mehrere kleinere Blöcke aufzuteilen.

2

Nun, System.arraycopy (src, fromPos, dest, toPos, Länge) wird im Allgemeinen als schneller als Arrays.copyOfRange betrachtet.

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

Das ist falsch: es geht nicht darum schneller zu sein, 'Arrays. copyOfRange' weist auch ein neues 'array' zu, während' System.arraycopy' nur Elemente in einem anderen 'array' kopiert, das als Parameter übergeben wurde. Mit der zweiten speichern Sie die Zuordnung. Deshalb ist es schneller. Wenn Sie die Definition von 'Array.copyOfRange' überprüfen, werden Sie sehen, dass es' System.arraycopy' aufruft. – Jack

+0

Yup, nur überprüft, Sie haben Recht. – bezmax

1

Sie haben zwei Möglichkeiten:

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

sie beide die gleiche Art und Weise arbeiten, aber während erste einzige Kopie verwaltet wird zweite gemeint sein verwendet, um den neuen Chunk zur gleichen Zeit zuzuweisen.

Ich bewertete sie mit einem Ergebnis, das System.arraycopy schneller ist, wenn Sie Chunks alle zusammen vor dem Aufteilen Ihres Arrays, aber etwas langsamer zuweisen, wenn Sie sie beim Kopieren zuweisen: in diesem Fall sollten Sie Array.copyOfRange verwenden.

+0

Sehr interessante Benchmark gegeben, dass Array.copyOfRange() System.arraycopy ruft: http://pastebin.com/SpSyx8Cd – bezmax

0

Dies tun ...

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

// fill source with some data... 

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

Damian erste Methode des Vash (die mit Arrays.copyOfRange()) Nullen an das Ende des letzten Brocken hinzufügt, wenn der Eingang nicht genau ein Vielfaches von chunksize ist .

Sie könnten dies wollen stattdessen verwenden:

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

und falls es ist sinnvoll, die gleiche Sache mit Arraylist suchen:

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

Wenn Sie schauen, um etwas Speicher sparen, eine leichte Modifikation Damian Vashs Antwort würde helfen (in diesem Fall wird jedem verbleibenden Block auch keine vollständige 64-Byte-Blockgröße zugewiesen ...)

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