It is required to split the file (usually an archive) into a certain number of parts. I found a ready working version on c #, but could not adapt it to java. Please help translate the code or suggest a solution, thanks.

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(); } 
  • one
    please show any decision you make. - Mikhail Vaysman
  • I do not have it, since I have not yet figured out in principle how this is implemented. So far it turned out to be packaged only in zip, but only in one volume how to pack in the n-th number of volumes did not figure it out either - fn12gl34
  • By the way, from the point of view of C #, the decision is awful: the source file is read all into memory - why? The using construct is not used - if an exception is thrown, the files will remain unclosed. (Well, from somewhere, an incomprehensible txtSourceFile.Text .) - VladD

2 answers 2

Look bad, took from here

 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); } } 

    You can do this:

     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; } } } } } 

    There are some problems with the size of the buffer, in extreme cases, everything can break.