【问题标题】:Encode/Decode a String to BigInteger in Java在 Java 中将字符串编码/解码为 BigInteger
【发布时间】:2019-08-23 05:51:38
【问题描述】:

我正在研究一个实现,我应该将长哈希 String 来回转换为 BigInteger(该函数应该是可逆的),但我不知道如何使它在 Java 中使用那些类。

我的第一个想法是做如下事情:

given s:String
for every character in the input string:
    convert char to decimal ASCII representation (i.e. 'a' -> '97')
    append result to s
build a BigDecimal with the resulting s

但问题是(正如许多用户所评论的那样)转换的长度,因为 ASCII 字符从 0 变为 255。它可以从 'a' -> '97' 更改为 'a' -> '097',但再次存在解码问题,删除每个字符的标题零(顺便说一句,算法效率较低)

因此,总而言之,这里提出的算法不是最好的主意,所以我对其他一些解决方案持开放态度。此外,如果String 和/或BigInteger 中有任何库或内置方法,它也很有帮助。签名是

public class EncodeUtil {
    public BigInteger encode(String s) {...}
    public String decode(BigInteger bi) {...}
}

条件是decode(encode("som3_We1rd/5+ring"))输出"som3_We1rd/5+ring"

我认为值得一提的是,接收到的用于解码的字符串是像 lQ5jkXWRkrbPlPlsRDUPcY6bwOD8Sm/tvJAVhYlLS3WwE5rGXv/rFRzyhn4XpUovwkLj2C3zS1JPTQ1FLPtxNXc2QLxfRcH1ZRi0RKJu1lK8TUCb6wm3cDw3VRXd21WRsnYKg6q9ytR+iFQykz6MWVs5UGM5NPsCw5KUBq/g3Bg= 这样的哈希值

欢迎任何想法/建议。提前感谢您的宝贵时间。

【问题讨论】:

  • 当你必须追加这么多次时,你应该使用 StringBuilder。
  • @ghoul932 可以肯定的是,我只是在尽可能抽象地编写算法,即使我们知道我们使用的是 Java
  • hash("abz") -> 9798122 将失败。你怎么知道在哪里分隔/分割整数?您不能使用两位数('z' -> 122)。
  • '可逆哈希'在术语上是矛盾的。你在这里做的是编码和解码。
  • q中提到的算法。仅在严格不使用某些字符(如 ASCII 值 1、10、11、12)时才有效。

标签: java hash hex ascii


【解决方案1】:

这大约可以满足您的要求 - 但是当每个“十进制 ASCII 表示”的位数是可变的时,您所要求的将不起作用。另外,你想要的不是hash function

public class Driver {
    public static void main(String[] args) {
        String s = "Reversible Hash a String to BigInteger in Java";

        System.out.println(HashUtil.notReallyHash(s));
        System.out.println(HashUtil.notReallyUnhash(HashUtil.notReallyHash(s)));
    }
}

class HashUtil {
    private static final byte SENTINEL = (byte) 1;

    public static BigInteger notReallyHash(String s) {
        CharBuffer charBuf = CharBuffer.wrap(s.toCharArray());
        ByteBuffer byteBuf = ByteBuffer.allocate(charBuf.length() * Character.BYTES + 1);

        byteBuf.put(SENTINEL); // need this in case first byte is 0 - biginteger will drop it
        byteBuf.asCharBuffer()
               .append(charBuf);

        return new BigInteger(1, byteBuf.array());
    }

    public static String notReallyUnhash(BigInteger bi) {
        ByteBuffer byteBuf = ByteBuffer.wrap(bi.toByteArray());

        byteBuf.get(); // SENTINEL

        CharBuffer charBuf = byteBuf.asCharBuffer();

        StringBuilder sb = new StringBuilder();

        int count = charBuf.length();
        for (int i = 0; i < count; i++) {
            sb.append(charBuf.get());
        }

        return sb.toString();
    }
}

产量:

361926078700757358567593716803587125664654843989863967556908753816306719264539871333731967310574715835858778584708939316915516582061621172700488541380894773554695375367299711405739159440282736685351257712598020862887985249
Reversible Hash a String to BigInteger in Java

【讨论】:

  • 谢谢,我会试试你的答案。此外,我根据您的观察对我的问题进行了一些修改
  • 哇!它完美地完成了这项工作。请问:你是从以前知道的方法还是你想出来的?您是如何得出这个解决方案的?
  • 查看 base64 - 在 Java 8 中有 java.util.Base64。我知道你可以打电话给BigInteger.toByteArray() 来获取一个数组,所以它遵循了一种机制来获取一个返回。我选择了这个构造函数,因为我什至不想尝试处理负值,但你可以尝试另一个接受字节数组的 ctor,看看它是否有效。最后,应该使用 base64 或任何其他编码方案。这不是一个明智的解决方案,但它确实说明了 ByteBuffers 和 CharBuffers 的使用!
猜你喜欢
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
  • 2016-06-17
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
相关资源
最近更新 更多