Dear Monks,
Is that any simple way just en/decode a unicode path that can be understand by any sub take path as parameter like dealing with ANSI? (I am working on windows.)
If I am directly dealing with the target directory/file read write, Win32::Unicode will do most of the job, but for modules/features that taking path as parameter, eg Storable, or sort of flock() functions, my Unicode path are mostly won't recognized.
And, my real deal is even more complex. Sometimes I read path list from text files, sometime I readdir() with recursive loop, or even `dir /s/b`. So I am looking a solution for a path translation that satisfy any kind of sub argument spec, instead of particular situation.
Any magic here? Thanks in advance.
=====================
Update, some code for SSCCE. Again, I am asking if anyway can make a path can be recognized in all other (CPAN) modules, if they don't use Unicode friendly method to take care of path.
use strict;
use utf8;
use Encode qw/encode/;
use Storable;
use Win32::Unicode::Util;
use Win32::Unicode::Native;
opendir my $D, encode ( "cp1252" => "./Test/我/XX" ) or die $!;
+#OK
print $/;
my $path = "./Test/我/";
opendir my $D, $path or die $!; # OK
my @files = readdir $D ;
close $D;
print "$_$/" foreach @files;
print $/;
$path .= "This.sto";
store { A => { Key => 'A' } }, $path or die $!;
__END__
Outputs
.
..
XX
們
地
can't create ./Test/我/This.sto: Invalid argument at C:\....\ope
+n.pl line 18.
=====================
Update 2: I came up with this package for myself.
package Win32::MakePathANSI;
require Exporter;our @ISA = qw/Exporter/;our @EXPORT = qw/ansi_path/ ;
use strict;
use utf8; use Win32;
use Win32::Unicode::Native;
sub _make_dir {
my $root = shift;
$root = Win32::GetFullPathName($root);
foreach my $part ( @_ ) {
$root .= "/$part";
mkdir $root;
die "Unable to assert dir for '$root' $!" unless Win32::GetSho
+rtPathName ($root);
}
return $root;
}
sub ansi_path {
my $path = shift;
my $assert = shift; # expects 'Dir' or 'File', where 'File' implie
+d 'Dir'
my $isDir = $path =~ /[\\\/]$/ ? 1 : 0;
$path =~ s/[\\\/]{2,}/\//g;
my $acpp = Win32::GetShortPathName($path);
return $acpp if $acpp;
return $path unless $assert ;
my @parts = split /\//, $path;
if ( $assert eq "File" ) {
my $file = pop @parts;
my $root = _make_dir ( @parts );
open my $f, ">", "$root/$file" or die $!;
close $f;
}
elsif ( $assert eq "Dir" ) {
_make_dir ( @parts );
}
else {
die "Expects 'Dir' or 'File'"
}
return Win32::GetShortPathName($path)||$path; #in case anything
}
1;
__END__
=Description
To make a Unicode path becomes ANSI on Win32, thus modules not support
+ing Unicode can still access the path ( I guess );
=cut
=Synopsis
use strict;
use Win32::MakePathANSI;
my $ansi_path = ansi_path ( $unicode_path, $assert ) ;
# $assert will create the path when the path not exists
# $assert expects 'Dir' or 'File', so this pkg knows what to assert
=cut
=Note
1. Will die if unable to assert
2. Without $assert, return origin path if not found
3. Origin path will be returned if unable to convert
=cut