mirror of
https://github.com/dmolony/DiskBrowser.git
synced 2024-06-03 16:29:29 +00:00
Combined DuplicateWorker with DuplicateHandler
This commit is contained in:
parent
4a36ec039c
commit
b728fe1f16
|
@ -368,6 +368,25 @@ public class DiskFactory
|
|||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
offset | size | description
|
||||
------ | ---- | -----------
|
||||
+$000 | Long | The integer constant '2IMG'. This integer should be little-endian, so on the Apple IIgs, this is equivalent to the four characters 'GMI2'; in ORCA/C 2.1, you can use the integer constant '2IMG'.
|
||||
+$004 | Long | A four-character tag identifying the application that created the file.
|
||||
+$008 | Word | The length of this header, in bytes. Should be 52.
|
||||
+$00A | Word | The version number of the image file format. Should be 1.
|
||||
+$00C | Long | The image format. See table below.
|
||||
+$010 | Long | Flags. See table below.
|
||||
+$014 | Long | The number of 512-byte blocks in the disk image. This value should be zero unless the image format is 1 (ProDOS order).
|
||||
+$018 | Long | Offset to the first byte of the first block of the disk in the image file, from the beginning of the file. The disk data must come before the comment and creator-specific chunks.
|
||||
+$01C | Long | Length of the disk data in bytes. This should be the number of blocks * 512.
|
||||
+$020 | Long | Offset to the first byte of the image comment. Can be zero if there's no comment. The comment must come after the data chunk, but before the creator-specific chunk. The comment, if it exists, should be raw text; no length byte or C-style null terminator byte is required (that's what the next field is for).
|
||||
+$024 | Long | Length of the comment chunk. Zero if there's no comment.
|
||||
+$028 | Long | Offset to the first byte of the creator-specific data chunk, or zero if there is none.
|
||||
+$02C | Long | Length of the creator-specific chunk; zero if there is no creator-specific data.
|
||||
+$030 | 16 bytes | Reserved space; this pads the header to 64 bytes. These values must all be zero.
|
||||
*/
|
||||
|
||||
private static FormattedDisk check2mgDisk (File file)
|
||||
{
|
||||
if (debug)
|
||||
|
|
|
@ -27,6 +27,10 @@ public class DiskDetails
|
|||
checksum = ComputeCRC32.getChecksumValue (file);
|
||||
}
|
||||
|
||||
public File getFile ()
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
public void addDuplicateChecksum (DiskDetails diskDetails)
|
||||
{
|
||||
|
|
|
@ -6,10 +6,12 @@ import java.util.Map;
|
|||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
public class DiskTableModel extends AbstractTableModel
|
||||
{
|
||||
static final String[] headers =
|
||||
{ "Path", "Name", "same name", "same data", "Checksum" };
|
||||
{ "Path", "Name", "Type", "Size (bytes)", "Dup name", "Dup data", "Checksum" };
|
||||
|
||||
Map<String, DiskDetails> fileNameMap;
|
||||
Map<Long, DiskDetails> checkSumMap;
|
||||
|
@ -65,10 +67,14 @@ public class DiskTableModel extends AbstractTableModel
|
|||
case 1:
|
||||
return line.shortName;
|
||||
case 2:
|
||||
return line.duplicateNames;
|
||||
return line.type;
|
||||
case 3:
|
||||
return line.duplicateChecksums;
|
||||
return line.size;
|
||||
case 4:
|
||||
return line.duplicateNames;
|
||||
case 5:
|
||||
return line.duplicateChecksums;
|
||||
case 6:
|
||||
return line.checksum;
|
||||
default:
|
||||
return "???";
|
||||
|
@ -83,12 +89,16 @@ public class DiskTableModel extends AbstractTableModel
|
|||
private final int duplicateNames;
|
||||
private final int duplicateChecksums;
|
||||
final DiskDetails diskDetails;
|
||||
private final String type;
|
||||
private final long size;
|
||||
|
||||
public TableLine (DiskDetails diskDetails)
|
||||
{
|
||||
this.diskDetails = diskDetails;
|
||||
shortName = diskDetails.getShortName ();
|
||||
checksum = diskDetails.getChecksum ();
|
||||
type = Utility.getSuffix (shortName);
|
||||
size = diskDetails.getFile ().length ();
|
||||
|
||||
String rootName = diskDetails.getRootName ();
|
||||
path = rootName.substring (0, rootName.length () - shortName.length ());
|
||||
|
|
|
@ -2,37 +2,32 @@ package com.bytezone.diskbrowser.duplicates;
|
|||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
public class DuplicateHandler
|
||||
public class DuplicateHandler extends SwingWorker<Void, ProgressState>
|
||||
{
|
||||
// private static final FileComparator fileComparator = new FileComparator ();
|
||||
// private static final int MAX_NAME_WIDTH = 34;
|
||||
// private static final String FORMAT = "%-" + MAX_NAME_WIDTH + "s %,10d%n";
|
||||
|
||||
private final File rootFolder;
|
||||
private int totalDisks;
|
||||
private int totalFolders;
|
||||
private final int rootFolderNameLength;
|
||||
|
||||
// private final boolean debug = false;
|
||||
|
||||
// total files for each suffix
|
||||
private final Map<String, Integer> typeList = new TreeMap<String, Integer> ();
|
||||
private final ProgressState progressState = new ProgressState ();
|
||||
DuplicateWindow owner;
|
||||
|
||||
// list of checksum -> DiskDetails
|
||||
final Map<Long, DiskDetails> checksumMap = new HashMap<Long, DiskDetails> ();
|
||||
private final Map<Long, DiskDetails> checksumMap = new HashMap<Long, DiskDetails> ();
|
||||
|
||||
// list of unique disk names -> File
|
||||
// list of unique disk names -> DiskDetails
|
||||
private final Map<String, DiskDetails> fileNameMap =
|
||||
new TreeMap<String, DiskDetails> ();
|
||||
|
||||
public DuplicateHandler (File rootFolder)
|
||||
public DuplicateHandler (File rootFolder, DuplicateWindow owner)
|
||||
{
|
||||
this.rootFolder = rootFolder;
|
||||
this.owner = owner;
|
||||
rootFolderNameLength = rootFolder.getAbsolutePath ().length ();
|
||||
}
|
||||
|
||||
|
@ -46,21 +41,9 @@ public class DuplicateHandler
|
|||
return checksumMap;
|
||||
}
|
||||
|
||||
void countDisks ()
|
||||
public ProgressState getProgressState ()
|
||||
{
|
||||
traverse (rootFolder);
|
||||
|
||||
System.out.printf ("%nFolders ..... %,7d%n", totalFolders);
|
||||
System.out.printf ("Disks ....... %,7d%n%n", totalDisks);
|
||||
|
||||
int grandTotal = 0;
|
||||
for (String key : typeList.keySet ())
|
||||
{
|
||||
int typeTotal = typeList.get (key);
|
||||
grandTotal += typeTotal;
|
||||
System.out.printf ("%13.13s %,7d%n", key + " ...........", typeTotal);
|
||||
}
|
||||
System.out.printf ("%nTotal ....... %,7d%n%n", grandTotal);
|
||||
return progressState;
|
||||
}
|
||||
|
||||
File getRootFolder ()
|
||||
|
@ -78,35 +61,35 @@ public class DuplicateHandler
|
|||
return;
|
||||
}
|
||||
|
||||
// Arrays.sort (files, fileComparator);
|
||||
|
||||
for (File file : files)
|
||||
{
|
||||
String fileName = file.getName ().toLowerCase ();
|
||||
|
||||
if (file.isDirectory ())
|
||||
{
|
||||
++totalFolders;
|
||||
progressState.incrementFolders ();
|
||||
traverse (file);
|
||||
}
|
||||
else if (Utility.validFileType (fileName))
|
||||
else if (Utility.validFileType (fileName) && file.length () > 0)
|
||||
{
|
||||
++totalDisks;
|
||||
incrementType (file, fileName);
|
||||
progressState.incrementType (file, fileName);
|
||||
checkDuplicates (file, fileName);
|
||||
|
||||
if ((progressState.totalDisks % 1000) == 0)
|
||||
publish (progressState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDuplicates (File file, String fileName)
|
||||
private void checkDuplicates (File file, String filename)
|
||||
{
|
||||
String rootName = file.getAbsolutePath ().substring (rootFolderNameLength);
|
||||
DiskDetails diskDetails = new DiskDetails (file, rootName, fileName);
|
||||
DiskDetails diskDetails = new DiskDetails (file, rootName, filename);
|
||||
|
||||
if (fileNameMap.containsKey (fileName))
|
||||
fileNameMap.get (fileName).addDuplicateName (diskDetails);
|
||||
if (fileNameMap.containsKey (filename))
|
||||
fileNameMap.get (filename).addDuplicateName (diskDetails);
|
||||
else
|
||||
fileNameMap.put (fileName, diskDetails);
|
||||
fileNameMap.put (filename, diskDetails);
|
||||
|
||||
long checksum = diskDetails.getChecksum ();
|
||||
if (checksumMap.containsKey (checksum))
|
||||
|
@ -115,19 +98,32 @@ public class DuplicateHandler
|
|||
checksumMap.put (checksum, diskDetails);
|
||||
}
|
||||
|
||||
private void incrementType (File file, String fileName)
|
||||
@Override
|
||||
protected void done ()
|
||||
{
|
||||
int pos = file.getName ().lastIndexOf ('.');
|
||||
if (pos > 0)
|
||||
try
|
||||
{
|
||||
String type = fileName.substring (pos + 1);
|
||||
if (typeList.containsKey (type))
|
||||
{
|
||||
int t = typeList.get (type);
|
||||
typeList.put (type, ++t);
|
||||
}
|
||||
else
|
||||
typeList.put (type, 1);
|
||||
owner.setDuplicateHandler (this);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void doInBackground () throws Exception
|
||||
{
|
||||
traverse (rootFolder);
|
||||
progressState.print ();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process (List<ProgressState> chunks)
|
||||
{
|
||||
if (false)
|
||||
for (ProgressState progressState : chunks)
|
||||
progressState.print ();
|
||||
}
|
||||
}
|
|
@ -75,7 +75,7 @@ public class DuplicateWindow extends JFrame
|
|||
|
||||
table.setModel (new DiskTableModel (duplicateHandler));
|
||||
|
||||
int[] columnWidths = { 300, 300, 40, 40, 100 };
|
||||
int[] columnWidths = { 300, 300, 30, 40, 40, 40, 100 };
|
||||
for (int i = 0; i < columnWidths.length; i++)
|
||||
table.getColumnModel ().getColumn (i).setPreferredWidth (columnWidths[i]);
|
||||
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
package com.bytezone.diskbrowser.duplicates;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
public class DuplicateWorker extends SwingWorker<DuplicateHandler, String>
|
||||
{
|
||||
DuplicateHandler duplicateHandler;
|
||||
DuplicateWindow owner;
|
||||
|
||||
public DuplicateWorker (File rootFolder, DuplicateWindow owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
duplicateHandler = new DuplicateHandler (rootFolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done ()
|
||||
{
|
||||
try
|
||||
{
|
||||
owner.setDuplicateHandler (get ());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace ();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DuplicateHandler doInBackground () throws Exception
|
||||
{
|
||||
duplicateHandler.countDisks ();
|
||||
|
||||
return duplicateHandler;
|
||||
}
|
||||
}
|
69
src/com/bytezone/diskbrowser/duplicates/ProgressState.java
Normal file
69
src/com/bytezone/diskbrowser/duplicates/ProgressState.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
package com.bytezone.diskbrowser.duplicates;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import com.bytezone.diskbrowser.utilities.Utility;
|
||||
|
||||
public class ProgressState
|
||||
{
|
||||
List<String> suffixes = Utility.suffixes;
|
||||
int totalDisks;
|
||||
int totalFolders;
|
||||
|
||||
// total files for each suffix (uncompressed, .gz, .zip)
|
||||
private final int[][] typeTotals = new int[3][suffixes.size ()];
|
||||
|
||||
public ProgressState ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void incrementFolders ()
|
||||
{
|
||||
++totalFolders;
|
||||
}
|
||||
|
||||
public void incrementType (File file, String filename)
|
||||
{
|
||||
int pos = Utility.getSuffixNo (filename);
|
||||
if (pos >= 0)
|
||||
{
|
||||
int cmp = 0;
|
||||
if (filename.endsWith (".gz"))
|
||||
cmp = 1;
|
||||
else if (filename.endsWith (".zip"))
|
||||
cmp = 2;
|
||||
typeTotals[cmp][pos]++;
|
||||
++totalDisks;
|
||||
}
|
||||
else
|
||||
System.out.println ("no suffix: " + filename);
|
||||
}
|
||||
|
||||
public void print ()
|
||||
{
|
||||
System.out.printf ("%nFolders ...... %,7d%n", totalFolders);
|
||||
System.out.printf ("Disks ........ %,7d%n%n", totalDisks);
|
||||
|
||||
int grandTotal[] = new int[3];
|
||||
|
||||
String line = "-------------- ------- ------- -------";
|
||||
System.out.println (" type uncmp .gz .zip");
|
||||
System.out.println (line);
|
||||
for (int i = 0; i < typeTotals[0].length; i++)
|
||||
{
|
||||
System.out.printf ("%14.14s ", Utility.suffixes.get (i) + " ...........");
|
||||
for (int j = 0; j < typeTotals.length; j++)
|
||||
{
|
||||
System.out.printf ("%,7d ", typeTotals[j][i]);
|
||||
grandTotal[j] += typeTotals[j][i];
|
||||
}
|
||||
System.out.println ();
|
||||
}
|
||||
|
||||
System.out.println (line);
|
||||
System.out.printf ("Total %,7d %,7d %,7d%n%n", grandTotal[0],
|
||||
grandTotal[1], grandTotal[2]);
|
||||
}
|
||||
}
|
|
@ -133,7 +133,13 @@ abstract class AbstractTab extends JPanel implements Tab
|
|||
// Trigger the TreeSelectionListener set by the real Tab (if the value is different)
|
||||
protected void showNode (DefaultMutableTreeNode showNode)
|
||||
{
|
||||
assert showNode != null;
|
||||
TreePath tp = getPathToNode (showNode);
|
||||
if (tp == null)
|
||||
{
|
||||
System.out.println ("Not found: " + showNode);
|
||||
return;
|
||||
}
|
||||
tree.setSelectionPath (tp);
|
||||
tree.scrollPathToVisible (tp);
|
||||
tree.requestFocusInWindow ();
|
||||
|
@ -143,6 +149,8 @@ abstract class AbstractTab extends JPanel implements Tab
|
|||
{
|
||||
DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel ();
|
||||
TreeNode[] nodes = treeModel.getPathToRoot (selectNode);
|
||||
if (nodes == null)
|
||||
return null;
|
||||
return new TreePath (nodes);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ import javax.swing.KeyStroke;
|
|||
|
||||
import com.bytezone.common.DefaultAction;
|
||||
import com.bytezone.diskbrowser.duplicates.DiskDetails;
|
||||
import com.bytezone.diskbrowser.duplicates.DuplicateHandler;
|
||||
import com.bytezone.diskbrowser.duplicates.DuplicateWindow;
|
||||
import com.bytezone.diskbrowser.duplicates.DuplicateWorker;
|
||||
import com.bytezone.diskbrowser.gui.RootDirectoryAction.RootDirectoryChangeListener;
|
||||
|
||||
public class DuplicateAction extends DefaultAction implements RootDirectoryChangeListener
|
||||
|
@ -49,7 +49,8 @@ public class DuplicateAction extends DefaultAction implements RootDirectoryChang
|
|||
if (window == null)
|
||||
{
|
||||
window = new DuplicateWindow (rootFolder, listeners);
|
||||
new DuplicateWorker (rootFolder, window).execute ();
|
||||
DuplicateHandler duplicateHandler = new DuplicateHandler (rootFolder, window);
|
||||
duplicateHandler.execute ();
|
||||
}
|
||||
else
|
||||
window.setVisible (true);
|
||||
|
|
|
@ -123,7 +123,16 @@ class FileSystemTab extends AbstractTab
|
|||
|
||||
void selectDisk (String path)
|
||||
{
|
||||
showNode (findNode (rootFolder.getAbsolutePath () + path));
|
||||
File file = new File (rootFolder.getAbsolutePath () + path);
|
||||
System.out.println (file);
|
||||
System.out.println (file.exists ());
|
||||
DefaultMutableTreeNode node = findNode (rootFolder.getAbsolutePath () + path);
|
||||
if (node != null)
|
||||
showNode (node);
|
||||
else
|
||||
{
|
||||
System.out.println ("Path not found: " + rootFolder.getAbsolutePath () + path);
|
||||
}
|
||||
}
|
||||
|
||||
private DefaultMutableTreeNode findNode (String absolutePath)
|
||||
|
@ -151,12 +160,15 @@ class FileSystemTab extends AbstractTab
|
|||
if (absolutePath.equals (path))
|
||||
return childNode;
|
||||
|
||||
if (fn2.file.isDirectory () && absolutePath.startsWith (path)
|
||||
&& absolutePath.charAt (path.length ()) == '/')
|
||||
if (fn2.file.isDirectory () && absolutePath.startsWith (path))
|
||||
{
|
||||
DefaultMutableTreeNode node2 = search (childNode, absolutePath);
|
||||
if (node2 != null)
|
||||
return node2;
|
||||
System.out.println (absolutePath.charAt (path.length ()));
|
||||
if (absolutePath.charAt (path.length ()) == File.separatorChar)
|
||||
{
|
||||
DefaultMutableTreeNode node2 = search (childNode, absolutePath);
|
||||
if (node2 != null)
|
||||
return node2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,10 @@ import java.util.List;
|
|||
public class Utility
|
||||
{
|
||||
public static final List<String> suffixes =
|
||||
Arrays.asList ("po", "dsk", "do", "hdv", "2mg", "v2d", "nib", "d13", "sdk", "gz");
|
||||
Arrays.asList ("po", "dsk", "do", "hdv", "2mg", "v2d", "nib", "d13", "sdk");
|
||||
|
||||
// not used - it doesn't work with Oracle's JDK
|
||||
public static boolean hasRetinaDisplay ()
|
||||
private static boolean hasRetinaDisplay ()
|
||||
{
|
||||
Object obj =
|
||||
Toolkit.getDefaultToolkit ().getDesktopProperty ("apple.awt.contentScaleFactor");
|
||||
|
@ -57,24 +57,49 @@ public class Utility
|
|||
return true;
|
||||
}
|
||||
|
||||
public static int getSuffixNo (String filename)
|
||||
{
|
||||
return suffixes.indexOf (getSuffix (filename));
|
||||
}
|
||||
|
||||
public static String getSuffix (String filename)
|
||||
{
|
||||
String lcFilename = filename.toLowerCase ();
|
||||
|
||||
if (lcFilename.endsWith (".gz"))
|
||||
lcFilename = lcFilename.substring (0, lcFilename.length () - 3);
|
||||
else if (lcFilename.endsWith (".zip"))
|
||||
lcFilename = lcFilename.substring (0, lcFilename.length () - 4);
|
||||
|
||||
int dotPos = lcFilename.lastIndexOf ('.');
|
||||
if (dotPos < 0)
|
||||
return "";
|
||||
|
||||
return lcFilename.substring (dotPos + 1);
|
||||
}
|
||||
|
||||
public static boolean validFileType (String filename)
|
||||
{
|
||||
int dotPos = filename.lastIndexOf ('.');
|
||||
if (dotPos < 0)
|
||||
return false;
|
||||
// String lcFilename = filename.toLowerCase ();
|
||||
// if (lcFilename.endsWith (".gz"))
|
||||
// lcFilename = lcFilename.substring (0, lcFilename.length () - 3);
|
||||
// else if (lcFilename.endsWith (".zip"))
|
||||
// lcFilename = lcFilename.substring (0, lcFilename.length () - 4);
|
||||
//
|
||||
// int dotPos = lcFilename.lastIndexOf ('.');
|
||||
// if (dotPos < 0)
|
||||
// return false;
|
||||
//
|
||||
// String suffix = lcFilename.substring (dotPos + 1);
|
||||
|
||||
String suffix = filename.substring (dotPos + 1).toLowerCase ();
|
||||
// int dotPos2 = filename.lastIndexOf ('.', dotPos - 1);
|
||||
// if (dotPos2 > 0)
|
||||
// {
|
||||
// String suffix2 = filename.substring (dotPos2 + 1, dotPos).toLowerCase ();
|
||||
// if (suffix.equals ("gz"))
|
||||
// return suffixes.contains (suffix2) && !"gz".equals (suffix2);
|
||||
// }
|
||||
|
||||
int dotPos2 = filename.lastIndexOf ('.', dotPos - 1);
|
||||
if (dotPos2 > 0)
|
||||
{
|
||||
String suffix2 = filename.substring (dotPos2 + 1, dotPos).toLowerCase ();
|
||||
// if (suffix.equals ("gz") && (suffix2.equals ("bxy") || suffix2.equals ("bny")))
|
||||
// return false;
|
||||
if (suffix.equals ("gz"))
|
||||
return suffixes.contains (suffix2) && !"gz".equals (suffix2);
|
||||
}
|
||||
|
||||
return suffixes.contains (suffix);
|
||||
return suffixes.contains (getSuffix (filename));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user