Win32 non-cp1252 filenames

ChrisDolan on 2008-10-07T05:11:14

There was a P5P thread recently about encoding filename on Win32. A while back, I wrote an app that had to support Shift-JIS and other filesystem encodings transparently. I came up with the following unpleasant but successful hack.

Whenever I want to pass a filename to any system function (open, opendir, unlink, -f, etc) I wrap the filename string in a localfile() call like so: unlink localfile("foo.txt"). The localfile() function is defined as follows

use Encode;
use English qw(-no_match_vars);

my $encoding; sub localfile { my ($filename) = @_; if (!defined $encoding) { $encoding = q{}; if ($OSNAME eq 'MSWin32') { require Win32::Codepage; $encoding = Win32::Codepage::get_encoding() || q{}; $encoding &&= Encode::resolve_alias($encoding) || q{}; } } return $encoding ? encode($encoding, $filename) : $filename; }


This solution is obnoxious because you have to wrap EVERY filename in your entire program. I tested by setting my working directory to something non-ASCII in a Shift-JIS Windows and looked for test failures.

It's the only solution that worked reliably for me, though, on arbitrarily-encoded filesystems. Just using utf8 filesystems is so much easier... Well, aside from normalization issues, that is.