Combined DuplicateWorker with DuplicateHandler

This commit is contained in:
Denis Molony 2016-12-11 16:18:04 +11:00
parent 4a36ec039c
commit b728fe1f16
11 changed files with 224 additions and 118 deletions

View File

@ -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)

View File

@ -27,6 +27,10 @@ public class DiskDetails
checksum = ComputeCRC32.getChecksumValue (file);
}
public File getFile ()
{
return file;
}
public void addDuplicateChecksum (DiskDetails diskDetails)
{

View File

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

View File

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

View File

@ -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]);

View File

@ -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;
}
}

View 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]);
}
}

View File

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

View File

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

View File

@ -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;
}
}
}

View File

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