Catalog
-
- Arbitrary Binary Conversion of Arbitrary Binary Numbers
- Converting Arbitrary Number to Decimal Number
- Several Interview Questions on parseInt
- Coding History
- Summary
Preface
In daily work, Base64 is frequently used to replace small icons in order to reduce HTTP requests and achieve performance optimization. Based on this, we will talk about the development of encoding, why Base64 is needed and how to implement base64. This article was first published in Talk about coding things, and by the way, implement base64 Please indicate the source for reprinting.
Conversion between binaries
Some pre-knowledge also involves some classical interview questions.
Arbitrary Binary Conversion of Arbitrary Binary Numbers
Number.prototype.toString(radix)
Converting Arbitrary Number to Decimal Number
Several Interview Questions on parseInt
Speaking of parseInt, I have to mention an interesting interview question.
// What will it output? [1, 2, 3].map(parseInt) // => 1, NaN, NaN
The first parameter of the map method is a function, which has three parameters, array. map ((item, index, array) => {...})
Actually equivalent to
function fn (item, index) { return parseInt(item, index) } [1, 2, 3].map(fn) // The parseInt iteration process is equivalent to the following // parseInt(1, 0) => 1 // parseInt(2, 1) => NaN // parseInt(3, 2) => NaN
Let's look at a similar interview question.
// What will it output? '1 2 3'.replace(/\d/g, parseInt) // => 1, NaN, 3
If the second parameter of the replace method is a function, the function will have several parameters. The first is a string matching a pattern; the second is a string matching a pattern neutron expression, with zero or more such parameters.
In fact, it is equivalent to the following
function fn (...args) { // Only the first two parameters will be taken. return parseInt(args[0], args[1]) } '1 2 3'.replace(/\d/g, fn) // The parseInt iteration process is equivalent to the following // parseInt('1', 0) => 1 // parseInt('2', 2) => NaN // parseInt('3', 4) => 3
In fact, parseInt/map/replace has been explained in detail in mdn. I hope you don't be too impetuous, don't be an outspoken party, calm down to chew the documents and do more practice, many interview questions will naturally be solved.
Coding History
ASCII
GBK2312
GBK
GB18030/DBCS
Unicode
UTF-8
The current standards have the following characteristics
- UTF-8 is the most widely used way to implement Unicode on the Internet.
- UTF-8 transmits data in eight units at a time.
- UTF-16 is 16 bits at a time.
- One of the biggest features of UTF-8 is that it is a variable-length encoding method.
- Unicode takes up 2 bytes for a Chinese character, UTF-8 takes up 3 bytes for a Chinese character.
- UTF-8 is one of the ways to implement Unicode
base64 encoding
Why base64 is needed
In development, there are often some small icon pictures, each picture will have an HTTP request, because the browser has a limited number of concurrent domain names, so we should try to reduce the number of HTTP requests.
This article mainly talks about coding, so it only talks about how to reduce HTTP requests from coding.
Within a computer, any information is ultimately stored in a series of binaries, and pictures are no exception.
And the src attribute of the img tag is followed by a base64 character. If the character is valid, the picture will be displayed normally.
How to Realize base64
All the code involved below is in Warehouse Interest can be self-selected.
Read buffer to json object
First, prepare a 2.txt file.
Feng Lanlan, I said the moonlight was so beautiful tonight, you said yes.
case.js code
const fs = require('mz/fs') const path = require('path') // Read as a buffer object async function read2JSON () { let ret = await fs.readFile(path.resolve(__dirname, '2.txt')) console.log(ret.toJSON()) return ret.toJSON() } read2JSON() // => { type: 'Buffer', data: [ 229, 134, 175, 229... ] }
The above dependencies mz/fs fs have been packaged as promise, so we can write more like synchronization.
The readFile function reads into a buffer stream if the second parameter is not specified and is composed of hexadecimal numbers.
buffer.toJSON You can convert a buffer stream to a json object, and hexadecimal is also converted to decimal. As shown in the output above.
Convert decimal to binary
Converting decimal to binary can be done by Number.toString(2) method
// Convert decimal to binary async function data2b () { let data = await read2JSON() let ret = [] data.data.forEach(item => { ret.push(item.toString(2)) }) console.log(ret) return ret } data2b() // => [ '11100101', '10000110', '10101111', '11100101'...]
Put the binary together by 3*8 and then divide it into 4*6
A Chinese character is composed of three bytes in UTF-8 specification, and one byte is composed of eight binary physical bits. So a Chinese character actually occupies 3*8 memory. In base64, we need 6 physical bits to represent a byte, that is, 2** 6, so we need to re-divide 4*6.
async function split () { let data = await data2b() let dataStr = data.join('') let ret = [] let splitUnit = 6 let flag = 0 while (flag < dataStr.length) { ret.push(dataStr.substr(flag, splitUnit)) flag = flag + splitUnit } console.log(ret) return ret } split() // => [ '111001', '011000', '011010', '101111'...]
Then convert the binary system to the decimal system
Binary to decimal can be converted by parseInt(string, 2) method
async function data20 () { let data = await split() let ret = data.map(item => { return parseInt(item, 2) }) console.log(ret) return ret } data20() // => [ 57, 24, 26, 47, 57, 24, 22, 48, 57, 24, 22, 48 ]
base64 code
64 in base64 is actually based on 2** 6, which is composed of capital letters, lowercase letters, numbers, +/
const lowerCases = 'abcdefghijklmnopqrstuvwxyz' const numbers = '0123456789' const base64lib = `${lowerCases.toUpperCase()}${lowerCases}${numbers}+/` console.log(base64lib) // => ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Get each base64 code
Then we can get each base64 code.
async function main () { let data = await data20() let ret = [] data.forEach(item => { ret.push(base64lib[item]) }) console.log(ret.join('')) return ret.join() } main() // => 5Yav5YWw5YWw5ZWK5oiR6K+05LuK5pma5pyI6Imy6L+Z5LmI576O77yM5L2g6K+05piv55qE44CC
We can go there. base64 Online Transcoding and Decoding Verify.
Simplified code
Code simplification for the above ideas
const CHARTS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' function transfer (str) { let buf = Buffer.from(str) let result = '' for(let b of buf){ result += b.toString(2) } return result.match(/(\d{6})/g).map(val => parseInt(val, 2)).map(val => CHARTS[val]).join('') } let fl = transfer('Feng') console.log(fl) // => 5Yav
Summary
If we can convert Chinese to base64, we can also convert pictures.
async function read2JSON () { // let ret = await fs.readFile(path.resolve(__dirname, '2.txt')) // Read pictures let ret = await fs.readFile(path.resolve(__dirname, '../assets/encoding-base64-example.png')) console.log(ret.toJSON()) return ret.toJSON() }
Special: Because Put the binary together by 3*8 and then divide it into 4*6 It used to take three bytes to store a Chinese character, but now it needs four bytes to store it, so it will be 3/1 larger than before when converted to base64.
The following pictures of smiling faces are displayed by the src attribute of img, but this article does not realize the conversion of pictures to base64, because its logic is more complex, but this article explains the general idea, which can be further studied.