Some JVM's do not allow seek beyond end of file, so zeros are written
first in that case. Reported by bohgammer@users in Open Disucssion
Forum.
506338
public void seek(long position) throws IOException {

        if (!readOnly && file.length() < position) {
            long tempSize = position - file.length();

            if (tempSize > 1 << 18) {
                tempSize = 1 << 18;
            }

            byte[] temp = new byte[(int) tempSize];

            try {
                long pos = file.length();

                for (; pos < position - tempSize; pos += tempSize) {
                    file.seek(pos);
                    file.write(temp, 0, (int) tempSize);
                }

                file.seek(pos);
                file.write(temp, 0, (int) (position - pos));

                realPosition = position;
            } catch (IOException e) {
                appLog.logContext(e, null);

                throw e;
            }
        }

        seekPosition = position;
    }
593531
public SF next() throws IOException {

		int remaining = afpData.remaining();
		if(remaining == 0) return null;
		if(remaining < 9) throw new IOException("trailing garbage at the end of file.");
		
		byte buf;
		long thisOffset = afpData.position();

		try {
			if(leadingLengthBytes == -1) {
				// we haven't tested for mvs download leading length bytes
				// we don't need them and don't want to see them
				int leadingLength = 0;
				do {
					buf = afpData.get();
					leadingLength++;
				} while((buf & 0xff) != 0x5a && afpData.remaining() > 0 && leadingLength < 5);
				
				leadingLengthBytes = leadingLength-1;
								
			} else {
				if(leadingLengthBytes > 0) afpData.position(afpData.position() + leadingLengthBytes); // just throw away those
				buf = afpData.get();
			}
			
			if((buf & 0xff) != 0x5a)
				throw new IOException("cannot find 5a magic byte");
			data[0] = buf;
			
			buf = afpData.get();
			data[1] = buf;
			length = (byte) buf << 8;

			buf = afpData.get();
			data[2] = (byte) (buf & 0xff);
			length |= (byte) buf & 0xff;
			
			length -= 2;
			
			if(length + 3 > data.length)
				throw new IOException("length of structured field is too large: "+length);
					
			afpData.get(data, 3, length);
		} catch (BufferUnderflowException e) {
			return null; // FIXME could also be an error
		}
		
		SF sf = factory.sf(data, 0, getLength() + 2);
		sf.setLength(length + 3);
		sf.setOffset(thisOffset);
		sf.setNumber(number++);
		
		return sf;
	}
538854
static OffsetIndex buildOffsetIndex(ByteSource source) throws IOException {
    final Map<Symbol, OffsetRange<ByteOffset>> ret = Maps.newHashMap();

    // we could be more efficient and deal with the byte stream as it comes along,
    // but these files don't exceed 50 MB, so it's simpler just to read it all in
    final byte[] fileAsBytes = source.read();

    // Okay, kids, don't try this at home. In general searching byte-by-byte through UTF-8 is a
    // bad idea, because multibyte characters will trip you up.  However, in this particular case:
    //   (a) all of the characters in our search strings are single-byte, and
    //   (b) for the begin and end probes, they are long enough that the chances of them occurring
    //         accidentally starting at a non-initial character of a multibyte character
    //         is vanishingly small.  It could be a problem for docIdEnd, being only a single character,
    //         but this will only be a problem if we have non-ASCII unicode characters in the doc IDs
    //         which is not the case for Gigaword.
    int startDocInclusive;
    int nextSearchIdx = 0;
    while ((startDocInclusive = findBytes(fileAsBytes, beginProbe, nextSearchIdx)) != NOT_FOUND) {
      final int startDocIDInclusive = startDocInclusive + beginProbe.length; // double check this!
      final int endDocIDIdxExclusive = findBytes(fileAsBytes, docIdEnd, startDocIDInclusive + 1);
      if (endDocIDIdxExclusive != NOT_FOUND) {
        final String docID = bytesAsString(fileAsBytes, startDocIDInclusive, endDocIDIdxExclusive);
        final int endTagIdx = findBytes(fileAsBytes, endProbe, endDocIDIdxExclusive + 1);
        if (endTagIdx != NOT_FOUND) {
          final int endDocIdxInclusive = endTagIdx + endProbe.length - 1;
          if (ret.containsKey(Symbol.from(docID))) {
            log.warn("Document ID {} occurs more than once; using latest version", docID);
          }
          ret.put(Symbol.from(docID),
              OffsetRange.byteOffsetRange(startDocInclusive, endDocIdxInclusive));
          nextSearchIdx = endDocIdxInclusive + 1;
        } else {
          throw new IOException("Failed to find closing document tag in " + source);
        }
      } else {
        throw new IOException("Failed to find end of document ID in " + source);
      }
    }
    return OffsetIndices.forMap(ret);
  }
986182
@Override
	public void writeInt(int v) throws IOException {
		growingByteBuffer.ensureExtraCapacity(4);
		dataOutputStream.write(0xFF & v);
		dataOutputStream.write(0xFF & (v >> 8));
		dataOutputStream.write(0xFF & (v >> 16));
		dataOutputStream.write(0xFF & (v >> 24));
	}
393396
public static GrowQueue_I64 zeros( int length ) {
		GrowQueue_I64 out = new GrowQueue_I64(length);
		out.size = length;
		return out;
	}
460563
@Override
	public void writeIntUnchecked(int v) throws IOException {
		outputStream.write(0xFF & v);
		outputStream.write(0xFF & (v >> 8));
		outputStream.write(0xFF & (v >> 16));
		outputStream.write(0xFF & (v >> 24));
		bytesWritten += 4;
	}
214395
public void writeLong(long value)
        throws IOException
    {
        int offset = _offset;
        byte[] buffer = _buffer;

        if (SIZE <= offset + 16) {
            flushBuffer();
            offset = _offset;
        }

        if (LONG_DIRECT_MIN <= value && value <= LONG_DIRECT_MAX) {
            buffer[offset++] = (byte) (value + BC_LONG_ZERO);
        }
        else if (LONG_BYTE_MIN <= value && value <= LONG_BYTE_MAX) {
            buffer[offset++] = (byte) (BC_LONG_BYTE_ZERO + (value >> 8));
            buffer[offset++] = (byte) (value);
        }
        else if (LONG_SHORT_MIN <= value && value <= LONG_SHORT_MAX) {
            buffer[offset++] = (byte) (BC_LONG_SHORT_ZERO + (value >> 16));
            buffer[offset++] = (byte) (value >> 8);
            buffer[offset++] = (byte) (value);
        }
        else if (-0x80000000L <= value && value <= 0x7fffffffL) {
            buffer[offset + 0] = (byte) BC_LONG_INT;
            buffer[offset + 1] = (byte) (value >> 24);
            buffer[offset + 2] = (byte) (value >> 16);
            buffer[offset + 3] = (byte) (value >> 8);
            buffer[offset + 4] = (byte) (value);

            offset += 5;
        }
        else {
            buffer[offset + 0] = (byte) 'L';
            buffer[offset + 1] = (byte) (value >> 56);
            buffer[offset + 2] = (byte) (value >> 48);
            buffer[offset + 3] = (byte) (value >> 40);
            buffer[offset + 4] = (byte) (value >> 32);
            buffer[offset + 5] = (byte) (value >> 24);
            buffer[offset + 6] = (byte) (value >> 16);
            buffer[offset + 7] = (byte) (value >> 8);
            buffer[offset + 8] = (byte) (value);

            offset += 9;
        }

        _offset = offset;
    }
281299
private int readShort(InputStream in, CRC32 crc) throws IOException {
        int b = readByte(in, crc);
        return ((readByte(in, crc) << 8) & 0x00ff00) | b;
    }
1188811
private static final int previousSpaceIndex(StringBuffer sb, int seek) {
    seek--;
    while (seek > 0) {
      if (sb.charAt(seek) == ' ') {
        while (seek > 0 && sb.charAt(seek - 1) == ' ')
          seek--;
        return seek;
      }
      seek--;
    }
    return 0;
  }
872652
@Override
  public void seek(long position) throws IOException {
    if (position != this.position) {
      this.position = position;
      blockSize = 0;
      data.seek(position);
    }
    bufPos = 0;
  }
313146
long parseDir(final String line, final String path) throws IOException {
        // read from the end of the line to find the last numeric
        // character on the line, then continue until we find the first
        // non-numeric character, and everything between that and the last
        // numeric character inclusive is our free space bytes count
        int bytesStart = 0;
        int bytesEnd = 0;
        int j = line.length() - 1;
        innerLoop1: while (j >= 0) {
            final char c = line.charAt(j);
            if (Character.isDigit(c)) {
                // found the last numeric character, this is the end of
                // the free space bytes count
                bytesEnd = j + 1;
                break innerLoop1;
            }
            j--;
        }
        innerLoop2: while (j >= 0) {
            final char c = line.charAt(j);
            if (!Character.isDigit(c) && c != ',' && c != '.') {
                // found the next non-numeric character, this is the
                // beginning of the free space bytes count
                bytesStart = j + 1;
                break innerLoop2;
            }
            j--;
        }
        if (j < 0) {
            throw new IOException("Command line 'dir /-c' did not return valid info " + "for path '" + path + "'");
        }

        // remove commas and dots in the bytes count
        final StringBuilder buf = new StringBuilder(line.substring(bytesStart, bytesEnd));
        for (int k = 0; k < buf.length(); k++) {
            if (buf.charAt(k) == ',' || buf.charAt(k) == '.') {
                buf.deleteCharAt(k--);
            }
        }
        return parseBytes(buf.toString(), path);
    }
420944
public static void writeLongLittleEndian(IO.WritableByteStream io, long value) throws IOException {
		io.write((byte)(value & 0xFF));
		io.write((byte)((value >> 8) & 0xFF));
		io.write((byte)((value >> 16) & 0xFF));
		io.write((byte)((value >> 24) & 0xFF));
		io.write((byte)((value >> 32) & 0xFF));
		io.write((byte)((value >> 40) & 0xFF));
		io.write((byte)((value >> 48) & 0xFF));
		io.write((byte)((value >> 56) & 0xFF));
	}
1330262
static int findNotZero( byte[] data , int index , int end ) {
		while( index < end && data[index] == 0 ) {
			index++;
		}
		return index;
	}
1203308
static int nextPrintfTerm(String message, int pos) throws ParseException {
    while (pos < message.length()) {
      if (message.charAt(pos++) != '%') {
        continue;
      }
      if (pos < message.length()) {
        char c = message.charAt(pos);
        if (c == '%' || c == 'n') {
          // We encountered '%%' or '%n', so keep going (these will be unescaped later).
          pos += 1;
          continue;
        }
        // We were pointing at the character after the '%', so adjust back by one.
        return pos - 1;
      }
      // We ran off the end while looking for the character after the first '%'.
      throw ParseException.withStartPosition("trailing unquoted '%' character", message, pos - 1);
    }
    // We never found another unescaped '%'.
    return -1;
  }
769085
static void zero(byte[] bytes, int off, int len) {
    // this is significantly faster than looping or Arrays.fill (which loops), particularly when
    // the length of the slice to be zeroed is <= to ARRAY_LEN (in that case, it's faster by a
    // factor of 2)
    int remaining = len;
    while (remaining > ARRAY_LEN) {
      System.arraycopy(ZERO_ARRAY, 0, bytes, off, ARRAY_LEN);
      off += ARRAY_LEN;
      remaining -= ARRAY_LEN;
    }

    System.arraycopy(ZERO_ARRAY, 0, bytes, off, remaining);
  }
183096
private int writeAtMost(ByteBuffer data, int offset, int length)
    {
        if (current >= bufferOffset + buffer.length)
            reBuffer();

        assert current < bufferOffset + buffer.length
        : String.format("File (%s) offset %d, buffer offset %d.", getPath(), current, bufferOffset);


        int toCopy = Math.min(length, buffer.length - bufferCursor());

        // copy bytes from external buffer
        ByteBufferUtil.arrayCopy(data, offset, buffer, bufferCursor(), toCopy);

        assert current <= bufferOffset + buffer.length
        : String.format("File (%s) offset %d, buffer offset %d.", getPath(), current, bufferOffset);

        validBufferBytes = Math.max(validBufferBytes, bufferCursor() + toCopy);
        current += toCopy;

        return toCopy;
    }
521616
@Override
  public synchronized int read(byte[] buf, int off, int len)
      throws IOException {
    checkNotClosed();

    validatePositionedReadArgs(nextReadPos, buf, off, len);
    if (len == 0) {
      return 0;
    }

    if (contentLength == 0 || (nextReadPos >= contentLength)) {
      return -1;
    }

    try {
      lazySeek(nextReadPos, len);
    } catch (EOFException e) {
      // the end of the file has moved
      return -1;
    }

    int bytesRead;
    try {
      bytesRead = wrappedStream.read(buf, off, len);
    } catch (EOFException e) {
      onReadFailure(e, len);
      // the base implementation swallows EOFs.
      return -1;
    } catch (IOException e) {
      onReadFailure(e, len);
      bytesRead = wrappedStream.read(buf, off, len);
    }

    if (bytesRead > 0) {
      pos += bytesRead;
      nextReadPos += bytesRead;
    }
    incrementBytesRead(bytesRead);
    return bytesRead;
  }