3636 * <p>
3737 *
3838 * @author IP2Location.com
39- * @version 8.6 .0
39+ * @version 8.7 .0
4040 */
4141public class IP2Location {
4242 private static final Pattern pattern = Pattern .compile ("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\ .){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" ); // IPv4
@@ -218,10 +218,11 @@ private boolean LoadBIN() throws IOException {
218218 try {
219219 if (IPDatabasePath .length () > 0 ) {
220220 aFile = new RandomAccessFile (IPDatabasePath , "r" );
221- final FileChannel inChannel = aFile . getChannel () ;
222- final MappedByteBuffer _HeaderBuffer = inChannel . map ( FileChannel . MapMode . READ_ONLY , 0 , 64 ); // 64 bytes header
223-
221+ byte [] _HeaderData = new byte [ 64 ] ;
222+ aFile . read ( _HeaderData );
223+ ByteBuffer _HeaderBuffer = ByteBuffer . wrap ( _HeaderData );
224224 _HeaderBuffer .order (ByteOrder .LITTLE_ENDIAN );
225+
225226 _MetaData = new MetaData ();
226227
227228 _MetaData .setDBType (_HeaderBuffer .get (0 ));
@@ -309,8 +310,17 @@ private boolean LoadBIN() throws IOException {
309310 CATEGORY_ENABLED = (CATEGORY_POSITION [dbtype ] != 0 );
310311
311312 if (_MetaData .getIndexed ()) {
312- final MappedByteBuffer _IndexBuffer = inChannel .map (FileChannel .MapMode .READ_ONLY , _MetaData .getIndexBaseAddr () - 1 , _MetaData .getBaseAddr () - _MetaData .getIndexBaseAddr ()); // reading indexes
313+ int readLen = _IndexArrayIPv4 .length ;
314+ if (_MetaData .getIndexedIPv6 ()) {
315+ readLen += _IndexArrayIPv6 .length ;
316+ }
317+
318+ byte [] _IndexData = new byte [readLen * 8 ]; // 4 bytes for both from row and to row
319+ aFile .seek (_MetaData .getIndexBaseAddr () - 1 );
320+ aFile .read (_IndexData );
321+ ByteBuffer _IndexBuffer = ByteBuffer .wrap (_IndexData );
313322 _IndexBuffer .order (ByteOrder .LITTLE_ENDIAN );
323+
314324 int pointer = 0 ;
315325
316326 // read IPv4 index
@@ -331,7 +341,7 @@ private boolean LoadBIN() throws IOException {
331341 }
332342
333343 if (UseMemoryMappedFile ) {
334- CreateMappedBytes (inChannel );
344+ CreateMappedBytes ();
335345 } else {
336346 DestroyMappedBytes ();
337347 }
@@ -365,6 +375,8 @@ public IPResult IPQuery(String IPAddress) throws IOException {
365375 RandomAccessFile filehandle = null ;
366376 ByteBuffer mybuffer = null ;
367377 ByteBuffer mydatabuffer = null ;
378+ byte [] row ;
379+ byte [] fullrow = null ;
368380
369381 try {
370382 if (IPAddress == null || IPAddress .length () == 0 ) {
@@ -407,6 +419,7 @@ public IPResult IPQuery(String IPAddress) throws IOException {
407419 long position ;
408420 BigInteger ipfrom ;
409421 BigInteger ipto ;
422+ int firstcol = 4 ; // IP From is 4 bytes
410423
411424 // Read BIN if haven't done so
412425 if (_MetaData == null ) {
@@ -444,6 +457,8 @@ public IPResult IPQuery(String IPAddress) throws IOException {
444457 high = _IndexArrayIPv4 [indexaddr ][1 ];
445458 }
446459 } else { // IPv6
460+ firstcol = 16 ; // IPv6 is 16 bytes
461+
447462 if (_MetaData .getOldBIN ()) {
448463 record .status = "IPV6_NOT_SUPPORTED" ;
449464 return record ;
@@ -475,26 +490,28 @@ public IPResult IPQuery(String IPAddress) throws IOException {
475490 rowoffset2 = rowoffset + mycolumnsize ;
476491
477492 if (UseMemoryMappedFile ) {
493+ // only reading the IP From fields
478494 overcapacity = (rowoffset2 >= mybufcapacity );
495+ ipfrom = read32or128 (rowoffset , myiptype , mybuffer , filehandle );
496+ ipto = (overcapacity ) ? BigInteger .ZERO : read32or128 (rowoffset2 , myiptype , mybuffer , filehandle );
497+ } else {
498+ // reading IP From + whole row + next IP From
499+ fullrow = readRow (rowoffset , mycolumnsize + firstcol , mybuffer , filehandle );
500+ ipfrom = read32or128Row (fullrow , 0 , firstcol );
501+ ipto = (overcapacity ) ? BigInteger .ZERO : read32or128Row (fullrow , mycolumnsize , firstcol );
479502 }
480503
481- ipfrom = read32or128 (rowoffset , myiptype , mybuffer , filehandle );
482- ipto = (overcapacity ) ? BigInteger .ZERO : read32or128 (rowoffset2 , myiptype , mybuffer , filehandle );
483-
484504 if (ipno .compareTo (ipfrom ) >= 0 && ipno .compareTo (ipto ) < 0 ) {
485- int firstcol = 4 ; // IP From is 4 bytes
486- if (myiptype == 6 ) { // IPv6
487- firstcol = 16 ; // IPv6 is 16 bytes
488- }
489505
490- // read the row here after the IP From column (remaining columns are all 4 bytes)
491506 int rowlen = mycolumnsize - firstcol ;
492- byte [] row ;
493- row = readRow (rowoffset + firstcol , rowlen , mybuffer , filehandle );
494507
495508 if (UseMemoryMappedFile ) {
509+ row = readRow (rowoffset + firstcol , rowlen , mybuffer , filehandle );
496510 mydatabuffer = _MapDataBuffer .duplicate (); // this is to enable reading of a range of bytes in multi-threaded environment
497511 mydatabuffer .order (ByteOrder .LITTLE_ENDIAN );
512+ } else {
513+ row = new byte [rowlen ];
514+ System .arraycopy (fullrow , firstcol , row , (int ) 0 , rowlen ); // extract the actual row data
498515 }
499516
500517 if (COUNTRY_ENABLED ) {
@@ -881,6 +898,13 @@ private byte[] readRow(final long position, final long mylen, final ByteBuffer m
881898 return row ;
882899 }
883900
901+ private BigInteger read32or128Row (byte [] row , final int from , final int len ) throws IOException {
902+ byte [] buf = new byte [len ];
903+ System .arraycopy (row , from , buf , (int ) 0 , len );
904+ reverse (buf );
905+ return new BigInteger (1 , buf );
906+ }
907+
884908 private BigInteger read32or128 (final long position , final int myiptype , final ByteBuffer mybuffer , final RandomAccessFile filehandle ) throws IOException {
885909 if (myiptype == 4 ) {
886910 return read32 (position , mybuffer , filehandle );
@@ -930,27 +954,37 @@ private BigInteger read32(final long position, final ByteBuffer mybuffer, final
930954 }
931955
932956 private String readStr (long position , final ByteBuffer mydatabuffer , final RandomAccessFile filehandle ) throws IOException {
933- final int size ;
957+ int size = 257 ; // max size of string field + 1 byte for the position
958+ final int len ;
959+ final byte [] data = new byte [size ];
934960 byte [] buf ;
935961
936962 if (UseMemoryMappedFile ) {
937963 position = position - _MapDataOffset ; // position stored in BIN file is for full file, not just the mapped data segment, so need to minus
938- size = _MapDataBuffer .get ((int ) position ); // use absolute offset to be thread-safe (keep using the original buffer since is absolute position & just reading 1 byte)
939-
940964 try {
941- buf = new byte [size ];
942- mydatabuffer .position ((int ) position + 1 );
943- mydatabuffer .get (buf , 0 , size );
965+ mydatabuffer .position ((int ) position );
966+ if (mydatabuffer .remaining () < size ) {
967+ size = mydatabuffer .remaining ();
968+ }
969+ mydatabuffer .get (data , 0 , size );
970+ len = data [0 ];
971+
972+ buf = new byte [len ];
973+ System .arraycopy (data , 1 , buf , (int ) 0 , len );
944974
945975 } catch (NegativeArraySizeException e ) {
946976 return null ;
947977 }
978+
948979 } else {
949980 filehandle .seek (position );
950- size = filehandle .read ();
951981 try {
952- buf = new byte [size ];
953- filehandle .read (buf , 0 , size );
982+ filehandle .read (data , 0 , size );
983+ len = data [0 ];
984+
985+ buf = new byte [len ];
986+ System .arraycopy (data , 1 , buf , (int ) 0 , len );
987+
954988 } catch (NegativeArraySizeException e ) {
955989 return null ;
956990 }
0 commit comments