0

So, I made a program that splits a .mp3 file in Java. Basically, it works fine on some files but on some, the first split file encounters an error after playing some part. The other files work completely fine though.

I think it has something to do with how a file cannot be a multiple of the size of my array and there should be some mod value left. Can anybody please identify the error in this code and correct it?

(here, splitval = no. of splits to be made, filename1= the selected file)

 int splitsize=filesize/splitval;
 String filecalled;
 try
 {
        byte []b=new byte[splitsize];
        FileInputStream fis = new FileInputStream(filename1);
        name1=filename2.replaceAll(".mp3", "");
        for(int j=1;j<=splitval;j++)
        {
            filecalled=name1+"_split_"+j+".mp3";
            FileOutputStream fos = new FileOutputStream(filecalled);
            int i=fis.read(b);
            fos.write(b, 0, i);
            //System.out.println("no catch");
         }
        JOptionPane.showMessageDialog(this, "split process successful");
     }
   catch(IOException e)
       {
           System.out.println(e.getMessage());

       }

Thanks in advance!

EDIT: I edited the code as suggested, ran it. Here:

C:\Users\dell5050\Desktop\Julien.mp3      5383930 bytes  
C:\Users\dell5050\Desktop\ Julien_split_1.mp3    1345984 bytes  
C:\Users\dell5050\Desktop\ Julien_split_2.mp3    1345984 bytes  
C:\Users\dell5050\Desktop\ Julien_split_3.mp3    1345984 bytes  
C:\Users\dell5050\Desktop\ Julien_split_4.mp3    1345978 bytes  

There is change in the last few bytes which means that the filesize%splitval is solved.. but still the first file in this.. containing '_split_1' has error while playing some of the last part.

The second file containing '_split_2' starts exactly where the first ended. So the split process is correct. Then, what exactly is the extra empty in the end of the first file?

Also, I noticed that the artwork and info of the original file carries over into the first file ONLY. No other files. Does it have something to do with that? Same thing doesnt happen in some other mp3 files.

CODE:

FileInputStream fis;
    FileOutputStream fos;
    int splitsize = (int)(filesize / splitval) + (int)(filesize % splitval);
    byte[] b = new byte[splitsize];
    System.out.println(filename1 + "            " + filesize + " bytes");
    try 
    {
        fis = new FileInputStream(file);
        name1 = filename2.replaceAll(".mp3", "");
        for (int j = 1; j <= splitval; j++) 
        {
            String filecalled = name1 + "_split_" + j + ".mp3";
            fos = new FileOutputStream(filecalled);
            int i = fis.read(b);
            fos.write(b, 0, i);
            fos.close();
            System.out.println(filecalled + "    " + i + " bytes");

        }
    }
    catch(IOException ie)
    {
        System.out.println(ie.getMessage());
    }                        

1 Answers1

2

I doubt you could split a mp3 file just by copying n-bytes to a file and go to the next. Mp3 has a specific format and you'll probably need a library to handle this format.

EDIT regarding the size of the part files being all equal:

You are not writing all the bytes of the file to the split files. If you sum the sizes of all split files and compare it to the size of the original file you'll find out that your missing some bytes. This is because your loop runs from 1 to splitval and always writes the exact number of bytes to each part file i.e. splitsize. So the number of bytes your are missing is filesize % splitval.

To resolve this problem simply add filesize % splitval to splitsize. This way you'll not be missing any bytes. The files from 1 to splitval - 1 will have the same size, the last file will be smaller.

Here is a corrected version of your code with some additions to merge the split files in order to perform an assertion using SHA1-checksum.

Disclaimer - The output files are not expected to be proper mp3 files

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import junit.framework.Assert;

import org.junit.Test;

public class SplitFile {

    @Test
    public void splitFile() throws IOException, NoSuchAlgorithmException {
        String filename1 = "mp3/Innocence_-_Nero.mp3";
        File file = new File(filename1);
        FileInputStream fis = null;
        FileOutputStream fos = null;
        long filesize = file.length();
        long filesizeActual = 0L;
        int splitval = 5;
        int splitsize = (int)(filesize / splitval) + (int)(filesize % splitval);
        byte[] b = new byte[splitsize];
        System.out.println(filename1 + "            " + filesize + " bytes");
        try {
            fis = new FileInputStream(file);
            String name1 = filename1.replaceAll(".mp3", "");
            String mergeFile = name1 + "_merge.mp3";
            for (int j = 1; j <= splitval; j++) {
                String filecalled = name1 + "_split_" + j + ".mp3";
                fos = new FileOutputStream(filecalled);
                int i = fis.read(b);
                fos.write(b, 0, i);
                fos.close();
                fos = null;
                System.out.println(filecalled + "    " + i + " bytes");
                filesizeActual += i;
            }
            Assert.assertEquals(filesize, filesizeActual);
            mergeFileParts(filename1, splitval);
            check(filename1, mergeFile);
        } finally {
            if(fis != null) {
                fis.close();
            }
            if(fos != null) {
                fos.close();
            }
        }
    }

    private void mergeFileParts(String filename1, int splitval) throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            String name1 = filename1.replaceAll(".mp3", "");
            String mergeFile = name1 + "_merge.mp3";
            fos = new FileOutputStream(mergeFile);
            for (int j = 1; j <= splitval; j++) {
                String filecalled = name1 + "_split_" + j + ".mp3";
                File partFile = new File(filecalled);
                fis = new FileInputStream(partFile);
                int partFilesize = (int) partFile.length();
                byte[] b = new byte[partFilesize];
                int i = fis.read(b, 0, partFilesize);
                fos.write(b, 0, i);
                fis.close();
                fis = null;
            }
        } finally {
            if(fis != null) {
                fis.close();
            }
            if(fos != null) {
                fos.close();
            }
        }
    }

    private void check(String expectedPath, String actualPath) throws IOException, NoSuchAlgorithmException {
        System.out.println("check...");

        FileInputStream fis = null;

        try {

            File expectedFile = new File(expectedPath);
            long expectedSize = expectedFile.length();

            File actualFile = new File(actualPath);
            long actualSize = actualFile.length();

            System.out.println("exp=" + expectedSize);
            System.out.println("act=" + actualSize);

            Assert.assertEquals(expectedSize, actualSize);

            fis = new FileInputStream(expectedFile);
            String expected = makeMessageDigest(fis);
            fis.close();
            fis = null;


            fis = new FileInputStream(actualFile);
            String actual = makeMessageDigest(fis);
            fis.close();
            fis = null;

            System.out.println("exp=" + expected);
            System.out.println("act=" + actual);

            Assert.assertEquals(expected, actual);

        } finally {
            if(fis != null) {
                fis.close();
            }
        }
    }

    public String makeMessageDigest(InputStream is) throws NoSuchAlgorithmException, IOException {
        byte[] data = new byte[1024];
        MessageDigest md = MessageDigest.getInstance("SHA1");
        int bytesRead = 0;

        while(-1 != (bytesRead = is.read(data, 0, 1024))) {
            md.update(data, 0, bytesRead);
        }

        return toHexString(md.digest());
    }

    private String toHexString(byte[] digest) {
        StringBuffer sha1HexString = new StringBuffer();
        for(int i = 0; i < digest.length; i++) {
            sha1HexString.append(String.format("%1$02x", Byte.valueOf(digest[i])));
        }

        return sha1HexString.toString();
    }
}

Output (for my test file)

mp3/Innocence_-_Nero.mp3            5048528 bytes
mp3/Innocence_-_Nero_split_1.mp3    1009708 bytes
mp3/Innocence_-_Nero_split_2.mp3    1009708 bytes
mp3/Innocence_-_Nero_split_3.mp3    1009708 bytes
mp3/Innocence_-_Nero_split_4.mp3    1009708 bytes
mp3/Innocence_-_Nero_split_5.mp3    1009696 bytes
check...
exp=5048528
act=5048528
exp=e81cf2dc65ab84e3df328e52d63a55301232b917
act=e81cf2dc65ab84e3df328e52d63a55301232b917
Community
  • 1
  • 1
A4L
  • 16,713
  • 6
  • 43
  • 60
  • The thing is that the whole code is working fine. Splits are made, files are playing. The first file is the thing troubling me. That too... in only a few files. – user2602294 Jul 26 '13 at 17:11
  • 1
    *"Splits are made, files are playing."* In *what*? Note that most players will go to ***extraordinary*** lengths to play broken files, and the way that code is splitting the files definitely breaks them. – Andrew Thompson Jul 26 '13 at 17:28
  • The windows media player works fine. I tried vlc. That works too. – user2602294 Jul 26 '13 at 17:37
  • 1
    @user2602294 well, a media player is a smart piece of software ;-) – A4L Jul 26 '13 at 17:39
  • That's the point.. the file is playing. Equal sized split files are being made, which should be wrong, logically. Because the file cannot be in multiples of my array size, which is equal to splitsize. – user2602294 Jul 26 '13 at 18:09
  • @user2602294 No, this has nothing to do with using or not using lists. See my edit for explanation. – A4L Jul 26 '13 at 19:10
  • @A4L I'm actually new to Java, lol. And thanks for the coding, but there's stuff in there that I dont understand as of now. I'll try to though. But, for writing that, thanks! XD – user2602294 Jul 26 '13 at 19:24
  • @user2602294 You're welcome. You don't need to bother with the stuff I added, just look at my edits to your code i.e. the body of the method `splitFile`. – A4L Jul 26 '13 at 19:27
  • Though, I did understand the logic you tried implementing. Everything you added before the coding. Few things after that. – user2602294 Jul 26 '13 at 19:28