Ajaxで取得したShift_JISのレスポンスを、固定長でスライスして読み込む方法。
とてもマイナーな要件で情報がない。
SJISでしかも固定長とは時代遅れも甚だしいが、日本の片隅に人知れず苦労している人がいるかもしれないのでシェアする。

ちなみに、Shift_JISのデータをAjaxで取得して丸ごとString化するだけであれば、もっと簡単で以下のようなことをやる必要はない。
そちらはググれば他にたくさん記事があるので割愛。

概要

やり方は知ってしまえば簡単。
ArrayBufferの形でHTTPレスポンスを取得して、固定長でバイナリデータをスライスした後、ライブラリでバイナリデータをテキスト化する。

ライブラリ

ライブラリはencoding.jsを使用。
こういったユーティリティーを作ってくださる方は本当にありがたい。

サンプルコード

以下の例では "http://localhost:8000/sample.txt" に配置されたSJISのテキストを固定長で区切ってログ出力する。
ES2015形式。エラー処理などは無視した必要最低限のコードとなる。

class Response {
    constructor(data) {
        this.data = data;
        this.readOffset = 0;
    }

    read(size) {
        const data = this.data.slice(this.readOffset, this.readOffset + size);

        const sjisData = new Uint8Array(data);
        // SJISのデータをEncodingライブラリでUnicodeのデータに変換する
        const unicodeData = Encoding.convert(sjisData, 'UNICODE', 'SJIS');
        // UnicodeのデータをEncodingライブラリでStringにする
        const text = Encoding.codeToString(unicodeData);

        this.readOffset += size;

        return text;
    }
}

class SJISReaderSample {

    readSJISData() {
        this.getData('http://localhost:8000/sample.txt', this.parseResponse)
    }

    parseResponse(responseData) {
        const response = new Response(responseData);

        const name = response.read(4); // 4バイト読み込みString化
        const age = response.read(6); // 6バイト読み込みString化

        console.log(`${name}${age} 歳`)
    }

    getData(url, onComplete) {
        const connection = new XMLHttpRequest();
        connection.responseType = 'arraybuffer'; // ☆arraybufferの形でデータを受け取ることで、固定長でデータをスライスできる

        connection.onreadystatechange = () => {
            if (connection.readyState === 4 && connection.status === 200) {
                onComplete(connection.response);
            }
        };

        connection.open('GET', url);
        connection.send();
    }
}

new SJISReaderSample().readSJISData();

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.