Decode Base64 to Hexadecimal string with javascript

前端 未结 5 1193
有刺的猬
有刺的猬 2020-12-06 09:52

Needing to convert a Base64 string to Hexadecimal with javascript.

Example:

var base64Value = \"oAAABTUAAg==\"

Need conversion m

5条回答
  •  情书的邮戳
    2020-12-06 10:36

    Here is my vanilla JavaScript solution that does not use atob and Buffer. Supports separator, suitable for binary data and React Native, relatively high performance.

    Usage :

    base64ToHex( 'MTIzYWJjIDotKQ==', '-' )
    // returns '31-32-33-61-62-63-20-3a-2d-29'
    

    Code :

    /* Convert base64 data to hex string.  https://stackoverflow.com/a/57909068/893578
     *   txt : Base64 string.
     *   sep : Hex separator, e.g. '-' for '1a-2b-3c'.  Default empty.
     */
    const base64ToHex = ( () => {
       // Lookup tables
       const values = [], output = [];
    
       // Main converter
       return function base64ToHex ( txt, sep = '' ) {
          if ( output.length <= 0 ) populateLookups();
          const result = [];
          let v1, v2, v3, v4;
          for ( let i = 0, len = txt.length ; i < len ; i += 4 ) {
             // Map four chars to values.
             v1 = values[ txt.charCodeAt( i   ) ];
             v2 = values[ txt.charCodeAt( i+1 ) ];
             v3 = values[ txt.charCodeAt( i+2 ) ];
             v4 = values[ txt.charCodeAt( i+3 ) ];
             // Split and merge bits, then map and push to output.
             result.push(
                output[ ( v1 << 2) | (v2 >> 4) ],
                output[ ((v2 & 15) << 4) | (v3 >> 2) ],
                output[ ((v3 &  3) << 6) |  v4 ]
             );
          }
          // Trim result if the last values are '='.
          if ( v4 === 64 ) result.splice( v3 === 64 ? -2 : -1 );
          return result.join( sep );
       };
    
       function populateLookups () {
          const keys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
          for ( let i = 0 ; i < 256 ; i++ ) {
             output.push( ( '0' + i.toString( 16 ) ).slice( -2 ) );
             values.push( 0 );
          }
          for ( let i = 0 ; i <  65 ; i++ )
             values[ keys.charCodeAt( i ) ] = i;
       }
    } )();
    

    Demo:

    const [ txt, b64, hex, sep ] = document.querySelectorAll( 'input, select' );
    
    function txtOnInput ({ target: { value }}) {
       hex.value = base64ToHex( b64.value = btoa( value ), sep.value ).toUpperCase();
    }
    
    function b64OnInput ({ target: { value }}) {
       hex.value = base64ToHex( value, sep.value ).toUpperCase();
       txt.value = atob( value );
    }
    
    txtOnInput({target:txt});
    
    // Different coding style, same result.
    function base64ToHex ( txt, sep = '' ) {
       let { val, out } = base64ToHex, v1, v2, v3, v4, result = [];
       if ( ! base64ToHex.val ) { // Populate lookup tables.
          out = base64ToHex.out = [];
          val = base64ToHex.val = Array( 255 ).fill( 0 );
          const keys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
          for ( let i = 0 ; i < 256 ; i++ ) out.push( ( '0' + i.toString(16) ).slice( -2 ) );
          for ( let i = 0 ; i <  65 ; i++ ) val[ keys.charCodeAt( i ) ] = i;
       }
       for ( let i = 0, len = txt.length ; i < len ; i += 4 ) {
          v1 = val[ txt.charCodeAt( i   ) ]; // Map four chars to values.
          v2 = val[ txt.charCodeAt( i+1 ) ];
          v3 = val[ txt.charCodeAt( i+2 ) ];
          v4 = val[ txt.charCodeAt( i+3 ) ];
          result.push( out[ (v1 << 2) | (v2 >> 4) ], // Split values, map to output.
                       out[ ((v2 & 15) << 4) | (v3 >> 2) ],
                       out[ ((v3 & 3) << 6) | v4 ] );
       } // After loop ended: Trim result if the last values are '='.
       if ( v4 === 64 ) result.splice( v3 === 64 ? -2 : -1 );
       return result.join( sep ); // Array is fast.  String append = lots of copying.
    }
    label { display: block; height: 1em; }
    input, select { position: absolute; left: 5em; width: calc( 100% - 6em ) }
    input[readonly] { background: #D8D8D8; }




    Note: this is done for geisterfurz007 because react-native-fs yields base64 for binary files, and (s)he needs to turn that into hex string. Not that I am happy with the efficiency of existing snippets...

提交回复
热议问题