如何将大型 UTF-8 字符串转换为 ASCII?

How to convert large UTF-8 strings into ASCII?

提问人:Robin Rodricks 提问时间:5/7/2009 最后编辑:Robin Rodricks 更新时间:1/18/2022 访问量:65119

问:

我需要将大型 UTF-8 字符串转换为 ASCII。它应该是可逆的,理想情况下是一种快速/轻量级的算法。

我该怎么做?我需要源代码(使用循环)或 JavaScript 代码。(不应依赖于任何平台/框架/库)

编辑:我知道 ASCII 表示看起来不正确,并且会比其 UTF-8 对应物大(以字节计),因为它是 UTF-8 原始的编码形式。

JavaScript UTF-8 字符编码 ASCII

评论

0赞 si28719e 5/7/2009
我对你的编辑感到困惑。这听起来像是你实际要做的是URL编码。是吗?
1赞 Robin Rodricks 5/7/2009
我没有投你反对票。而且我不关心 UTF-8 的二进制格式。
2赞 Robin Rodricks 5/7/2009
如果我不知道我在问什么,我甚至不会得到一些正确的答案。(如 Escaping/Base64)
1赞 Christoph 5/8/2009
你应该考虑接受大卫的答案 - / 更适合解决你的问题endoceURI()decodeURI()quote()/eval()
1赞 bogdan 12/23/2009
杰里米,看看人们在评论什么并更新你的问题,目前标题和描述非常错误。否则,你将继续得到其他人的反对票。

答:

8赞 Neall 5/7/2009 #1

任何可逆转换为 ASCII 的 UTF-8 字符串都已经是 ASCII。

UTF-8 可以表示任何 Unicode 字符 - ASCII 不能。

评论

2赞 Robin Rodricks 5/7/2009
“ASCII 不能”——当然可以!看看上面公认的答案。
6赞 Rômulo Ceccon 5/8/2009
@Jeremy:那就少偷偷摸摸地说出你的问题吧!“UTF-8 到 ASCII 转换”听起来像是一个字符编码转换问题,而您真正想要的是一种使用 ASCII 字符集和已知字符转义语法来表示 Unicode(与 UTF-8 不同)字符的方法。
1赞 Neall 6/18/2010
@Pat 这是对 UTF-8 最常见的误解之一。UTF-8 和 UTF-16 实际上具有可变的位长度,其中任何一个都可以表示任何 Unicode 字符。en.wikipedia.org/wiki/UTF-8
5赞 Quentin 5/7/2009 #2

正如其他人所说,您无法在不删除数据的情况下将 UTF-8 文本/纯文本转换为 ASCII 文本/纯文本。

您可以将 UTF-8 文本/纯文本转换为其他/格式的 ASCII。例如,HTML 允许 UTF-8 中的任何字符使用字符引用在 ASCII 数据文件中表示。

如果我们继续这个例子,在 JavaScript 中,charCodeAt 可以帮助使用 HTML 字符引用将字符串转换为它的表示形式。

另一种方法是由 URL 采用,并在 JS 中作为 encodeURIComponent 实现。

2赞 Guffa 5/7/2009 #3

如果字符串编码为 UTF-8,则它不再是字符串。它是二进制数据,如果要将二进制数据表示为 ASCII,则必须将其格式化为可以使用有限的 ASCII 字符集表示的字符串。

一种方法是使用 base-64 编码(在 C# 中为示例):

string original = "asdf";
// encode the string into UTF-8 data:
byte[] encodedUtf8 = Encoding.UTF8.GetBytes(original);
// format the data into base-64:
string base64 = Convert.ToBase64String(encodedUtf8);

如果要将字符串编码为 ASCII 数据:

// encode the base-64 string into ASCII data:
byte[] encodedAscii = Encoding.ASCII.GetBytes(base64);

评论

0赞 Robin Rodricks 5/7/2009
好主意,虽然我想要 JS。谢谢。
11赞 fforw 5/7/2009 #4

您可以使用 Douglas Crockford 的 json2.js 引用函数的仅限 ASCII 版本。它看起来像这样:

    var escapable = /[\\\"\x00-\x1f\x7f-\uffff]/g,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        };

    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        escapable.lastIndex = 0;
        return escapable.test(string) ?
            '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + string + '"';
    }

这将生成一个有效的仅 ASCII 的输入字符串,以 javascript 引号

例如: 将是“Doppelg\u00e4nger!quote("Doppelgänger!")

要恢复编码,只需评估结果即可

var encoded = quote("Doppelgänger!");
var back = JSON.parse(encoded); // eval(encoded);

评论

0赞 Fowl 5/7/2009
为什么不使用 eval() 以外的东西呢?比如说,html 实体?
0赞 fforw 5/7/2009
主要是因为你不需要实现任何回归,而且它会非常快。您也可以使用基于正则表达式的 unquote 方法,这与 quote 函数非常相似。
0赞 fforw 5/7/2009
..或者您可以使用正则表达式验证来保护基于 eval 的取消引用,就像 json2.js 对完整 JSON 所做的那样。
4赞 Joachim Sauer 5/8/2009
请注意,严格来说,这不是“转换为 ASCII”。您实际上是在 ASCII 之上实现自己的编码方案。对于要求来说,这可能是完全可以的(而且似乎适合您),但这不仅仅是简单的“转换为 ASCII”。
1赞 Tracker1 1/22/2015
您可以使用 eval(encoded) 代替(这在幕后是类似的,但更安全)JSON.parse(encoded)
-1赞 Christoph 5/7/2009 #5

函数的实现可以执行所需的操作。 我的版本可以在这里找到quote()

您可以使用反转编码:eval()

var foo = 'Hägar';
var quotedFoo = quote(foo);
var unquotedFoo = eval(quotedFoo);
alert(foo === unquotedFoo);

评论

0赞 Christoph 5/7/2009
@Jeremy:不是真的——同样的事情,不同的实现;如果我在发布自己的答案之前看到 fforw 的答案,我就不会打扰了;我的版本还有更多选项(在单引号或双引号之间进行选择,可以选择不转义非 ASCII 字符),但很可能它会更慢
1赞 mpen 9/26/2017
死链接-----
3赞 Joachim Sauer 5/7/2009 #6

你的要求很奇怪。

将 UTF-8 转换为 ASCII 将丢失有关 Unicode 代码点的所有信息> 127(即 ASCII 中未包含的所有内容)。

但是,您可以尝试使用与 ASCII 兼容的编码(如 UTF-7)对 Unicode 数据(无论使用何种源编码)进行编码。这意味着生成的数据在法律上可以解释为 ASCII,但它实际上是 UTF-7。

评论

0赞 Robin Rodricks 5/7/2009
“丢失所有信息” - 它可以是无损的!看看上面公认的答案。
0赞 Robin Rodricks 5/8/2009
不过,关于 UTF-7 的好主意。
3赞 Joachim Sauer 5/8/2009
@Jeremy:它可以是无损的,但你不再只是“转换为 ASCII”,然后你正在转换为一些在 ASCII 字符集之上实现的编码方案......
1赞 Fowl 5/7/2009 #7

您想去除所有非 ascii 字符(斜杠将它们替换为“?”等)还是将 Unicode 码位存储在非 unicode 系统中?

首先可以在循环中检查 128 >值并替换它们。

如果你不想使用“任何平台/框架/库”,那么你需要编写自己的编码器。否则,我只会使用 JQuery 的 .html();

3赞 sorin 12/23/2009 #8

无法将 UTF-8 字符串转换为 ASCII,但可以将 Unicode 编码为 ASCII 兼容字符串。

可能您想使用 Punycode - 这已经是一种标准的 Unicode 编码,将所有 Unicode 字符编码为 ASCII。对于 JavaScript 代码,请检查此问题

请编辑您的问题标题和描述,以防止其他人投反对票 - 不要使用术语转换,使用编码。

0赞 Francois Girard 4/23/2015 #9

这是一个将 UTF8 口音转换为 ASCII 口音(àéèî 等)的函数 例如,如果字符串中有重音,则将其转换为 %239 然后在另一边,我解析字符串,我知道什么时候有重音以及什么是 ASCII 字符。

我在 javascript 软件中使用它来将数据发送到以 ASCII 工作的微控制器。

convertUtf8ToAscii = function (str) {
    var asciiStr = "";
    var refTable = { // Reference table Unicode vs ASCII
        199: 128, 252: 129, 233: 130, 226: 131, 228: 132, 224: 133, 231: 135, 234: 136, 235: 137, 232: 138,
        239: 139, 238: 140, 236: 141, 196: 142, 201: 144, 244: 147, 246: 148, 242: 149, 251: 150, 249: 151
    };
    for(var i = 0; i < str.length; i++){
        var ascii = refTable[str.charCodeAt(i)];
        if (ascii != undefined)
            asciiStr += "%" +ascii;
        else
            asciiStr += str[i];
    }
    return asciiStr;
}
2赞 LitileXueZha 1/18/2022 #10
function utf8ToAscii(str) {
    /**
     * ASCII contains 127 characters.
     * 
     * In JavaScript, strings is encoded by UTF-16, it means that
     * js cannot present strings which charCode greater than 2^16. Eg:
     * `String.fromCharCode(0) === String.fromCharCode(2**16)`
     *
     * @see https://developer.mozilla.org/en-US/docs/Web/API/DOMString/Binary
     */
    const reg = /[\x7f-\uffff]/g; // charCode: [127, 65535]
    const replacer = (s) => {
        const charCode = s.charCodeAt(0);
        const unicode = charCode.toString(16).padStart(4, '0');
        return `\\u${unicode}`;
    };

    return str.replace(reg, replacer);
}

更好的方式

另请参阅 Uint8Array 到 Javascript 中的字符串。您可以使用和:TextEncoderUint8Array

function utf8ToAscii(str) {
    const enc = new TextEncoder('utf-8');
    const u8s = enc.encode(str);

    return Array.from(u8s).map(v => String.fromCharCode(v)).join('');
}
// For ascii to string
// new TextDecoder().decode(new Uint8Array(str.split('').map(v=>v.charCodeAt(0))))