Open6

JavaScriptで文字コード変換(Uint8Arrayや、Bufferってなに?)

mtskhsmtskhs

背景

CSVファイルをアップロードしてもらい、データ一括保存する処理を検討したときのメモ

よくある、Windowsでさわっていると知らぬ間に、ShiftJISになっている問題に対応するため

mtskhsmtskhs

使うライブラリ

# 文字コードが何なのか判定するためのライブラリ
import * as chardet from "chardet";


const encode = chardet.detect(data)!.toString();
console.log(encode)
// OUTPUT:  UTF-8 etc
// https://github.com/runk/node-chardet#supported-encodings

# 文字コードのdecode・変換するためのライブラリ
import * as iconv from "iconv-lite";

const str = iconv.decode(Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f]), "win1251");

mtskhsmtskhs

JSの文字を扱うtypeがいっぱいあってむずかしかった

Uint8Arrayや、Bufferってなに?!どう変換するの?

chardet.detect(data)!.toString(); //detect() は、引数にUint8Arrayをとる
iconv.decode(buffer, encode); // decode() は、引数にBufferをとる
  • React.jsでファイルアップロード処理

  const onSelectedFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
    if (!e || !e.target || !e.target.files) return;
    const file: File = e.target.files[0];
    const data = await parseCSV(file);
  };

const parseCSV = async (file: File): Promise<any[]> => {
    return new Promise((resolve, reject) => {
      try {
        const reader = new FileReader();
        reader.onload = (e) => {
          const decodedString = decodeBuffer(reader);
          Papa.parse(decodedString, {
            header: true,
            dynamicTyping: true,
            skipEmptyLines: true,
            complete: ({ data, errors }) => {
              if (errors?.length) {
                reject(errors);
              }
              resolve(data);
            }
          });
        };
        reader.readAsArrayBuffer(file);
      } catch (e) {
        reject(e);
      }
    });
  };

return (
<>
{/* 省略 */}
      <input type="file" accept="text/csv" onChange={onSelectedFile} />
</>
)
  • デコード処理
 const decodeBuffer = (reader: FileReader): string => {
     // 上記から、readerにファイルの中身がはいっている
      const buffer = reader?.result! as ArrayBuffer;
      const data = new Uint8Array(buffer);
      const encode = chardet.detect(data)!.toString(); //detect() は、引数にUint8Arrayをとる
      const decodedString = iconv.decode(Buffer.from(buffer), encode); // decode() は、引数にBufferをとる
mtskhsmtskhs

とりあえずできたけど、

FileReader、
Uint8Arrayや、Bufferあたりの概念を理解しておきたい。

Goでいう、io.Reader, string, rune, bytes.Buffer あたりの概念だと思われる。