Windows11 zip圧縮 文字化け選手権

# 動機と目的
ダウンロードしたzipファイルをAndroidで解凍したら文字化けした。
未だにこんなことあるのかとがっかりした。
実際にWindows11でzipファイルを作成して犯人探しをする。

# 実験手順

## 圧縮

ファイル名が日本語のファイルを作成した。
`echo Hello world! > サンプル.txt`

以下の環境と名前で計5つのzipファイルを作成した。

***ArchLinux*** : `zip サンプル.txt linux.zip`

| Windows11 | 標準機能 *`右クリック > 圧縮先... > ZIPファイル`* | 7zip |
|:-:|:-:|:-:|
| utf8オフ | `win.zip` | `win7z.zip` |
| utf8オン | `u8win.zip` | `u8win7z.zip` |

utf8オンとは以下の状態のこと。
![u8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/35a8b60d-79f1-8315-938d-0bb955641dd0.png)

標準機能での圧縮については以下の記事を参照。

https://forest.watch.impress.co.jp/docs/shseri/win1124h2/1615026.html

## 解凍

圧縮を行った5つの環境に加えて、以下の3つの環境でも解凍を行った。

- iPadOS 18.3 @ iPad Air 5
    - Apple "ファイル"
    - Readdle "Documents"
- Android 14 @ Pixel 7a
    - Google "Files"

# 結果
殆どの場合において文字化けすることなく解凍できた。
問題のあった組み合わせを以下に示す。

- `win7z.zip`
    - Readdle "Documents"
      ![qunJ0ipH.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/2f125e8c-33ba-caaf-e057-4aa6df72744c.jpeg)

    - Google "Files"
      ![JoYZDrCd.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/c03b98ef-a555-69a9-557e-c604a24eea68.jpeg)

linuxで解凍した様子を以下に示す。
問題こそ起きなかったが`u8win7z.zip`では何故かASCIIで読んでいるようだ。

```
[root@toko-aero linux]# unzip linux.zip -d linux
Archive:  linux.zip
 extracting: linux/サンプル.txt  
[root@toko-aero linux]# unzip u8win.zip -d u8win 
Archive:  u8win.zip
  inflating: u8win/サンプル.txt  
[root@toko-aero linux]# unzip u8win7z.zip -d u8win7z
Archive:  u8win7z.zip
サンプル.txt:  mismatching "local" filename (уВ╡уГ│уГЧуГл.txt),
         continuing with "central" filename version
 extracting: u8win7z/サンプル.txt  
[root@toko-aero linux]# unzip win.zip -d win
Archive:  win.zip
  inflating: win/サンプル.txt    
[root@toko-aero linux]# unzip win7z.zip -d win7z
Archive:  win7z.zip
 extracting: win7z/サンプル.txt
```

# imhexで覗く

文字化けに深く関わってくるのが`GeneralPurposeFlag`の`UTF8`フラグとファイル名のエンコード方法である。

↓UTF8フラグの立っている状態
![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/c5df3eca-d1da-c803-e191-232ba4b751bb.png)

↓ファイル名がutf-8でエンコードされている状態
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/3eb8cb9a-4352-1f34-0240-00a458c1cffd.png)

以下実際のファイルである。

↓`linux.zip`
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/8a285198-432d-f131-9629-3bd8f5fcaeaf.png)

↓`u8win.zip`
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/7f70fe53-694b-d60d-afea-7cb0ddfb5019.png)

↓`u8win7z.zip`
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/725048d0-631b-59a8-13ab-dbd4bd7eb99a.png)

↓`win.zip`
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/f5fecc1d-c0ea-207b-b8c2-33b02b5f01c1.png)

↓`win7z.zip`
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/331fab93-6e1e-2903-87fb-9bdb012a03c9.png)

Windows11標準機能で圧縮した2つは同一のバイナリであった。

注目すべきはやはり`win7z.zip`である。
UTF8ビットが立っていないのも、sjisエンコードされているのも、このファイルのみである。

拡張領域にタグ`0x75 0x70`としてutf-8エンコードされたファイル名が書かれていることが確認できる。

<https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT>　4.6.1より抜粋

>4.6 Third Party Mappings
>------------------------
>                 
>4.6.1 Third party mappings commonly used are:
>
>  0x07c8        Macintosh
>  ...
>  0x6854        THEOS
>  0x7075        Info-ZIP Unicode Path Extra Field ←これ
>  0x7441        AtheOS/Syllable
>  ...

# 追加実験
## `win7z.zip`の拡張領域を消してみる
utf-8エンコードされたファイル名の存在する拡張領域2箇所を`00`で埋めた。
これで予告無しにsjisエンコードされたファイル名を突きつけるzipファイルが出来上がった。
***ArchLinux***上のunzipコマンドで解凍した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479627/cd77645a-9624-6a0c-768f-d331b603ec40.png)

```
 zip % unzip mod.zip
Archive:  mod.zip
 extracting: ГTГУГvГЛ.txt 
```

化けた。

至って真っ当な結果である。

# まとめ
## 文字化け選手権、選ばれたのは...
... ***7zip*** でした...

- sjisでファイル名を吐く
- ロケール設定で挙動が変わる
    - utf8にしていても問題が起きる

オプション`cu=on`を指定すればutf8エンコードのファイルを吐くようだが、知らないと使えないので意味をなさない。
筆者然り、何も知らずにとりあえず7zipで圧縮している人は多いだろう。
文句は言わないので[***ArchLinux、今すぐインストール。***](https://qiita.com/McbeEringi/items/23a2f254728f655f9f29)

## 使うべきは...
... ***Windows11標準機能*** でした...

- インストール不要
- utf-8エンコードしてくれる
- 変なロケール設定に惑わされない
- 中身が小さくても律儀にdeflateする
    - かわいい
    - 実用上の問題はない

## 知っておこう
今日は、ファイル名がshift-jisでエンコードされたzipファイルが文字化けしない理由について、知っておこう。

~~( "Documents" で解凍する )
う〜ん、化けたね！、じゃ！~~

*答: 拡張領域にutf8でエンコードされたファイル名があるから*