【问题标题】:byte[] to String to byte[] againbyte[] 到 String 再到 byte[]
【发布时间】:2013-02-15 07:13:45
【问题描述】:

这就是我想要做的。我有一个 byte[] 需要用键(比如 key1)存储在 Redis 中,Redis 会将其存储为字符串。我需要在通过 key1 检索值时重建 byte[]

    //here is a byte array
    byte[] bArr = new byte[] {83, 71, 86, 115, 98, 71, 56, 103, 84, 88, 73, 117, 73, 69, 104, 118, 100, 121, 66, 107, 98, 121, 66, 53, 98, 51, 85, 103, 90, 71, 56, 47}; //"Hello World"; 

    // I will have to store this as a byte string into redis
    //Base64 encoding
    bArr = Base64.encodeBase64(bArr);
    String storeStr = Arrays.toString(bArr) ;
    // storeStr is what gets stored in redis
    System.out.println("storeStr>>" + storeStr+ "<<");
    // I will get this string back from redis
    // now trying to reconstruct the byte[]
    byte[] aArr = Base64.decodeBase64(storeStr); 
    System.out.println("readStr>>" + Arrays.toString(aArr)+ "<<");  

但我得到以下输出:

storeStr>>[85, 48, 100, 87, 99, 50, 74, 72, 79, 71, 100, 85, 87, 69, 108、49、83、85、86、111、100、109、82、53、81、109、116、105、101、 85、73、49、89、106、78、86、90、49、112、72、79、67、56、61]>[-13, -98, 60, -41, 77, 60, -17, -33, 121, -45, -66, 59, -37, -65, 123, -41, 93, 52, -13、-97、59、-21、-35、116、-13、-113、124、-33、-50、124、-21、93、117、-41、77、53、-45、- 33、54、-25、127、53、-41、79、117、-41、-83、116、-25、93、53、-13、-98、-9、-29、-33、61、 -41、78、-69、-13、-50、-67、-45、-113、117、-41、110、-10、-17、-34、-69、-25、-82、-75 ]

我做错了什么?有没有更好的解决方案?

【问题讨论】:

    标签: java bytearray


    【解决方案1】:

    我不知道您使用的是什么 base64 编码器,但使用 base64 编码字节数组的结果应该已经String... 并且在您解码时也是如此,它应该将String 转换为byte[]。不幸的是,一些 base64 API 在这方面设计得不是很好 -

    我建议你看看这个public domain library 有一个更明智的API:

    byte[] binary = ...;
    String encoded = Base64.encodeBytes(binary);
    
    // Send encoded to Redis...
    
    byte[] decoded = Base64.decode(encoded);
    

    【讨论】:

      【解决方案2】:

      Arrays.toString() 不会将字节数组转换为字符串。它给出了一个字节数组的字符串表示,用于调试目的,就像List&lt;Byte&gt;.toString() 所做的那样。

      Base64.encode() 应该将字节数组转换为字符串。而Base64.decode() 应该将base64 字符串转换为相应的字节数组。我见过的所有 Base64 库都内置了这样的方法。你的可能也有一个。如果没有,Base64 包含 ASCII 字符,你可以简单地使用

      String storeStr = new String(base64Array, "ASCII");
      

      byte[] bytes = storeStr.getBytes("ASCII");
      

      【讨论】:

      • 找到了正确的方法:String storeStr = Base64.encodeBase64String(bArr);
      • 为什么要停在 B64? Redis 是二进制安全的,因此它可以处理任何非打印 ASCII 字符。那么,当你可以使用 256 个状态时,为什么要为每个字符使用 64 个可能的状态呢?使用 1/4 的空间。
      【解决方案3】:

      您可以使用构造函数从 byte[] 创建字符串:

      //assuming you have a byte[] bytes
      String string = new String(bytes);
      

      然后将其写回:

      byte[] bytes = string.getBytes();
      

      【讨论】:

        【解决方案4】:

        请记住,base 64 之所以被称为是因为它的基数为 64(64 个可能的值)。这意味着每个字符是 2^6 或 6 位。 Redis 支持二进制安全字符串,因此它甚至可以接受非打印字符。没有理由将自己限制在 64 个漂亮的打印、网络安全字符(为什么人们使用 B64)。

        另一个问题是ASCII是0-127,但是字节是-128 to 127,所以我们不能直接映射,我们失去了一半的范围(2^8 vs 2^7)。如果我们使用 UTF-8,我们会得到所有这些位,因此 2^8 或基数 256。结果是我们可以将一个字节填充到 1.25 个 B64 字符或单个 UTF-8 字符中。因此,UTF-8 编码将使用约 75% 的空间作为 B64 编码数据。下面我们比这更好,因为 B64 使用了所有额外的填充 = 字符。

        示例,编码 19 个字节:

        B64 字符串:28 个字符

        UTF8 字符串:19 个字符(节省 32%!)

        // setup
        byte[] bytes = new byte[]{-10, 1, 3, 85, 48, 100, 87, 99, 050, 74, 79, 71, 100, 85, 87, -120, 108, -128, 30};
        
        // full UTF-8 range
        String outFullRange = new String(bytes, "UTF-8");
        System.out.println(outFullRange); // prints �U0dWc(JOGdUW�l�
        
        // just Base64
        String outB64 = Base64.encode(bytes);
        System.out.println(outB64);// 9gEDVTBkV2MoSk9HZFVXiGyAHg==
        

        请记住,由于 Redis 位于内存中,而且内存非常宝贵,因此您可能希望在应用开始填满时将二进制数据切换为 UTF-8 编码,以快速节省一些空间。缺点是它不像 B64 那样可读。

        【讨论】:

        • 感谢您介绍binary safe strings,但您的new String(bytes, "UTF-8") 可能不正确。并非所有字节序列都可以正确解析为 UTF-8 字节而不会丢失数据。请改用iso-8859-1
        【解决方案5】:

        使用这2个函数来转换和转换回来

        Convert.ToBase64String(en)
        
        Convert.FromBase64String(input)
        

        它桥接了字节和字符串之间的链接。并确保没有数据添加或丢失。 这是一个特殊的字符串。

        https://en.wikipedia.org/wiki/Base64

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-14
          • 2011-02-15
          • 2012-10-07
          相关资源
          最近更新 更多