求一段 utf8转gb2312的实例代码,百度一下午了
发布于 9 年前 作者 captainblue2013 5370 次浏览 最后一次编辑是 8 年前 来自 问答

各种转成buffer,各种锟斤拷。。。。

10 回复

原因就在于【百度一下午了】,用 google 就好了

原因就在于【百度一下午了】,用 google 就好了

@alsotang 别抖机灵了,国外有用gb2312吗?

@xadillax 试过了,官方给的是string->buffer,或者buffer->string,此处有个疑问。

你是解决导出文件时候乱码还是。。

@wewoor 不是文件,就是字符串

utf8转gb2312,必须查对照表,用 iconv-lite 是正道,“锟斤拷” 是你不会用。。。

/* GBK_USC2_TABLE : GBK 与 USC2 对照表来自: https://github.com/ashtuchkin/iconv-lite 感谢iconv-lite作者*/

//GBK_USC2_TABLE很长。。。请自己补全
var GBK_USC2_TABLE={33088:19970,33089:19972,33090:19973,33091:19974,......};

// 上面表的反转表, 即 usc2 -> gkb
var UCS2_GBK_TABLE = {}; 
for(var k in GBK_USC2_TABLE) { 
  UCS2_GBK_TABLE[ GBK_USC2_TABLE[k] ] = k;
}
function __EmptyStr(str) {
  if(typeof(str)=='undefined') return '';
  if(str==null) return '';
  return ''+str.toString();
}
function utf8_to_gbk(utf8_buffer) {
  if(!Buffer.isBuffer(utf8_buffer) || utf8_buffer.length<=0) return new Buffer(0);
  return str_to_gbk( utf8_buffer.toString('utf8') );
}
function str_to_gbk(str) {
  var s = __EmptyStr(str);
  var b = new Buffer(s.length * 2);   
  // s.length 是串的字符个数,不是字节数,
  // 所以,即使全部是汉字,转gbk后最大就是2倍长度  
  var k = 0;
  for(var i=0; i<s.length; i++) {
    var c = s.charCodeAt(i); //console.log(c);
    if(c<=0xFF) { 
      // 单字节
      b[k++] = c;    
      continue; 
    }
    if(c in UCS2_GBK_TABLE) {
      // 合法的GBK编码,转成两个字节
      c = UCS2_GBK_TABLE[c];
      b[k++] = c >> 8;    // first
      b[k++] = c &  0xFF; // second
      continue; 
    }
    // 非法的GBK编码,用两个问号代替
    b[k++] = 0x3F; // 0x3F = ?
    b[k++] = 0x3F; // 0x3F = ?
  }
  return b.slice(0, k); // 返回实际长度的buffer
}
function gbk_to_utf8(gbk_buffer){
  if(!Buffer.isBuffer(gbk_buffer) || gbk_buffer.length<=0) return new Buffer(0);
  var n = gbk_buffer.length;
  var b = new Buffer(n * 2); 
  // s.length 是gbk字节数,
  // 所以,即使全部是非汉字,转ucs2后最大就是2倍长度
  var k = 0;
  for(var i=0; i < n; i++) {
    var c = gbk_buffer[i];
    if(i+1<n) {
      // gbk 编码规范:
      // 第一字节的范围是81–FE, 不含两头 80 和 FF
      // 第二字节的范围是40–FE,但是去掉中间的 7F
      if(0x81<=c && c<=0xFE) { // && 0x40<=c2 && c2<=0xFE && c2!=0x7F) { 
        var cu = c * 256 + gbk_buffer[i+1];
        if(cu in GBK_USC2_TABLE) { // 找到对应的 ucs2 编码
          c = GBK_USC2_TABLE[cu];
          i++; // 重要,表示本次处理了 2 个字节
        }
      }
    }
    // 现在的 c 可能是单字节,也可能是ucs2编码,根据 ucs2->utf8的规则来转换
    if(c <= 0x007F) 
      b[k++] = c & 0xFF;
    else {
      if(c <= 0x07FF) {
        b[ k++ ] = 0xC0 + ( c >> 6);            // 1100 0000 + c >> 6
        b[ k++ ] = 0x80 + ( c  & 0x003F);       // 1000 0000 + c & 0011 1111
      } 
      else {
        b[ k++ ] = 0xE0 + ( c >> 12);           // 1110 0000 + c >> 12
        b[ k++ ] = 0x80 + ((c >>  6) & 0x003F); // 1000 0000 + c >>  6 & 0011 1111
        b[ k++ ] = 0x80 + ( c  & 0x003F);       // 1000 0000 + c & 0011 1111
      }
    }
  }
  return b.slice(0, k); // b 现在是 utf8 编码了~  console.log(b);
}
function gbk_to_str(gbk_buffer)
{
  return gbk_to_utf8(gbk_buffer).toString('utf8');
}

function ucs2_to_gbk(usc2_buffer) {
  if(!Buffer.isBuffer(usc2_buffer) || usc2_buffer.length<=0) return null;
  var s = usc2_buffer.toString('usc2');
  var b = new Buffer(s.length * 2);
  // s.length 是串的字符个数,不是字节数,
  // 所以,即使全部是汉字,转gbk后最大就是2倍长度
  var k = 0;
  for(var i=0; i<s.length; i++) {
    var c = s.charCodeAt(i); //console.log(c);
    if(c<=0xFF) { 
      // 单字节
      b[k++] = c;    
      continue; 
    }
    if(c in UCS2_GBK_TABLE) {
      // 合法的GBK编码,转成两个字节
      c = UCS2_GBK_TABLE[c];
      b[k++] = c >> 8;    // first
      b[k++] = c &  0xFF; // second
      continue; 
    }
    // 非法的GBK编码,用两个问号代替
    b[k++] = 0x3F; // 0x3F = ?
    b[k++] = 0x3F; // 0x3F = ?
  }
  return b.slice(0, k); // 返回实际长度的buffer
}
function gbk_to_ucs2(gbk_buffer) {
  if(!Buffer.isBuffer(gbk_buffer) || gbk_buffer.length<=0) return null;
  var n = gbk_buffer.length;
  var b = new Buffer(n * 2); 
  // s.length 是gbk字节数,
  // 所以,即使全部是非汉字,转ucs2后最大就是2倍长度
  var k = 0;
  for(var i=0; i < n; i++) {
    var c = gbk_buffer[i];
    if(i+1<n) {
      // gbk 编码规范:
      // 第一字节的范围是81–FE, 不含两头 80 和 FF
      // 第二字节的范围是40–FE,但是去掉中间的 7F
      if(0x81<=c && c<=0xFE) { // && 0x40<=c2 && c2<=0xFE && c2!=0x7F) { 
        var cu = c * 256 + gbk_buffer[i+1];
        if(cu in GBK_USC2_TABLE) { // 找到对应的 ucs2 编码
          c = GBK_USC2_TABLE[cu];
          i++; // 重要,表示本次处理了 2 个字节
        }
      }
    }
    // 现在的 c 可能是单字节,也可能是ucs2编码
    b[k++] = c &  0xFF;
    b[k++] = c >> 8;
  }
  return b.slice(0, k); // b 现在是 ucs2 编码了~  console.log(b);
}
// exports 的函数
module.exports.UTF8_TO_GBK_bb = utf8_to_gbk;  // buffer到buffer
module.exports.UCS2_TO_GBK_bb = ucs2_to_gbk;  // buffer到buffer
module.exports.GBK_TO_UTF8_bb = gbk_to_utf8;  // buffer到buffer
module.exports.GBK_TO_UCS2_bb = gbk_to_ucs2;  // buffer到buffer
module.exports.UTF8_TO_GBK_sb = str_to_gbk;   // string到buffer
module.exports.GBK_TO_UTF8_bs = gbk_to_str;   // buffer到string

// 测试...
//
// var s = '\u00FE a盘1苙2苘&暻-鎔-# \u82DA';
// console.log(s);
// 
// var b = new Buffer(s, 'utf8'); 
// console.log('utf8 buffer = ',  b );
// 
// var cb1 = new Buffer(s, 'ucs2');
// console.log('ucs2 buffer = ', cb1 );
// console.log(cb1.toString('ucs2'));
// 
// var gb = utf8_to_gbk(b);
// console.log('gbk  buffer = ', gb );
// //console.log( gb.toString('binary') );
// 
// var ub = gbk_to_utf8(gb);
// console.log('utf8 buffer = ',  ub );
// console.log(ub.toString('utf8'));
// 
// var ub2 = gbk_to_ucs2(gb);
// console.log('ucs2 buffer = ',  ub2 );
// console.log(ub2.toString('ucs2'));
回到顶部