Added old book importer

This commit is contained in:
2020-02-10 13:49:13 +00:00
parent 13d8dc4612
commit da3b88e083
5 changed files with 119 additions and 262 deletions

View File

@@ -246,6 +246,14 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
} }
}); });
JMenuItem openOld = new JMenuItem("Import old audiobook...");
openOld.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Debug.trace();
importOldStyleBook();
}
});
fileOptions = new JMenuItem("Options"); fileOptions = new JMenuItem("Options");
fileOptions.addActionListener(new ActionListener() { fileOptions.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@@ -266,6 +274,7 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
fileMenu.add(fileNewBook); fileMenu.add(fileNewBook);
fileMenu.add(fileOpenBook); fileMenu.add(fileOpenBook);
fileMenu.add(fileOpenArchive); fileMenu.add(fileOpenArchive);
fileMenu.add(openOld);
fileMenu.add(fileSave); fileMenu.add(fileSave);
fileMenu.addSeparator(); fileMenu.addSeparator();
fileMenu.add(fileOptions); fileMenu.add(fileOptions);
@@ -2145,8 +2154,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
if (recording == null) return; if (recording == null) return;
recording.stopRecording(); recording.stopRecording();
// getBook().reloadTree();
bookTree.expandPath(new TreePath(((DefaultMutableTreeNode)recording.getParent()).getPath())); bookTree.expandPath(new TreePath(((DefaultMutableTreeNode)recording.getParent()).getPath()));
bookTree.setSelectionPath(new TreePath(recording.getPath())); bookTree.setSelectionPath(new TreePath(recording.getPath()));
bookTree.scrollPathToVisible(new TreePath(recording.getPath())); bookTree.scrollPathToVisible(new TreePath(recording.getPath()));
@@ -2257,225 +2264,92 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
} }
} }
/* Retained for legacy use...! */ public Chapter convertChapter(String name, String id, Properties data) {
public void buildBook(Properties prefs) { Chapter c = new Chapter(id, data.getProperty("chapter." + name + ".name"));
c.setPostGap(Utils.s2i(data.getProperty("chapter." + name + ".post-gap")));
c.setPreGap(Utils.s2i(data.getProperty("chapter." + name + ".pre-gap")));
for (int i = 0; i < 100000000; i++) {
String sid = data.getProperty(String.format("chapter." + name + ".sentence.%08d.id", i));
String text = data.getProperty(String.format("chapter." + name + ".sentence.%08d.text", i));
int gap = Utils.s2i(data.getProperty(String.format("chapter." + name + ".sentence.%08d.post-gap", i)));
if (sid == null) break;
Sentence s = new Sentence(sid, text);
s.setPostGap(gap);
s.setStartOffset(Utils.s2i(data.getProperty(String.format("chapter." + name + ".sentence.%08d.start-offset", i))));
s.setEndOffset(Utils.s2i(data.getProperty(String.format("chapter. " + name + ".sentence.%08d.end-offset", i))));
s.setLocked(Utils.s2b(data.getProperty(String.format("chapter." + name + ".sentence.%08d.locked", i))));
s.setAttentionFlag(Utils.s2b(data.getProperty(String.format("chapter." + name + ".sentence.%08d.attention", i))));
s.setGain(Utils.s2d(data.getProperty(String.format("chapter." + name + ".sentence.%08d.gain", i))));
s.setEffectChain(data.getProperty(String.format("chapter." + name + ".sentence.%08d.effect", i)));
s.setPostGapType(data.getProperty(String.format("chapter." + name + ".sentence.%08d.gaptype", i)));
c.add(s);
}
return c;
}
public void importOldStyleBook() {
Debug.trace(); Debug.trace();
/* JFileChooser jc = new JFileChooser(new File(Options.get("path.storage")));
book = new Book(prefs, prefs.getProperty("book.name")); FileNameExtensionFilter filter = new FileNameExtensionFilter("Old Audiobooks", "abk");
jc.addChoosableFileFilter(filter);
jc.setFileFilter(filter);
jc.setDialogTitle("Select Old Audiobook");
int r = jc.showOpenDialog(this);
getBook().setAuthor(prefs.getProperty("book.author")); if (r == JFileChooser.APPROVE_OPTION) {
getBook().setGenre(prefs.getProperty("book.genre")); File f = jc.getSelectedFile();
getBook().setComment(prefs.getProperty("book.comment")); if (f.exists()) {
getBook().setACX(prefs.getProperty("book.acx")); convertOldStyleBook(f);
getBook().loadEffects();
String defaultEffectChain = prefs.getProperty("audio.effect.default");
if (defaultEffectChain == null) {
defaultEffectChain = "none";
}
getBook().setDefaultEffect(defaultEffectChain);
int sr = Utils.s2i(prefs.getProperty("audio.recording.samplerate"));
if (sr == 0) {
sr = Options.getInteger("audio.recording.samplerate");
}
getBook().setSampleRate(sr);
int chans = Utils.s2i(prefs.getProperty("audio.recording.channels"));
if (chans == 0) {
chans = Options.getInteger("audio.recording.channels");
}
getBook().setChannels(chans);
int res = Utils.s2i(prefs.getProperty("audio.recording.resolution"));
if (res == 0) {
res = Options.getInteger("audio.recording.resolution");
}
getBook().setResolution(res);
bookTreeModel = new DefaultTreeModel(book);
bookTree = new JTree(bookTreeModel);
bookTree.setEditable(true);
bookTree.setUI(new CustomTreeUI(mainScroll));
bookTree.setCellRenderer(new BookTreeRenderer());
InputMap im = bookTree.getInputMap(JComponent.WHEN_FOCUSED);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "startStopPlayback");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_DOWN_MASK), "startPlaybackFrom");
bookTree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
Debug.trace();
DefaultMutableTreeNode n = (DefaultMutableTreeNode)bookTree.getLastSelectedPathComponent();
if (n instanceof BookTreeNode) {
BookTreeNode btn = (BookTreeNode)n;
btn.onSelect(btn);
}
if (n instanceof Sentence) {
Sentence s = (Sentence)n;
//selectedSentence = s;
sampleWaveform.setData(s.getDoubleAudioData(effectsEnabled));
sampleWaveform.setMarkers(s.getStartOffset(), s.getEndOffset());
s.updateCrossings();
sampleWaveform.setAltMarkers(s.getStartCrossing(), s.getEndCrossing());
postSentenceGap.setValue(s.getPostGap());
gainPercent.setValue((int)(s.getGain() * 100d));
locked.setSelected(s.isLocked());
attention.setSelected(s.getAttentionFlag());
setEffectChain(s.getEffectChain());
postSentenceGap.setEnabled(!s.isLocked());
gainPercent.setEnabled(!s.isLocked());
reprocessAudioFFT.setEnabled(!s.isLocked());
reprocessAudioPeak.setEnabled(!s.isLocked());
selectCutMode.setEnabled(!s.isLocked());
selectSplitMode.setEnabled(!s.isLocked());
doCutSplit.setEnabled(false);
selectCutMode.setSelected(false);
selectSplitMode.setSelected(false);
} else {
//selectedSentence = null;
sampleWaveform.clearData();
postSentenceGap.setValue(0);
gainPercent.setValue(100);
locked.setSelected(false);
attention.setSelected(false);
selectCutMode.setEnabled(false);
selectSplitMode.setEnabled(false);
doCutSplit.setEnabled(false);
selectCutMode.setSelected(false);
selectSplitMode.setSelected(false);
}
} }
}); }
}
public void convertOldStyleBook(File f) {
Debug.trace();
try {
Properties data = new Properties();
data.loadFromXML(new FileInputStream(f));
File sourceFolder = f.getParentFile();
bookTree.addMouseListener(new MouseAdapter() { Book book = new Book(data.getProperty("book.name"));
public void mousePressed(MouseEvent e) { book.setAuthor(data.getProperty("book.author"));
Debug.trace(); book.setGenre(data.getProperty("book.genre"));
if (e.isPopupTrigger()) { book.setComment(data.getProperty("book.comment"));
treePopup(e); book.setACX(data.getProperty("book.acx"));
}
book.setDefaultEffect(data.getProperty("audio.effect.default"));
book.add(convertChapter("audition", "audition", data));
book.add(convertChapter("open", "open", data));
book.add(convertChapter("close", "close", data));
for (int cno = 1; cno < 10000; cno++) {
String oldid = String.format("%04d", cno);
String newid = UUID.randomUUID().toString();
if (data.getProperty("chapter." + oldid + ".name") == null) break;
book.add(convertChapter(oldid, newid, data));
} }
public void mouseReleased(MouseEvent e) { book.save();
Debug.trace();
if (e.isPopupTrigger()) {
treePopup(e);
}
}
});
mainScroll.setViewportView(bookTree);
Chapter c = new Chapter("audition", prefs.getProperty("chapter.audition.name"));
c.setPostGap(Utils.s2i(prefs.getProperty("chapter.audition.post-gap")));
c.setPreGap(Utils.s2i(prefs.getProperty("chapter.audition.pre-gap")));
bookTreeModel.insertNodeInto(c, getBook(), 0);
for (int i = 0; i < 100000000; i++) { File destFolder = book.getLocation();
String id = prefs.getProperty(String.format("chapter.audition.sentence.%08d.id", i));
String text = prefs.getProperty(String.format("chapter.audition.sentence.%08d.text", i)); // If we are importing from the storage area and nothing changes then we are done.
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.post-gap", i))); if (destFolder.equals(sourceFolder)) return;
if (id == null) break;
Sentence s = new Sentence(id, text); // Otherwise we need to copy everything over.
s.setPostGap(gap); Utils.copyFolder(sourceFolder, destFolder);
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.start-offset", i))));
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.audition.sentence.%08d.end-offset", i)))); // Save again, just to be sure.
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.audition.sentence.%08d.locked", i)))); book.save();
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.audition.sentence.%08d.attention", i))));
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.audition.sentence.%08d.gain", i)))); // Add the book to the tree
s.setEffectChain(prefs.getProperty(String.format("chapter.audition.sentence.%08d.effect", i))); loadXMLBookStructure(new File(book.getLocation(), "audiobook.abx"));
s.setPostGapType(prefs.getProperty(String.format("chapter.audition.sentence.%08d.gaptype", i))); updateOpenBookList();
bookTreeModel.insertNodeInto(s, c, c.getChildCount()); } catch (Exception ex) {
ex.printStackTrace();
} }
c = new Chapter("open", prefs.getProperty("chapter.open.name"));
c.setPostGap(Utils.s2i(prefs.getProperty("chapter.open.post-gap")));
c.setPreGap(Utils.s2i(prefs.getProperty("chapter.open.pre-gap")));
bookTreeModel.insertNodeInto(c, getBook(), 0);
for (int i = 0; i < 100000000; i++) {
String id = prefs.getProperty(String.format("chapter.open.sentence.%08d.id", i));
String text = prefs.getProperty(String.format("chapter.open.sentence.%08d.text", i));
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.post-gap", i)));
if (id == null) break;
Sentence s = new Sentence(id, text);
s.setPostGap(gap);
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.start-offset", i))));
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.open.sentence.%08d.end-offset", i))));
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.open.sentence.%08d.locked", i))));
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.open.sentence.%08d.attention", i))));
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.open.sentence.%08d.gain", i))));
s.setEffectChain(prefs.getProperty(String.format("chapter.open.sentence.%08d.effect", i)));
s.setPostGapType(prefs.getProperty(String.format("chapter.open.sentence.%08d.gaptype", i)));
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
}
for (int cno = 1; cno < 10000; cno++) {
String cname = prefs.getProperty(String.format("chapter.%04d.name", cno));
if (cname == null) break;
c = new Chapter(String.format("%04d", cno), cname);
c.setPostGap(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.post-gap", cno))));
c.setPreGap(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.pre-gap", cno))));
bookTreeModel.insertNodeInto(c, getBook(), getBook().getChildCount());
for (int i = 0; i < 100000000; i++) {
String id = prefs.getProperty(String.format("chapter.%04d.sentence.%08d.id", cno, i));
String text = prefs.getProperty(String.format("chapter.%04d.sentence.%08d.text", cno, i));
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.post-gap", cno, i)));
if (id == null) break;
Sentence s = new Sentence(id, text);
s.setPostGap(gap);
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.start-offset", cno, i))));
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.end-offset", cno, i))));
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.locked", cno, i))));
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.attention", cno, i))));
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.gain", cno, i))));
s.setEffectChain(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.effect", cno, i)));
s.setPostGapType(prefs.getProperty(String.format("chapter.%04d.sentence.%08d.gaptype", cno, i)));
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
}
}
c = new Chapter("close", prefs.getProperty("chapter.close.name"));
c.setPostGap(Utils.s2i(prefs.getProperty("chapter.close.post-gap")));
c.setPreGap(Utils.s2i(prefs.getProperty("chapter.close.pre-gap")));
bookTreeModel.insertNodeInto(c, getBook(), getBook().getChildCount());
for (int i = 0; i < 100000000; i++) {
String id = prefs.getProperty(String.format("chapter.close.sentence.%08d.id", i));
String text = prefs.getProperty(String.format("chapter.close.sentence.%08d.text", i));
int gap = Utils.s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.post-gap", i)));
if (id == null) break;
Sentence s = new Sentence(id, text);
s.setPostGap(gap);
s.setStartOffset(Utils.s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.start-offset", i))));
s.setEndOffset(Utils.s2i(prefs.getProperty(String.format("chapter.close.sentence.%08d.end-offset", i))));
s.setLocked(Utils.s2b(prefs.getProperty(String.format("chapter.close.sentence.%08d.locked", i))));
s.setAttentionFlag(Utils.s2b(prefs.getProperty(String.format("chapter.close.sentence.%08d.attention", i))));
s.setGain(Utils.s2d(prefs.getProperty(String.format("chapter.close.sentence.%08d.gain", i))));
s.setEffectChain(prefs.getProperty(String.format("chapter.close.sentence.%08d.effect", i)));
s.setPostGapType(prefs.getProperty(String.format("chapter.close.sentence.%08d.gaptype", i)));
bookTreeModel.insertNodeInto(s, c, c.getChildCount());
}
bookTree.expandPath(new TreePath(getBook().getPath()));
// noiseFloorLabel.setNoiseFloor(getBook().getNoiseFloorDB());
getBook().setIcon(Icons.book);
*/
} }
public void openBook() { public void openBook() {
@@ -3302,11 +3176,6 @@ public class AudiobookRecorder extends JFrame implements DocumentListener {
} }
} }
public String getDefaultEffectsChain() {
Debug.trace();
return getBook().getDefaultEffect();
}
public synchronized boolean getLock() { public synchronized boolean getLock() {
Debug.trace(); Debug.trace();
if (state == RECORDING) return false; if (state == RECORDING) return false;

View File

@@ -46,9 +46,6 @@ public class Book extends BookTreeNode {
String manuscript; String manuscript;
String defaultEffect = "none"; String defaultEffect = "none";
Sentence roomNoise = null; Sentence roomNoise = null;
int sampleRate;
int channels;
int resolution;
String notes = null; String notes = null;
ImageIcon icon; ImageIcon icon;
File location; File location;
@@ -65,16 +62,9 @@ public class Book extends BookTreeNode {
setIcon(Icons.book); setIcon(Icons.book);
roomNoise = new Sentence("room-noise", "Room Noise"); roomNoise = new Sentence("room-noise", "Room Noise");
roomNoise.setParentBook(this); roomNoise.setParentBook(this);
loadEffects();
} }
/*
public Book(Element root) {
super(getTextNode(root, "title"));
Debug.trace();
name = getTextNode(root, "title");
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
setIcon(Icons.book);
}
*/
public Book(File inputFile) throws SAXException, IOException, ParserConfigurationException { public Book(File inputFile) throws SAXException, IOException, ParserConfigurationException {
Debug.trace(); Debug.trace();
Debug.d("Loading book from", inputFile.getCanonicalPath()); Debug.d("Loading book from", inputFile.getCanonicalPath());
@@ -98,10 +88,6 @@ public class Book extends BookTreeNode {
Element audioSettings = getNode(settings, "audio"); Element audioSettings = getNode(settings, "audio");
Element effectSettings = getNode(settings, "effects"); Element effectSettings = getNode(settings, "effects");
sampleRate = Utils.s2i(getTextNode(audioSettings, "samplerate"));
channels = Utils.s2i(getTextNode(audioSettings, "channels"));
resolution = Utils.s2i(getTextNode(audioSettings, "resolution"));
defaultEffect = getTextNode(settings, "default"); defaultEffect = getTextNode(settings, "default");
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!! AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
@@ -127,13 +113,6 @@ public class Book extends BookTreeNode {
roomNoise = new Sentence("room-noise", "Room Noise"); roomNoise = new Sentence("room-noise", "Room Noise");
roomNoise.setParentBook(this); roomNoise.setParentBook(this);
AudioFormat fmt = getAudioFormat();
if (fmt != null) {
sampleRate = (int)fmt.getSampleRate();
channels = fmt.getChannels();
resolution = fmt.getSampleSizeInBits();
}
Element chapters = getNode(root, "chapters"); Element chapters = getNode(root, "chapters");
NodeList chapterList = chapters.getElementsByTagName("chapter"); NodeList chapterList = chapters.getElementsByTagName("chapter");
for (int i = 0; i < chapterList.getLength(); i++) { for (int i = 0; i < chapterList.getLength(); i++) {
@@ -161,10 +140,6 @@ public class Book extends BookTreeNode {
Element audioSettings = getNode(settings, "audio"); Element audioSettings = getNode(settings, "audio");
Element effectSettings = getNode(settings, "effects"); Element effectSettings = getNode(settings, "effects");
sampleRate = Utils.s2i(getTextNode(audioSettings, "samplerate"));
channels = Utils.s2i(getTextNode(audioSettings, "channels"));
resolution = Utils.s2i(getTextNode(audioSettings, "resolution"));
defaultEffect = getTextNode(settings, "default"); defaultEffect = getTextNode(settings, "default");
AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!! AudiobookRecorder.window.setTitle("AudioBook Recorder :: " + name); // This should be in the load routine!!!!
@@ -341,13 +316,6 @@ public class Book extends BookTreeNode {
return name; return name;
} }
public int getSampleRate() { Debug.trace(); return sampleRate; }
public void setSampleRate(int sr) { Debug.trace(); sampleRate = sr; }
public int getChannels() { Debug.trace(); return channels; }
public void setChannels(int c) { Debug.trace(); channels = c; }
public int getResolution() { Debug.trace(); return resolution; }
public void setResolution(int r) { Debug.trace(); resolution = r; }
public AudioFormat getAudioFormat() { public AudioFormat getAudioFormat() {
Debug.trace(); Debug.trace();
if (cachedFormat != null) { if (cachedFormat != null) {
@@ -414,13 +382,6 @@ public class Book extends BookTreeNode {
Element settingsNode = doc.createElement("settings"); Element settingsNode = doc.createElement("settings");
root.appendChild(settingsNode); root.appendChild(settingsNode);
Element audioSettingsNode = doc.createElement("audio");
settingsNode.appendChild(audioSettingsNode);
audioSettingsNode.appendChild(makeTextNode(doc, "channels", channels));
audioSettingsNode.appendChild(makeTextNode(doc, "resolution", resolution));
audioSettingsNode.appendChild(makeTextNode(doc, "samplerate", sampleRate));
Element effectsNode = doc.createElement("effects"); Element effectsNode = doc.createElement("effects");
settingsNode.appendChild(effectsNode); settingsNode.appendChild(effectsNode);
@@ -625,7 +586,7 @@ public class Book extends BookTreeNode {
Debug.trace(); Debug.trace();
effects = new TreeMap<String,EffectGroup>(); effects = new TreeMap<String,EffectGroup>();
loadEffectsFromFolder(new File(Options.get("path.storage"), "System")); loadEffectsFromFolder(new File(Options.get("path.storage"), "System"));
if (getBook() != null) { if (location != null) {
loadEffectsFromFolder(location); loadEffectsFromFolder(location);
} }
} }
@@ -720,8 +681,6 @@ public class Book extends BookTreeNode {
if (ob instanceof Chapter) { if (ob instanceof Chapter) {
Chapter c = (Chapter)ob; Chapter c = (Chapter)ob;
len += c.getLength(); len += c.getLength();
len += (c.getPreGap() / 1000d);
len += (c.getPostGap() / 1000d);
} }
} }
return len; return len;

View File

@@ -395,6 +395,11 @@ public class Chapter extends BookTreeNode {
len += (s.getPostGap() / 1000d); len += (s.getPostGap() / 1000d);
} }
} }
if (len > 0) {
len += (getPreGap() / 1000d);
len += (getPostGap() / 1000d);
}
return len; return len;
} }

View File

@@ -1427,7 +1427,7 @@ public class Sentence extends BookTreeNode implements Cacheable {
// Add processing in here. // Add processing in here.
String def = AudiobookRecorder.window.getDefaultEffectsChain(); String def = getBook().getDefaultEffect();
if ((def != null) && (book.effects != null)) { if ((def != null) && (book.effects != null)) {
Effect eff = book.effects.get(def); Effect eff = book.effects.get(def);

View File

@@ -9,6 +9,9 @@ import java.awt.Graphics2D;
import java.awt.Desktop; import java.awt.Desktop;
import java.util.Date; import java.util.Date;
import java.util.TimeZone; import java.util.TimeZone;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class Utils { public class Utils {
public static Image getScaledImage(Image srcImg, int w, int h){ public static Image getScaledImage(Image srcImg, int w, int h){
@@ -108,4 +111,25 @@ public class Utils {
return out; return out;
} }
public static void copyFolder(File from, File to) throws IOException {
File[] files = from.listFiles();
for (File source : files) {
File destination = new File(to, source.getName());
if (destination.exists()) {
if (!destination.isDirectory()) {
destination.delete();
}
}
if (source.isDirectory()) {
if (!destination.exists()) {
destination.mkdirs();
}
copyFolder(source, destination);
} else {
Files.copy(source.toPath(), destination.toPath());
}
}
}
} }