javascriptでsjisのcsv出力例


## はじめに
shift-jis変換してcsv出力で中々うまいこといかなかったので、表示できた例をのせておく

```index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>csv出力のサンプル</title>
    <style>
    </style>
</head>

<body>
   <!-- IDを取得するボタン -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/encoding-japanese/2.0.0/encoding.min.js"></script>

    <script src="script.js"></script>

</body>

</html>

```

```script.js
// CSVデータの準備
const csvData = [
    ["ID", "名前", "メール"],
    [1, "山田太郎", "yamada@example.com"],
    [2, "田中花子", "tanaka@example.com"]
].map(row => row.join(',')).join('\r\n');

function downloadCSV(csvData, filename) {
    // SHIFT-JISにエンコード
    const sjisData = Encoding.convert(csvData, {to: 'SJIS', from: 'UNICODE', type: 'arraybuffer'});

    // 先にUint16ArrayからUint8Arrayに変換する
    const uint8Array = new Uint8Array(sjisData);
    // Blobでデータを作成
    const blob = new Blob([uint8Array], { type: 'text/csv;charset=shift-jis;' });

    // ダウンロードリンクを作成
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = filename;

    // ダウンロードリンクをクリック
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    // 後処理
    URL.revokeObjectURL(link.href);
}

// ファイルとしてダウンロード
downloadCSV(csvData, 'export.csv');


```

https://qiita.com/fumihiko-hidaka/items/1fb8933072db76214079

https://norm-nois.com/blog/archives/5502

### メモ
・メモ１
```javascript
const csvData = [
    ["ID", "名前", "メール"],
    [1, "山田太郎", "yamada@example.com"],
    [2, "田中花子", "tanaka@example.com"]
].map(row => row.join(',')).join('\r\n');
```
は以下と同じ。
```javascript
const csvData = [
    ["ID", "名前", "メール"],
    [1, "山田太郎", "yamada@example.com"],
    [2, "田中花子", "tanaka@example.com"]
].map(row => {
    console.log(row); // 元の配列の内容をログに出力
    const joinedRow = row.join(','); // 配列の各要素をカンマで結合
    console.log(joinedRow); // 結合した文字列をログに出力
    return joinedRow; // 結合した文字列を返す
}).join('\r\n');
```

```console.log
(3) ['ID', '名前', 'メール']
ID,名前,メール
(3) [1, '山田太郎', 'yamada@example.com']
1,山田太郎,yamada@example.com
(3) [2, '田中花子', 'tanaka@example.com']
2,田中花子,tanaka@example.com
```

・メモ２
```javascript
const csvData1 = ["ID", "名前", "メール"];
const csvData2 = [1, "山田太郎", "yamada@example.com"];
const csvData3 = [2, "田中花子", "tanaka@example.com"];

// 配列の配列を作成する（ここで新しい配列を追加することができます）
const allCsvData = [csvData1, csvData2, csvData3];

// CSV形式の文字列を作成
const csvString = allCsvData.map(row => row.join(',')).join('\r\n');
```

```javascript
// 最初の配列
const allCsvData = [["ID", "名前", "メール"]];

// 他のデータを動的に追加する場合
allCsvData.push([1, "山田太郎", "yamada@example.com"]);
allCsvData.push([2, "田中花子", "tanaka@example.com"]);
// さらに追加が必要な場合は、allCsvData.push([...])を繰り返す

// CSV形式の文字列を作成
const csvString = allCsvData.map(row => row.join(',')).join('\r\n');
```
### SHIFT-JISとUTF8の違い
SHIFT-JIS
```javascript
// UnicodeでCSV文字列を作成
const csvString = [
    ["ID", "名前", "メール"],
    [1, "山田太郎", "yamada@example.com"],
    [2, "田中花子", "tanaka@example.com"]
].map(row => row.join(',')).join('\r\n');

// encoding.jsを使って、CSV文字列をSJISのバイナリデータに変換
const sjisData = Encoding.convert(csvString, {to: 'SJIS', from: 'UNICODE', type: 'arraybuffer'});

// SJISのバイナリデータをBlobとして扱う
const blob = new Blob([sjisData], { type: 'text/csv;charset=shift-jis;' });

// Blobをダウンロードするためのリンクを作成
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'example.csv';
link.click();

```


UTF-8
```javascript
// Unicode（UTF-8）でCSV文字列を作成
const csvString = [
    ["ID", "名前", "メール"],
    [1, "山田太郎", "yamada@example.com"],
    [2, "田中花子", "tanaka@example.com"]
].map(row => row.join(',')).join('\r\n');

// UTF-8の文字列からBlobを作成
const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' });

// Blobをダウンロードするためのリンクを作成
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'example.csv';
document.body.appendChild(link); // IEの場合はこの行が必要
link.click();
document.body.removeChild(link); // IEの場合はこの行が必要

```

UTF-8BOM追加
エクセルファイル対応
UTF-8エンコーディングのファイルにByte Order Mark (BOM) を追加することで、Excelがファイルを正しくUTF-8として認識することがあります。BOMはファイルの最初に特定のバイトシーケンスを追加することで、ファイルがUTF-8であることを示します。
```javascript
const BOM = new Uint8Array([0xEF, 0xBB, 0xBF]);
const blob = new Blob([BOM, csvString], { type: 'text/csv;charset=utf-8;' });

```

### UnicodeとUTF-8の違い
UnicodeとUTF-8は関連は深いですが、実際には異なる概念です。混同しやすいので、それぞれの意味を明確に説明します。

**Unicode**:
Unicodeは、世界中のすべての文字に固有の番号（コードポイント）を割り当てる文字コードの標準です。これにより、異なる言語やプラットフォーム間でテキストデータを一貫して扱うことができます。Unicode自体は、どのように各文字をバイトとしてエンコードするかは定義していません。

**UTF-8**:
UTF-8は、Unicodeのコードポイントをエンコードするための実際の形式の一つです。UTF-8は可変長のエンコーディングで、1バイトから4バイトまでを使ってUnicodeのコードポイントを表現します。ASCII文字は1バイトで表され、それ以外の多くの文字は2バイト以上を使います。これは、ウェブ上で最も広く使われているエンコーディングで、特にHTMLや多くのプログラミング言語で標準的に使われています。

**JavaScriptとUnicode / UTF-8**:
JavaScriptの内部では、テキストはUnicodeとして扱われますが、実際にテキストデータをファイルやネットワークを通じて送信する際には、UTF-8などのエンコーディング形式を使用します。JavaScriptの文字列は基本的にはUnicodeのコードポイントとして保持され、ブラウザやサーバーとの間でやり取りする際にはUTF-8形式でエンコードされることが一般的です。

要するに、Unicodeは「文字の集合」であり、UTF-8はその文字集合を「バイトとしてどのように表現するか」を定義したエンコーディング方式の一つです。

### \nと\r\nの違い
- `\n` は、UNIXやLinux、MacOS XなどのUnixベースのシステムで一般的に使用される改行コードです。
- `\r\n` は、Windowsで一般的に使用される改行コードで、キャリッジリターン（CR）とラインフィード（LF）の組み合わせです。

CSVファイルを作成する場合は、ファイルを開く予定のシステムの標準に合わせるのが良いでしょう。多くのモダンなテキストエディタやアプリケーションは、どちらの改行コードも適切に扱うことができますが、一部のアプリケーションやシステムでは問題が生じることがあります。

たとえば、Windowsシステムで使用する場合は `\r\n` を使うと、より互換性が高まります。しかし、ファイルがWebサーバーにアップロードされ、さまざまなプラットフォームからアクセスされる場合は、`\n` を使用するのが一般的です。多くのプログラミング言語やツールが、内部的に `\n` を改行コードとして解釈するため、クロスプラットフォームの互換性を保つためには `\n` の使用が推奨される場合もあります。

### Shift-JISとUTF-8のBlobセットの違い
Q:Blobにセットするデータについて
shift-jisの場合Blobにセットするのはバイナリデータにセットしたもので、UTF-8はバイナリデータに変換していません、Blobはそういうセットでそれぞれの文字コードに対応するという仕様なのですか

A:回答
Blobオブジェクトは、不透明なデータを表すために使用され、バイナリデータの塊として扱われます。`Blob` コンストラクタは、バイナリデータの配列や文字列など、さまざまな型のデータを受け取り、それを一つのBlobオブジェクトにまとめることができます。

UTF-8はウェブの標準的なエンコーディングであり、JavaScriptは内部的にUTF-8を使用して文字列を処理します。そのため、UTF-8でエンコードされた文字列は直接 `Blob` に渡すことができます。一方で、SHIFT-JISなどの他のエンコーディングを使用する場合は、対応するバイナリデータに変換する必要があります。これは、ブラウザやJavaScriptの環境が通常、UTF-8以外のエンコーディングでの文字列操作を直接サポートしていないためです。

以下はそれぞれの場合での違いを説明しています。

### UTF-8の場合

- JavaScriptの文字列は既にUTF-8として扱われているため、直接Blobに渡すことができます。
- `new Blob([csvString], { type: 'text/csv;charset=utf-8;' });` のように、文字列配列とMIMEタイプを指定してBlobを作成します。
- ブラウザはこのBlobをUTF-8テキストとして適切に扱います。

### SHIFT-JISの場合

- JavaScriptの文字列はSHIFT-JISとして直接扱うことができません。
- `encoding.js` のようなライブラリを使って、文字列をSHIFT-JISのバイナリデータに変換します。
- `new Blob([new Uint8Array(sjisData)], { type: 'text/csv;charset=shift-jis;' });` のように、バイナリデータ（`Uint8Array`）をBlobに渡します。
- ブラウザはこのBlobをSHIFT-JISエンコードされたテキストファイルとして適切に扱います。

この違いは、ブラウザがUTF-8エンコーディングをデフォルトでサポートしているのに対し、他のエンコーディングは特別な処理が必要だからです。SHIFT-JISなどのエンコーディングに対応するためには、バイナリデータとしてエンコードすることで、ブラウザがそれを適切に解釈できるようにする必要があります。