webForumDet fria alternativet

PerlTk - getOpenFile

9 svar · 649 visningar · startad av Jojoxx

JojoxxMedlem sedan juni 20004 306 inlägg
#1

Jag har märkt ett spännande (irriterande) fenomen med PerlTk och getOpenFile. Egentligen är fenomenet det samma oavset filväljare under PerlTk som jag testat. Exempelkod:

use Tk; 
use strict; 

my $top = MainWindow->new;
my $file=$top->getOpenFile(-filetypes =>
	[
		['Text Files',       ['.txt', '.text']],
		['All Files',        '*',             ],
	],
	-initialdir       => "c:/",
	-title            => "Select file",
);
print -e $file?"Filen existerar":"Filen existerar inte...";

Välj en fil med natinella tecken i filnamnet (å, ä, ö) i filnamnet så kan scriptet inte hitta den. Hårdkodar jag filnamnet i scriptet ("örjans ångbåt välter.txt") så är det inga problem. Jämför jag strängen med filnamnet från getOpenFile så är de lika, byte för byte. (POSIX och locale verkar inte göra någon skillnad). Någon annan som har stött på samma problem och hittat en lösning?

aronMedlem sedan mars 2004487 inlägg
#2

Borde inte det där ha och göra med teckenuppsättningarna, och vilket filsystem man använder?

JojoxxMedlem sedan juni 20004 306 inlägg
#3

Ja, det antar jag också :) Men som sagt, frågan är hur man kommer runt det. POSIX och locale har jag försökt använda utan framgång.

aronMedlem sedan mars 2004487 inlägg
#4

Ja, nu vet inte jag så mycket om perlTK.

Men det jag tror är viktigt är vilken teckenuppsätning "verktygen" använder, vilket system du har, och i vilket format du skriver textfilerna i.

Därför så är det smartast att bara använda ASCII för att det ska funka så bra som möjligt.

Testa att skriva dina textfiler i utf-8, det kan vara en lösning.

JojoxxMedlem sedan juni 20004 306 inlägg
#5

Jag tror du missuppfattade frågan.

Det handlar inte om innehållet i filen utan sökvägen till den. getOpenFile är en filväljar-widget och det "ogiltiga" filnamnet finns inte med i koden. Som jag skrev, hårdkodar jag filnamnet i scriptet är det inga problem. Problemet är alltså begränsat till getOpenFile.

aronMedlem sedan mars 2004487 inlägg
#6

A.. nu förstår jag...

Sökte runt lite på nätet... och det verkar som om det är en teckenuppsättnings-krock. Nyare Perl använder utf-8, medans TK fortfarande använder iso-8859-1. Så om jag inte har fel så är lösningen en ny TK-verison eller att använda en gammal perl-verison.

http://www.codecomments.com/archive234-2004-4-159930.html

r\ Kan det inte vara så att TK från början var till för att användas tillsamans med TCL?

JojoxxMedlem sedan juni 20004 306 inlägg
#7

Jag är helt övertygad att felet har med en teckenuppsättnings-krock att göra. Tyvärr verkar det vara ett internt problem som är svårt att komma runt. Det räcker inte med att konvertera strängen till UTF-8:

use strict;
use Unicode::String;
use Tk;

my $top = MainWindow->new;
my $file = "C:/örjan.txt";
print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n";

$file=$top->getOpenFile(-filetypes =>
	[
		['Text Files',       ['.txt', '.text']],
		['All Files',        '*',             ],
	],
	-initialdir       => "c:/",
	-title            => "Select file",
);

print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n";
$file=Unicode::String::latin1($file);
print "UTF-8:\n";
print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n";

Lite spännande output:

Filen C:/÷rjan.txt existerar
Filen C:/÷rjan.txt existerar inte...
...

Men, jag tror jag ger upp detta. Jag har kommit på att filväljaren i Win32::GUI inte har dessa problem.

Du skall ha tack för hjälpen i alla fall, det är alltid bra att ha någon att bolla idéer med.

aronMedlem sedan mars 2004487 inlägg
#8

Ok, ska bara försöka förstå det här själv... kastar in komentarer i din kod mellan {{ här }} efter koden jag komenterar.

use strict;
use Unicode::String;
use Tk;

my $top = MainWindow->new;
my $file = "C:/örjan.txt";  {{här skapar du en utf-8 filvariabel }}
print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n"; 
{{ vilket gör att det funkar här }}

$file=$top->getOpenFile(-filetypes => 
{{här blir det dock en krock iso-8859-1 text sparas som utf-8... här blir det fel alltså }}
	[
		['Text Files',       ['.txt', '.text']],
		['All Files',        '*',             ],
	],
	-initialdir       => "c:/",
	-title            => "Select file",
);

print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n"; 
{{ Och då blir det fel här }}
$file=Unicode::String::latin1($file); 
{{ och så här går det ju inte att göra då heller }}
print "UTF-8:\n";
print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n"; 
{{ och här blir det fel igen }}

Nå... kan det inte vara så.

22/9 2005 (tillägg):
Det verkar som om getOpenFile retunerar ett 7-bitars ascii värde.
Kanske går det att omvandla till ISO-8859-1 eller UTF-8 på nått anat sätt än dom som diskuteras nedan.

JojoxxMedlem sedan juni 20004 306 inlägg
#9

Jag ska inte säga emot dig, men om getOpenFile returnerar en iso-8859-1-sträng så borde detta exempel göra om den till utf-8 (Unicode::String::latin1 verkar inte vara rätt väg att gå):

use strict;
use Encode;
use Tk;

my $top = MainWindow->new;
my $file = "C:/örjan.txt";
print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n";

$file=encode("utf8",$top->getOpenFile(-filetypes =>
	[
		['Text Files',       ['.txt', '.text']],
		['All Files',        '*',             ],
	],
	-initialdir       => "c:/",
	-title            => "Select file",
));

print -e $file?"Filen $file existerar\n" : "Filen $file existerar inte...\n";

Tittar man på outputen så ser man att efter konverteringen har du 2 tecken för ö ("├Â") så UTF-8 är det, och filen hittas fortfarande inte. Efter att ha läst lite perl docs så verkar det som att perl internt har en flagga som talar om ifall den aktuella strängen är utf-8 eller inte. Detta gör det hela mycket mer intressant. Jag skulle tippa på att även om perl internt använder utf-8 för att lagra strängar, och du lagrar en sträng med ex "ö" så resulterar det i 2 bytes, men tar du length på "ö" så får du 1 som svar eftersom det ses som 1 logiskt tecken (ungefär som "\n" är ett logiskt tecken men det på en windowsplattform egentligen är 2: cr, lf).

Jag skulle tippa på att det är något som skaparen av Perl/TK har missat i.o.m. att Win32::GUI hanterar det utan problem.

JojoxxMedlem sedan juni 20004 306 inlägg
#10

Om någon i framtiden skulle stöta på samma problem.

use strict;
use Win32::GUI;

my $file=Win32::GUI::GetOpenFileName;
print (-e $file?"Hittade filen $file.":"Hittade inte filen $file.");
Genererad på 522 ms · cache AV · v20260730165559-full.f96bc7eb