/*
* Copyright (C) 2011 Google Inc.
*
* Licensed 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.
*/
package com.cellbots.logger;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* An {@link OutputStream} that splits the files while writing.
*
* @author birmiwal@google.com (Shishir Birmiwal)
*/
public class SplittingOutputStream extends OutputStream {
private static final String OUTPUT_FILENAME_FORMAT = "%s.part-%04d";
int fileCounter;
private FileOutputStream fileOutputStream;
private final String filenamePrefix;
private final int maxFileSize;
private int numBytesWrittenToPresentFile;
public static OutputStream getOutputStream(String filename, int maxSize)
throws FileNotFoundException {
if (maxSize <= 0) {
return new FileOutputStream(new File(filename));
}
return new SplittingOutputStream(filename, maxSize);
}
@Override
public void write(int oneByte) throws IOException {
swapUnderlyingFileIfRequiredToWrite(1);
fileOutputStream.write(oneByte);
numBytesWrittenToPresentFile += 1;
}
@Override
public void write(byte[] buffer) throws IOException {
swapUnderlyingFileIfRequiredToWrite(buffer.length);
fileOutputStream.write(buffer);
numBytesWrittenToPresentFile += buffer.length;
}
@Override
public void write(byte[] buffer, int offset, int count) throws IOException {
swapUnderlyingFileIfRequiredToWrite(count);
fileOutputStream.write(buffer, offset, count);
numBytesWrittenToPresentFile += count;
}
@Override
public void close() throws IOException {
fileOutputStream.close();
}
@Override
public void flush() throws IOException {
fileOutputStream.flush();
}
private SplittingOutputStream(String filenamePrefix, int maxFileSize)
throws FileNotFoundException {
this.filenamePrefix = filenamePrefix;
this.maxFileSize = maxFileSize;
openNextFileForOutput();
}
private void openNextFileForOutput() throws FileNotFoundException {
fileOutputStream = new FileOutputStream(getNextFilename());
numBytesWrittenToPresentFile = 0;
}
private String getNextFilename() {
return String.format(OUTPUT_FILENAME_FORMAT, filenamePrefix, fileCounter++);
}
private void swapUnderlyingFileIfRequiredToWrite(int numBytes) throws IOException {
// TODO(birmiwal): To get exact maxFileSize bytes, write
// (maxFileSize-(numBytesWrittenToPresentFile + numBytes)) bytes.
// then write remaining bytes to the next file.
if (numBytesWrittenToPresentFile + numBytes <= maxFileSize) {
return;
}
// swap file
fileOutputStream.flush();
fileOutputStream.close();
openNextFileForOutput();
}
}