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

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

新規登録して質問してみよう
ただいま回答率
85.50%
char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

5回答

2294閲覧

SHIFT_JISのプレインテクストがUTF-8に変換できない

NANASHI-TAROU

総合スコア13

char

charは文字データ型を指します。一文字分の文字コードの格納を想定としている型です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

UTF-8

UTF-8は8ビット符号単位の文字符号化形式及び文字符号化スキームです。データ交換方式、ファイル形式としては、一般的にUTF-8が使われる傾向があります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

2クリップ

投稿2018/04/03 08:55

編集2018/04/04 05:03

前提・実現したいこと

axiosで取得したSHIFT_JISでエンコードされたプレインテクストがコンソールでちゃんと表示されないので、エンコードをUTF-8に変更したい。

発生している問題・エラーメッセージ

文字化けが発生してる。
iconv等ググって見つかったやり方を試しているが、文字化けが全く治らない。

該当のソースコード

javascript

1(ひとつめ) 2 const axios = require('axios'); 3 const iconv = require('iconv-lite'); 4axios.get("http://awabi.2ch.sc/news4plus/subject.txt").then(res => { 5 const text = res.data 6 const buf = new Buffer(text, "SHIFT_JIS") 7 const str = iconv.decode(buf, "UTF-8") 8 console.log(str) 9})

javascript

1(ふたつめ) 2 const axios = require('axios'); 3 const jconv = require('jconv'); 4 axios.get("http://awabi.2ch.sc/news4plus/subject.txt").then(res => { 5 const text = res.data 6 const convert = jconv.convert(res.data, "SJIS", "UTF8") 7 console.log(convert) 8 const text2 = jconv.decode(convert, "UTF") 9 console.log(text2) 10 }).catch(e => {console.log(e)}) 11})

試したこと

他にもいろいろ試しましたが、ダメでした。

補足情報(FW/ツールのバージョンなど)

試した環境
ローカル環境のWindows10でNodeJS最新版
DigitalOceanのUbuntuマシン
など

最後に

お忙しいなか、ありがとうございます。
よろしくお願いいたします。

###解決しました
すみません、解決しました。
axiosが取得したデータをUTF-8であると勝手に決めつけて、デコードしてしまっていたようです。
StackOverflowのこれで解決しました。
https://stackoverflow.com/questions/12040643/nodejs-encoding-using-request

みなさん、ご知見を共有していただきありがとうございました。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

サーバーからascii/utf-8以外でエンコードされた応答をどう扱うかという観点で試してみました。

axiosで取得したSHIFT_JISでエンコードされたプレインテクストがコンソールでちゃんと表示されない

コンソールで文字化けが起きているというより、レスポンスを受信した時点でSHIFT_JISのテキストが(文字エンコーディングを無視してutf-8として)stringへ変換されているのが原因だと思います。

Shift-JISなどのascii/utf-8以外の文字エンコーディングをstringへ強引に変換してしまうと、ascii以外の範囲の文字はU+FFFD(変換不能文字としてよく使われる文字?)にマッピングされてしまったり変換エラーを起こしたりすると思います。

Node.js(あるいはECMAScript)の文字列は内部がUTF-16となっており外部とのやりとりをする際に使える文字エンコーディングは「ascii、utf-8、以上!」みたいなところがあるのでShift-JISなどのエンコーディングのバイト列は生のバイナリーデータとしてiconv-liteなどへ与えてやれば正しく解釈できますが、それをする前にどこかでstringにうっかり(というより無理やり?)変換されてしまうと、最早正しい解釈が不可能になってしまいます。

実際、get(...).then(res => ...)のthen部でtypeof res.dataをログに出してみたところstringになってましたので、then部でどう頑張っても正しい結果は得られないと思います。

つまりaxiosでレスポンスをバイナリーとして得られるようにするのが第一歩かと思います。さて、以下を見ますと

https://github.com/axios/axios

// 'responseType' indicates the type of data that the server will respond with
// options are 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
responseType: 'json', // default

とかいてあり、axiosはデフォルトでレスポンスをjsonとしてパースするようです。jsonというぐらいですから入力はどこかでテキストとして(つまりstringとして)解釈されるでしょうから、これではまずそうです。

他のオプションをみるとarraybufferなどバイナリーを受け取れそうなものがあるようですのでとりあえずそれらを使うとよいと思います。試しにarraybufferとしてみると先ほどのthen部でres.data.constructor.nameBufferに変わりましたのでこれならiconv-liteで変換できると思います。

Javascript

1const iconv = require('iconv-lite') 2const axios = require('axios').create({ 3 'responseType': 'arraybuffer' 4}) 5 6const url = "http:..." 7 8axios.get(url).then(res => { 9 const str = iconv.decode(res.data, "Shift-JIS") 10 console.log(`res.data = '${str.substring(0, 80)}'`) 11})

上記は決め打ちでShift-JISを仮定してますが、真面目にやるには応答のcontent-type属性のcharsetなどをみてどのエンコーディングかを判断しつつ適切にデコードすべきなのだろうと思います。

投稿2018/04/03 12:35

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

「shift-jis」や「sjis」を「cp932」に変えて試してみてください。

node.jsは知りませんが、少なくともコマンドラインでのiconvで「﨑」の文字を含むutf-8のテキストファイルを変換しようとした場合、「cp932」ではコンバートできましたが、「shift_jis」ではエラーになりました。

$ iconv -f utf-8 -t cp932 a.txt > a.cp932 $ iconv -f utf-8 -t shift_jis a.txt > a.sjis iconv: 位置 0 に不正な入力シーケンスがあります

投稿2018/04/03 14:33

katsuko

総合スコア3462

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/04/04 04:11 編集

少なくとも質問者さんのアクセスしているURLの応答には ×:iconv -f Shift_JIS -t utf8 〇:iconv -f cp932 -t utf8 のような文字は含まれてませんでした。 レスポンスはcontent-type: text/html; charset=Shift_JISですけどそんな場合、cp932が正しいデコーダーであると仮定できるのでしょうか?つまり本来はcharset=cp932などとすべきなのにサーバーがcharset=Shift_JISで応答することがよくあるみたいな?
katsuko

2018/04/04 06:37

httpレスポンスのcharsetはShift_JIS(もしくはその別名)しかないと思ってましたけど、調べてみたら「Windows-31J」や「cp932」(ただし非IANAらしい)もあるんですね。 見た事なかったので、知らなかった。
KSwordOfHaste

2018/04/04 06:50

ShiftJIS系の取り扱いは難しいですよね。Windows31-Jだったり932だったりCP932だったりJavaだとMS932だったりその意味を把握するだけで一苦労です><
katsuko

2018/04/04 08:01

全く同意ですw
guest

0

一応、コンソール上では、普通に文字列として表示はされてました(macOS Chrome

javascript

1const axios = require('axios'); 2const iconv = require('iconv-lite'); 3 4axios.get('./sjis.txt', { 5 responseType : 'arraybuffer', 6 transformResponse : (data) => { 7 const sjis = new Buffer(data, "SHIFT_JIS"); 8 const utf8 = iconv.decode(sjis, "SHIFT_JIS"); 9 return utf8; 10 }, 11}) 12 .then((res) => { 13 console.log(res.data); 14 });

axios内部でXMLHttpRequest.overrideMimeTypeメソッドが実行できれば、手っ取く出来そうなのですが。。。

投稿2018/04/04 03:37

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/04/04 04:07

responseTypeはgetメソッドのオプションにも指定できたんですね! ちなみにnew Buffer(data, encoding)はdataがstringの際にそれをどう解釈するかで用いられる気がします。ここではdataがBuffer(バイナリー)なので、new Buffer(data, "SHIFT_JIS")としてもencodingは解釈されず単に無視されるのではないでしょうか?実際に (data) => {  const utf8 = iconv.decode(data, "SHIFT_JIS")  return utf8 } とやっても同じ結果になるのではないでしょうか?
guest

0

Ubuntu(Linux系)であればnkfコマンドで変換可能なので、コマンドの実行結果を受け取るようにすればなんとか.

投稿2018/04/03 09:30

defghi1977

総合スコア4756

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

windowsであれば、桜エディタで変換できますよ。
保存時に、文字コードセットを指定すればよいかと。

投稿2018/04/03 08:59

ikapy

総合スコア1167

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NANASHI-TAROU

2018/04/03 09:25

ご回答ありがとうございます。 自分が作っているソフトウェアの一部なので、それでは少し難しいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問