package moe.nekojimi.friendcloud; import moe.nekojimi.friendcloud.objects.NetworkFile; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class FilePieceAccess implements Closeable { private final NetworkFile networkFile; private final File file; private final RandomAccessFile randomAccessFile; private final OpenMode openMode; public FilePieceAccess(NetworkFile networkFile, OpenMode openMode) throws IOException { this.networkFile = networkFile; this.file = networkFile.getOrCreateLocalFile(); this.randomAccessFile = new RandomAccessFile(file,openMode == OpenMode.READ_WRITE ? "rw" : "r"); this.openMode = openMode; if (openMode == OpenMode.READ_WRITE) randomAccessFile.setLength(file.length()); } public long getPieceOffset(int index) { return (index * networkFile.getPieceSize()); } public int getPieceSize(int index) { if (index != networkFile.getPieceCount()-1) return Math.toIntExact(networkFile.getPieceSize()); int ret = Math.toIntExact(networkFile.getSize() % networkFile.getPieceSize()); if (ret == 0) ret = Math.toIntExact(networkFile.getPieceSize()); return ret; } public byte[] readPiece(int index) throws IOException { if (index >= networkFile.getPieceCount()) throw new IllegalArgumentException("Piece index out of range!!"); if (index < 0) throw new IllegalArgumentException("Piece index is negative!!"); if (!networkFile.hasPiece(index)) return null; int pieceSize = getPieceSize(index); byte[] buffer = new byte[pieceSize]; long pieceOffset = getPieceOffset(index); System.out.println("Reading piece " + index + " from file " + file.getName() + " (offset=" + pieceOffset + ", size=" + pieceSize + ")"); randomAccessFile.seek(pieceOffset); randomAccessFile.read(buffer); return buffer; } public void writePiece(int index, byte[] buffer) throws IOException { if (openMode == OpenMode.READ_ONLY) throw new IllegalStateException("File was opened read-only!"); else if (buffer.length != getPieceSize(index)) throw new IllegalArgumentException("Received a file piece that's the wrong size!! Length = " + buffer.length + " != Piece Size = " + getPieceSize(index)); else if (index >= networkFile.getPieceCount()) throw new IllegalArgumentException("Received a file piece with an index past the end of the file!!"); randomAccessFile.seek(getPieceOffset(index)); randomAccessFile.write(buffer); networkFile.setHasPiece(index, true); } @Override public void close() throws IOException { randomAccessFile.close(); } public enum OpenMode { READ_ONLY, READ_WRITE; } }