Datei double finder.dart

Aus Info-Theke
Version vom 20. Januar 2021, 13:51 Uhr von Hamatoma (Diskussion | Beiträge) (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…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

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>[];