2014-10-03 9 views
6

Mam plik uchwyt otwarty w pliku z cp1252 znaków w nim. Chcę udostępnić ten otwarty uchwyt pliku do biblioteki, która oczekuje surowych bajtów utf8, wyśle ​​je przez sieć.Perl konwertuj uchwyt pliku w miejscu/przesyłanie strumieniowe z cp1252 na utf-8?

Naiwny sposób to zrobić byłoby zapisać plik z drugiego pliku z prawej kodowania i dać drugą uchwytu pliku do biblioteki:

use Fcntl qw/SEEK_SET/; 

open my $fh_1252, "<:encoding(cp1252)", "1252.txt" || die $!; 

open my $fh_utf8, "+>:encoding(utf8)", "utf8.txt" || die $!; 

while (<$fh_1252>){ print $fh_utf8 $_ }; 

seek($fh_utf8, 0, SEEK_SET); 

# now give $fh_utf8 to the library for transmission 

który wydaje się jak banda dodatkowej pracy . Czy istnieje sposób, aby po prostu przesyłać strumieniowo? Wiem, że mógłbym użyć IO :: Scalar, aby usunąć potrzebę zapisu na dysk, ale nadal musiałbym czytać całość w pamięci. Wygląda na to, że istnieje sposób na przeskanowanie go potokiem, ale nie mam na myśli sposobu, by to zrobić teraz.

+0

Mówisz o perl biblioteki lub braku Perl biblioteka/propgram? Czy mógłbyś nazwać swój system operacyjny (unix/windows)? – AnFi

+1

Uwaga: 'otwórz ...," 1252.txt "|| die $ !; 'oznacza' otwórz ..., ("1252.txt" || die $!); '(który nigdy nie umiera). Chcesz 'otwórz ...,» 1252.txt «lub zgiń $ !;' – ikegami

Odpowiedz

3

Możesz napisać własny moduł konwersji dla PerlIO i używać go z :via(MODULE). Twój moduł może przekazywać dane przez Text::Iconv, aby konwertować z jednego zestawu znaków na inny.

Ten sposób opisany jest w instrukcji obsługi PerlIO::via(3pm). W skrócie, musisz utworzyć własny moduł, np. PerlIO::via::Example -to jest dokonać PerlIO/via katalog i umieścić Example.pm tam, o następującej treści:

package PerlIO::via::Example; 

use strict; 
use warnings; 

use Text::Iconv; 
my $converter = Text::Iconv->new("windows-1252", "utf-8"); 

sub PUSHED 
{ 
    my ($class, $mode, $fh) = @_; 
    # When writing we buffer the data 
    my $buf = ''; 
    return bless \$buf, $class; 
} 

sub FILL 
{ 
    my ($obj, $fh) = @_; 
    my $line = <$fh>; 
    return (defined $line) ? 'converted: ' . $converter->convert($line) : undef; 
    # 'converted: ' is added here for debugging purposes 
} 

sub WRITE 
{ 
    my ($obj,$buf,$fh) = @_; 
    $$obj .= $buf; # we do nothing here 
    return length($buf); 
} 

sub FLUSH 
{ 
    my ($obj, $fh) = @_; 
    print $fh $$obj or return -1; 
    $$obj = ''; 
    return 0; 
} 

1; 

a następnie używać go w open jak tutaj:

use strict; 
use warnings; 

use PerlIO::via::Example; 

open(my $fh, "<:via(Example)", "input.txt"); 
while (<$fh>) { 
    print; 
} 
close $fh; 
+0

Wyglądało na to, że zadziała, ale inżynier pracujący nad tym problemem odpowiedział: "Jego odpowiedź zadziałałaby, gdybyśmy mieli do czynienia z plikiem na lokalnym systemie plików (w jego przykładzie "input.txt"), ale otrzymujemy już otwarty plik filehandle z powrotem z mogilefs, więc nie możemy przekazać go przez nowy moduł PerlIO, który on opisuje. " Niesamowita odpowiedź, dzięki! –

0

Możesz użyć zewnętrznego programu do konwersji pliku wejściowego. Aby uzyskać szczegółowe informacje, patrz perldoc -f open.

open(my $ft, '-|' "iconf -f CP1252 -t UTF-8 1252.txt") || die $!; 

P.S. Istnieją prostsze rozwiązania dla bibliotek Perla. Powyższe jest najbardziej ogólne IMHO.

Powiązane problemy