private static long scanForLocSig ( FileChannel channel ) throws IOException { channel . position ( 0 ) ; ByteBuffer bb = getByteBuffer ( CHUNK_SIZE ) ; long end = channel . size ( ) ; while ( channel . position ( ) <= end ) { read ( bb , channel ) ; int bufferPos = 0 ; while ( bufferPos <= bb . limit ( ) - SIG_PATTERN_LENGTH ) { // Following is based on the Boyer Moore algorithm but simplified to reflect // a) the size of the pattern is static // b) the pattern is static and has no repeating bytes int patternPos ; for ( patternPos = SIG_PATTERN_LENGTH - 1 ; patternPos >= 0 && LOCSIG_PATTERN [ patternPos ] == bb . get ( bufferPos + patternPos ) ; -- patternPos ) { // empty loop while bytes match } // Outer switch gives same results as checking the "good suffix array" in the Boyer Moore algorithm switch ( patternPos ) { case - 1 : { // Pattern matched. Confirm is this is the start of a valid local file record long startLocRecord = channel . position ( ) - bb . limit ( ) + bufferPos ; long currentPos = channel . position ( ) ; if ( validateLocalFileRecord ( channel , startLocRecord , - 1 ) ) { return startLocRecord ; } // Restore position in case it shifted channel . position ( currentPos ) ; // wasn't a valid local file record; continue scan bufferPos += 4 ; break ; } case 3 : { // No bytes matched; the common case. // With our pattern, this is the only case where the Boyer Moore algorithm's "bad char array" may // produce a shift greater than the "good suffix array" (which would shift 1 byte) int idx = bb . get ( bufferPos + patternPos ) - Byte . MIN_VALUE ; bufferPos += LOC_BAD_BYTE_SKIP [ idx ] ; break ; } default : // 1 or more bytes matched bufferPos += 4 ; } } } return - 1 ; }
Boyer Moore scan that proceeds forwards from the end of the file looking for the first LOCSIG