1 package org.apache.lucene.store;
2
3 /**
4 * Copyright 2004 The Apache Software Foundation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 import java.io.IOException;
20
21 /** Abstract class for output to a file in a Directory. A random-access output
22 * stream. Used for all Lucene index output operations.
23 * @see Directory
24 * @see InputStream
25 */
26 public abstract class OutputStream {
27 static final int BUFFER_SIZE = 1024;
28
29 private final byte[] buffer = new byte[BUFFER_SIZE];
30 private long bufferStart = 0; // position in file of buffer
31 private int bufferPosition = 0; // position in buffer
32
33 /** Writes a single byte.
34 * @see InputStream#readByte()
35 */
36 public final void writeByte(byte b) throws IOException {
37 if (bufferPosition >= BUFFER_SIZE)
38 flush();
39 buffer[bufferPosition++] = b;
40 }
41
42 /** Writes an array of bytes.
43 * @param b the bytes to write
44 * @param length the number of bytes to write
45 * @see InputStream#readBytes(byte[],int,int)
46 */
47 public final void writeBytes(byte[] b, int length) throws IOException {
48 for (int i = 0; i < length; i++)
49 writeByte(b[i]);
50 }
51
52 /** Writes an int as four bytes.
53 * @see InputStream#readInt()
54 */
55 public final void writeInt(int i) throws IOException {
56 writeByte((byte)(i >> 24));
57 writeByte((byte)(i >> 16));
58 writeByte((byte)(i >> 8));
59 writeByte((byte) i);
60 }
61
62 /** Writes an int in a variable-length format. Writes between one and
63 * five bytes. Smaller values take fewer bytes. Negative numbers are not
64 * supported.
65 * @see InputStream#readVInt()
66 */
67 public final void writeVInt(int i) throws IOException {
68 while ((i & ~0x7F) != 0) {
69 writeByte((byte)((i & 0x7f) | 0x80));
70 i >>>= 7;
71 }
72 writeByte((byte)i);
73 }
74
75 /** Writes a long as eight bytes.
76 * @see InputStream#readLong()
77 */
78 public final void writeLong(long i) throws IOException {
79 writeInt((int) (i >> 32));
80 writeInt((int) i);
81 }
82
83 /** Writes an long in a variable-length format. Writes between one and five
84 * bytes. Smaller values take fewer bytes. Negative numbers are not
85 * supported.
86 * @see InputStream#readVLong()
87 */
88 public final void writeVLong(long i) throws IOException {
89 while ((i & ~0x7F) != 0) {
90 writeByte((byte)((i & 0x7f) | 0x80));
91 i >>>= 7;
92 }
93 writeByte((byte)i);
94 }
95
96 /** Writes a string.
97 * @see InputStream#readString()
98 */
99 public final void writeString(String s) throws IOException {
100 int length = s.length();
101 writeVInt(length);
102 writeChars(s, 0, length);
103 }
104
105 /** Writes a sequence of UTF-8 encoded characters from a string.
106 * @param s the source of the characters
107 * @param start the first character in the sequence
108 * @param length the number of characters in the sequence
109 * @see InputStream#readChars(char[],int,int)
110 */
111 public final void writeChars(String s, int start, int length)
112 throws IOException {
113 final int end = start + length;
114 for (int i = start; i < end; i++) {
115 final int code = (int)s.charAt(i);
116 if (code >= 0x01 && code <= 0x7F)
117 writeByte((byte)code);
118 else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0) {
119 writeByte((byte)(0xC0 | (code >> 6)));
120 writeByte((byte)(0x80 | (code & 0x3F)));
121 } else {
122 writeByte((byte)(0xE0 | (code >>> 12)));
123 writeByte((byte)(0x80 | ((code >> 6) & 0x3F)));
124 writeByte((byte)(0x80 | (code & 0x3F)));
125 }
126 }
127 }
128
129 /** Forces any buffered output to be written. */
130 protected final void flush() throws IOException {
131 flushBuffer(buffer, bufferPosition);
132 bufferStart += bufferPosition;
133 bufferPosition = 0;
134 }
135
136 /** Expert: implements buffer write. Writes bytes at the current position in
137 * the output.
138 * @param b the bytes to write
139 * @param len the number of bytes to write
140 */
141 protected abstract void flushBuffer(byte[] b, int len) throws IOException;
142
143 /** Closes this stream to further operations. */
144 public void close() throws IOException {
145 flush();
146 }
147
148 /** Returns the current position in this file, where the next write will
149 * occur.
150 * @see #seek(long)
151 */
152 public final long getFilePointer() throws IOException {
153 return bufferStart + bufferPosition;
154 }
155
156 /** Sets current position in this file, where the next write will occur.
157 * @see #getFilePointer()
158 */
159 public void seek(long pos) throws IOException {
160 flush();
161 bufferStart = pos;
162 }
163
164 /** The number of bytes in the file. */
165 public abstract long length() throws IOException;
166
167
168 }