更改JavaScript字符串编码

23

目前,我有一个很长的JavaScript字符串,想要写入文件,但使用另一种编码(ISO-8859-1)。我希望使用 downloadify 等工具来实现。Downloadify只接受普通的JavaScript字符串或base64编码的字符串。

因此,我决定使用 JSZip 来压缩字符串,生成一个漂亮的base64编码字符串,可以传递给 downloadify 并下载到桌面。问题是压缩后的字符串仍然使用了错误的编码方式。

幸运的是,JSZip可以将Uint8Array作为数据,而不是字符串。那么,有没有办法将javascript字符串转换为ISO-8859-1编码的字符串并将其存储在 Uint8Array中呢?

或者,如果我整个方法都错了,是否有更好的解决方案呢?是否有一种高级的JavaScript字符串类可以使用不同的内部编码?

编辑:澄清一下,我不是将该字符串推送到网页上,所以它不会自动为我转换。我的操作流程大致如下:

var zip = new JSZip();
zip.file("genSave.txt", result);

return zip.generate({compression:"DEFLATE"});
为了让这有意义,我需要结果以适当的编码方式(JSZip仅支持字符串,数组缓冲区或uint8arrays)呈现。最终编辑(这不是重复的问题,因为结果没有在浏览器中显示或传输到可以更改编码的服务器):这事情比我想象的更为晦涩,所以我最终自行解决。它不像一个合适的解决方案那样健壮,但它可以将JavaScript字符串转换为windows-1252编码,并将其放入Uint8Array中。
var enc = new string_transcoder("windows-1252");
var tenc = enc.transcode(result); //This is now a Uint8Array
你可以像我这样在数组中使用它:
//Make this into a zip
var zip = new JSZip();   
zip.file("genSave.txt", tenc);   
return zip.generate({compression:"DEFLATE"});

或者使用此字符串编码库将其转换为 windows-1252 编码的字符串:

var string = TextDecoder("windows-1252").decode(tenc);

要使用此功能,请使用以下方法之一:

<script src="//www.eu4editor.com/string_transcoder.js"></script>

或者包括这个:

function string_transcoder (target) {

    this.encodeList = encodings[target];
    if (this.encodeList === undefined) {
        return undefined;
    }

    //Initialize the easy encodings
    if (target === "windows-1252") {
        var i;
        for (i = 0x0; i <= 0x7F; i++) {
            this.encodeList[i] = i;          
        }
        for (i = 0xA0; i <= 0xFF; i++) {
            this.encodeList[i] = i;
        }
    }

}

string_transcoder.prototype.transcode = function (inString) {


    var res = new Uint8Array(inString.length), i;


    for (i = 0; i < inString.length; i++) {
        var temp = inString.charCodeAt(i);
        var tempEncode = (this.encodeList)[temp];
        if (tempEncode === undefined) {
            return undefined; //This encoding is messed up
        } else {
            res[i] = tempEncode;
        }
    }

    return res;
};

encodings = {

    "windows-1252": {0x20AC:0x80, 0x201A:0x82, 0x0192:0x83, 0x201E:0x84, 0x2026:0x85, 0x2020:0x86, 0x2021:0x87, 0x02C6:0x88, 0x2030:0x89, 0x0160:0x8A, 0x2039:0x8B, 0x0152:0x8C, 0x017D:0x8E, 0x2018:0x91, 0x2019:0x92, 0x201C:0x93, 0x201D:0x94, 0x2022:0x95, 0x2013:0x96, 0x2014:0x97, 0x02DC:0x98, 0x2122:0x99, 0x0161:0x9A, 0x203A:0x9B, 0x0153:0x9C, 0x017E:0x9E, 0x0178:0x9F}     

};

这样的代码 utfstring = unescape(encodeURIComponent(originalstring)); 行得通吗? - Joren
1
很遗憾不行。我想在以ISO-8859-1方式查看最终文件时看到'Ile'。正常写入文件时,它会按UCS-2方式写入,以ISO-8859-1方式查看时结果为'ÃŽle'。使用您的方法时,结果是'Île'。这与提出的重复问题不同,因为我没有要求浏览器显示它,因此更改HTML5元标记无法解决该问题。 - David
你是否回答了自己的问题?还是我漏看了什么? - Enigmadan
是的,我做了。它被错误地关闭为重复项,我不想让它无人回答而悬挂在那里。 - David
6
@David:如果那次编辑是答案,请回滚它并以自我回答的形式发布(然后您可以接受它)。 - Bergi
дҪ е°қиҜ•иҝҮдҪҝз”Ёscriptе…ғзҙ зҡ„charsetеұһжҖ§еҗ—пјҹhttp://www.w3.org/TR/html401/interact/scripts.html#h-18.2.1 - Martín Schonaker
3个回答

6

这个问题比[作者]预想的要难懂一些,所以[作者]最终采用了自己的解决方案。这个解决方案不像一个正确的解决方案那样健壮,但它可以将JavaScript字符串转换为windows-1252编码并将其放入Uint8Array中:

var enc = new string_transcoder("windows-1252");
var tenc = enc.transcode(result); //This is now a Uint8Array

你可以像[作者]那样在数组中使用它:
//Make this into a zip
var zip = new JSZip();   
zip.file("genSave.txt", tenc);   
return zip.generate({compression:"DEFLATE"});

或者使用这个字符串编码库将其转换为windows-1252编码的字符串:

var string = TextDecoder("windows-1252").decode(tenc);

要使用此功能,请使用以下方法之一:
<script src="//www.eu4editor.com/string_transcoder.js"></script>

或者包含这个:

function string_transcoder (target) {

    this.encodeList = encodings[target];
    if (this.encodeList === undefined) {
        return undefined;
    }

    //Initialize the easy encodings
    if (target === "windows-1252") {
        var i;
        for (i = 0x0; i <= 0x7F; i++) {
            this.encodeList[i] = i;          
        }
        for (i = 0xA0; i <= 0xFF; i++) {
            this.encodeList[i] = i;
        }
    }

}

string_transcoder.prototype.transcode = function (inString) {


    var res = new Uint8Array(inString.length), i;


    for (i = 0; i < inString.length; i++) {
        var temp = inString.charCodeAt(i);
        var tempEncode = (this.encodeList)[temp];
        if (tempEncode === undefined) {
            return undefined; //This encoding is messed up
        } else {
            res[i] = tempEncode;
        }
    }

    return res;
};

encodings = {

    "windows-1252": {0x20AC:0x80, 0x201A:0x82, 0x0192:0x83, 0x201E:0x84, 0x2026:0x85, 0x2020:0x86, 0x2021:0x87, 0x02C6:0x88, 0x2030:0x89, 0x0160:0x8A, 0x2039:0x8B, 0x0152:0x8C, 0x017D:0x8E, 0x2018:0x91, 0x2019:0x92, 0x201C:0x93, 0x201D:0x94, 0x2022:0x95, 0x2013:0x96, 0x2014:0x97, 0x02DC:0x98, 0x2122:0x99, 0x0161:0x9A, 0x203A:0x9B, 0x0153:0x9C, 0x017E:0x9E, 0x0178:0x9F}     

};

1
谢谢! :) 恰好,这是我找到的第一个解决方案,用于在NetFramework中编码HTTP状态描述的问题:Response.StatusDescription以CP1252编码,而我的浏览器总是尝试将其解码为CP1251。 - ornic
1
上面链接的 https://code.google.com/p/stringencoding/ 库已经不存在了。但是另一篇帖子的答案 https://dev59.com/72Yr5IYBdhLWcg3w29hI#54883467 可能会有所帮助,并且可能与它的继承者 https://github.com/inexorabletash/text-encoding 有关。 - Andreas Covidiot

1

测试以下脚本:

<script type="text/javascript" charset="utf-8">

不,这并不适用。这是所有内部JavaScript字符串编码(不是字面量,也不是由浏览器格式化的)。 - David

0

对我来说最好的解决方案是这里发布的,这是我的一行代码:

<!-- Required for non-UTF encodings (quite big) -->
<script src="encoding-indexes.js"></script>

<script src="encoding.js"></script>
...
// windows-1252 is just one typical example encoding/transcoding
let transcodedString = new TextDecoder( 'windows-1252' ).decode( 
                         new TextEncoder().encode( someUtf8String ))

如果需要在多个输入上重复使用编码器和解码器进行转码,则可以使用此选项:

let srcArr = [ ... ]  // some UTF-8 string array
let encoder = new TextEncoder()
let decoder = new TextDecoder( 'windows-1252' )
let transcodedArr = srcArr.forEach( (s,i) => { 
                      srcArr[i] = decoder.decode( encoder.encode( s )) })

(来自相关问题的略作修改的其他答案:)

This is what I found after a more specific Google search than just UTF-8 encode/decode. so for those who are looking for a converting library to convert between encodings, here you go.

github.com/inexorabletash/text-encoding

var uint8array = new TextEncoder().encode(str);
var str = new TextDecoder(encoding).decode(uint8array);

Paste from repo readme

All encodings from the Encoding specification are supported:

utf-8 ibm866 iso-8859-2 iso-8859-3 iso-8859-4 iso-8859-5 iso-8859-6 
iso-8859-7 iso-8859-8 iso-8859-8-i iso-8859-10 iso-8859-13 iso-8859-14 
iso-8859-15 iso-8859-16 koi8-r koi8-u macintosh windows-874 windows-1250 
windows-1251 windows-1252 windows-1253 windows-1254 windows-1255 
windows-1256 windows-1257 windows-1258 x-mac-cyrillic gb18030 hz-gb-2312 
big5 euc-jp iso-2022-jp shift_jis euc-kr replacement utf-16be utf-16le 
x-user-defined

(一些编码可能会以其他名称支持,例如asciiiso-8859-1等。请参见编码以获取每种编码的附加标签。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接