1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package ubic.basecode.io;
20
21 import org.apache.commons.lang3.ArrayUtils;
22 import org.apache.commons.lang3.StringUtils;
23
24 import java.lang.reflect.Array;
25 import java.nio.*;
26 import java.nio.charset.Charset;
27 import java.util.ArrayList;
28 import java.util.List;
29
30
31
32
33
34
35
36 public final class ByteArrayConverter {
37
38
39
40
41 private static final int DOUBLE_SIZE = 8;
42
43 public byte[] booleanArrayToBytes( boolean[] boolarray ) {
44 if ( boolarray == null ) return null;
45 ByteBuffer buffer = ByteBuffer.allocate( boolarray.length );
46 for ( boolean b : boolarray ) {
47 buffer.put( b ? ( byte ) 1 : ( byte ) 0 );
48 }
49 return buffer.array();
50 }
51
52 public boolean[] byteArrayToBooleans( byte[] barray ) {
53 if ( barray == null ) return null;
54 boolean[] iarray = new boolean[barray.length];
55 for ( int i = 0; i < barray.length; i++ ) {
56 iarray[i] = barray[i] != 0;
57 }
58 return iarray;
59 }
60
61 public byte[] doubleArrayToBytes( double[] darray ) {
62 if ( darray == null ) {
63 return null;
64 }
65 ByteBuffer buffer = ByteBuffer.allocate( 8 * darray.length );
66 for ( double d : darray ) {
67 buffer.putDouble( d );
68 }
69 return buffer.array();
70 }
71
72 public double[] byteArrayToDoubles( byte[] barray ) {
73 if ( barray == null ) return null;
74 DoubleBuffer buf = ByteBuffer.wrap( barray ).asDoubleBuffer();
75 double[] array = new double[buf.remaining()];
76 buf.get( array );
77 return array;
78 }
79
80 public byte[] doubleMatrixToBytes( double[][] testm ) {
81 if ( testm == null ) {
82 return null;
83 }
84 if ( testm.length == 0 ) {
85 return new byte[0];
86 }
87 int rowSize = testm[0].length;
88 double[] a = new double[testm.length * rowSize];
89 for ( int i = 0; i < testm.length; i++ ) {
90 if ( testm[i].length != rowSize ) {
91 throw new IllegalArgumentException( "Cannot serialize ragged matrix" );
92 }
93 System.arraycopy( testm[i], 0, a, rowSize * i, rowSize );
94 }
95 return doubleArrayToBytes( a );
96 }
97
98
99
100
101 public double[][] byteArrayToDoubleMatrix( byte[] barray ) {
102 if ( barray == null ) {
103 return null;
104 }
105 int numDoubles = barray.length / DOUBLE_SIZE;
106 int columns = ( int ) Math.sqrt( numDoubles );
107 if ( columns * columns != barray.length / DOUBLE_SIZE ) {
108 throw new IllegalArgumentException( "The byte array is not square." );
109 }
110 return byteArrayToDoubleMatrix( barray, columns );
111 }
112
113
114
115
116
117
118 public double[][] byteArrayToDoubleMatrix( byte[] barray, int columns ) throws IllegalArgumentException {
119 if ( barray == null ) {
120 return null;
121 }
122 if ( barray.length == 0 ) {
123 return new double[0][columns];
124 }
125 int numDoubles = barray.length / DOUBLE_SIZE;
126 if ( numDoubles % columns != 0 ) {
127 throw new IllegalArgumentException( "The number of doubles in the byte array (" + numDoubles
128 + ") does not divide evenly into the number of items expected per row (" + columns + ")." );
129 }
130 int numRows = numDoubles / columns;
131 double[][] answer = new double[numRows][];
132 byte[] row = new byte[columns * DOUBLE_SIZE];
133 int bytesPerRow = columns * DOUBLE_SIZE;
134 for ( int rownum = 0; rownum < numRows; rownum++ ) {
135 System.arraycopy( barray, rownum * bytesPerRow, row, 0, bytesPerRow );
136 answer[rownum] = byteArrayToDoubles( row );
137 }
138 return answer;
139 }
140
141
142
143
144
145
146
147 public byte[] stringArrayToBytes( String[] stringArray, Charset charset ) {
148 if ( stringArray == null ) return null;
149 int size = 0;
150 for ( String element : stringArray ) {
151 size += element != null ? element.getBytes( charset ).length : 0;
152 size += 1;
153 }
154 ByteBuffer buffer = ByteBuffer.allocate( size );
155 for ( String element : stringArray ) {
156 if ( element != null ) {
157 buffer.put( element.getBytes( charset ) );
158 }
159 buffer.put( ( byte ) 0 );
160 }
161 return buffer.array();
162 }
163
164
165
166
167
168
169
170
171
172
173 public String[] byteArrayToStrings( byte[] bytes, Charset charset ) {
174 if ( bytes == null ) {
175 return null;
176 }
177 List<String> strings = new ArrayList<>();
178 int len = 0;
179 for ( int i = 0; i < bytes.length; i++ ) {
180 byte element = bytes[i];
181 if ( element == '\u0000' ) {
182 strings.add( new String( bytes, i - len, len, charset ) );
183 len = 0;
184 } else {
185 len++;
186 }
187 }
188 return strings.toArray( new String[0] );
189 }
190
191
192
193
194
195
196
197
198
199
200 public byte[] stringArrayToTabbedBytes( String[] strings, Charset charset ) {
201 if ( strings == null ) return null;
202 String[] escapedStrings = new String[strings.length];
203 for ( int i = 0; i < strings.length; i++ ) {
204 escapedStrings[i] = formatAsTabbedString( strings[i] );
205 }
206 return StringUtils.join( escapedStrings, '\t' ).getBytes( charset );
207 }
208
209 public String[] byteArrayToTabbedStrings( byte[] bytes, Charset charset ) {
210 if ( bytes == null ) return null;
211 return StringUtils.splitPreserveAllTokens( new String( bytes, charset ), '\t' );
212 }
213
214
215
216
217
218
219
220
221
222 public String byteArrayToTabbedString( byte[] bytes, Class<?> type, Charset charset ) {
223 if ( bytes == null ) return null;
224 if ( type.equals( Float.class ) ) {
225 Float[] array = ArrayUtils.toObject( byteArrayToFloats( bytes ) );
226 return formatAsTabbedString( array );
227 } else if ( type.equals( Double.class ) ) {
228 Double[] array = ArrayUtils.toObject( byteArrayToDoubles( bytes ) );
229 return formatAsTabbedString( array );
230 } else if ( type.equals( Integer.class ) ) {
231 Integer[] array = ArrayUtils.toObject( byteArrayToInts( bytes ) );
232 return formatAsTabbedString( array );
233 } else if ( type.equals( Long.class ) ) {
234 Long[] array = ArrayUtils.toObject( byteArrayToLongs( bytes ) );
235 return formatAsTabbedString( array );
236 } else if ( type.equals( String.class ) ) {
237 return new String( bytes, charset );
238 } else if ( type.equals( Boolean.class ) ) {
239 Boolean[] array = ArrayUtils.toObject( byteArrayToBooleans( bytes ) );
240 return formatAsTabbedString( array );
241 } else if ( type.equals( Character.class ) ) {
242 Character[] array = ArrayUtils.toObject( byteArrayToChars( bytes ) );
243 return formatAsTabbedString( array );
244 } else {
245 throw new UnsupportedOperationException( "Can't convert " + type.getName() );
246 }
247 }
248
249 private String formatAsTabbedString( Object[] array ) {
250 StringBuilder buf = new StringBuilder();
251 for ( int i = 0; i < array.length; i++ ) {
252 buf.append( formatAsTabbedString( array[i] ) );
253 if ( i != array.length - 1 ) buf.append( "\t" );
254 }
255 return buf.toString();
256 }
257
258 private String formatAsTabbedString( Object object ) {
259 if ( object == null ) {
260 return "";
261 }
262 return String.valueOf( object )
263 .replace( "\t", "\\t" );
264 }
265
266 public byte[] charArrayToBytes( char[] carray ) {
267 if ( carray == null ) return null;
268 ByteBuffer buffer = ByteBuffer.allocate( 2 * carray.length );
269 for ( char c : carray ) {
270 buffer.putChar( c );
271 }
272 return buffer.array();
273 }
274
275 public char[] byteArrayToChars( byte[] barray ) {
276 if ( barray == null ) return null;
277 CharBuffer buf = ByteBuffer.wrap( barray ).asCharBuffer();
278 char[] array = new char[buf.remaining()];
279 buf.get( array );
280 return array;
281 }
282
283 public byte[] floatArrayToBytes( float[] darray ) {
284 if ( darray == null ) {
285 return null;
286 }
287 ByteBuffer buffer = ByteBuffer.allocate( 4 * darray.length );
288 for ( float d : darray ) {
289 buffer.putFloat( d );
290 }
291 return buffer.array();
292 }
293
294 public float[] byteArrayToFloats( byte[] barray ) {
295 if ( barray == null ) return null;
296 FloatBuffer buf = ByteBuffer.wrap( barray ).asFloatBuffer();
297 float[] array = new float[buf.remaining()];
298 buf.get( array );
299 return array;
300 }
301
302 public byte[] intArrayToBytes( int[] iarray ) {
303 if ( iarray == null ) {
304 return null;
305 }
306 ByteBuffer buffer = ByteBuffer.allocate( 4 * iarray.length );
307 for ( int i : iarray ) {
308 buffer.putInt( i );
309 }
310 return buffer.array();
311 }
312
313 public int[] byteArrayToInts( byte[] barray ) {
314 if ( barray == null ) return null;
315 IntBuffer intBuf = ByteBuffer.wrap( barray ).asIntBuffer();
316 int[] array = new int[intBuf.remaining()];
317 intBuf.get( array );
318 return array;
319 }
320
321 public byte[] longArrayToBytes( long[] larray ) {
322 if ( larray == null ) {
323 return null;
324 }
325 ByteBuffer buffer = ByteBuffer.allocate( 8 * larray.length );
326 for ( long i : larray ) {
327 buffer.putLong( i );
328 }
329 return buffer.array();
330 }
331
332
333
334
335 public long[] byteArrayToLongs( byte[] barray ) {
336 if ( barray == null ) return null;
337 LongBuffer buf = ByteBuffer.wrap( barray ).asLongBuffer();
338 long[] array = new long[buf.remaining()];
339 buf.get( array );
340 return array;
341 }
342
343
344
345
346
347
348
349
350 public <T> byte[] objectArrayToBytes( T[] array, Charset charset ) {
351 if ( array == null ) return null;
352 if ( array instanceof Boolean[] ) {
353 return booleanArrayToBytes( ArrayUtils.toPrimitive( ( Boolean[] ) array ) );
354 } else if ( array instanceof Float[] ) {
355 return floatArrayToBytes( ArrayUtils.toPrimitive( ( Float[] ) array ) );
356 } else if ( array instanceof Double[] ) {
357 return doubleArrayToBytes( ArrayUtils.toPrimitive( ( Double[] ) array ) );
358 } else if ( array instanceof Character[] ) {
359 return charArrayToBytes( ArrayUtils.toPrimitive( ( Character[] ) array ) );
360 } else if ( array instanceof String[] ) {
361 return stringArrayToBytes( ( String[] ) array, charset );
362 } else if ( array instanceof Integer[] ) {
363 return intArrayToBytes( ArrayUtils.toPrimitive( ( Integer[] ) array ) );
364 } else if ( array instanceof Long[] ) {
365 return longArrayToBytes( ArrayUtils.toPrimitive( ( Long[] ) array ) );
366 } else if ( array.getClass().equals( Object[].class ) ) {
367
368 if ( array.length != 0 ) {
369
370 T[] typedArray = ( T[] ) Array.newInstance( array[0].getClass(), array.length );
371 System.arraycopy( array, 0, typedArray, 0, array.length );
372 return objectArrayToBytes( typedArray, charset );
373 } else {
374 return new byte[0];
375 }
376 } else {
377 throw new UnsupportedOperationException( "Can't convert " + array[0].getClass() + " to bytes" );
378 }
379 }
380
381
382
383
384
385 @SuppressWarnings("unchecked")
386 public <T> T[] byteArrayToObjects( byte[] barray, Class<T> type, Charset charset ) {
387 if ( Boolean.class.isAssignableFrom( type ) ) {
388 return ( T[] ) ArrayUtils.toObject( byteArrayToBooleans( barray ) );
389 } else if ( Character.class.isAssignableFrom( type ) ) {
390 return ( T[] ) ArrayUtils.toObject( byteArrayToChars( barray ) );
391 } else if ( Float.class.isAssignableFrom( type ) ) {
392 return ( T[] ) ArrayUtils.toObject( byteArrayToFloats( barray ) );
393 } else if ( Double.class.isAssignableFrom( type ) ) {
394 return ( T[] ) ArrayUtils.toObject( byteArrayToDoubles( barray ) );
395 } else if ( Integer.class.isAssignableFrom( type ) ) {
396 return ( T[] ) ArrayUtils.toObject( byteArrayToInts( barray ) );
397 } else if ( Long.class.isAssignableFrom( type ) ) {
398 return ( T[] ) ArrayUtils.toObject( byteArrayToLongs( barray ) );
399 } else if ( String.class.isAssignableFrom( type ) ) {
400 return ( T[] ) byteArrayToStrings( barray, charset );
401 } else {
402 throw new UnsupportedOperationException( "Can't convert " + type + " from bytes" );
403 }
404 }
405 }