下面,详细介绍Base64的编码转换方式。

所谓Base64,就是说选出64个字符----小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"(再加上作为垫字的"=",实际上是65个字符)----作为一个基本字符集。然后,其他所有符号都转换成这个字符集中的字符。

具体来说,转换方式可以分为四步。

第一步,将每三个字节作为一组,一共是24个二进制位。

第二步,将这24个二进制位分为四组,每个组有6个二进制位。

第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节。

第四步,根据下表,得到扩展后的每个字节的对应符号,这就是Base64的编码值。

  0 A  17 R   34 i   51 z

  1 B  18 S   35 j   52 0

  2 C  19 T   36 k   53 1

  3 D  20 U   37 l   54 2

  4 E  21 V   38 m   55 3

  5 F  22 W   39 n   56 4

  6 G  23 X   40 o   57 5

  7 H  24 Y   41 p   58 6

  8 I   25 Z   42 q   59 7

  9 J  26 a   43 r   60 8

  10 K  27 b   44 s   61 9

  11 L  28 c   45 t   62 +

  12 M  29 d   46 u   63 /

  13 N  30 e   47 v

  14 O  31 f   48 w   

  15 P  32 g   49 x

  16 Q  33 h   50 y

因为,Base64将三个字节转化成四个字节,因此Base64编码后的文本,会比原文本大出三分之一左右。

4.

举一个具体的实例,演示英语单词Man如何转成Base64编码。

Text content M a n
ASCII 77 97 110
Bit pattern 0 1 0 0 1 1 0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 1 0
Index 19 22 5 46
Base64-Encoded T W F u

第一步,"M"、"a"、"n"的ASCII值分别是77、97、110,对应的二进制值是01001101、01100001、01101110,将它们连成一个24位的二进制字符串010011010110000101101110。

第二步,将这个24位的二进制字符串分成4组,每组6个二进制位:010011、010110、000101、101110。

第三步,在每组前面加两个00,扩展成32个二进制位,即四个字节:00010011、00010110、00000101、00101110。它们的十进制值分别是19、22、5、46。

第四步,根据上表,得到每个值对应Base64编码,即T、W、F、u。

因此,Man的Base64编码就是TWFu。

5.

如果字节数不足三,则这样处理:

a)二个字节的情况:将这二个字节的一共16个二进制位,按照上面的规则,转成三组,最后一组除了前面加两个0以外,后面也要加两个0。这样得到一个三位的Base64编码,再在末尾补上一个"="号。

比如,"Ma"这个字符串是两个字节,可以转化成三组00010011、00010110、00010000以后,对应Base64值分别为T、W、E,再补上一个"="号,因此"Ma"的Base64编码就是TWE=。

b)一个字节的情况:将这一个字节的8个二进制位,按照上面的规则转成二组,最后一组除了前面加二个0以外,后面再加4个0。这样得到一个二位的Base64编码,再在末尾补上两个"="号。

比如,"M"这个字母是一个字节,可以转化为二组00010011、00010000,对应的Base64值分别为T、Q,再补上二个"="号,因此"M"的Base64编码就是TQ==。

6.

再举一个中文的例子,汉字"严"如何转化成Base64编码?

这里需要注意,汉字本身可以有多种编码,比如gb2312、utf-8、gbk等等,每一种编码的Base64对应值都不一样。下面的例子以utf-8为例。

首先,"严"的utf-8编码为E4B8A5,写成二进制就是三字节的"11100100 10111000 10100101"。将这个24位的二进制字符串,按照第3节中的规则,转换成四组一共32位的二进制值"00111001 00001011 00100010 00100101",相应的十进制数为57、11、34、37,它们对应的Base64值就为5、L、i、l。

所以,汉字"严"(utf-8编码)的Base64值就是5Lil。

7.

PHP语言中,有一对专门的函数用于Base64转换:base64_encode()用于编码、base64_decode()用于解码。

这对函数的特点是,它们不管输入文本的编码是什么,都会按照规则进行Base64编码。因此,如果你想得到utf-8编码下的Base64对应值,你就必须自己保证,输入的文本是utf-8编码的。

8.

这一节介绍如何用JavaScript语言进行Base64编码。

首先,假定网页的编码是utf-8,我们希望对于同样的字符串,用PHP和Javascript可以得到同样的Base64编码。

这里就会产生一个问题。因为Javascript内部的字符串,都以utf-16的形式进行保存,因此编码的时候,我们首先必须将utf-8的值转成utf-16再编码,解码的时候,则是解码后还需要将utf-16的值转回成utf-8。

网上已经有人写好了现成的Javascript函数:

/* utf.js - UTF-8 <=> UTF-16 convertion * * Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp> * Version: 1.0 * LastModified: Dec 25 1999 * This library is free. You can redistribute it and/or modify it. */

/* * Interfaces: * utf8 = utf16to8(utf16); * utf16 = utf8to16(utf8); */

function utf16to8(str) { var out, i, len, c;

out = ""; len = str.length; for(i = 0; i < len; i++) { c = str.charCodeAt(i); if ((c >= 0x0001) && (c <= 0x007F)) { out += str.charAt(i); } else if (c > 0x07FF) { out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F)); out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } else { out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F)); out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F)); } } return out; }

function utf8to16(str) { var out, i, len, c; var char2, char3;

out = ""; len = str.length; i = 0; while(i < len) { c = str.charCodeAt(i++); switch(c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: // 0xxxxxxx out += str.charAt(i-1); break; case 12: case 13: // 110x xxxx 10xx xxxx char2 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: // 1110 xxxx 10xx xxxx 10xx xxxx char2 = str.charCodeAt(i++); char3 = str.charCodeAt(i++); out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; } }

return out; }

上面的这段代码中定义了两个函数,utf16to8()用于将utf-16转成utf-8,utf8to16用于将utf-8转成utf-16。

下面才是真正用于base64编码的函数。

/* Copyright (C) 1999 Masanao Izumo <iz@onicos.co.jp> * Version: 1.0 * LastModified: Dec 25 1999 * This library is free. You can redistribute it and/or modify it. */

/* * Interfaces: * b64 = base64encode(data); * data = base64decode(b64); */

var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var base64DecodeChars = new Array( -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);

function base64encode(str) { var out, i, len; var c1, c2, c3;

len = str.length; i = 0; out = ""; while(i < len) { c1 = str.charCodeAt(i++) & 0xff; if(i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt((c1 & 0x3) << 4); out += "=="; break; } c2 = str.charCodeAt(i++); if(i == len) { out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); out += base64EncodeChars.charAt((c2 & 0xF) << 2); out += "="; break; } c3 = str.charCodeAt(i++); out += base64EncodeChars.charAt(c1 >> 2); out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)); out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)); out += base64EncodeChars.charAt(c3 & 0x3F); } return out; }

function base64decode(str) { var c1, c2, c3, c4; var i, len, out;

len = str.length; i = 0; out = ""; while(i < len) { /* c1 */ do { c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while(i < len && c1 == -1); if(c1 == -1) break;

/* c2 */ do { c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]; } while(i < len && c2 == -1); if(c2 == -1) break;

out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

/* c3 */ do { c3 = str.charCodeAt(i++) & 0xff; if(c3 == 61) return out; c3 = base64DecodeChars[c3]; } while(i < len && c3 == -1); if(c3 == -1) break;

out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

/* c4 */ do { c4 = str.charCodeAt(i++) & 0xff; if(c4 == 61) return out; c4 = base64DecodeChars[c4]; } while(i < len && c4 == -1); if(c4 == -1) break; out += String.fromCharCode(((c3 & 0x03) << 6) | c4); } return out; }

上面代码中的base64encode()用于编码,base64decode()用于解码。

因此,对utf-8字符进行编码要这样写:

sEncoded=base64encode(utf16to8(str));

然后,解码要这样写:

sDecoded=utf8to16(base64decode(sEncoded));

(完)

详细介绍Base64的编码转换方式的更多相关文章

  1. Base64的编码转换方式

    下面,详细介绍Base64的编码转换方式. 所谓Base64,就是说选出64个字符----小写字母a-z.大写字母A-Z.数字0-9.符号"+"."/"(再加上 ...

  2. java基础:进制详细介绍,进制快速转换,二维数组详解,循环嵌套应用,杨辉三角实现正倒直角正倒等腰三角,附练习案列

    1.Debug模式 1.1 什么是Debug模式 是供程序员使用的程序调试工具,它可以用于查看程序的执行流程,也可以用于追踪程序执行过程来调试程序. 1.2 Debug介绍与操作流程 如何加断点 选择 ...

  3. Java base64 图片编码转换

    package com.test; import org.junit.Test; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encode ...

  4. [2015.02.02]文本编码转换专家 v2.6

    软件名称:文本编码转换专家最新版本:v2.6操作系统:XP/2003/Win7/Win2008软件介绍:文本编码转换专家,界面简洁易用,功能强大实用.自动识别文件编码,有效转换成目标编码.真正的多线程 ...

  5. 中文字符串的编码转换(c实现)

    中文字符串在c/c++中表示为字节序列,在分词的时候需要根据不同的编码方式进行分词,一般分词器需要转换成统一的编码方式再进行转换,有些分词器如ICTCLAS在分词的时候可以不显示定义编码方式,可以检测 ...

  6. 完整的java字符串编码转换代码

    package book.String; import java.io.UnsupportedEncodingException; /** *//** * 转换字符串的编码 * @author joe ...

  7. JAVA字符串编码转换常用类

    无论是对程序的本地化还是国际化,都会涉及到字符编码的转换的问题.尤其在web应用中常常需要处理中文字符,这时就需要进行字符串的编码转换,将字符串编码转换为GBK或者GB2312.一.关键技术点:    ...

  8. java字符编码转换

    在开发的过程中.字符编码经常令我们头痛.经常会出现各种各样的乱码.以下就介绍java的编码转换和常见的乱码是使用什么样的编码去读取的: 先看一张图片: watermark/2/text/aHR0cDo ...

  9. Base64图片编码原理,base64图片工具介绍,图片在线转换Base64

    Base64图片编码原理,base64图片工具介绍,图片在线转换Base64 DataURI 允许在HTML文档中嵌入小文件,可以使用 img 标签或 CSS 嵌入转换后的 Base64 编码,减少  ...

随机推荐

  1. 在大负载中使用LoadRunner进行负载测试()

    在大负载中使用LoadRunner进行负载测试,需要配置一些环境来满足大负载下各种资源的充足: 1.为了避免出现“No Buffer Space Available”的错误,需要进行如下配置: 1)修 ...

  2. Ubuntu18.04下希捷移动硬盘Seagate Backup Plus读写慢

    去年买的一块Seagate Backup Plus 4TB, 专门用来备份的, 之前在win7下用过几次, 但是在Ubuntu下可能只用过一两次, 今天备份的时候, 感觉写入速度不太正常, 大概只有1 ...

  3. Java实现的简单神经网络(基于Sigmoid激活函数)

    主体代码 NeutronNetwork.java package com.rockbb.math.nnetwork; import java.util.ArrayList; import java.u ...

  4. ios中网络请求缓存

    #import <Foundation/Foundation.h> #import "ASIFormDataRequest.h" @protocol NetWorkde ...

  5. linux shell 脚本攻略学习13--file命令详解,diff命令详解

    一.file命令详解 find命令可以通过查看文件内容来找出特定类型的文件,在UNIX/ Linux系统中,文件类型并不是由文件扩展名来决定的(windows中却正是这么做的),file命令的目的是从 ...

  6. linux shell 脚本攻略学习2

    1.关于文件描述符和重定向: 文件描述符是与一个打开的文件或数据流相关联的整数.文件描述符0.1以及2是系统预留的. 0——stdin(标准输入) 1——stdout(标准输出) 2——stderr( ...

  7. 题外话:我想立刻辞职,然后闭关学习编程语言,我给自己3个月时间学习C语言!这样行的通吗

    以下文章虽然是编程,但是对于IT行业都通用 文章背景,回答提问:我想立刻辞职,然后闭关学习编程语言,我给自己3个月时间学习C语言!这样行的通吗? 我的建议是这样:1. 不要辞职.首先说,你对整个开发没 ...

  8. idea上activiti插件的安装及使用

    最近做的东西需要用到activiti,做个笔记 首先下载activti插件- actiBPM File - settings-plugins-Browse-Repositories 搜索 actiBP ...

  9. linux达人养成计划学习笔记(一)——命令基本格式及文件处理命令

    一.shell终端初始 快捷键Ctrl + Alt + T,可以快速打开终端 bluemoutain 当前用户名 bluemoutain-CN155 本机名 ~ 当前目录(家目录,root用户为/ro ...

  10. 忙里偷闲写的小例子---读取android根目录下的文件或文件夹

    最近几天真的是各种意义上的忙,忙着考试,还要忙着课程设计,手上又有外包的项目,另一边学校的项目还要搞,自己的东西还在文档阶段,真的是让人想死啊!! 近半个月来,C#这方面的编码比较多,android和 ...