6
votes

Existe-t-il un moyen d'obtenir le hashcode d'un InputStream en utilisant Guava?

Existe-t-il un moyen d'obtenir le HashCode d'un InputStream en Java, J'essaie de télécharger une image en utilisant le de PrimeFaces, en la convertissant en HashCode et en la comparant à une autre image.

Pour le moment, j'essaye ceci:

public void save(FileUploadEvent event) throws IOException {
        HashCode hashCode = null;
        HashCode hashCodeCompare = null;
        hashCode = Files.asByteSource(new File(event.toString())).hash(Hashing.murmur3_128(50));
        hashCodeCompare = Files.asByteSource(new File(FilePathOfFileToCompare)).hash(Hashing.murmur3_128(50));
        boolean hashTrueFalse;
        if(hashCode.equals(hashCodeCompare)) {
            System.out.println("true");
        } else{
            System.out.println("false");
        }

        try (InputStream input = event.getFile().getInputstream()) {
            String imageName = generateFileName() + "." + fileExtensions(event.getFile().getFileName());
            String imageLink = PICTURE_DESTINATION + "\\" + imageName;


            Picture picture = new Picture();
            picture.setPictureUrl(imageLink);
            pictureService.createOrUpdate(picture);

            personForm.getCurrentPersonDTO().setPictureDTO(pictureMapper.toDTO(picture));


        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Existe-t-il un moyen de transformer le InputStream en un hashcode?


8 commentaires

Attendez, essayez-vous d'obtenir le HashCode d'un flux ou d'une image? Vous pouvez obtenir un HashCode de n'importe quel objet Java en appelant .hashCode () bien sûr, mais le plus important est ce que représente l'int et pourquoi vous voulez l'utiliser.


J'essaie de télécharger une image, de la transformer en valeur de hachage et de la comparer avec une autre image pour voir si elle existe déjà. J'ai essayé d'utiliser .hashCode () mais cela m'a donné un hashCode différent si j'essayais de comparer les mêmes imiges en tant que flux d'entrée et en tant que fichier


Et si vous essayez d'utiliser HashCode pour comparer des images, que se passe-t-il si l'image est un JPG ou une autre image stockée à l'aide de la compression avec perte? Les bits du fichier image peuvent être très différents, mais les images elles-mêmes peuvent être fonctionnellement identiques.


Alors, quelle serait votre méthode de choix préférée pour comparer un téléchargement d'image et une image réelle? J'ai juste besoin d'idées / contributions de l'extérieur car je travaille sur ce problème depuis 2,5h maintenant D:


Cela dépend de ce que vous essayez de faire. Si vous essayez de vérifier si les bits de deux fichiers de taille raisonnable sont identiques, vous pouvez lire tous les octets selon cette réponse < / a>. Si les images sont volumineuses, vous pouvez comparer les hachages de leurs flux similaires à cette réponse . Si c'est l'apparence réelle de l'image que vous devez comparer, alors c'est tout à fait différent.


Je veux comparer si l'image que j'ai téléchargée existe déjà! C'est tout ce que je veux faire. Pour évaluer si j'ai besoin de sauvegarder une nouvelle image ou simplement d'utiliser une image existante!


Lisez le InputStream dans un octet [] puis exécutez une fonction de hachage sur le tableau d'octets. Vous ne souhaitez probablement pas utiliser hashCode () pour cela. Utilisez plutôt SHA256.


Ce n'est pas un problème XY. La comparaison des hachages d'images est une approche parfaitement raisonnable et largement utilisée pour résoudre ce problème de déduplication de correspondance exacte.


3 Réponses :


5
votes

Vous devez lire le InputStream si vous comptez calculer un hachage sur les octets qu'il contient. Lisez d'abord InputSteam sur un octet [].

Avec Guava, utilisez ByteStreams:

byte[] sha256Hash = hin.hash().asBytes();

Une autre façon populaire de le faire est d'utiliser Commons IO :

while(hin.read() != -1);

Ensuite, vous pouvez appeler Arrays.hashCode () sur le tableau d'octets: p>

HashingInputStream hin = new HashingInputStream(Hashing.sha256(), in);

Cependant, vous pouvez envisager d'utiliser SHA256 comme fonction de hachage à la place car vous êtes moins susceptible d'avoir une collision:

MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] sha256Hash = digest.digest(bytes);

Si vous ne voulez pas lire le flux entier dans un tableau d'octets en mémoire, vous pouvez calculer le hachage pendant que l'InputStream est lu par quelqu'un d'autre. Par exemple, vous souhaiterez peut-être diffuser le InputStream sur le disque dans une base de données. Guava fournit une classe qui encapsule un InputStream qui le fait pour vous HashingInputStream :

Enveloppez d'abord votre InputStream avec un HashinInputStream

int hash = java.util.Arrays.hashCode(bytes);

Ensuite, laissez ce HashingInputStream être lu dans n'importe quel comme vous le souhaitez

InputStream in = ...;
byte[] bytes = IOUtils.toByteArray(in);

Ensuite, récupérez le hachage de HashingInputStream

InputStream in = ...;
byte[] bytes = ByteStreams.toByteArray(in);


0 commentaires

6
votes

Ce que vous voulez faire est ByteStreams.copy (input, Funnels.asOutputStream (hasher)) hasher est acquis par ex. Hashing.sha256 (). newHasher () . Ensuite, appelez hasher.hash () pour obtenir le HashCode résultant.


1 commentaires

Je ne sais pas pourquoi cela n'a pas plus de votes positifs, la plupart des autres solutions nécessitent une copie du flux d'entrée dans un octet [], ou une boucle dans le flux d'entrée en dehors du hachage.



1
votes

Je suggérerais d'utiliser Files.asByteSource(fileSource.getFile()).hash(hashFunction).padToLong()


0 commentaires