今日を乗り切るExcel研究所

Excel に働かされていませんか

【改良版】シフトJISをUTF-8に変換するバッチ

以前の記事で公開した「シフトJIS⇒UTF-8変換」バッチを改良しましたので再度公開します。

バッチを書き直しました

以前、当ブログの記事で「シフトJIS⇒UTF-8変換」バッチを紹介しました。

実はこのバッチ、入力ファイル名に半角カッコ「()」など特定の記号が含まれていると、そのファイルを処理できない問題があることが最近判明しました。これは Winodow バッチの限界に起因する問題で手の打ちようがなく、困っていました。

そんな折、前回の CSV 変換の記事を書いているうちに、 PowerShell という技術についてちょっと詳しくなってしまいました。

このとき得た知見から、 PowerShell をうまく使えばその問題が解消する見通しが得られました。

そこでこの機会にバッチを書き直して改良版を作成することにしました。

今回の改良版バッチでは以下2点が改善されています。

  • 特定の記号文字がファイル名に含まれると処理されない問題を解消
  • 複数ファイルを一括処理したときのパフォーマンスを改善

 



UTF-8 変換バッチ取り揃え

使い方は旧記事のバッチと同じです。 下記バッチスクリプトを BAT ファイルとして保存後、その BAT ファイルにテキストファイルをドラッグ&ドロップするだけです。

シフト JIS ⇒ BOM なし UTF-8

@setlocal & set PS1="%TEMP%\%~n0.%TIME::=%.ps1"
@more +3 "%~f0">%PS1% && powershell -nop -exec bypass -f %PS1% %*
@del %PS1% & pause & exit /b

# Shift_JIS -> UTF-8 (no BOM)

$enc=".utf8"
$ext="\.(txt|csv)$"
function dst($f){$f -replace $ext,"`$0$enc`$0"}

filter utf8bytes {[Text.Encoding]::UTF8.GetBytes($_)}
$args -match $ext|?{Test-Path -li $_}|%{$_
  gc -li $_ -raw | utf8bytes | sc -li (dst $_) -enc byte
}

シフト JIS ⇒ BOM あり UTF-8

@setlocal & set PS1="%TEMP%\%~n0.%TIME::=%.ps1"
@more +3 "%~f0">%PS1% && powershell -nop -exec bypass -f %PS1% %*
@del %PS1% & pause & exit /b

# Shift_JIS -> UTF-8 (BOM)

$enc=".utf8-bom"
$ext="\.(txt|csv)$"
function dst($f){$f -replace $ext,"`$0$enc`$0"}

$args -match $ext|?{Test-Path -li $_}|%{$_
  gc -li $_ -raw | sc -li (dst $_) -nonewline -enc UTF8
}

BOM あり UTF-8 ⇒ BOM なし UTF-8

@setlocal & set PS1="%TEMP%\%~n0.%TIME::=%.ps1"
@more +3 "%~f0">%PS1% && powershell -nop -exec bypass -f %PS1% %*
@del %PS1% & pause & exit /b

# UTF-8 (BOM) -> UTF-8 (no BOM)

$enc=".no-bom"
$ext="\.(txt|csv)$"
function dst($f){$f -replace $ext,"`$0$enc`$0"}

$args -match $ext|?{Test-Path -li $_}|%{$_
  gc -li $_ -enc byte | select -skip 3 | sc -li (dst $_) -enc byte
}

BOM なし UTF-8 ⇒ BOM あり UTF-8

@setlocal & set PS1="%TEMP%\%~n0.%TIME::=%.ps1"
@more +3 "%~f0">%PS1% && powershell -nop -exec bypass -f %PS1% %*
@del %PS1% & pause & exit /b

# UTF-8 (no BOM) -> UTF-8 (BOM)

$enc=".bom"
$ext="\.(txt|csv)$"
function dst($f){$f -replace $ext,"`$0$enc`$0"}

$bom=[Byte[]](0xEF,0xBB,0xBF)
$args -match $ext|?{Test-Path -li $_}|%{$_
  &{$bom; gc -li $_ -enc byte}| sc -li (dst $_) -enc byte
}

【使い方】

  1. 上記のうち使いたいバッチスクリプトをテキストエディタにコピー&ペーストし、適当な名前で BAT ファイルとして保存します
    • ファイル名の拡張子を「.bat」にします
  2. 作成した BAT ファイルのアイコンに、変換元(シフトJISなど)のテキストファイルをドラッグ&ドロップします
    • 拡張子が「.txt」か「.csv」のファイルのみ変換します
    • 複数のテキストファイルをまとめてドラッグ&ドロップできます
  3. UTF-8 に変換されたテキストファイルが変換元ファイルと同じ場所に作成されます
    • 変換元ファイルは上書き・変更されません
    • 書き込み不可な場所では変換ファイル作成に失敗します。

UTF-8 変換を頻繁に行うようなら、BAT ファイルをコンテキストメニューの「送る」メニューへ登録しておくと便利です。 そうするとどこでも、変換したいテキストファイルを右クリックして「送る」メニューからこのバッチを実行することができます。

バッチを「送る」に追加するには、フォルダ(エクスプローラ)のアドレスバーに「sendto」と入力して開かれるフォルダに、そのバッチファイルを移動します。

【制限事項】

  • Windows のコマンドの長さの制約(8191 文字)のため、ドラッグ&ドロップするファイル数が多すぎると正しく動作しなくなる可能性があります
  • ファイル名に含まれると正しく動作しない文字として アンパサンド(&)キャレット(^)は使用できませんのであらかじめご確認ください
  • Windows のロケール設定でシステムエンコーディングを UTF-8 に設定されている環境での動作は未検証ですので動作保証できません

PowerShell は処理を並列化することも可能なようです。ファイル変換処理を並列化すればもっとパフォーマンスの向上が見込めるのですが、それは今後の課題としたいと思います。

ファイル名を変更せずに中身のエンコーディングだけを変更してほしいというご要望もあるようです。 そのように作るのは可能なのですが、本ブログでは、事故になるリスクをできる限り避けるため、元ファイルはできるだけ変更しない方針でいますので、ご理解を。

【注意】 本記事のバッチに限らず、BAT ファイルはメールやチャットに添付したり、Webや共有フォルダで公開される状態に置かないでください。 内容を確認せずに BAT ファイルを実行するのは非常に危険です。信頼できないバッチやスクリプトはうかつに実行しないように注意してください。

まとめ

旧「シフトJIS⇒UTF-8変換」バッチの改良版バッチを作成しました。旧バッチの一部不具合が解消され、パフォーマンスも向上しています。

最近は Windows もヘンクツを言ってられない状況になってきたようで、システムレベルで UTF-8 への移行が進んでいます。

「メモ帳」でさえも、Windows10 の2019年春のアップデートから、BOM なしのUTF-8 がデフォルトのエンコーディングになるようです。

Windows が標準 UTF-8 に移行しても、これまで保存してきた既存のテキストや CSV ファイルはシフトJISのままですので、必要に応じて 標準 UTF-8 へ変換する作業が発生するかと思います。

そのような時に、本記事のバッチが皆さんのお役に立てればと思います。

なので、なにか不具合を見つけられた時は、コメントか Twitter にてご一報ください。
いやお願いしますよ、ほんとに。

本バッチは WIndow 10 / PowerShell 5.1 で動作検証しました。

関連記事

www.shegolab.jp

www.shegolab.jp