質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.92%

Amazon AWS Lambda@Edge(Node.js)で文字コード「Shift_JIS」として出力するにはどうすればいいですか

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 1,328

score 106

PHPの「mb_convert_encoding($str, 'Shift_JIS', 'UTF-8')」と同じことがしたいです。

私は今、PHPで出来たシステムをnode.jsに移行することを検証中です。

node.jsというモダンな開発環境なのに、ガラケー用サイトの対応が必要でして、
どうしてもShift_JISの文字コードでHTMLページを表示しなければいけません。
(User Agentで判別して、DoCoMoとかならガラケー用ページのHTMLテンプレートを表示する感じです)

ネットで調べると、SJISその他からUTF-8に変換するものはよく見かけますが、
その逆で、UTF-8からSJISに変換するという記事を全然見かけません。

Node.jsではそういったことが出来ないのですか?

やり方をご存知の方、ソースコードをご提示いただけませんでしょうか。

もしNode.jsでは対応できないのであれば、
EC2を使うなど、別の方法を考えることにします。

一応、私のソースコードを下記します。

現在は検証中の段階ですので、
ライブラリはICONVやJCONVなど、違うものでも全然構いません。

function encodeTo(unicodeStr, toEncode = 'SJIS')
{
  var ENCODING = require('encoding-japanese');

  var availableEncodings = ['UTF16','UTF16BE','UTF16LE','JIS','UTF8','EUCJP','SJIS','UNICODE'];
  if(availableEncodings.includes(toEncode) === false){
    return false;
  }

  var unicodeArray = ENCODING.stringToCode(unicodeStr);
  var utf8Array    = ENCODING.convert(unicodeArray, { to: 'UTF8', from : 'UNICODE' });
  var sjisArray    = ENCODING.convert(unicodeArray, { to: 'SJIS', from : 'UNICODE' });

  console.log("unicodeArray: " + ENCODING.detect(unicodeArray));
  console.log("utf8Array: " + ENCODING.detect(utf8Array));
  console.log("sjisArray: " + ENCODING.detect(sjisArray));

  var unicodeStr = ENCODING.codeToString(unicodeArray);
  var utf8Str    = ENCODING.codeToString(utf8Array);
  var sjisStr    = ENCODING.codeToString(sjisArray);

  console.log("unicodeStr: " + unicodeStr);
  console.log("utf8Str: " + utf8Str);
  console.log("sjisStr: " + sjisStr);

  return sjisStr;
};

console.log(encodeTo("あいうえお"));
$ node test.js

unicodeArray: UNICODE
utf8Array: UTF8
sjisArray: SJIS
unicodeStr: あいうえお
utf8Str: �����
sjisStr: � �¢�¤�¦�¨
� �¢�¤�¦�¨
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

ご質問の方法で、変換できているのではないでしょうか。
(HTTP応答はしたことがありませんが、テキストファイルの文字コード変換は試したことがあります)

NodeJS では 文字コード変換後のバイト配列(Buffer や ArrayBufferでも可)を
再度、文字列(string)として扱おうとすると、バイト配列が破壊された文字列になりました(NodeJS v6 時代)。
このため、変換の成否確認はバイト配列で行い、バイナリ保存した経験があります。


HTTP応答の直前に変換する方向で確認されてはどうでしょうか。

  1. HTMLなどのソース内でcharsetを指定すべき箇所は Shift_JIS に変換する(string)
  2. 応答直前に文字コード変換し、バイト配列を作成。
  3. Content-Length 用に バイト配列長を取得
  4. Content-Type に ; charset=Shift_JIS を付与。
  5. バイト配列を(ストリームなどで)HTTP応答

utf8 => Shift_JIS の文字コード変換:

  1. utf8など から Unicode の コードポイント を取得
  2. 対応する JIS X 0213 文字集合の 面、区、点の各番号(Unicodeにおけるコードポイントに相当)を取得
  3. 面区点番号を符号化表現(エンコーディング)のバイト配列にする

参考 : 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

納期の関係もあり、出来ないことへの検証に時間をかけられないので
EC2で既存システムを動かす方向性にしました。

一応、未来の自分のために、私が試したSJIS変換のソースコードを全て以下に記します。
もし、SJIS変換をする良いやり方をご存知の方がいましたら、是非是非ご回答ください。
引き続き、お待ちしております。

/**
 * [使用中止] Convert Unicode String To Specified Encoding
 * 色々な方法でUTF-8 -> SJIS変換を試したが全てうまくいかなかった
 * そのため、ガラケー用ページの表示は Lambda@Edge では行わず
 * EC2上のPHPで処理することにした
 *
 * @param  string unicodeStr
 * @param  string toEncoding [optional]
 * @return string
 */
function encodeTo(unicodeStr, toEncoding = 'SJIS')
{
  // 以下の方法は全てうまくいかなかったが、いつか必要になった時のためソースコードを残す
  // 実行する場合は当該の node_modules をLambda@Edgeに置くこと

  var availableEncodings = ['UTF16','UTF16BE','UTF16LE','JIS','UTF8','EUCJP','SJIS','UNICODE'];
  if(availableEncodings.includes(toEncoding) === false){
    return false;
  }

  // 1. encoding.js を使う場合
  var ENCODING = require('encoding-japanese');
  var arr = ENCODING.convert(ENCODING.stringToCode(unicodeStr), { to: toEncoding, from : 'UNICODE' });
  var str = ENCODING.codeToString(arr);
  return str;

  // 2. iconv-lite を使う場合
  var ICONV = require('iconv-lite');
  var str = ICONV.decode(unicodeStr, toEncoding);
  return str;

  // 3. jconv を使う場合
  var JCONV = require('jconv');
  var buffer = JCONV.convert(unicodeStr, 'UTF-8', toEncoding);
  var str = JCONV.decode(buffer, toEncoding);
  return str;

  // 4. Lambda に標準搭載されている iconv を CUI で実行する場合(ローカル環境では実行不可)
  // 以下のやり方を行う場合はこれを参照する関数全てに async/await をつけること
  return new Promise((resolve, reject) => {
    var FS = require('fs');
    var EXEC = require('child_process').exec;

    var filePath = "/tmp/sjis";
    FS.writeFileSync(filePath, unicodeStr);

    var cmd = 'iconv -f UTF-8 -t Shift_JIS ' + filePath;

    var child = EXEC(cmd, (err, stdout, stderr) => {
      if(err){
        reject(err);
      }
      else {
        resolve(stdout);
      }
    });
  });
};

console.log(encodeTo("あいうえお", "SJIS"));
$ node test.js

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る