0

因此,我制作了一个在 Java 中拆分 .mp3 文件的程序。基本上,它在某些文件上运行良好,但在某些文件上,第一个拆分文件在播放某些部分后遇到错误。其他文件虽然工作得很好。

我认为这与文件如何不能是我的数组大小的倍数有关,并且应该留下一些 mod 值。任何人都可以找出这段代码中的错误并纠正它吗?

(这里,splitval = 要进行的分割数,filename1= 所选文件)

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

       }

提前致谢!

编辑:我按照建议编辑了代码,运行它。这里:

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  

最后几个字节发生了变化,这意味着文件大小%splitval 已解决。但在播放最后一部分时,包含“_split_1”的第一个文件仍然存在错误。

包含“_split_2”的第二个文件正好从第一个文件结束的地方开始。所以拆分过程是正确的。那么,第一个文件末尾的多余空白到底是什么?

另外,我注意到原始文件的图稿和信息仅保留到第一个文件中。没有其他文件。它与此有关吗?同样的事情不会发生在其他一些 mp3 文件中。

代码:

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

1 回答 1

2

我怀疑您是否可以mp3仅通过将 n 字节复制到文件并转到下一个来拆分文件。Mp3 具有特定的格式,您可能需要一个来处理这种格式。

编辑关于部分文件的大小都是相等的:

您没有将文件的所有字节都写入split文件。如果将所有split文件的大小相加并将其与原始文件的大小进行比较,您会发现丢失了一些字节。这是因为您的循环从1to运行splitval并始终将确切的字节数写入每个部分文件,即splitsize. 所以你丢失的字节数是filesize % splitval.

要解决此问题,只需添加filesize % splitvalsplitsize. 这样你就不会丢失任何字节。从1到的文件splitval - 1将具有相同的大小,最后一个文件将更小。

这是您的代码的更正版本,其中添加了一些用于合并split 文件以便使用 SHA1 校验和执行断言的内容。

免责声明- 输出文件不应是正确的 mp3 文件

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

输出(用于我的测试文件)

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
于 2013-07-26T16:38:57.273 回答