Разбиение файла на n частей java

1041
12 января 2017, 03:18

Требуется разбить файл (как правило архив) на определенное количество частей. Нашел готовый рабочий вариант на c#, но не смог его адаптировать к java. Прошу помочь перевести код или подсказать решение, спасибо.

 private void SplitFile(string FileInputPath, string FolderOutputPath, int OutputFiles)
    {
        // Store the file in a byte array
        Byte[] byteSource = System.IO.File.ReadAllBytes(FileInputPath);
        // Get file info
        FileInfo fiSource = new FileInfo(txtSourceFile.Text);
        // Calculate the size of each part
        int partSize = (int)Math.Ceiling((double)(fiSource.Length / OutputFiles));
        // The offset at which to start reading from the source file
        int fileOffset = 0;
        // Stores the name of each file part
        string currPartPath;
        // The file stream that will hold each file part
        FileStream fsPart;
        // Stores the remaining byte length to write to other files
        int sizeRemaining = (int)fiSource.Length;
        // Loop through as many times we need to create the partial files
        for (int i = 0; i < OutputFiles; i++)
        {
            // Store the path of the new part
            currPartPath = FolderOutputPath + "\\" + fiSource.Name + "." + String.Format(@"{0:D4}", i) + ".part";
            // A filestream for the path
            if (!File.Exists(currPartPath))
            {
                fsPart = new FileStream(currPartPath, FileMode.CreateNew);
                // Calculate the remaining size of the whole file
                sizeRemaining = (int)fiSource.Length - (i * partSize);
                // The size of the last part file might differ because a file doesn't always split equally
                if (sizeRemaining < partSize)
                {
                    partSize = sizeRemaining;
                }
                fsPart.Write(byteSource, fileOffset, partSize);
                fsPart.Close();
                fileOffset += partSize;
            }
        }
    }
    private void JoinFiles(string FolderInputPath, string FileOutputPath)
    {
        DirectoryInfo diSource = new DirectoryInfo(FolderInputPath);
        FileStream fsSource = new FileStream(FileOutputPath, FileMode.Append);
        foreach (FileInfo fiPart in diSource.GetFiles(@"*.part"))
        {
            Byte[] bytePart = System.IO.File.ReadAllBytes(fiPart.FullName);
            fsSource.Write(bytePart, 0, bytePart.Length);
        }
        fsSource.Close();
    }
Answer 1

Плохо ищите, взял отсюда

public static void main(String[] args) throws Exception
{
    RandomAccessFile raf = new RandomAccessFile("test.csv", "r");
    long numSplits = 10; //from user input, extract it from args
    long sourceSize = raf.length();
    long bytesPerSplit = sourceSize/numSplits ;
    long remainingBytes = sourceSize % numSplits;
    int maxReadBufferSize = 8 * 1024; //8KB
    for(int destIx=1; destIx <= numSplits; destIx++) {
        BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+destIx));
        if(bytesPerSplit > maxReadBufferSize) {
            long numReads = bytesPerSplit/maxReadBufferSize;
            long numRemainingRead = bytesPerSplit % maxReadBufferSize;
            for(int i=0; i<numReads; i++) {
                readWrite(raf, bw, maxReadBufferSize);
            }
            if(numRemainingRead > 0) {
                readWrite(raf, bw, numRemainingRead);
            }
        }else {
            readWrite(raf, bw, bytesPerSplit);
        }
        bw.close();
    }
    if(remainingBytes > 0) {
        BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+(numSplits+1)));
        readWrite(raf, bw, remainingBytes);
        bw.close();
    }
        raf.close();
}
static void readWrite(RandomAccessFile raf, BufferedOutputStream bw, long numBytes) throws IOException {
    byte[] buf = new byte[(int) numBytes];
    int val = raf.read(buf);
    if(val != -1) {
        bw.write(buf);
    }
}
Answer 2

Можно сделать так:

private void fileSplit(String fileName, int partCount) throws Exception {
    Path filePath = Paths.get(fileName);
    try (BufferedInputStream input = 
                   new BufferedInputStream(Files.newInputStream(filePath))) {
        long size = Files.size(filePath);
        //сделать более хитрее
        byte[] buffer = new byte[1024];
        long partSize = size / partCount;
        for (int i = 0; i < partCount; i++) {
          String partFileName = fileName + "$" + i;
          try (OutputStream outputStream = Files.newOutputStream(Paths.get(partFileName));
                 BufferedOutputStream output = new BufferedOutputStream(outputStream)) {
                int currentSize = 0;
                while (currentSize < partSize) {
                    int byteCount = input.read(buffer);
                    output.write(buffer, 0, byteCount);
                    currentSize += byteCount;
                }
            }
        }
    }
}

Есть небольшие проблемы с размером буфера, в крайних случаях, все может поломаться.

READ ALSO
Использование фильтра в bindingsource при использовании entity framework

Использование фильтра в bindingsource при использовании entity framework

Здравствуйте, возникли проблемы при фильтрации в bindingSourceНасколько я понимаю, если использовать entity framework, то свойство SupportsFiltering bindingsource принимает...

398
Как грамотно убрать фокус с TextBox?

Как грамотно убрать фокус с TextBox?

Всем доброе утроКак грамотно убрать фокус с TextBox? Свойство Focused для данного контрола доступно только для чтения

910
Создать собственный вариант TileMode c# WPF

Создать собственный вариант TileMode c# WPF

Можно как-то создать собственный вариант ImageDrawingTileMode в c# wpf

292
Указать url для пагинации в CalendarController

Указать url для пагинации в CalendarController

Добрый день! Есть проект на Yii2, в контроллере CalendarController я через action index во view вывожу ListViewВсе работает замечательно, но при переключении пагинации,...

372