Datei double finder.dart: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
Die Seite wurde neu angelegt: „= Links = * Projekt ddouble = Zielsetzung = Hier werden nur Besonderheiten der Datei double_finder.dart besprochen. Viele Teile dieser Datei sind ähnlic…“ |
(kein Unterschied)
|
Version vom 20. Januar 2021, 11:51 Uhr
Links
Zielsetzung
Hier werden nur Besonderheiten der Datei double_finder.dart besprochen.
Viele Teile dieser Datei sind ähnlich wie [Datei search_engine.dart], z. B. das Festlegen der Optionen.
Die Klasse SearchEngine
Die Klasse implementiert ("realisiert") die Suche nach Duplikaten.
Die Attribute
Zuerst werden die Attribute definiert:
class DoubleFinder {
static bool storeResult = false;
final startTime = DateTime.now();
Map<int, List<FileInfo>> processedFiles = {};
final int verboseLevel;
final startLength;
final blockSize;
int startBlockCount = 0;
int fullBlockCounts = 0;
int fullBlockFiles = 0;
int doubles = 0;
final lines = <String>[];
var hashBuilder = md5;
Der Konstruktor
DoubleFinder({this.verboseLevel, this.blockSize, this.startLength});
- Keine Besonderheiten.
Die Methode find()
Diese Methode erledigt den Kern des Programms.
/// Finds the duplicates in a list of [filePatterns].
void find(List<String> filePatterns, FileOptions fileOptions) {
fileOptions.yieldDirectory =
fileOptions.yieldLinkToDirectory = fileOptions.yieldLinkToFile = false;
fileOptions.recursive = true;
final supplier = FileSupplier(
fileOptions: fileOptions,
filePatterns: filePatterns,
verboseLevel: verboseLevel);
final toRemove = <FileInfo>[];
for (var filename in supplier.next()) {
final file = supplier.currentEntity as File;
final size = file.lengthSync();
if (size == 0){
continue;
}
var newEntry = FileInfo(filename, size);
if (!processedFiles.containsKey(size)) {
if (verboseLevel >= 4) {
print('= new size $size');
}
processedFiles[size] = [newEntry];
continue;
}
for (var processedFile in processedFiles[size]) {
processedFile.hashStart ??= calcHash(file, calculateStartBlock: true);
if (processedFile.hashStart == null) {
toRemove.add(processedFile);
continue;
}
newEntry.hashStart ??= calcHash(file, calculateStartBlock: true);
if (newEntry.hashStart == null) {
newEntry = null;
break;
}
if (processedFile.hashStart == newEntry.hashStart) {
if (verboseLevel >= 4) {
print('= start block is the same: $filename ${processedFile.name}');
}
processedFile.hashFull ??=
calcHash(File(processedFile.name), calculateStartBlock: false);
if (processedFile.hashFull == null) {
toRemove.add(processedFile);
continue;
}
newEntry.hashFull ??= calcHash(file, calculateStartBlock: false);
if (newEntry.hashFull == null) {
newEntry = null;
break;
}
if (processedFile.hashFull == newEntry.hashFull) {
doubles++;
final line = '${newEntry.name} = ${processedFile.name} size: $size';
if (verboseLevel >= 2) {
if (storeResult) {
lines.add(line);
} else {
print(line);
}
}
// we search only one duplicate.
break;
}
}
}
for (var processedFile in toRemove) {
processedFiles[size].remove(processedFile);
}
toRemove.clear();
if (newEntry != null) {
processedFiles[size].add(newEntry);
}
}
if (verboseLevel >= 1) {
print('= duplicates: $doubles start blocks: $startBlockCount full blocks: $fullBlockFiles files with $fullBlockCounts blocks');
print(supplier.summary.join('\n'));
final diff = DateTime.now().difference(startTime);
final milliSeconds =
(diff.inMilliseconds % 1000).toString().padLeft(3, '0');
print(
'= runtime: ${diff.inHours}h${diff.inMinutes % 60}m${diff.inSeconds % 60}.$milliSeconds');
}
if (!DoubleFinder.storeResult) {
// Exit at once: release resources faster.
exit(0);
}
}
fileOptions.yieldDirectory =
fileOptions.yieldLinkToDirectory = fileOptions.yieldLinkToFile = false;Der Filenamensgenerator soll nur die Namen von reguläre Dateien liefern (keine Verzeichnisnamen, keine Links).final toRemove = <FileInfo>[];