CompoundFileWriterpublic final class CompoundFileWriter extends Object Combines multiple files into a single compound file.
The file format:
- VInt fileCount
- {Directory}
fileCount entries with the following structure:
- long dataOffset
- UTFString extension
- {File Data}
fileCount entries with the raw data of the corresponding file
The fileCount integer indicates how many files are contained in this compound
file. The {directory} that follows has that many entries. Each directory entry
contains an encoding identifier, an long pointer to the start of this file's
data section, and a UTF String with that file's extension. |
Fields Summary |
---|
private Directory | directory | private String | fileName | private HashSet | ids | private LinkedList | entries | private boolean | merged |
Constructors Summary |
---|
public CompoundFileWriter(Directory dir, String name)Create the compound stream in the specified file. The file name is the
entire name (no extensions are added).
if (dir == null)
throw new IllegalArgumentException("Missing directory");
if (name == null)
throw new IllegalArgumentException("Missing name");
directory = dir;
fileName = name;
ids = new HashSet();
entries = new LinkedList();
|
Methods Summary |
---|
public void | addFile(java.lang.String file)Add a source stream. If sourceDir is null, it is set to the
same value as the directory where this compound stream exists.
The id is the string by which the sub-stream will be know in the
compound stream. The caller must ensure that the ID is unique. If the
id is null, it is set to the name of the source file.
if (merged)
throw new IllegalStateException(
"Can't add extensions after merge has been called");
if (file == null)
throw new IllegalArgumentException(
"Missing source file");
if (! ids.add(file))
throw new IllegalArgumentException(
"File " + file + " already added");
FileEntry entry = new FileEntry();
entry.file = file;
entries.add(entry);
| public void | close()Merge files with the extensions added up to now.
All files with these extensions are combined sequentially into the
compound stream. After successful merge, the source files
are deleted.
if (merged)
throw new IllegalStateException(
"Merge already performed");
if (entries.isEmpty())
throw new IllegalStateException(
"No entries to merge have been defined");
merged = true;
// open the compound stream
OutputStream os = null;
try {
os = directory.createFile(fileName);
// Write the number of entries
os.writeVInt(entries.size());
// Write the directory with all offsets at 0.
// Remember the positions of directory entries so that we can
// adjust the offsets later
Iterator it = entries.iterator();
while(it.hasNext()) {
FileEntry fe = (FileEntry) it.next();
fe.directoryOffset = os.getFilePointer();
os.writeLong(0); // for now
os.writeString(fe.file);
}
// Open the files and copy their data into the stream.
// Remeber the locations of each file's data section.
byte buffer[] = new byte[1024];
it = entries.iterator();
while(it.hasNext()) {
FileEntry fe = (FileEntry) it.next();
fe.dataOffset = os.getFilePointer();
copyFile(fe, os, buffer);
}
// Write the data offsets into the directory of the compound stream
it = entries.iterator();
while(it.hasNext()) {
FileEntry fe = (FileEntry) it.next();
os.seek(fe.directoryOffset);
os.writeLong(fe.dataOffset);
}
// Close the output stream. Set the os to null before trying to
// close so that if an exception occurs during the close, the
// finally clause below will not attempt to close the stream
// the second time.
OutputStream tmp = os;
os = null;
tmp.close();
} finally {
if (os != null) try { os.close(); } catch (IOException e) { }
}
| private void | copyFile(org.apache.lucene.index.CompoundFileWriter$FileEntry source, org.apache.lucene.store.OutputStream os, byte[] buffer)Copy the contents of the file with specified extension into the
provided output stream. Use the provided buffer for moving data
to reduce memory allocation.
InputStream is = null;
try {
long startPtr = os.getFilePointer();
is = directory.openFile(source.file);
long length = is.length();
long remainder = length;
int chunk = buffer.length;
while(remainder > 0) {
int len = (int) Math.min(chunk, remainder);
is.readBytes(buffer, 0, len);
os.writeBytes(buffer, len);
remainder -= len;
}
// Verify that remainder is 0
if (remainder != 0)
throw new IOException(
"Non-zero remainder length after copying: " + remainder
+ " (id: " + source.file + ", length: " + length
+ ", buffer size: " + chunk + ")");
// Verify that the output length diff is equal to original file
long endPtr = os.getFilePointer();
long diff = endPtr - startPtr;
if (diff != length)
throw new IOException(
"Difference in the output file offsets " + diff
+ " does not match the original file length " + length);
} finally {
if (is != null) is.close();
}
| public org.apache.lucene.store.Directory | getDirectory()Returns the directory of the compound file.
return directory;
| public java.lang.String | getName()Returns the name of the compound file.
return fileName;
|
|