Open6
JavaScriptで文字コード変換(Uint8Arrayや、Bufferってなに?)
背景
CSVファイルをアップロードしてもらい、データ一括保存する処理を検討したときのメモ
よくある、Windowsでさわっていると知らぬ間に、ShiftJISになっている問題に対応するため
使うライブラリ
# 文字コードが何なのか判定するためのライブラリ
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");
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をとる
とりあえずできたけど、
FileReader、
Uint8Arrayや、Bufferあたりの概念を理解しておきたい。
Goでいう、io.Reader, string, rune, bytes.Buffer あたりの概念だと思われる。
Buffer objects are used to represent a fixed-length sequence of bytes. Many Node.js APIs support Buffers.
Bufferは、bytesの固定長の連なりを表すもの、とのこと。
これが詳しそう。
JavaScript でのバイナリデータは、他の言語と比べて非標準的な方法で実装されています。しかし、一度整理できれば、すべてがとても簡単になります。