オルタナティブ・ブログ > プログラマー社長のブログ >

プログラミングでメシが食えるか!?

ファイル名の長さと文字コードの問題

»

あるシステムで、ファイルをZIPで圧縮する仕組みを作っていました。ZIPで圧縮する処理はLinuxで行うのですが、解凍するのはWindowsがメインということで、結構面倒なのです。。

まず、文字コードの問題があります。LinuxやMacOSでは、ファイル名は一般的にUTF-8です。WindowsはNTFSではUNICODEらしいのですが、アプリではShift_JIS(CP932)になるらしいです(あまり興味ないので・・・)。そのため、ZIPで固める際に、UTF-8のまま固めると文字化けしてしまいます。仕方ないので、LinuxやMacOSで無理矢理CP932のファイル名でファイルを作ってZIPで固めるとうまくいきます。が、MacOSでCP932のファイル名を作るとOSごと重くなることが多い気がするのでLinuxの方がマシです。。

さて、文字コードの問題をクリアーしたと思うと、今度はファイル名の長さの問題が立ちふさがります。Windowsではパスも含めて256文字までらしいので、長いファイル名はエラーになってしまいます。仕方ないので、長いファイル名は切り詰めるしかないのですが、ASCII文字の切り詰めは簡単ですが、マルチバイト文字の切り詰めは面倒です。適当なところで切ってしまうと文字化けしてしまいます。仕方ないので、C言語などではワイド文字に変換して切り詰めて、またマルチバイトに戻す感じになります。

昔はWindowsはCP932、UNIX系はEUCが多くて、どちらも日本語は2バイトという想定が使える場合が多かったのですが、インターネットが普及して世界各国の文字が共存するようになってきて、マルチバイトは2バイトどころではなくなってしまい、自力で何とかするのは大変になってしまいました。素直にマルチバイト処理ようのライブラリを使うのが良いでしょう・・・。

さらに・・・Windowsではファイル名に使えない文字が存在します。'/'':'';'',''?''"''<''>''|''\'このあたりの文字は使わない方が無難です。Linuxでも'/'と'¥0'は駄目ですね。ということで、これらの文字は置き換えが必要です。置き換えもワイド文字状態で行う方が確実です。

これでようやくWindowsで解凍できる見込みのファイル名にすることができます。「見込み」というのは、パスの長さが256文字までなので、展開するディレクトリによってはオーバーしてしまったりする可能性もあるためです。

ちなみに、LinuxなどのUNIX系OSでは、ファイル名の最大長は255バイト。パスの最大長は1023バイト(システムコールに渡す際の制限)と、Windowsよりはかなり扱いやすくなります。

まあ、そんなに長いファイル名など関係ないと思うかもしれませんが、プログラムを作っていると、限界テストという感じで、あえておかしな動きになりそうなデータを与えてテストをするものでして。。

正常系の処理を作るより、異常系の処理を作る方が大変なこともよくあるくらいなのです。特にユーザが直接操作する部分は、何をされても大丈夫なように、と、大変です。ユーザインターフェースなどはまさにエラーチェックなどだけで嫌になるくらいです。

ワイド文字の扱い方を忘れていたので、著書を引っ張り出してきました。すでに絶版ですが・・・。

Comment(2)

コメント

morya

自分の記憶ではWindowsでの長さ制限は、確かフルパスが255文字というのはVFATの制限で、NTFSはファイル名(フォルダ名)が255文字で、フルパスは32767文字だったと思ったんですが・・・
で、ちょっと検索してみたらこんなマヌケな現象があるようですね。
http://jabnz.blog69.fc2.com/blog-entry-462.html
>多くの Windows で採用されているファイルシステム「NTFS」では、ファイルのパスに最大 32767 文字が使えます。しかし、Windows エクスプローラなど一部の Windows のアプリケーションでは、取り扱えるパス文字列の最大長が 260 文字(MAX_PATH:260文字)となっています。

だそうです。
つまり、エクスプローラ等を使わず、自前のアプリで直にNTFSにアクセスすれば長いフルパスでもファイル作成等できるが、エクスプローラでそれを操作しようとするとエラーとなるようです。
マイクロソフトさん中途半端はやめて・・・orz

moryaさん、情報ありがとうございます。
Windowsは旧バージョンとの互換性のこともあり、パスも文字コードも中途半端ですね。。
Linuxは割と冷たく旧バージョンとの互換性(とくにバイナリ互換)を切り捨てますが、オープンソースで好きなパージョンを使えるからなのでしょうね。

コメントを投稿する