我有一个构建过程的一部分,在Windows中创建一个可怕的长路径.这不是我的错.这是几个目录深,没有一个目录名异常长; 它们只是很长很多,足以让它完成MAX_PATH(260个字符).我在这些名称中没有使用除ASCII以外的任何东西.
最大的问题是,在目标期间,爆炸发生在Module :: Build的内部深处dist,尽管我认为构建系统无关紧要,因为它们会创建相同的目录.
创建其中一个过长的目录File::Path失败:
use File::Path qw( make_path );
make_path( 'C:\\.....' ); # fails if path is over 260 chars
Run Code Online (Sandbox Code Playgroud)
类似地,一旦绝对路径结束,手动构建每个目录级别就会失败MAX_PATH.
这不是新的,不是Perl的错,而且Microsoft在命名文件,路径和命名空间中记录它.他们的修复建议\\?\在任何路径前添加访问Unicode文件名API.但是,这似乎不是Perl脚本的完整修复,因为它仍然失败:
use File::Path qw( make_path );
make_path( '\\\\?\\C:\\.....' ); # still fails if path is over MAX_PATH, works otherwise
Run Code Online (Sandbox Code Playgroud)
这可能是因为make_path拉开了它的参数,然后一次一个级别地遍历目录,所以\\?\只适用于顶层,这是在其中MAX_PATH.
我向ActiveState挖出了一个错误报告,表明我还需要修改一些其他内容来获取Unicode文件名,而Jan Dubois在Re 2:Windows 2K/XP上的"长"文件名中提供了更多细节,尽管我是不确定它是否适用(并且非常古老).perlrun提到这个用途是转换的工作-C,但显然这部分被放弃了.perl RT队列有一个更新的错误60888:Win32:支持文件名中的完整unicode(使用Wide-system调用). …
Windows控制台至少可以识别十年,并且可能早在Windows NT上.但是由于某些原因,主要的跨平台脚本语言(包括Perl和Python)只输出各种8位编码,因此需要很多麻烦才能解决.Perl给出了"打印中的宽字符"警告,Python给出了一个charmap错误并退出.为什么在这么多年之后它们不仅仅是简单地调用输出UTF-16 Unicode的Win32 -W API而不是通过ANSI /代码页瓶颈强制一切?
仅仅是跨平台性能是低优先级吗?这些语言是否在内部使用UTF-8并且发现输出UTF-16太麻烦了?或者-WAP本身是否破坏到不能按原样使用的程度?
UPDATE
似乎责任可能需要各方共同承担责任.我想象脚本语言只能wprintf在Windows上调用,让操作系统/运行时担心重定向等问题.但事实证明,即使是Windows上的wprintf,也会在打印到控制台之前将宽字符转换为ANSI并返回!
如果这个问题已得到解决,请告诉我,因为错误报告链接似乎已损坏但我的Visual C测试代码仍然无法用于wprintf并成功用于WriteConsoleW.
更新2
实际上,您可以使用C语言将UTF-16打印到控制台,wprintf但前提是这样做_setmode(_fileno(stdout), _O_U16TEXT).
从C你可以将UTF-8打印到一个控制台,其代码页设置为代码页65001,但Perl,Python,PHP和Ruby都有防止这种情况的错误.Perl和PHP通过在包含至少一个宽字符的行之后添加额外的空行来破坏输出.Ruby的损坏输出略有不同.Python崩溃了.
更新3
Node.js是第一个没有出现此问题的脚本语言.
Python开发团队慢慢意识到这是一个真正的问题,因为它是在2007年底首次报道的,并且已经看到了大量的活动,以完全理解并完全修复2016年的错误.
我正在努力创建一个包含非ascii字符的文件.
以下脚本工作正常,如果使用0as参数调用但在调用时死亡1.
错误消息已打开:C:\ temp\filename.pl第15行的参数无效.
该脚本在内部启动cmd.exe.
我希望它能写出一个名字相同的文件(取决于参数)äöü.txt或äöü?.txt.但我无法创建包含笑脸的文件名.
use warnings;
use strict;
use Encode 'encode';
# Text is stored in utf8 within *this* file.
use utf8;
my $with_smiley = $ARGV[0];
my $filename = 'äöü' .
($with_smiley ? '?' : '' ).
'.txt';
open (my $fh, '>', encode('cp1252', $filename)) or die "open: $!";
print $fh "Filename: $filename\n";
close $fh;
Run Code Online (Sandbox Code Playgroud)
我可能错过了一些对他人来说很明显的东西,但是我找不到,所以我很欣赏任何解决这个问题的指针.
我有以下代码
use utf8;
open($file, '>:encoding(UTF-8)', "?????.txt") or die $!;
print $file "?????";
Run Code Online (Sandbox Code Playgroud)
但我得到的文件名为ã•ã,ã°,".",".txt
我想知道是否有一种方法可以让我的工作正如我所期望的那样(意思是我有一个unicode文件名),而不需要使用Win32 :: API,Win32API ::*或移动到另一个平台并使用Samba共享来修改文件.
目的是确保我们没有任何需要加载的Win32特定模块(甚至是有条件的).
我很难创建包含Unicode的目录名.我在Windows XP和Perl Camelbox 5.10.0上.
到目前为止,我曾经use File::Path qw ( make_path )创建过目录 - 在第一个西里尔文目录出现之前一直运行良好.
Win32API::File qw ( CreateFileW )如果文件名是UTF-16LE编码,文件工作正常.目录有类似的东西吗?或者也许是一个参数来告诉CreateFileW创建Unicode路径,如果它不存在?
谢谢,
尼尔
我正在编写一个脚本来批量重命名和复制基于csv文件的图像.csv由第1列组成:旧名称和第2列:新名称.我想使用csv文件作为perl脚本的输入,以便它检查旧名称并使用新名称将副本复制到新文件夹中.(我认为)我与图像有关的问题.它们包含像ß等utf8字符.当我运行脚本时,它打印出来:Barfu├ƒg├ñsschen它应该是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.
Run Code Online (Sandbox Code Playgroud)
我知道它与Binmode utf8有关,但即使我尝试一个简单的脚本(在这里看到它:如何从Perl输出UTF-8?):
use strict;
use utf8;
my $str = 'Çirçös';
binmode(STDOUT, ":utf8");
print "$str\n";
Run Code Online (Sandbox Code Playgroud)
它打印出来:Ã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 …Run Code Online (Sandbox Code Playgroud)