Base64 解码纯 Javascript

Base64 Decode Pure Javascript

我正在尝试使用 Snowflake 中的用户定义函数对来自 Kafka <> Debezium 有效负载的值(16 位签名大端)进行 base64 解码。不幸的是,我只能使用 Javascript 而 Snowflake 使用 Javascript 标准库。我找到了一个使用 Buffer 模块的 NodeJS 工作示例,但在 Javascript.

中不可用
 var kafkaDecodeNumber = function(base64EncodedNumber) {
     var byteArray = Buffer.from(base64EncodedNumber, 'base64');
     var value = 0;
     for (var i = 0; i < byteArray.length; i++) {
         value = (value * 256) + byteArray[i];
     }
     return value;
 };

var float = parseFloat(kafkaDecodeNumber( price )).toFixed(38) / 100

这是我在别处使用的一些工作代码示例

Python

    ctx = decimal.Context()
    ctx.prec = 38
    result = ctx.create_decimal(
        int.from_bytes(base64.b64decode(byte_value), byteorder='big')
        ) / 100
    return result

Ruby

event.get('price').unpack1('m*').unpack1('B*').to_i(2) / 100.0)

如果有任何帮助,那就太好了!

以下是使用 atob(根据需要使用 polyfill)Uint8Array 和 DataView 的方法

请注意,原始 data 数组被“填充”为偶数长度 - 但最后两个字节需要交换,我相信

var kafkaDecodeNumber = function(base64EncodedNumber) {
    var data = atob(base64EncodedNumber).split('').map(v => v.charCodeAt(0));
    if (data.length % 2) {
        data.push(0, data.pop());
    }
    var uint8 = new Uint8Array(data);
    return new DataView(uint8.buffer).getInt16(0);
}

var float = parseFloat(kafkaDecodeNumber( 'D6A=' )).toFixed(38) / 100;
console.log(float);

float = parseFloat(kafkaDecodeNumber( '/w==' )).toFixed(38) / 100;
console.log(float);

实际上,由于代码只会得到一个编码的 int16 - 代码要简单得多

var kafkaDecodeNumber = function(base64EncodedNumber) {
    const [a, b] = atob(base64EncodedNumber).split('').map(v => v.charCodeAt(0));
    return b === undefined ? a : a * 256 + b;
    
}

var float = parseFloat(kafkaDecodeNumber( 'D6A=' )).toFixed(38) / 100;
console.log(float);

float = parseFloat(kafkaDecodeNumber( '/w==' )).toFixed(38) / 100;
console.log(float);

实际上,只是找到了最简单的方法,因为您只会得到一个 16 位的数字 - 而且这种方法不需要任何 base64 polyfill

var kafkaDecodeNumber = function(base64EncodedNumber) {
    const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
    const bits = base64EncodedNumber
      .replace(/=+$/g, '')
      .split('')
      .reduce((a, b) => a + b64.indexOf(b).toString(2).padStart(6, '0'), '');
      
    return parseInt(bits.match(/[01]{8}/g).join('').padStart(16, '0'), 2);
}

var float = parseFloat(kafkaDecodeNumber( 'D6A=' )).toFixed(38) / 100;
console.log(float);

float = parseFloat(kafkaDecodeNumber( '/w==' )).toFixed(38) / 100;
console.log(float);