【Perl】ファイル名に日本語が含まれる場合の処理

Perlでファイル名に日本語が含まれる場合の処理でハマったので対応方法をメモしておく。

サンプルコード

環境はWindows、言語はPerl、ファイル名は"fileopen.pl"、ファイルのエンコードは"utf8″。対象フォルダにある、ファイル名が"日本語"で始まるファイルを探して、その中身を表示するコードです。

#!/usr/local/bin/perl

# -*- Encoding: UTF-8 -*-

use strict;
use warnings;

use utf8;

use IO::Dir;
use IO::File;

binmode STDIN,  ":encoding(cp932)";
binmode STDOUT, ":encoding(cp932)";
binmode STDERR, ":encoding(cp932)";

my $target_dir = './';
my $prefix     = '日本語';

my $dir = IO::Dir->new($target_dir) or die $!;

if ( defined $dir ) {
    while ( my $file = $dir->read ) {
        next if $file =~ /^\./;

        print "対象フォルダ\"$target_dir\"に[$file]というファイルが見つかりました.\n";

        if ( $file =~ /^$prefix/ ) {
            print "[$file]はファイル名が\"$prefix\"で始まるので中身を表示します.\n";

            my $fh = IO::File->new( "$target_dir$file", '<:encoding(cp932)' )
              or die $!;

            print "-- ここから --\n";

            while ( my $line = $fh->getline ) {
                print $line;
            }

            print "\n-- ここまで --\n";

            $fh->close;
        }
    }
}

exit;

__END__

開きたいファイルは"日本語のファイル名.txt"、ファイルのエンコードは"cp932″です。中身は「あいうえお」。

このまま実行すると下のようになる。

デコードして文字化けを回避する

日本語が含まれるファイル名に対して何かしら処理をする前にデコードしておかないといけない。「$file = decode( 'cp932’, $file );」のようにファイル名をデコードする命令を追加する。decode関数を使うために「use Encode qw(decode);」も追加してモジュールをロードする。

とりあえず文字化けはしなくなった。

エンコードしてファイルを開く

ファイルをオープンする前にエンコードしないといけなかった。「$file = encode( 'cp932’, $file );」のようにファイル名をエンコードする命令を追加する。encode関数を使うために「use Encode qw(decode encode);」のようにuse文を変更する。

目的通りの動きをしてくれるようになりました。最終的なコードは下記のとおり。

#!/usr/local/bin/perl

# -*- Encoding: UTF-8 -*-

use strict;
use warnings;

use utf8;
use Encode qw(decode encode);

use IO::Dir;
use IO::File;

binmode STDIN,  ":encoding(cp932)";
binmode STDOUT, ":encoding(cp932)";
binmode STDERR, ":encoding(cp932)";

my $target_dir = './';
my $prefix     = '日本語';

my $dir = IO::Dir->new($target_dir) or die $!;

if ( defined $dir ) {
    while ( my $file = $dir->read ) {
        next if $file =~ /^\./;

        $file = decode( 'cp932', $file );

        print "対象フォルダ\"$target_dir\"に[$file]というファイルが見つかりました.\n";

        if ( $file =~ /^$prefix/ ) {
            print "[$file]はファイル名が\"$prefix\"で始まるので中身を表示します.\n";

            $file = encode( 'cp932', $file );

            my $fh = IO::File->new( "$target_dir$file", '<:encoding(cp932)' )
              or die $!;

            print "-- ここから --\n";

            while ( my $line = $fh->getline ) {
                print $line;
            }

            print "\n-- ここまで --\n";

            $fh->close;
        }
    }
}

exit;

__END__

過去の同じ日の記事一覧


Willi HeidelbachによるPixabayからの画像を使用しています。