V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
wuyiccc
V2EX  ›  程序员

前端上传 base64 格式的图片的时候,为什么 Java 后端要对 byte 类型的负数值+256?

  •  
  •   wuyiccc · 2023-12-23 23:47:58 +08:00 · 1537 次点击
    这是一个创建于 370 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这几天看了好几个关于前端上传 base64 格式的图片到 java 后端,后端需要 for 循环 byte 类型的数据,对于小于 0 的 byte 值要加 256 ,这一点没看懂,java byte 值的范围不是-128~127 么,负数值的 byte 数据+256 也是原值,感觉好像没变化~~~,这一点处理代码没看懂,是有啥隐藏知识么,有没有大佬指点一下?

    代码如下

     byte[] b = new byte[0];
     b = decoder.decodeBuffer(baseStrs[1]);
    
     for (int i = 0; i < b.length; ++i) {
         if (b[i] < 0) {
             b[i] += 256;
         }
     } 
    

    资料来源 csdn https://blog.csdn.net/ShuSheng0007/article/details/118230374?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-118230374-blog-119354309.235%5Ev39%5Epc_relevant_3m_sort_dl_base4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-118230374-blog-119354309.235%5Ev39%5Epc_relevant_3m_sort_dl_base4&utm_relevant_index=2


    chatgpt 的回答: 在 Java 中,对于负数进行 Base64 编码时,通常需要加上 256 ,这是因为 Java 中的 byte 类型是有符号的,其取值范围是-128 到 127 。而 Base64 编码是基于字节的,它期望输入的字节是无符号的。

    在进行 Base64 编码时,负数的二进制表示形式和正数不同。如果不进行处理,可能导致 Base64 编码输出的结果与预期不符。

    假设有一个负数 x ,其在二进制中表示为 b1b2b3b4b5b6b7b8 。由于 Java 中的 byte 是有符号的,b8 表示符号位,如果直接对其进行 Base64 编码,可能会导致编码器处理符号位的问题。因此,为了确保正确的 Base64 编码,可以将负数加上 256 ,将其转换为一个正数,然后再进行 Base64 编码。

    以下是一个简单的例子,演示了对负数进行 Base64 编码的问题和解决方法:

    import java.util.Base64;
    
    public class Base64Example {
        public static void main(String[] args) {
            int negativeNumber = -42;
    
            // 直接对负数进行 Base64 编码,可能导致意外结果
            String base64Direct = Base64.getEncoder().encodeToString(new byte[]{(byte) negativeNumber});
            System.out.println("Base64 Direct: " + base64Direct);
    
            // 将负数加上 256 ,然后进行 Base64 编码
            int adjustedNumber = negativeNumber + 256;
            String base64Adjusted = Base64.getEncoder().encodeToString(new byte[]{(byte) adjustedNumber});
            System.out.println("Base64 Adjusted: " + base64Adjusted);
        }
    }
    
    

    有大佬指点一下么~~~ 感谢!

    zjsxwc
        1
    zjsxwc  
       2023-12-24 00:23:12 +08:00 via Android
    没有意义吧,8 位的二进制不管是有符号数还是无符号数,256 一直都是 2^(9-1),也就是第 9 位二进制才能表达,但 8 位的 byte 是无论如何都不能表达 9 位的 256 ,所以加 256 是脱裤子放屁?
    arloor
        2
    arloor  
       2023-12-24 01:19:49 +08:00
    因为 base64 是转成 int 处理的,补码下面,负号要处理掉
    leonshaw
        3
    leonshaw  
       2023-12-24 02:37:16 +08:00 via Android
    以讹传讹
    geelaw
        4
    geelaw  
       2023-12-24 05:31:08 +08:00 via iPhone
    你引用的 CSDN 文章已经说了要加上 256 是错误的。

    问 ChatGPT 得到的答案不可靠,尤其是带着具体细节提问的时候,因为 ChatGPT 一容易编造内容,二容易“讨好”用户,用户尝试错误地更正它的回复的时候,它很容易“好好先生”地同意用户的说法——如果你问 ChatGPT 为什么要做 XYZ ,那么它很可能不会考虑这是否是伪命题(即实际上可能不需要做 XYZ )。
    XXWHCA
        5
    XXWHCA  
       2023-12-24 07:46:46 +08:00
    你会发现去掉也能 decode
    lovelylain
        6
    lovelylain  
       2023-12-24 09:40:24 +08:00 via Android
    对接过一份接口,签名算法是对传入数据,如果长度为奇数后面补一个 0 凑成偶数,然后十六进制解码再 hash 再十六进制编码。知道为什么要奇数补 0 吗,因为他们十六进制编解码是自己实现,编码正确,对 hex 数据解码也正确,但是还能对不是 hex 的数据解码,签名算法的传入数据就是未经 hex 编码的原始数据,最后只好把他们这个 hex 解码抄了一遍。
    wuyiccc
        7
    wuyiccc  
    OP
       2023-12-25 10:23:28 +08:00
    @geelaw 哦哦,看到了
    wuyiccc
        8
    wuyiccc  
    OP
       2023-12-25 10:23:43 +08:00
    @XXWHCA 是的,感觉目前没啥影响
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1062 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:12 · PVG 03:12 · LAX 11:12 · JFK 14:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.