The ReplayFileAppender now changes Replay Files in one go (on Windows machines) if there is already a File to be added

This commit is contained in:
CrushedPixel
2015-06-02 20:33:51 +02:00
parent 1bc80cc257
commit de78c1116e
2 changed files with 72 additions and 42 deletions

View File

@@ -1,5 +1,7 @@
package eu.crushedpixel.replaymod.registry; package eu.crushedpixel.replaymod.registry;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import eu.crushedpixel.replaymod.gui.GuiReplaySaving; import eu.crushedpixel.replaymod.gui.GuiReplaySaving;
import eu.crushedpixel.replaymod.utils.ReplayFileIO; import eu.crushedpixel.replaymod.utils.ReplayFileIO;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@@ -7,14 +9,14 @@ import net.minecraftforge.fml.client.FMLClientHandler;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
public class ReplayFileAppender extends Thread { public class ReplayFileAppender extends Thread {
private Queue<Pair<Pair<File, String>, File>> filesToMove = new ConcurrentLinkedQueue<Pair<Pair<File, String>, File>>(); private Multimap<File, Pair<File, String>> filesToMove = ArrayListMultimap.create();
private Queue<File> filesToRewrite = new ConcurrentLinkedQueue<File>();
private boolean shutdown = false; private boolean shutdown = false;
private List<GuiReplaySaving> listeners = new ArrayList<GuiReplaySaving>(); private List<GuiReplaySaving> listeners = new ArrayList<GuiReplaySaving>();
@@ -50,43 +52,59 @@ public class ReplayFileAppender extends Thread {
} }
public void registerModifiedFile(File toAdd, String name, File replayFile) { public void registerModifiedFile(File toAdd, String name, File replayFile) {
for(Pair<Pair<File, String>, File> p : new ArrayList<Pair<Pair<File, String>, File>>(filesToMove)) { //first, remove any files with the same name assigned to this Replay File
if(p.getLeft().getRight().equals(name) && p.getRight().equals(replayFile)) { if(filesToMove.get(replayFile) != null) {
filesToMove.remove(p); for(Pair<File, String> p : new ArrayList<Pair<File, String>>((Collection<Pair<File, String>>)filesToMove.get(replayFile))) {
if(p.getRight().equals(name)) {
filesToMove.remove(replayFile, p);
}
} }
} }
filesToMove.add(Pair.of(Pair.of(toAdd, name), replayFile)); //then, assign the file/name pair to the Replay File
filesToMove.put(replayFile, Pair.of(toAdd, name));
//finally, add the Replay File to the Queue if not already contained
if(!filesToRewrite.contains(replayFile)) {
filesToRewrite.add(replayFile);
}
} }
public void shutdown() { public void shutdown() {
shutdown = true; shutdown = true;
} }
public boolean isBusy() {
return !filesToMove.isEmpty() && !newReplayFileWriting;
}
public void addFinishListener(GuiReplaySaving gui) { public void addFinishListener(GuiReplaySaving gui) {
listeners.add(gui); listeners.add(gui);
} }
@Override @Override
public void run() { public void run() {
while(!shutdown || !filesToMove.isEmpty()) { while(!shutdown || !filesToRewrite.isEmpty()) {
Pair<Pair<File, String>, File> mv = filesToMove.poll(); File replayFile = filesToRewrite.poll();
if(mv != null) { if(replayFile != null) {
if(mv.getRight().canWrite()) { if(replayFile.canWrite()) {
try { try {
ReplayFileIO.addFileToZip(mv.getRight(), mv.getLeft().getLeft(), mv.getLeft().getRight()); HashMap<String, File> toAdd = new HashMap<String, File>();
for(Pair<File, String> p : filesToMove.get(replayFile)) {
toAdd.put(p.getRight(), p.getLeft());
}
ReplayFileIO.addFilesToZip(replayFile, toAdd);
//delete all written files
for(Pair<File, String> p : filesToMove.get(replayFile)) {
p.getLeft().delete();
}
filesToMove.removeAll(replayFile);
} catch(Exception e) { } catch(Exception e) {
e.printStackTrace(); e.printStackTrace();
filesToMove.add(mv); filesToRewrite.add(replayFile);
} finally { } finally {
callListeners(); callListeners();
} }
} else { } else {
filesToMove.add(mv); filesToRewrite.add(replayFile);
} }
} }
try { try {

View File

@@ -20,10 +20,7 @@ import org.apache.commons.io.IOUtils;
import java.io.*; import java.io.*;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
@@ -317,7 +314,14 @@ public class ReplayFileIO {
Files.write(file.toPath(), json.getBytes()); Files.write(file.toPath(), json.getBytes());
} }
public static void addFileToZip(File zipFile, File toAdd, String fileName) throws IOException { /**
* Adds Files as entries to a ZIP File.
* @param zipFile The ZIP File to add the files to.
* @param toAdd A Map containing the file's desired names as the keys and the files themselves as the values.
* Files may be null in order to remove entries with the respective name from the ZIP File.
* @throws IOException
*/
public static void addFilesToZip(File zipFile, HashMap<String, File> toAdd) throws IOException {
// get a temp file // get a temp file
File tempFile = File.createTempFile(zipFile.getName(), null, zipFile.getParentFile()); File tempFile = File.createTempFile(zipFile.getName(), null, zipFile.getParentFile());
// delete it, otherwise you cannot rename your existing zip to it. // delete it, otherwise you cannot rename your existing zip to it.
@@ -328,13 +332,15 @@ public class ReplayFileIO {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(tempFile)); ZipOutputStream out = new ZipOutputStream(new FileOutputStream(tempFile));
ZipEntry entry = zin.getNextEntry(); ZipEntry entry = zin.getNextEntry();
while(entry != null) { while(entry != null) {
String name = entry.getName(); String name = entry.getName();
boolean isFile = name.equalsIgnoreCase(fileName);
if(!isFile) { // Don't rewrite (keep) the old file if one of the new files uses the same name
// Add ZIP entry to output stream. boolean willBeOverwritten = toAdd.containsKey(name);
if(!willBeOverwritten) {
out.putNextEntry(new ZipEntry(name)); out.putNextEntry(new ZipEntry(name));
// Transfer bytes from the ZIP file to the output file // Transfer bytes from the ZIP entry to the output entry
int len; int len;
while((len = zin.read(buf)) > 0) { while((len = zin.read(buf)) > 0) {
out.write(buf, 0, len); out.write(buf, 0, len);
@@ -346,11 +352,17 @@ public class ReplayFileIO {
zin.close(); zin.close();
// Compress the files // Compress the files
if(toAdd != null) { // Write all files to Replay File
InputStream in = new FileInputStream(toAdd); if(!toAdd.isEmpty()) {
for(Map.Entry<String, File> e : toAdd.entrySet()) {
String fileName = e.getKey();
File toWrite = e.getValue();
// The File may be null to simply be removed
if(toWrite != null) {
InputStream in = new FileInputStream(toWrite);
// Add ZIP entry to output stream. // Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(fileName)); out.putNextEntry(new ZipEntry(fileName));
// Transfer bytes from the file to the ZIP file
int len; int len;
if(fileName.equals("thumb")) out.write(uniqueBytes); if(fileName.equals("thumb")) out.write(uniqueBytes);
@@ -361,8 +373,8 @@ public class ReplayFileIO {
// Complete the entry // Complete the entry
out.closeEntry(); out.closeEntry();
in.close(); in.close();
}
toAdd.delete(); }
} }
// Complete the ZIP file // Complete the ZIP file