/*
* Copyright 2014 Robert von Burg <eitch@eitchnet.ch>
*
* 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 li.strolch.utils.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* <p>
* This sub class of {@link FileInputStream} allows to follow the currently read bytes of a {@link File}. In conjunction
* with a {@link Thread} and a {@link FileProgressListener} it is possible to track the progress of a long running job
* on bigger files
* </p>
*
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class ProgressableFileInputStream extends FileInputStream {
private volatile long fileSize;
private volatile long bytesRead;
private volatile boolean closed;
/**
* Constructs a normal {@link FileInputStream} with the given {@link File}
*
* @param file
* the file to read
* @throws FileNotFoundException
* thrown if the {@link File} does not exist
*/
public ProgressableFileInputStream(File file) throws FileNotFoundException {
super(file);
this.fileSize = file.length();
}
/**
* @see java.io.FileInputStream#read()
*/
@Override
public int read() throws IOException {
synchronized (this) {
this.bytesRead++;
}
return super.read();
}
/**
* @see java.io.FileInputStream#read(byte[], int, int)
*/
@Override
public int read(byte[] b, int off, int len) throws IOException {
int read = super.read(b, off, len);
if (read != -1) {
synchronized (this) {
this.bytesRead += read;
}
}
return read;
}
/**
* @see java.io.FileInputStream#read(byte[])
*/
@Override
public int read(byte[] b) throws IOException {
int read = super.read(b);
if (read != -1) {
synchronized (this) {
this.bytesRead += read;
}
}
return read;
}
/**
* @see java.io.FileInputStream#skip(long)
*/
@Override
public long skip(long n) throws IOException {
long skip = super.skip(n);
if (skip != -1) {
synchronized (this) {
this.bytesRead += skip;
}
}
return skip;
}
/**
* @see java.io.FileInputStream#close()
*/
@Override
public void close() throws IOException {
this.closed = true;
super.close();
}
/**
* Returns the size of the file being read
*
* @return the size of the file being read
*/
public long getFileSize() {
return this.fileSize;
}
/**
* Returns the number of bytes already read
*
* @return the number of bytes already read
*/
public long getBytesRead() {
synchronized (this) {
if (this.bytesRead > this.fileSize)
this.bytesRead = this.fileSize;
return this.bytesRead;
}
}
/**
* Returns the percent read of the file
*
* @return the percentage complete of the process
*/
public int getPercentComplete() {
long currentRead;
synchronized (this) {
if (this.bytesRead > this.fileSize)
this.bytesRead = this.fileSize;
currentRead = this.bytesRead;
}
double read = (100.0d / this.fileSize * currentRead);
return (int) Math.ceil(read);
}
/**
* Returns true if {@link #close()} was called, false otherwise
*
* @return the closed
*/
public boolean isClosed() {
return this.closed;
}
}