Die Umstellung auf BufferedStreams ergab bei mir eine Zeitoptimierung um ca den Faktor 6, was das ganze schon angenehmer macht.
aktueller Code
[spoiler]
public class XORCrypter {
public enum CrypterMode {
ENCRYPT,
DECRYPT;
}
private File inputFile;
private File outputFile;
private File keyFile;
private CrypterMode mode;
private List<CrypterListener> listener = new ArrayList<CrypterListener>();
private boolean running = false;
private XORCrypter(File inputFile, File outputFile, File keyFile, CrypterMode mode) throws IllegalArgumentException {
this.inputFile = inputFile;
this.outputFile = outputFile;
this.keyFile = keyFile;
this.mode = mode;
if(keyFile.length() - inputFile.length() < 100) {
throw new IllegalArgumentException("key file needs to be larger than input file");
}
}
/**
* Creates a crypter object to encrypt
*
* @param inputFile
* @param outputFile
* @param keyFile
* @throws Exception
*/
public XORCrypter(File inputFile, File outputFile, File keyFile) throws IllegalArgumentException {
this(inputFile, outputFile, keyFile, CrypterMode.ENCRYPT);
}
/**
* Creates a crypter object to decrypt
*
* @param inputFile
* @param keyFile
* @throws Exception
*/
public XORCrypter(File inputFile, File keyFile) throws IllegalArgumentException {
this(inputFile, null, keyFile, CrypterMode.DECRYPT);
}
public void doWork() {
running = true;
InputStream inputIn = null;
InputStream keyIn = null;
OutputStream outputOut = null;
try {
inputIn = new BufferedInputStream(new FileInputStream(inputFile));
keyIn = new BufferedInputStream(new FileInputStream(keyFile));
if(mode == CrypterMode.DECRYPT) {
//read prefix
//get length
byte[] prefixData = new byte[4];
inputIn.read(prefixData);
byte[] keyData = new byte[prefixData.length];
keyIn.read(keyData);
prefixData = crypt(prefixData, keyData);
int prefixLength = byteArrayToInt(prefixData);
if(prefixLength > 64) {
//invalid length
//generate one and lets see what happens
prefixLength = new Random().nextInt(61) + 4;
}
//get prefix data
prefixData = new byte[prefixLength];
inputIn.read(prefixData);
keyData = new byte[prefixData.length];
keyIn.read(keyData);
prefixData = crypt(prefixData, keyData);
String outputFileName = getNextPossibleFileName(new String(prefixData));
outputFile = new File(outputFileName);
}
outputOut = new BufferedOutputStream(new FileOutputStream(outputFile));
if(mode == CrypterMode.ENCRYPT) {
//write prefix
byte[] prefixData = generatePrefix();
byte[] keyData = new byte[prefixData.length];
keyIn.read(keyData);
prefixData = crypt(prefixData, keyData);
outputOut.write(prefixData);
}
byte[] dataBuffer = new byte[1024];
byte[] keyBuffer = new byte[1024];
int bytesRead = 0;
while(running && (bytesRead = inputIn.read(dataBuffer)) != -1) {
keyIn.read(keyBuffer);
outputOut.write(crypt(dataBuffer, keyBuffer, bytesRead));
}
if(running) {
for(CrypterListener l : listener) {
l.finished();
}
running = false;
}
else {
//aborted
for(CrypterListener l : listener) {
l.failed("process stopped");
}
}
} catch (FileNotFoundException e) {
for(CrypterListener l : listener) {
l.failed(e.getMessage());
}
} catch (IOException e) {
for(CrypterListener l : listener) {
l.failed(e.getMessage());
}
}
finally {
try {
if(inputIn != null)
inputIn.close();
if(keyIn != null)
keyIn.close();
if(outputOut != null)
outputOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void addListener(CrypterListener l) {
listener.add(l);
}
public void removeListener(CrypterListener l) {
listener.remove(l);
}
private byte[] crypt(byte[] data, byte[] key) {
return crypt(data, key, data.length);
}
private byte[] crypt(byte[] data, byte[] key, int length) {
byte[] cryptedData = new byte[length];
for(int i = 0; i < cryptedData.length; i++) {
cryptedData** = (byte) (data**^key**);
}
return cryptedData;
}
public boolean isRunning() {
return running;
}
public void stop() {
running = false;
}
private byte[] generatePrefix() {
String fileName = inputFile.getName();
ByteBuffer b = ByteBuffer.allocate(4 + fileName.getBytes().length);
b.putInt(fileName.getBytes().length);
b.put(fileName.getBytes());
return b.array();
}
private int byteArrayToInt(byte[] b) {
return b[3] & 0xFF |
(b[2] & 0xFF) << 8 |
(b[1] & 0xFF) << 16 |
(b[0] & 0xFF) << 24;
}
private String getNextPossibleFileName(String name) {
int counter = 0;
String nameToTest = name;
while(new File(nameToTest).exists()) {
counter++;
nameToTest = counter + "_" + name;
}
return nameToTest;
}
}
[/spoiler]
Zwecks Verbessungen lass ich mir die Anregungen aus diesem Thread weiter durch den Kopf gehen und gönn mir noch etwas Theorie