2010-08-04 3 views
9

Я хотел бы разделить большой массив байтов на более мелкие куски (скажем, 64 байта). Пожалуйста, помогите мне с этим.разделите массив на более мелкие части

+1

Звучит похоже на http://stackoverflow.com/questions/3395547/how-to-get-a-sub-array-of-array-in-java-without-copying-data/ –

ответ

14

Вы можете использовать метод Arrays.copyOfRange (оригинал, от, до)

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

Или Вы можете использовать как Макс предложил 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

Это действительно полезно для меня. спасибо –

+1

Остерегайтесь того, что второй из них, как представляется, выделяет «слишком большой» последний кусок, если source.length не является четным кратным chunksize ... – rogerdpack

0

См Arrays.copyOfRange помощи. Вы можете использовать это в цикле, чтобы разделить ваш массив на несколько небольших кусков.

2

Ну, System.arraycopy (src, fromPos, dest, toPos, length) обычно считается быстрее, чем Arrays.copyOfRange.

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

Это неверно: это не вопрос ускорения, «Массивы. copyOfRange' также выделяет новый 'array', тогда как' System.arraycopy' просто копирует элементы в другой 'array', передаваемый как параметр. Итак, со вторым вы сохраняете выделение .. поэтому он быстрее. Если вы проверите определение 'Array.copyOfRange', вы увидите, что он вызывает' System.arraycopy'. – Jack

+0

Yup, только что проверил, вы правы. – bezmax

1

У вас есть два варианта:

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

оба они работают так же, но в то время как первый один управляет только копию, второй один предназначается, чтобы быть используется для одновременного выделения нового фрагмента.

Я протестированные их с результатом, который System.arraycopy работает быстрее, если вам удастся выделить куски вместе, прежде чем разделить его массив, но немного медленнее, если вы выделяете их whle скопировать: в этом случае вы должны использовать Array.copyOfRange.

+0

Очень интересный тест, учитывая, что Array.copyOfRange() вызывает System.arraycopy: http://pastebin.com/SpSyx8Cd – bezmax

0

Это будет делать ...

первый метод
byte[] source = new byte[2048]; 
    byte[] target = new byte[1024]; 

// fill source with some data... 

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

Дамиана VASH (в один с помощью Arrays.copyOfRange()) добавляет нули к концу последнего куска, если вход не точно кратны chunksize ,

Вы можете использовать вместо этого:

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

и в случае, если это полезно, то же самое с помощью 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

Если вы хотите сохранить некоторую память, небольшая модификация для Ответ Дамиана Ваша помог бы (в этом случае любой оставшийся кусок не будет иметь полный размер блока размером в 64 байта ...)

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; 
} 
Смежные вопросы