【问题标题】:Copy/rename images with utf8 names using csv file使用 csv 文件复制/重命名具有 utf8 名称的图像
【发布时间】:2012-11-11 19:24:14
【问题描述】:

我正在编写一个脚本来批量重命名和复制基于 csv 文件的图像。 csv 由第 1 列:旧名称和第 2 列:新名称组成。我想使用 csv 文件作为 perl 脚本的输入,以便它检查旧名称并使用新名称将副本复制到新文件夹中。 (我认为)我遇到的问题与图像有关。它们包含 utf8 字符,如 ß 等。当我运行脚本时,它会打印出:Barfu├ƒg├ñsschen where it should be Barfußgässchen 和以下错误:

Unsuccessful stat on filename containing newline at C:/Perl64/lib/File/Copy.pm line 148, <$INFILE> line 1.
Copy failed: No such file or directory at X:\Script directory\correction.pl line 26, <$INFILE> line 1.

我知道这与 Binmode utf8 有关,但即使我尝试了一个简单的脚本(在这里看到它:How can I output UTF-8 from Perl?):

use strict;
use utf8;
my $str = 'Çirçös';
binmode(STDOUT, ":utf8");
print "$str\n";

它打印出这个:Ãirþ÷s

这是我的整个脚本,有人可以向我解释我哪里出错了吗? (它不是最干净的代码,因为我正在测试东西)。

use strict;
use warnings;
use File::Copy;
use utf8;

my $inputfile  = shift || die "give input!\n";
#my $outputfile = shift || die "Give output!\n";

open my $INFILE,  '<', $inputfile   or die "In use / not found :$!\n";
#open my $OUTFILE, '>', $outputfile  or die "In use / not found :$!\n";

binmode($INFILE, ":encoding(utf8)");

#binmode($OUTFILE, ":encoding(utf8)");

while (<$INFILE>) {
s/"//g;
my @elements = split /;/, $_;

my $old = $elements[1];
my $new = "new/$elements[3]";
binmode STDOUT, ':utf8';
print "$old | $new\n";

copy("$old","$new") or die "Copy failed: $!";
#copy("Copy.pm",\*STDOUT);

#   my $output_line = join(";", @elements);
#    print $OUTFILE $output_line;
#print "\n"
}

close $INFILE;
#close $OUTFILE;

exit 0;

【问题讨论】:

  • 关于你的第一个 sn-p:.pl 文件本身是用 utf8 编码的吗? use utf8 pragma 告诉 Perl 你的源代码是用 utf8 编写的。它与数据无关。
  • 您要将输出打印到哪里?一个Linux外壳?另外,你是如何创建文件的?
  • 我可以确认您的第一个 sn-p 在我的 Linux shell 上运行良好,LANG 设置为 en_GB.UTF-8,Putty 设置为 UTF-8。我在同一个 shell 中使用 VIM 创建了文件。
  • @Fuzzyfelt 如果这就是你的意思,我正在使用 Windows 系统。我手动创建了 csv 文件。在目录上做了一个 dir 命令并在 excel 中打开它。我还在同一个文件中创建了新名称。

标签: perl csv utf-8


【解决方案1】:

您需要确保流程的每一步都使用 UTF-8。

当您创建输入 CSV 时,您需要确保它保存为 UTF-8,最好没有 BOM。 Windows 记事本将添加 BOM,因此请尝试使用 Notepad++,它可以让您更好地控制编码。

您还遇到 Windows 控制台默认不兼容 UTF-8 的问题。见Unicode characters in Windows command line - how?。使用chcp 65001 设置代码页或不更改STDOUT 编码。

就您的代码而言,关于新行的第一个错误可能是由于 CSV 中的尾随新行。在while (&lt;$INFILE&gt;) {之后添加chomp()

更新:

要“解决”您需要在正确的语言环境中对文件名进行编码的文件 - 请参阅 How do you create unicode file names in Windows using PerlWhat is the universal way to use file I/O API with unicode filenames?。假设您使用的是 Western 1252 / Latin,这意味着您的复制命令将如下所示:

copy(encode("cp1252", $old), encode("cp1252", $new))

此外,您的 open 还应该对文件名进行编码:

open my $INFILE,  '<', encode("cp1252", $inputfile)

更新 2:

当您在 DOS 窗口中运行时,删除 binmode(STDOUT, ":utf8"); 并保留默认代码页。

【讨论】:

  • 我在 notepad++ 中将 CSV 创建为没有 BOM 的 utf8,所以不应该这样。我正在检查你现在给我的另外 2 条建议。
  • while (&lt;$INFILE&gt;) { 之后添加chomp; 可以解决第一个错误。首先设置代码页然后再次尝试脚本不会改变任何内容。我仍然收到消息复制失败。我打印旧名称和新名称,您可以看到旧名称不正确,这就是它与实际文件不匹配并失败的原因
猜你喜欢
  • 2021-10-02
  • 2021-12-04
  • 2014-06-01
  • 2018-11-30
  • 2011-01-27
  • 1970-01-01
  • 2014-02-07
  • 2015-03-17
  • 2014-01-22
相关资源
最近更新 更多