package org.apache.lucene.store; /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.IOException; /** Abstract base class for input from a file in a {@link Directory}. A * random-access input stream. Used for all Lucene index input operations. * @see Directory */ public abstract class IndexInput implements Cloneable { private char[] chars; // used by readString() /** Reads and returns a single byte. * @see IndexOutput#writeByte(byte) */ public abstract byte readByte() throws IOException; /** Reads a specified number of bytes into an array at the specified offset. * @param b the array to read bytes into * @param offset the offset in the array to start storing bytes * @param len the number of bytes to read * @see IndexOutput#writeBytes(byte[],int) */ public abstract void readBytes(byte[] b, int offset, int len) throws IOException; /** Reads four bytes and returns an int. * @see IndexOutput#writeInt(int) */ public int readInt() throws IOException { return ((readByte() & 0xFF) << 24) | ((readByte() & 0xFF) << 16) | ((readByte() & 0xFF) << 8) | (readByte() & 0xFF); } /** Reads an int stored in variable-length format. Reads between one and * five bytes. Smaller values take fewer bytes. Negative numbers are not * supported. * @see IndexOutput#writeVInt(int) */ public int readVInt() throws IOException { byte b = readByte(); int i = b & 0x7F; for (int shift = 7; (b & 0x80) != 0; shift += 7) { b = readByte(); i |= (b & 0x7F) << shift; } return i; } /** Reads eight bytes and returns a long. * @see IndexOutput#writeLong(long) */ public long readLong() throws IOException { return (((long)readInt()) << 32) | (readInt() & 0xFFFFFFFFL); } /** Reads a long stored in variable-length format. Reads between one and * nine bytes. Smaller values take fewer bytes. Negative numbers are not * supported. */ public long readVLong() throws IOException { byte b = readByte(); long i = b & 0x7F; for (int shift = 7; (b & 0x80) != 0; shift += 7) { b = readByte(); i |= (b & 0x7FL) << shift; } return i; } /** Reads a string. * @see IndexOutput#writeString(String) */ public String readString() throws IOException { int length = readVInt(); if (chars == null || length > chars.length) chars = new char[length]; readChars(chars, 0, length); return new String(chars, 0, length); } /** Reads UTF-8 encoded characters into an array. * @param buffer the array to read characters into * @param start the offset in the array to start storing characters * @param length the number of characters to read * @see IndexOutput#writeChars(String,int,int) */ public void readChars(char[] buffer, int start, int length) throws IOException { final int end = start + length; for (int i = start; i < end; i++) { byte b = readByte(); if ((b & 0x80) == 0) buffer[i] = (char)(b & 0x7F); else if ((b & 0xE0) != 0xE0) { buffer[i] = (char)(((b & 0x1F) << 6) | (readByte() & 0x3F)); } else buffer[i] = (char)(((b & 0x0F) << 12) | ((readByte() & 0x3F) << 6) | (readByte() & 0x3F)); } } /** * Expert * * Similar to {@link #readChars(char[], int, int)} but does not do any conversion operations on the bytes it is reading in. It still * has to invoke {@link #readByte()} just as {@link #readChars(char[], int, int)} does, but it does not need a buffer to store anything * and it does not have to do any of the bitwise operations, since we don't actually care what is in the byte except to determine * how many more bytes to read * @param length The number of chars to read */ public void skipChars(int length) throws IOException{ for (int i = 0; i < length; i++) { byte b = readByte(); if ((b & 0x80) == 0){ //do nothing, we only need one byte } else if ((b & 0xE0) != 0xE0) { readByte();//read an additional byte } else{ //read two additional bytes. readByte(); readByte(); } } } /** Closes the stream to futher operations. */ public abstract void close() throws IOException; /** Returns the current position in this file, where the next read will * occur. * @see #seek(long) */ public abstract long getFilePointer(); /** Sets current position in this file, where the next read will occur. * @see #getFilePointer() */ public abstract void seek(long pos) throws IOException; /** The number of bytes in the file. */ public abstract long length(); /** Returns a clone of this stream. * *

Clones of a stream access the same data, and are positioned at the same * point as the stream they were cloned from. * *

Expert: Subclasses must ensure that clones may be positioned at * different points in the input from each other and from the stream they * were cloned from. */ public Object clone() { IndexInput clone = null; try { clone = (IndexInput)super.clone(); } catch (CloneNotSupportedException e) {} clone.chars = null; return clone; } }