zoukankan      html  css  js  c++  java
  • JavaScript——编码问题

    本文内容

    • Unicode 编码
    • 本地 / Unicode
    • 本地 / UTF-8
    • 本地 / ASCII
    • 本地 / URI 编码

    Unicode 编码


    最近搞蜘蛛程序,经常遇到编码问题,原因有两个:一是各站点所使用的传输编码不同。我特别使用了“传输编码”这个说法,后面会解释;二是站点自己做的手脚。因为,谁也不想自己的资源,被蜘蛛搞走。网络上运行的蜘蛛实在很多。第一个问题很好解决,但是第二个问题,就有点麻烦——做手脚的手段千奇百怪。

    本文之所以用 Unicode 开头,而不是 ASCII 或 UTF-8 ,是因为 Unicode 编码包含各个国家的字符(ASCII 当然在其范围),得到系统内核支持,而其他常见编码都是建立在该编码基础上的。应该从两方面认识 Unicode 编码:编码方式和其实现方式。Unicode 对各个国家的字符进行了编码,但未规定它的实现方式。Unicode 实现方式不同于其编码方式。一个字符的 Unicode 编码是确定的。但在实际存储和传输过程中,由于不同系统的设计不一定一致,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为“Unicode 转换格式(Unicode Transformation Format,UTF)”。

    实现方式的不同,体现在,比如,用多个字节表示一个汉字,存在字节顺序的问题——大端(Big-Endian,BE)和小端(Little-Endian,LE)。Mac 机是小端,而 Windows 机则是大端。若有十六进制 4E59,Mac 机认为是 594E,汉字为“奎”;而 Windows 机认为是 4E59,汉字为“乙”。再如,Unicode 是定长编码,可一个英文字母用一个字节就能表示,这就存在存储代价。实现时,如 UTF-8 把定长编码变成变长的。这就是为什么 XML 和 HTML 这样需要网络传输的把 UTF-8 作为标准字符集的主要原因。

    目前通用的实现方式是 UTF-16 Big-Endian、UTF-16 Little-Endian 和 UTF-8。比如,Windows 7 的 记事本,在“另存为”可以看到四种编码方式:ANSI(即英文系统为 ASCII,中文系统为 GB2312 或 Big5),Unicode(即 UTF-16 Little-Endian)、Unicode big endian(即 UTF-16 Big-Endian)和 UTF-8。

    现在,很多浏览器只能显示 UCS-2 完整字符集(Unicode 版本中的一个小子集),这部分是由于 Unicode 版本发展原因。

    本地 / Unicode


    你可能对“本地”有点迷惑。刚开始,我也不理解,应该是编码之间转换才对。因为本地字符有编码,那么把这个编码转换成 Unicode 编码的说法很合理。其实,所有国家字符的 Unicode 编码都是确定的,无论是你输入的是哪国语。

    示例 1:

    例子lizi

    Unicode 十进制和十六进制编码分别为:

    例子lizi
    例子lizi

    本地到 Unicode 转换的 JavaScript 代码如下所示:

    function nativeToUnicode(str) {
        var des = [];
        for (var i = 0; i < str.length; i++)
            des.push("&#" + str.charCodeAt(i) + ";");
            //des.push("&#x" + str.charCodeAt(i).toString(16) + ";");
        return des.join("");
    }

    Unicode 到本地转换的 JavaScript 代码如下所示:

    function unicodeToNative(str) {
        var src = str.match(/&#(\d+);/g);
        if (src != null) {
            var des = [];
            for (var i = 0; i < src.length; i++)
                des.push(String.fromCharCode(src[i].replace(/[&#;]/g, "")));
            return des.join("");
        }
        return "";
    }

    说明:

    • String.charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数。
    • String.fromCharCode() 方法可接受一个指定的 Unicode 值,然后返回一个字符串。

    本地 / UTF-8


    UTF-8 是 Unicode 的实现方式之一,把定长编码改成变长的,减少了存储和传输的开销。从下面示例可以看到,中文是编码,而对用一个字节就能表示的英文字符,没有变化。

    示例 2:

    例子lizi

    UTF-8 编码为:

    &#x4F8B;&#x5B50;lizi

    本地转换 UTF-8 的 JavaScript 代码如下所示:

    function navtiveToUTF8(str) {
        return str.replace(/[^\u0000-\u00FF]/g, function ($0) { return escape($0).replace(/(%u)(\w{4})/gi, "&#x$2;") });
    }

    UTF-8 转换本地的 JavaScript 代码如下所示:

    function utfToNative(str) {
        return unescape(str.replace(/&#x/g, '%u').replace(/;/g, ''));
    }

    说明:

    • escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。
    • unescape() 函数可对通过 escape() 编码的字符串进行解码。

    本地 / ASCII


    示例 3:

    例子lizi

    ASCII 码转换或不转换 ASCII 的编码为:

    \u4f8b\u5b50lizi

    \u4f8b\u5b50\u006c\u0069\u007a\u0069

    本地转换 ASCII 的 JavaScript 代码如下所示:

    function nativeToASCII(str, isIgnoreLetter) {
        var character = str.split("");
        var ascii = [];
        for (var i = 0; i < character.length; i++) {
            var code = Number(character[i].charCodeAt(0));
            if (!isIgnoreLetter || code > 127) {
                var charAscii = code.toString(16);
                charAscii = new String("0000").substring(charAscii.length, 4) + charAscii;
                ascii.push("\\u" + charAscii);
            }
            else {
                ascii.push(character[i]);
            }
        }
        return ascii.join("");
    }

    ASCII 转换本地的 JavaScript 代码如下所示:

    function asciiToNative(str) {
        var character = str.split("\\u");
        var res = character[0];
        for (var i = 1; i < character.length; i++) {
            var code = character[i];
            res += String.fromCharCode(parseInt("0x" + code.substring(0, 4)));
            if (code.length > 4) {
                res += code.substring(4, code.length);
            }
        }
        return res;
    }

    本地 / URI 编码


    URI 编码不用以上编码,它的主要是出于安全性考虑,让链接的内容不能一目了然地看到是什么,防止恶意的偷看者。下面是 cnblogs 的“找找看”检索链接,对其进行编码。

    示例 4:

    http://zzk.cnblogs.com/s?w=例子lizi&t=

    URI 编码和组件编码分别为:

    http://zzk.cnblogs.com/s?w=%E4%BE%8B%E5%AD%90lizi&t=

    http%3A%2F%2Fzzk.cnblogs.com%2Fs%3Fw%3D%E4%BE%8B%E5%AD%90lizi%26t%3D

    说明:

    • encodeURI() 函数可把字符串作为 URI 进行编码。
    • decodeURI() 函数可对 encodeURI() 函数编码过的 URI 进行解码。
    • encodeURIComponent() 函数可把字符串作为 URI 组件进行编码。
    • decodeURIComponent() 函数可对 encodeURIComponent() 函数编码的 URI 进行解码。

    下载 Demo

  • 相关阅读:
    Scrum Meeting Beta
    Scrum Meeting Beta
    Scrum Meeting Beta
    Scrum Meeting Beta
    《人月神话》读后感
    【最后的总结】我们的Sprint3冲刺——闹钟的添加和管理(刘铸辉,何晓楠)
    【软件结课】软件工程课的评价
    【软件结课】软件工程课的收获
    springt2第二次冲刺计划表
    给出一个 m*n 的二维数组(元素可为正可为负),求该二维数组的一个子数组,且此子数组中所有元素的和最大,并输出该数组的和。
  • 原文地址:https://www.cnblogs.com/liuning8023/p/2810518.html
Copyright © 2011-2022 走看看