Immediately following Indexwriter: Lucene Index Creation and Maintenance, IndexOutput, a random-access output stream. is used for all Lucene index output operations.
IndexOutput is binded with Directory, which can be easily deduced from Class Diagram,

and also from source code:
// Directory.java
public abstract class Directory implements Closeable {
/** Creates a new, empty file in the directory with the given name.
Returns a stream writing this file. */
public abstract IndexOutput createOutput(String name, IOContext context) throws IOException;
}
Remember SimpleTextStoredFieldsWriter? It is initialized with one Directory instance.
// SimpleTextStoredFieldsFormat.java
public class SimpleTextStoredFieldsFormat extends StoredFieldsFormat {
@Override
public StoredFieldsWriter fieldsWriter(Directory directory, SegmentInfo si, IOContext context) throws IOException {
return new SimpleTextStoredFieldsWriter(directory, si.name, context);
}
}
Put Directory aside, let’s focus on IndexOutput.
DataOutput
Link to heading
DataOutput is abstract base class for performing write operations of Lucene’s low-level data types. The instrument of method can be inferred from its name:
writeIntwriteIntwriteString
// DataOutput.java
public abstract class DataOutput {
public abstract void writeByte(byte b) throws IOException;
// Writes a single byte
public abstract void writeByte(byte b) throws IOException;
// Writes an int as for bytes
public void writeInt(int i) throws IOException {
writeByte((byte)(i >> 24));
writeByte((byte)(i >> 16));
writeByte((byte)(i >> 8));
writeByte((byte) i);
}
// Writes a string
public void writeString(String s) throws IOException {
final BytesRef utf8Result = new BytesRef(s);
writeVInt(utf8Result.length);
writeBytes(utf8Result.bytes, utf8Result.offset, utf8Result.length);
}
}
IndexOutput
Link to heading
IndexOutput extends DataOutput and imlements Closeable which requires it override close method. Besides this, IndexOutput affiliates name and description for DataOutput.
// IndexOutput.java
public abstract class IndexOutput extends DataOutput implements Closeable {
/** Full description of this output, e.g. which class such as FSIndexOutput, and the full path to the file */
private final String resourceDescription;
/** Just the name part from resourceDescription */
private final String name;
@Override
public abstract void close() throws IOException;
}
OutputStreamIndexOutput
Link to heading
When it comes to OutputStreamIndexOutput, the derived of IndexOutput, it implements for buffered that wites to an OutputStream.
// OutputStreamIndexOutput.java
public class OutputStreamIndexOutput extends IndexOutput {
private final BufferedOutputStream os;
@Override
public final void writeByte(byte b) throws IOException {
os.write(b);
bytesWritten++;
}
@Override
public void close() throws IOException {
try (final OutputStream o = os) {
// We want to make sure that os.flush() was running before close:
// BufferedOutputStream may ignore IOExceptions while flushing on close().
// We keep this also in Java 8, although it claims to be fixed there,
// because there are more bugs around this! See:
// # https://bugs.openjdk.java.net/browse/JDK-7015589
// # https://bugs.openjdk.java.net/browse/JDK-8054565
if (!flushedOnClose) {
flushedOnClose = true; // set this BEFORE calling flush!
o.flush();
}
}
}
}
For more details about BufferedOutputStream, go to java.io.BufferedOutputStream.