在JavaScript中计算用ISO 8859-7编码的文件的字节大小

Con*_*ien 5 javascript encoding character-encoding

背景

我正在写一种叫做Jolf的深奥语言.它用于可爱的网站codegolf SE.如果您还不知道,则会以字节为单位对很多挑战进行评分.人们已经做出 很多的 语言是利用或者自己的编码或预先存在的编码.

在我的语言的解释器上,我有一个字节计数器.正如您所料,它计算代码中的字节数.到现在为止,我一直在使用UTF-8 en/decoder(utf8.js).我现在使用的是带有希腊字符的ISO 8859-7编码.文本上传实际上也不起作用.我需要计算上传文件中包含的实际字节数.还有,有办法读取所述编码文件的内容吗?

鉴于从<input>页面上的元素获得的ISO 8859-7编码的文件,有没有办法获得该文件中包含的字节数?并且,给定"明文"(即文本直接放入a <textarea>),我如何计算其中的字节,好像它是在ISO 8859-7中编码的?

我试过的

调用input元素isogreek.该文件位于<input>元素中.内容是?X?希腊字符,拉丁字符(每个字符应该是一个字节)和一个中文字符,它应该超过一个字节(?).

isogreek.files[0].size;      // is 3; should be more.

var reader = new FileReader();
reader.readAsBinaryString(isogreek.files[0]);      // corrupts the string to `ÖX?`
reader.readAsText(isogreek.files[0]);              // ?X?
reader.readAsText(isogreek.files[0],"ISO 8859-7"); // ?X?
Run Code Online (Sandbox Code Playgroud)

ETH*_*ons 6

从此评论中扩展而来.

正如评论中提到的@pvg一样,产生的字符串readAsBinaryString是正确的,但由于两个原因而被破坏:

A.结果显示在ISO-8859-编码1.您可以使用函数来解决此问题:

function convertFrom1to7(text) {
  // charset is the set of chars in the ISO-8859-7 encoding from 0xA0 and up, encoded with this format:
  // - If the character is in the same position as in ISO-8859-1/Unicode, use a "!".
  // - If the character is a Greek char with 720 subtracted from its char code, use a ".".
  // - Otherwise, use \uXXXX format.
  var charset = "!\u2018\u2019!\u20AC\u20AF!!!!.!!!!\u2015!!!!...!...!.!....................!............................................!";
  var newtext = "", newchar = "";
  for (var i = 0; i < text.length; i++) {
    var char = text[i];
    newchar = char;
    if (char.charCodeAt(0) >= 160) {
      newchar = charset[char.charCodeAt(0) - 160];
      if (newchar === "!") newchar = char;
      if (newchar === ".") newchar = String.fromCharCode(char.charCodeAt(0) + 720);
    }
    newtext += newchar;
  }
  return newtext;
} 
Run Code Online (Sandbox Code Playgroud)

B.中文字符不是ISO-8859-7字符集的一部分(因为字符集最多支持256个唯一字符,如表所示).如果要在程序中包含任意Unicode字符,则可能需要执行以下两项操作之一:

  1. 计算该程序的字节,即UTF-8或UTF-16.您可以使用链接的库轻松完成此操作.但是,如果您希望自动完成此操作,则需要一个函数来检查textarea的内容是否是有效的ISO-8859-7文件,如下所示:
function isValidISO_8859_7(text) {
  var charset = /[\u0000-\u00A0\u2018\u2019\u00A3\u20AC\u20AF\u00A6-\u00A9\u037A\u00AB-\u00AD\u2015\u00B0-\u00B3\u0384-\u0386\u00B7\u0388-\u038A\u00BB\u038C\u00BD\u038E-\u03CE]/;
  var valid = true;
  for (var i = 0; i < text.length; i++) {
    valid = valid && charset.test(text[i]);
  }
  return valid;
}
Run Code Online (Sandbox Code Playgroud)
  1. 创建自己的ISO-8859-7自定义变体,它使用特定字节(或多个字节)来表示接下来的2或3个字节属于单个Unicode字符.这可以非常简单或复杂,从一个表示2字节字符的char和一个表示3-byter之间的所有内容809F设置为接下来的几个字符.这是一个基本的例子,80用作2-byter和813-byter(假设文本在ISO-8859-1中编码):
function reUnicode(text) {
  var newtext = "";
  for (var i = 0; i < text.length; i++) {
    if (text.charCodeAt(i) === 0x80) {
      newtext += String.fromCharCode((text.charCodeAt(++i) << 8) + text.charCodeAt(++i));
    } else if (text.charCodeAt(i) === 0x81) {
      var charcode = (text.charCodeAt(++i) << 16) + (text.charCodeAt(++i) << 8) + text.charCodeAt(++i) - 65536;
      newtext += String.fromCharCode(0xD800 + (charcode >> 10), 0xDC00 + (charcode & 1023)); // Convert into a UTF-16 surrogate pair
    } else {
      newtext += convertFrom1to7(text[i]);
    }
  }
  return newtext;
}
Run Code Online (Sandbox Code Playgroud)

如果你愿意,我可以更详细地讨论这两种方法.