【问题标题】:Is there any way to get the hashcode of an InputStream using Guava?有没有办法使用 Guava 获取 InputStream 的哈希码?
【发布时间】:2019-06-12 20:18:42
【问题描述】:

有没有办法在 Java 中获取 InputStream 的 HashCode, 我正在尝试使用 PrimeFaces 中的<p:fileUpload/> 上传图片,将其转换为 HashCode 并将其与另一张图片进行比较。

目前我正在尝试这个:

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

有什么方法可以将InputStream 变成哈希码?

【问题讨论】:

  • 等等,你是要获取流的HashCode还是图像的HashCode?你当然可以通过调用.hashCode() 来获取任何Java 对象的HashCode,但更重要的是int 代表什么以及为什么要使用它。
  • 我尝试上传一张图片,并将其转为hashvalue,并与另一张图片进行比较,看是否已经存在。我尝试使用.hashCode(),但如果我尝试将相同的图像与输入流和文件进行比较,它会给我一个不同的 hashCode
  • 如果您尝试使用 HashCode 来比较图像,如果图像是 JPG 或其他使用有损压缩存储的图像怎么办?图像文件位可能完全不同,但图像本身在功能上可能相同。
  • 那么,您首选的比较图片上传和实际图片的方法是什么?我只需要一些来自外部的 iedeas/输入,因为我现在在这个问题上工作了 2.5 小时 D:
  • 将 InputStream 读入 byte[] 然后在字节数组上运行哈希函数。您可能不想为此使用 hashCode() 。请改用 SHA256。

标签: java file hash inputstream guava


【解决方案1】:

我建议使用Files.asByteSource(fileSource.getFile()).hash(hashFunction).padToLong()

【讨论】:

    【解决方案2】:

    如果要计算其包含的字节的哈希值,则必须读取 InputStream。首先将 InputSteam 读取到 byte[]。

    在 Guava 中使用 ByteStreams:

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

    另一种流行的方法是使用Commons IO

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

    然后你可以在字节数组上调用Arrays.hashCode():

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

    但是,您可能会考虑使用 SHA256 作为哈希函数,因为您不太可能发生冲突:

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

    如果您不想将整个流读取到内存字节数组中,您可以在其他人读取 InputStream 时计算哈希值。例如,您可能希望将 InputStream 流式传输到磁盘到数据库中。 Guava 提供了一个封装了 InputStream 的类,它会为您执行此操作HashingInputStream

    首先用 HashinInputStream 包装你的 InputStream

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

    然后让 HashingInputStream 以你喜欢的任何方式读取

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

    然后从 HashingInputStream 中获取哈希

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

    【讨论】:

      【解决方案3】:

      你想要做的是ByteStreams.copy(input, Funnels.asOutputStream(hasher)),其中hasher是从例如获取的。 Hashing.sha256().newHasher()。然后,调用hasher.hash() 得到结果HashCode

      【讨论】:

      • 我不知道为什么这没有更多的赞成票,大多数其他解决方案都需要将输入流复制到一个字节[],或者在哈希器之外循环输入流。
      • ByteStreams.copy(in, out) 正在为您循环输入流。使用此解决方案的缺点是您将哈希器用作接收器。因此,当您散列它们时,您会丢失字节。这通常是不可取的,例如您正在处理用户刚刚上传的输入流。你们都想将字节传递到存储中并生成哈希。但是这里的字节会在从 InputStream 中读取时丢失。
      • @bhspencer:老实说,实际上在大多数情况下,我实际上并不想保留字节。
      猜你喜欢
      • 2010-10-09
      • 1970-01-01
      • 2020-09-29
      • 2023-03-23
      • 2013-06-29
      • 2022-10-23
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      相关资源
      最近更新 更多