fanticla has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!

I am struggling with the following piece of code. My need: selecting a directory (possibly with UTF characters) and save a text file. This piece of code creates a folder and put inside it the file. How can I prevent the creation of the folder (this is the part I found on the web)? I just took away the "unless" part of the code, but if doing so, the script is no longer able to write in a folder with UTF characters! What am I missing? Thanks. Cla

use Tk; use strict; use warnings; use Encode qw( encode ); use File::Slurp; use File::Spec::Functions qw( catfile ); use Win32; use Win32::API; use constant ERROR_ALREADY_EXISTS => 0xb7; my $mw = MainWindow->new; $mw->title('Menu'); my $menubar = $mw->Menu(-type => 'menubar'); $mw->configure(-menu => $menubar); my $mfile = $menubar->cascade(-label => '~File', -tearoff => 0); $mfile->command(-label => '~Save', -command => \&save_file4); my $exit = $mw->Button(-text => 'Exit', -command => [$mw => 'destroy']); $exit->pack; my $types = [ ['HTML files', '.txt'], ['All Files', '*'],]; MainLoop; sub save_file4 { my $save = $mw->getSaveFile(-filetypes => $types, -initialfile => 'test', -defaultextension => '.txt'); unless ( Win32::CreateDirectory($save) ) { my $err = $^E; if ( $err == ERROR_ALREADY_EXISTS ) { warn "Directory exists, no problem\n"; } else { die Win32::FormatMessage($^E); } } my $ansi_path = Win32::GetANSIPathName($save); warn "$ansi_path\n"; my $file = catfile($ansi_path, 'test.txt'); open(OUT,">$file") or die $!; print OUT $file; close OUT; }

Replies are listed 'Best First'.
Re: path encoding folder
by moritz (Cardinal) on Nov 19, 2010 at 15:11 UTC
    the script is no longer able to write in a folder with UTF characters!

    What happens if you try? Does your computer burst into flames? Or do you get an error message? if so, what does it say?

      with the script as above, it works fine (create new folder, even with "UTF characters", and write in it the text file). Without the "unless" code, I get the error: TK::Error: No such file or directory at open(OUT,">$file") or die $!;

Re: path encoding folder
by ikegami (Patriarch) on Nov 19, 2010 at 15:43 UTC

    Could you add

    use Devel::Peek; Dump($save); Dump($ansi_path); print(STDERR `chcp`);

    where the warn is located and provide the output please? (I'm away from my Windows box at the moment.)

      C:\Documents and Settings\FC\Desktop>perl script.pl SV = PV(0x2e33e00) at 0x2d70c60 REFCNT = 1 FLAGS = (PADBUSY,PADMY,POK,pPOK,UTF8) PV = 0x2e52784 "C:/Documents and Settings/FC/Desktop/\303\274/test.t +xt"\0 [UTF 8 "C:/Documents and Settings/FC/Desktop/\x{fc}/test.txt"] CUR = 48 LEN = 52 SV = PV(0x2e33cf8) at 0x2d70d08 REFCNT = 1 FLAGS = (PADBUSY,PADMY,POK,pPOK) PV = 0x2e58004 "C:/Documents and Settings/FC/Desktop/\374/test.txt"\ +0 CUR = 47 LEN = 48 Tabella codici attiva: 850 Tk::Error: No such file or directory at a.pl line 44. (menu invoke)

        getSaveFile appears to return the file name as decoded text. CreateDirectory expects decoded text according to the documentation, so that's good. As for open, it (more or less) expects text encoded using the current locale (unix) or ANSI code page (Windows). GetANSIPathName is there to do that conversion.

        I was trying to use chcp to figure out what's your code page, but it returns the OEM code page. We're interested in the ANSI one. Your ANSI code page is probably cp1252 (a superset of iso-8859-1).

        The output you gave shows that .../ü/test.txt gets properly encoded to cp1252, so everything is fine on the encoding side.

        The output you gave also shows that you are trying to create file .../Desktop/ü/test.txt/test.txt since you append test.txt to the displayed value. (Note the double "test.txt".) I'm guessing directory .../Desktop/ü/test.txt doesn't exist (though I don't know why CreateDirectory didn't given an error when it didn't create it).

        The problem is that you're using the file path as the directory path. That's why it's always a good idea to include the file name in error messages for open.