LuaでUTF-8なString文字列をSJISに変換してWindowsのコマンドとして渡す

# 結論

[GitHub - AoiSaya/FlashAir_UTF8toSJIS: FlashAir library to convert from UTF-8 to Shift _ JIS](https://github.com/AoiSaya/FlashAir_UTF8toSJIS)

を使う。

ただし、変換した文字数が極少量なのでFlashAir用がどこまでかかっているのかは要チェック。

# 環境

Windows7

Lua自体は別アプリに付属しているスクリプト実行環境のため詳細は不明。

# 前段

Lua初心者がLuaからディレクトリ内のファイル一覧を取得したかった。
取得コード自体は
[filenames - How to get list of directories in Lua - Stack Overflow](https://stackoverflow.com/questions/5303174/how-to-get-list-of-directories-in-lua)
のベストアンサー、ではなくLuaFileSystemを使わない方
>I hate having to install libraries

I love you:kissing_closed_eyes:

しかし…

# 症状


```lua
popen('dir "'..directory..'" /b /ad')
```

にてファイルがひとつも取得できない状態に陥った。
エラー出力もなし。

ただし、別途紹介されているコード

```lua
 for dir in io.popen([[dir "C:\Program Files\" /b /ad]]):lines() do print(dir) end
```

は正常に成功していたことから、原因を推測。
仮定として、目的のディレクトリパスに日本語名が入っていることを原因とした。

# 解決方法

いろいろ探し回り
[GitHub - AoiSaya/FlashAir_UTF8toSJIS: FlashAir library to convert from UTF-8 to Shift _ JIS](https://github.com/AoiSaya/FlashAir_UTF8toSJIS)
にたどり着く。
>FlashAir用のLua ライブラリ

とあるが、コンバート自体はLua単体で完結しているので安心した。

`Utf8Sjis.tbl`
と
`UTF8toSJIS.lua`
を(本来`UTF8toSJIS.lua`はlib以下に設置するが)目的のLuaスクリプトと同一ディレクトリに設置する。

`sample.lua`
の内容を確認しつつ、

```lua
local UTF8toSJIS = require("UTF8toSJIS")
local UTF8SJIS_table = "Utf8Sjis.tbl"
```
と読み込む。
ただし、`UTF8toSJIS.lua`には私の環境では存在しない
`sleep(0)`
があったのでこれをコメントアウトしておいた。

これで読み込めるようになったので、サンプルコードを改良する。
今回はファイル書き出しでもなく、また複数行の変換でもないのでサンプルにあるループ処理は不要となり、最終的に

```lua
local UTF8toSJIS = require("UTF8toSJIS")
local UTF8SJIS_table = "Utf8Sjis.tbl"

local directory = [[C:\Users\USERNAME\ほげほげ\ふがふが\]] -- 日本語入りパス
local fht = io.open(script_path() .. UTF8SJIS_table, "r")
local strUTF8, strSJIS, sj_length
local sjisdirectory = ""
strSJIS, sj_length = UTF8toSJIS:UTF8_to_SJIS_str_cnv(fht, directory)
--print(sj_length)
--print(strSJIS)
fht:close()

local i, t, popen = 0, {}, io.popen
local pfile = popen('dir "'.. strSJIS ..'" /b')
for filename in pfile:lines() do
    i = i + 1
    --print(filename)
    t[i] = filename
end
pfile:close()
```

とすることで目的を達成できた。

# 失敗した他方法

ここからは解決方法にいたるまでのほかの失敗したアプローチを書き残す。

なお、行わなかったアプローチとしてはicovを利用した変換も提案されていたことを記しておく。

## スクリプトファイルの文字コード変換

SJISが期待されている場所にUTF-8の文字列が渡されることが問題なので、ソースコード自体をSJISで記述すればWindowsに渡される文字列もSJISになるはずである。

というわけでよくある連携する側の文字コードにスクリプトファイルの文字コードを合わせる対応を取ってみた。
SJISで保存しなおしたLuaスクリプトは正常に動作し、期待していたとおりパスに日本語を含むディレクトリからもファイル一覧を取得できた。
しかし、Lua側でファイルのフルパス(当然日本語が含まれている)を利用すると、今度はLua側で日本語が文字化けするので正しいパスとして認められなかった。

* SJISで書くと日本語はWindowsでは使えるがLuaでは使えない
* UTF-8で書くと日本語はLuaでは使えるがWindowsでは使えない

という状態になったと予測する。
仮にマルチバイトを使う場面が全てWindowsへのコマンドのみで、Luaへは英数字のみを使うならばSJISで記述しても問題ないように思えたが、惜しくも今回はフルパスを使う必要があったため、
**部分的な文字コードの変換**が必要だった。

## 変換テーブルを使った別コード

変換テーブルを使った変換として
[utf 8 - How to convert windows-1256 to utf-8 in lua? - Stack Overflow](https://stackoverflow.com/questions/16624036/how-to-convert-windows-1256-to-utf-8-in-lua)
が見つかった。
私は`local win2utf_list = [[`
のほうを利用してみたが、うまく変換されなかった。

というかたった今記事を書いていてわかったが
>convert windows-1256 to utf-8

なので思いっきり逆だった。

## kconvを使った変換

他の日本語変換ツールに
[Lua kconv 漢字コード変換ライブラリ](http://www.rtpro.yamaha.co.jp/RT/utility/index.html)
が見つかった。
幸いなことに今回問題になっている日本語はすべて漢字だったため、このライブラリで解決できるかと思われたが、
私のLuaへの知識不足から正常にrequireすることがかなわなかった。
moduleあたりの知識を蓄えれば今後なんとか使えるか…

# 検索の劣悪さ

LuaでSJIS、日本語対応を調べると、

* Lua本体のSJIS、日本語対応
* Luaを使うC#(あるいは別言語)側での対応
* SJISに対応した秀丸のためのhmJT
* Lua に渡される/が読み込むファイル 文字列がSJIS

等々、なかなか検索に苦労した。
毎度のコトながら記事を書く段階では解決策のURLへの到達方法が思い出せない状況でもある。
GitHubで「`sjis lua`」で検索したんだったかな？

***

とにかくローカルを操作するには今後も
`popen('cmd ...')`
とこのSJIS変換を多用すると思われる。