package org.jaudiotagger.test; import java.io.*; import java.text.DateFormat; import java.util.Date; /** * Simple class that will attempt to recusively read all files within a directory ending in .mp3 (but * only actually expected to contain id3 tags), merge them with a given mp3 and write them to the provided * output folder (which must already exist) */ public class MergeID3AndMP3Files { public static void main(final String[] args) { MergeID3AndMP3Files test = new MergeID3AndMP3Files(); if (args.length == 0) { System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); System.err.println(" You must enter the from dir,outputdir and the mp3file to append"); System.exit(1); } else if (args.length != 3) { System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); System.err.println(" Only three parameters accepted"); System.exit(1); } File rootDir = new File(args[0]); if (!rootDir.isDirectory()) { System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); System.err.println(" Directory " + args[0] + " could not be found"); System.exit(1); } File toDir = new File(args[1]); if (!rootDir.isDirectory()) { System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); System.err.println(" Directory " + args[1] + " could not be found"); System.exit(1); } File mp3File = new File(args[2]); if (!mp3File.isFile()) { System.err.println("usage MergeID3AndMP3Files FromDir ToDir mp3File"); System.err.println(" Mp3File " + args[2] + " could not be found"); System.exit(1); } Date start = new Date(); System.out.println("Started to merge from:" + rootDir.getPath() + " at " + DateFormat.getTimeInstance().format(start)); test.scanSingleDir(rootDir, toDir, mp3File); Date finish = new Date(); System.out.println("Finished to merge from:" + rootDir.getPath() + DateFormat.getTimeInstance().format(finish)); System.out.println("Attempted to merge:" + MergeID3AndMP3Files.count); System.out.println("Successful to merge:" + (MergeID3AndMP3Files.count - MergeID3AndMP3Files.failed)); System.out.println("Failed to merge:" + MergeID3AndMP3Files.failed); } private static int count = 0; private static int failed = 0; /** * Recursive function to scan directory * * @param fromDir * @param toDir * @param mp3File */ private void scanSingleDir(final File fromDir, final File toDir, final File mp3File) { final File[] audioFiles = fromDir.listFiles(new MergeID3AndMP3Files.MP3FileFilter()); if (audioFiles.length > 0) { for (File audioFile : audioFiles) { MergeID3AndMP3Files.count++; try { copyAudioToTmp(toDir, audioFile, mp3File); } catch (Throwable t) { System.err.println("Unable to merge record:" + MergeID3AndMP3Files.count + ":" + mp3File.getPath()); MergeID3AndMP3Files.failed++; t.printStackTrace(); } } } final File[] audioFileDirs = fromDir.listFiles(new MergeID3AndMP3Files.DirFilter()); if (audioFileDirs.length > 0) { for (File audioFileDir : audioFileDirs) { scanSingleDir(audioFileDir, new File(toDir, audioFileDir.getName()), mp3File); } } } final class MP3FileFilter extends javax.swing.filechooser.FileFilter implements java.io.FileFilter { /** * allows Directories */ private final boolean allowDirectories; /** * Create a default MP3FileFilter. The allowDirectories field will * default to false. */ public MP3FileFilter() { this(false); } /** * Create an MP3FileFilter. If allowDirectories is true, then this filter * will accept directories as well as mp3 files. If it is false then * only mp3 files will be accepted. * * @param allowDirectories whether or not to accept directories */ private MP3FileFilter(final boolean allowDirectories) { this.allowDirectories = allowDirectories; } /** * Determines whether or not the file is an mp3 file. If the file is * a directory, whether or not is accepted depends upon the * allowDirectories flag passed to the constructor. * * @param file the file to test * @return true if this file or directory should be accepted */ public final boolean accept(final File file) { return (((file.getName()).toLowerCase().endsWith(".mp3")) || (file.isDirectory() && (this.allowDirectories))); } /** * Returns the Name of the Filter for use in the Chooser Dialog * * @return The Description of the Filter */ public final String getDescription() { return ".mp3 Files"; } } public final class DirFilter implements java.io.FileFilter { public DirFilter() { } /** * Determines whether or not the file is an mp3 file. If the file is * a directory, whether or not is accepted depends upon the * allowDirectories flag passed to the constructor. * * @param file the file to test * @return true if this file or directory should be accepted */ public final boolean accept(final File file) { return file.isDirectory(); } public static final String IDENT = "$Id: MergeID3AndMP3Files.java 836 2009-11-12 15:44:07Z paultaylor $"; } public static File copyAudioToTmp(File toDir, File tagFile, File mp3File) { File outputFile = new File(toDir.getPath(), tagFile.getName()); boolean result = append(tagFile, mp3File, outputFile); return outputFile; } private static boolean append(File fromFile1, File fromFile2, File toFile) { try { FileInputStream in = new FileInputStream(fromFile1); FileInputStream in2 = new FileInputStream(fromFile2); toFile.getParentFile().mkdirs(); FileOutputStream out = new FileOutputStream(toFile); BufferedInputStream inBuffer = new BufferedInputStream(in); BufferedInputStream inBuffer2 = new BufferedInputStream(in2); BufferedOutputStream outBuffer = new BufferedOutputStream(out); int theByte; while ((theByte = inBuffer.read()) > -1) { outBuffer.write(theByte); } while ((theByte = inBuffer2.read()) > -1) { outBuffer.write(theByte); } outBuffer.close(); inBuffer.close(); inBuffer2.close(); out.close(); in.close(); in2.close(); // cleanupif files are not the same length if ((fromFile1.length() + fromFile2.length()) != toFile.length()) { toFile.delete(); return false; } return true; } catch (IOException e) { e.printStackTrace(); return false; } } }