I have a big file, it's expected to be around 12 GB. I want to load it all into memory on a beefy 64-bit machine with 16 GB RAM, but I think Java does not support byte arrays that big:
File f = new File(file); long size = f.length(); byte data[] = new byte[size]; // <- does not compile, not even on 64bit JVM
Is it possible with Java?
The compile error from the Eclipse compiler is:
Type mismatch: cannot convert from long to int
javac gives:
possible loss of precision found : long required: int byte data[] = new byte[size];
The 32-bit Java int can go to a maximum of 2,147,483,647, so that is the theoretical maximum Java array size. However, virtual machines for different operating systems may not allocate every available bit to the elements in the Java array.
If you try to access the array position (index) greater than its size, the program gets compiled successfully but, at the time of execution it generates an ArrayIndexOutOfBoundsException exception.
If you want to change the size, you need to create a new array of the desired size, and then copy elements from the old array to the new array, and use the new array. In our example, arr can only hold int values. Arrays can hold primitive values, unlike ArrayList, which can only hold object values.
Java array indices are of type int
(4 bytes or 32 bits), so I'm afraid you're limited to 231 − 1 or 2147483647 slots in your array. I'd read the data into another data structure, like a 2D array.
package com.deans.rtl.util; import java.io.FileInputStream; import java.io.IOException; /** * * @author [email protected] * * Written to work with byte arrays requiring address space larger than 32 bits. * */ public class ByteArray64 { private final long CHUNK_SIZE = 1024*1024*1024; //1GiB long size; byte [][] data; public ByteArray64( long size ) { this.size = size; if( size == 0 ) { data = null; } else { int chunks = (int)(size/CHUNK_SIZE); int remainder = (int)(size - ((long)chunks)*CHUNK_SIZE); data = new byte[chunks+(remainder==0?0:1)][]; for( int idx=chunks; --idx>=0; ) { data[idx] = new byte[(int)CHUNK_SIZE]; } if( remainder != 0 ) { data[chunks] = new byte[remainder]; } } } public byte get( long index ) { if( index<0 || index>=size ) { throw new IndexOutOfBoundsException("Error attempting to access data element "+index+". Array is "+size+" elements long."); } int chunk = (int)(index/CHUNK_SIZE); int offset = (int)(index - (((long)chunk)*CHUNK_SIZE)); return data[chunk][offset]; } public void set( long index, byte b ) { if( index<0 || index>=size ) { throw new IndexOutOfBoundsException("Error attempting to access data element "+index+". Array is "+size+" elements long."); } int chunk = (int)(index/CHUNK_SIZE); int offset = (int)(index - (((long)chunk)*CHUNK_SIZE)); data[chunk][offset] = b; } /** * Simulates a single read which fills the entire array via several smaller reads. * * @param fileInputStream * @throws IOException */ public void read( FileInputStream fileInputStream ) throws IOException { if( size == 0 ) { return; } for( int idx=0; idx<data.length; idx++ ) { if( fileInputStream.read( data[idx] ) != data[idx].length ) { throw new IOException("short read"); } } } public long size() { return size; } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With