/* Copyright 2019-2020 Dmitry Isaenko This file is part of NS-USBloader. NS-USBloader is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. NS-USBloader is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with NS-USBloader. If not, see . */ package nsusbloader.COM.Helpers; import java.io.*; /** * Handle Split files * */ public class NSSplitReader implements Closeable { private final String splitFileDir; private final long referenceSplitChunkSize; private byte subFileNum; private long curPosition; private BufferedInputStream biStream; public NSSplitReader(File file, long seekToPosition) throws IOException, NullPointerException { this.splitFileDir = file.getAbsolutePath()+File.separator; File subFile = new File(file.getAbsolutePath()+File.separator+"00"); if (! file.exists()) throw new FileNotFoundException("File not found on "+file.getAbsolutePath()+File.separator+"00"); this.referenceSplitChunkSize = subFile.length(); this.subFileNum = (byte) (seekToPosition / referenceSplitChunkSize); this.biStream = new BufferedInputStream(new FileInputStream(splitFileDir + String.format("%02d", subFileNum))); this.curPosition = seekToPosition; seekToPosition -= referenceSplitChunkSize * subFileNum; if (seekToPosition != biStream.skip(seekToPosition)) throw new IOException("Unable to seek to requested position of "+seekToPosition+" for file "+splitFileDir+String.format("%02d", subFileNum)); } public long seek(long position) throws IOException{ byte subFileRequested = (byte) (position / referenceSplitChunkSize); if ((subFileRequested != this.subFileNum) || (curPosition > position)) { biStream.close(); biStream = new BufferedInputStream(new FileInputStream(splitFileDir + String.format("%02d", subFileRequested))); this.subFileNum = subFileRequested; this.curPosition = referenceSplitChunkSize * subFileRequested; } long retVal = biStream.skip(position - curPosition); retVal += curPosition; this.curPosition = position; return retVal; } public int read(byte[] readBuffer) throws IOException, NullPointerException { final int requested = readBuffer.length; int readPrtOne; if ( (curPosition + requested) <= (referenceSplitChunkSize * (subFileNum+1))) { if ((readPrtOne = biStream.read(readBuffer)) < 0 ) return readPrtOne; curPosition += readPrtOne; return readPrtOne; } int partOne = (int) (referenceSplitChunkSize * (subFileNum+1) - curPosition); int partTwo = requested - partOne; int readPrtTwo; if ( (readPrtOne = biStream.read(readBuffer, 0, partOne)) < 0) return readPrtOne; curPosition += readPrtOne; if (readPrtOne != partOne) return readPrtOne; biStream.close(); subFileNum += 1; biStream = new BufferedInputStream(new FileInputStream(splitFileDir + String.format("%02d", subFileNum))); if ( (readPrtTwo = biStream.read(readBuffer, partOne, partTwo) ) < 0) return readPrtTwo; curPosition += readPrtTwo; return readPrtOne + readPrtTwo; } @Override public void close() throws IOException { if (biStream != null) biStream.close(); } }