使用 JavaScript 读取/写入文件时的字符编码


Character encoding when reading/writing a file with JavaScript

我目前在客户端JavaScript中的字符编码方面遇到了一些问题。我的基本程序流程是这样的:客户端JavaScript使用漂亮的FileReader读取本地文本文件。然后,我对字符串进行大量编辑,然后尝试为用户提供一种下载新的更改文件的方法。这是我的问题,我正在读取的文件(根据记事本++)是用ANSI编码的,我想写的文件也需要用ANSI编码。

当我尝试像这样从文件中读取时:

reader.readAsText(this.files[0], "ANSI");
...
cachedFile = e.target.result.split("'n");
console.log(cachedFile[179544]);

我的结果是这样的(Î字符未正确读取):

name="�le-de-France" 

但是,当我使用 ISO-8859-1 作为编码参数(完全随机选择)时,由于某种原因,结果是正确的:

name="Île-de-France" 

所以很有可能我不知道发生了什么。所以我用ISO-8859-1编码保留了它,做了各种编辑,然后尝试准备下载。我不能简单地将其发布到未压缩的服务器并准备一个文件以供下载,因为坦率地说,这个文件相当大(~14 mb)。但是,由于它是纯文本,因此它确实压缩得非常好。问题是我找到的任何JavaScript压缩库(如jszip,它很好地让你生成一个文件并将其粘贴到.zip中)似乎都保持JavaScript的内部字符串编码,我相信是UTF-16。.zip文件也被编码为 base64(我刚刚在我的 PHP 服务器上解码)。当然,这样做会给出如下结果的最终结果:

name="ÃŽle-de-France"

所以我的问题来了,我有一个用 ANSI 编码的文件,我使用 ISO-8859-1 解析它,我用 UTF-16 编辑它,我需要找到一种方法让它回到 ANSI 并放到一个人的桌面上。有没有一种标准方法可以在压缩之前将 JavaScript 字符串转换为 ANSI,以便我可以将压缩文件提供给我的用户下载?或者有没有办法使用 PHP 在服务器端解压缩字符串,转换为 ANSI,然后提供下载?仅供参考,我当前的PHP代码就是这样:

<?php 
 $res = $_POST["saveString"];
 $maybe = base64_decode($res);
 header('Content-Type: application/download');
 header('Content-Disposition: attachment; filename="genSave.zip"');
 header("Content-Length: " . strlen($maybe));
 echo $maybe;
?>

我的猜测是[如果不正确,我将删除答案]您的编码值无效。记事本所说的"ANSI"是Windows-1252,几乎与ISO-8859-1相同。您期望"ANSI"除了ISO-8859-1之外是什么?这应该有效:

reader.readAsText(this.files[0], "iso-8859-1");
reader.readAsText(this.files[0], "windows-1252");

请参阅 W3C 规范以供参考。

我最终得到了一个稍微迂回的解决方案,它可能没有达到应有的效率。我使用 JavaScript 将一个 1200 万个字符的 UTF-16 编码字符串放入一个 .zip 文件中,将其 POST 到以 base64 编码的服务器,将其转换回字符串,放入临时文件,将该临时文件作为 .zip 文件打开,解压缩,将其转换为 ISO-8859-1,重新打包,然后将其下载到客户端。

最终的服务器端代码非常简单,但不幸的是速度很慢:

<?php 
   $res = $_POST["saveString"];
   $zipInMem = base64_decode($res);
   $file = tempnam("tmp", "zip"); 
   file_put_contents ($file, $zipInMem);
   $zip = zip_open($file);
   $zip_entry = zip_read($zip);
   zip_entry_open($zip, $zip_entry);
   $contents = utf8_decode(zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)));
   $zip = new ZipArchive();
   $zip->open($file, ZipArchive::OVERWRITE);
   $zip->addFromString('genFile.eu4', $contents);
   $zip->close();
   header('Content-Type: application/zip');
   header('Content-Disposition: attachment; filename="genSave.zip"');
   header("Content-Length: " . filesize($file));
   readfile($file);
   unlink($file);
?>