12
votes

Façon la plus efficace de comparer une mémoire Mémoire à un fichier C # .NET

J'ai une mémoire Mémoire de mémoire Mémoire contenant les octets d'une image codée PNG et souhaitez vérifier s'il y a un duplicata exact de ces données d'image dans un répertoire sur disque. La première étape évidente consiste uniquement à rechercher des fichiers correspondant à la longueur exacte, mais après cela, je voudrais savoir quel est le moyen le plus efficace de comparer la mémoire par rapport aux fichiers. Je ne suis pas très expérimenté de travailler avec des ruisseaux.

J'ai eu quelques pensées sur la question:

Premièrement, si je pouvais obtenir un code de hachage pour le fichier, il serait (probablement) être plus efficace de comparer les codes de hachage plutôt que tous les octets de l'image. De même, je pouvais comparer quelques-uns des octets de l'image, donner une réponse "assez proche".

Et puis bien sûr, je pouvais simplement comparer tout le flux, mais je ne sais pas à quel point cela serait rapide.

Quelle est la meilleure façon de comparer un fichier mémoire à un fichier? Octet-byte dans une boucle pour la boucle?


4 commentaires

"... seulement recherchez des fichiers correspondant à la longueur exacte ..." Attention: la taille du fichier sur disque peut probablement être différente de la taille du flux ... Le fichier de disque pourrait avoir une vignette intégrée qui Le flux en mémoire n'est pas .... Les fichiers image peuvent être un peu goofy de cette façon :)


Dans mon cas, je crée également les fichiers image sur le disque, de sorte que cela devrait être en sécurité non?


Oui filtream.length == fileinfo.length ... mais si vous utilisez image.fromfile et enregistrez-le sur une mémoire Morthstream, ils n'auront pas la même longueur ... Je travaille habituellement avec des objets d'image, d'où ma préoccupation.


Intéressant. Eh bien, cela semble fonctionner jusqu'à présent. Je garderai vos préoccupations à l'esprit si les choses commencent à agir. :) Merci!


5 Réponses :


14
votes

Premièrement, obtenir HashCode des deux flux ne vous aidera pas - à calculer les hashcodes, vous devez lire tout le contenu et effectuer un calcul simple pendant la lecture. Si vous comparez les fichiers octet-byte ou à l'aide de tampons, vous pouvez vous arrêter plus tôt (après avoir trouvé les deux premiers octets / blocs) qui ne correspondent pas.

Toutefois, cette approche aurait un sens si vous aviez besoin de comparer le MemoryStream contre plusieurs fichiers, car vous auriez alors besoin de boucler dans le MemoryStream une seule fois (à Calculez le hashcode) et la boucle TNE à travers tous les fichiers.

Dans tous les cas, vous devrez écrire du code pour lire l'intégralité du fichier. Comme vous l'avez mentionné, cela peut être fait par octet-byte ou utiliser des tampons. La lecture des données dans la mémoire tampon est une bonne idée, car elle peut être une opération plus efficace lors de la lecture du disque dur (par exemple, la lecture de 1kb tampon). De plus, vous pouvez utiliser la méthode asynchrone beginread si vous devez traiter plusieurs fichiers en parallèle.

Résumé :

  • Si vous devez comparer plusieurs fichiers, utilisez HASHCODE
  • Pour lire / comparer le contenu du fichier unique:
    • Lire 1kb de données dans un tampon des deux flux
    • Voir s'il y a une différence (si oui, quittez)
    • Continuer la boucle

      Implémentez les étapes ci-dessus de manière asynchrone à l'aide de begayread si vous devez traiter des fichiers mutliples en parallèle.


5 commentaires

Il est important de connaître la possibilité (peu probable) des collisions de hachage. La comparaison des octets serait nécessaire pour éviter ce problème.


Donc, pour être clair, je lirais 1 Ko des morceaux du fichier dans un tampon, puis comparez ces tampons à l'octet mmstream par octet?


BufferedStream en tant que wrapper pour le filtream devrait s'occuper du problème tampon.


La lecture simultanée de plusieurs fichiers du même disque dur n'est pas nécessairement plus efficace qu'une à la fois, en raison du repositionnement de la tête.


@chaiguy: Oui, cela devrait être l'option la plus efficace, bien que si vous utilisez bufferedream , la lecture octet-byte devrait également fonctionner. Vous pouvez également exécuter des tests de performance pour identifier la meilleure taille de mémoire tampon.



22
votes

Une autre solution: xxx


5 commentaires

À peu près de la mémoire critique, mais convient parfaitement à mes besoins pour de petits ruisseaux. ;)


Pourquoi définissez-vous la position = 0? MemoryStream.toarray () Documentation dit "écrit le contenu du flux à un tableau d'octets, quelle que soit la propriété de position".


Juste habitude que je suppose, d'être un peu à l'aide de la position avant de fonctionner sur le flux.


C'est une solution médiocre, tout à l'écart du fait qu'il nécessite d'attribuer autant de mémoire que toute la longueur du fichier (fois deux). Si vous avez deux gros fichiers et qu'ils diffèrent au début du flux, cela attendra que l'ensemble du contenu des deux fichiers a été lu pour détecter cela et abandonner.


@ Mahmoudal-qunsi La demande était de comparer deux flux de mémoire, qui par définition sont déjà en mémoire, pas de fichiers.



-7
votes

Utilisation d'un flux Nous n'obtenons pas le résultat, chaque fichiers a une identité unique, telle que la dernière date modifiée et ainsi de suite. Donc, chaque fichier est différent. Ces informations sont incluses dans le flux


1 commentaires

Si vous lisez un fichier avec un flux, vous ne lisez que son contenu, non plus de métadonnées stockées par le système de fichiers. De plus, cette question est particulièrement sur la comparaison du contenu des fichiers.



2
votes

Nous avons ouvert la source une bibliothèque pour faire face à cela chez Neosmart Technologies, car nous avons J'ai dû comparer les objets opaques des objets de ByTewise Equality une fois trop nombreux. Il est disponible sur Nuget comme StreamCompare et vous pouvez lire sur ses avantages sur les approches existantes Dans l'annonce de publication officielle .

L'utilisation est très simple: xxx

Il est écrit à résumé loin du nombre d'emballages de gotchas et de performances dans la mesure du possible, et contient un certain nombre d'optimisations pour accélérer les comparaisons (et pour minimiser l'utilisation de la mémoire). Il y a aussi un wrapper de comparaison de fichiers filecompare inclus dans l'emballage, qui peut être utilisé pour comparer deux fichiers par chemin.

streamcompare est publié sous le mit Licence et exécute sur .NET Standard 1.3 et plus. Packages Nuget pour .NET Standard 1.3, .NET Standard 2.0, .NET CORE 2.2 et .NET CORE 3.0 sont disponibles. La documentation complète est dans le fichier README .


1 commentaires

Semble plutôt élaboré mais serait parfait pour comparer le flux de fichiers. Pour le flux de mémoire, je pense que cela sera moins efficace



0
votes

Premièrement, obtenir le hashcode des deux flux ne vous aidera pas - à calculer les hashcodes, vous devez lire tout le contenu et effectuer un calcul simple pendant la lecture.

Je ne suis pas sûr si je l'ai mal compris ou que ceci n'est tout simplement pas vrai. Voici l'exemple de calcul de hachage à l'aide de flux xxx

J'ai mesuré ce code avec Benchmark.net et il a alloué 384 octets sur un fichier de 900 Mo. Inutile de dire à quel point le fichier entier de chargement inefficace en mémoire dans ce cas.

Cependant, c'est vrai

Il est important d'être conscient de la possibilité (improbable) des collisions de hachage. La comparaison des octets serait nécessaire pour éviter ce problème.

Ainsi, dans le cas où les hashes ne correspondent pas, vous devez effectuer des contrôles supplémentaires afin d'être sûr que les fichiers sont 100% différents. Dans un tel cas, la suivante est une excellente approche.

Comme vous l'avez mentionné, cela peut être fait par octet-octet ou utiliser des tampons. La lecture de données dans la mémoire tampon est une bonne idée, car elle peut être une opération plus efficace lors de la lecture du disque dur (par exemple, la lecture de 1kb tampon 1kb).

Récemment, je devais effectuer de telles vérifications afin que je posterai des résultats de cet exercice sous forme de 2 méthodes utilitaires xxx


0 commentaires