package test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.LinkedList;
import java.util.List;
public class Main
{
public static void main(String[] args)
{
File source = new File("Y:\\copy\\Knoppix 5.1.0 - 30. 12. 2006 - Deutsch.iso");
File target = new File("Y:\\copy\\target.iso");
try
{
splitFile(source, target, 32 * 1024 * 1024);
source.delete();
mergeFile(target, source, true);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* Kopiert eine Datei und splitted sie in mehrere Ziele auf.
* @param source Die ursprüngliche Datei.
* @param target Die neue Dateinamenbasis. Dieser werden der Reihe nach die Extensions ".partN", also .part1,
* .part2 usw angehängt.
* @param chunkSize Die Größe der Parts. Darf keinesfalls höher als der der VM zu Verfügung gestellte RAM
* sein.
* @throws Falls eine IOException fliegt.
*/
public static void splitFile(File source, File target, int chunkSize) throws IOException
{
String targetNameBase = target.getAbsolutePath();
FileInputStream in = null;
FileChannel inChannel = null;
try
{
in = new FileInputStream(source);
inChannel = in.getChannel();
long fileLenght = source.length();
long bytesTransfered = 0L;
for(int i = 1; bytesTransfered < fileLenght; i++)
{
long bytesToTransfer = Math.min(chunkSize, fileLenght - bytesTransfered);
File realTargetFile = new File(targetNameBase + ".part" + i);
if(!realTargetFile.exists())
realTargetFile.createNewFile();
FileOutputStream out = null;
FileChannel outChannel = null;
try
{
out = new FileOutputStream(realTargetFile);
outChannel = out.getChannel();
long nowBytesTransfered = inChannel.transferTo(bytesTransfered, bytesToTransfer, outChannel);
bytesTransfered += nowBytesTransfered;
}
finally
{
try
{
if(outChannel != null)
outChannel.close();
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
if(out != null)
{
out.flush();
out.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
finally
{
try
{
if(inChannel != null)
inChannel.close();
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
if(in != null)
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
/**
* Führt eine zuvor gesplittete Datei wieder zusammen.
* @param source Die Dateinamenbasis. Diese muss <b>OHNE</b> ".partN" angegeben werden.
* @param target Die Datei, in die zusammengeführt werden soll.
* @param autoclear True, falls benutzte Parts automatisch gelöscht werden sollen, falls wenn nicht.
* Gelöscht wird ausschließlich, falls das Schreiben fehlerfrei ausgeführt wurde.
* @throws Falls eine IOException fliegt.
*/
public static void mergeFile(File source, File target, boolean autoclear) throws IOException
{
String sourceNameBase = source.getAbsolutePath();
FileOutputStream out = null;
FileChannel outChannel = null;
List<File> deleteFilesList = null;
if(autoclear)
deleteFilesList = new LinkedList<File>();
try
{
if(!target.exists())
target.createNewFile();
out = new FileOutputStream(target);
outChannel = out.getChannel();
File realSourceFile = null;
for(int i = 1; (realSourceFile = new File(sourceNameBase + ".part" + i)).exists(); i++)
{
FileInputStream in = null;
FileChannel inChannel = null;
try
{
int chunkSize = (int) realSourceFile.length();
in = new FileInputStream(realSourceFile);
inChannel = in.getChannel();
inChannel.transferTo(0, chunkSize, outChannel);
}
finally
{
try
{
if(inChannel != null)
inChannel.close();
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
if(in != null)
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
if(autoclear)
deleteFilesList.add(realSourceFile);
}
}
finally
{
try
{
if(out != null)
{
out.flush();
out.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
if(autoclear)
for(File f:deleteFilesList)
f.delete();
}
}