Как я создаю затем использование длинные пути Windows от Perl?

Немного фона здесь....

Никакая система счисления не может обработать все вещественные числа точно. У всех есть их ограничения, и это включает обоих стандартная плавающая точка IEEE и подписанное десятичное число. Плавающая точка IEEE более точна на используемый бит, но это не имеет значения здесь.

Финансовые числа основаны на веках практики бумаги-и-пера со связанными конвенциями. Они довольно точны, но что еще более важно, они восстанавливаемы. Два бухгалтера, работающие с различными числами и уровнями, должны придумать то же число. Любая комната для несоответствия является комнатой для мошенничества.

Поэтому для финансовых вычислений, правильный ответ - то, что дает тот же ответ как CPA, кто способен к арифметике. Это - десятичная система счисления, не плавающая точка IEEE.

19
задан brian d foy 7 January 2013 в 12:48
поделиться

5 ответов

Ход выполнения:

Следующий сценарий работает: он записывает строку в файл в каталоге с длинным путем и может считывать ту же строку. (При успешном запуске консоль не выводится). Я также предпринял громоздкую попытку переопределить open .

#!/usr/bin/perl

use strict;
use warnings;

use Carp;
use Encode qw( encode );
use Symbol;

use Win32;

use Win32API::File qw(
    CreateFileW OsFHandleOpen
    FILE_GENERIC_READ FILE_GENERIC_WRITE
    OPEN_EXISTING CREATE_ALWAYS FILE_SHARE_READ
);

use Win32::API;
use File::Spec::Functions qw(catfile);

Win32::API->Import(
    Kernel32 => qq{BOOL CreateDirectoryW(LPWSTR lpPathNameW, VOID *p)}
);

my %modes = (
    '<' => {
        access => FILE_GENERIC_READ,
        create => OPEN_EXISTING,
        mode   => 'r',
    },
    '>' => {
        access => FILE_GENERIC_WRITE,
        create => CREATE_ALWAYS,
        mode   => 'w',
    },
    # and the rest ...
);

use ex::override open => sub(*;$@) {
    $_[0] = gensym;

    my %mode = %{ $modes{$_[1]} };

    my $os_fh = CreateFileW(
        encode('UCS-2le', "$_[2]\0"),
        $mode{access},
        FILE_SHARE_READ,
        [],
        $mode{create},
        0,
        [],
    ) or do {$! = $^E; return };

    OsFHandleOpen($_[0], $os_fh, $mode{mode}) or return;
    return 1;
};

my $path = '\\\\?\\' . Win32::GetLongPathName($ENV{TEMP});
my @comps = ('0123456789') x 30;

my $dir = mk_long_dir($path, \@comps);
my $file = 'test.txt';
my $str = "This is a test\n";

write_test_file($dir, $file, $str);

$str eq read_test_file($dir, $file) or die "Read failure\n";

sub write_test_file {
    my ($dir, $file, $str) = @_,

    my $path = catfile $dir, $file;

    open my $fh, '>', $path
        or croak "Cannot open '$path':$!";

    print $fh $str or die "Cannot print: $!";
    close $fh or die "Cannot close: $!";
    return;
}

sub read_test_file {
    my ($dir, $file) = @_,

    my $path = catfile $dir, $file;

    open my $fh, '<', $path
        or croak "Cannot open '$path': $!";

    my $contents = do { local $/; <$fh> };
    close $fh or die "Cannot close: $!";
    return $contents;
}

sub mk_long_dir {
    my ($path, $comps) = @_;

    for my $comp ( @$comps ) {
        $path = catfile $path, $comp;
        my $ucs_path = encode('UCS-2le', "$path\0");
        CreateDirectoryW($ucs_path, undef)
            or croak "Failed to create directory: '$path': $^E";
    }
    return $path;
}

Использование Win32 :: GetANSIPathName () со встроенным open не работает: Путь возвращено слишком долго.

См. историю изменений неудачных экспериментов.

9
ответ дан 30 November 2019 в 04:59
поделиться

Следующий код фактически создает довольно глубокую (более 260 символов) структуру каталогов. По крайней мере, на моей машине:

use Win32::API;

$cd = Win32::API->new('kernel32', 'CreateDirectoryW', 'PP', 'N');

$dir = '\\\\?\\c:\\!experiments';

$res = 1;

do
{
    print 'path length: ' . length($dir) . "\n";
    $dirname = pack('S*', unpack('C*', "$dir\0"));  #dirty way to produce UTF-16LE string

    $res = $cd->Call($dirname, 0);
    print "$res\n";

    $dir .= '\\abcde';

} while ( $res );
6
ответ дан 30 November 2019 в 04:59
поделиться

Я понимаю, что это не решение вашей конкретной проблемы. Однако существует множество сценариев, в которых возможность сопоставить очень длинный путь с буквой диска позволит обойти проблему и, следовательно, будет полезна при работе с очень длинными именами путей без необходимости преодолевать множество Код и документация для Windows.

Несмотря на все усилия, которые я приложил, чтобы выяснить, как это сделать, я собираюсь как-то порекомендовать использовать SUBST . Win32 :: FileOp предоставляет Subst и Unsubst . Затем вы можете сопоставить рабочий каталог верхнего уровня с неиспользуемой буквой диска (которую можно найти с помощью Substed ). Я бы начал проверять с Z и работать в обратном направлении.

Или вы можете раскошелиться,

2
ответ дан 30 November 2019 в 04:59
поделиться

Это действительно должен быть комментарий, но размещение кода в комментариях вряд ли полезно.

Пути UNC тоже не работают:

C:\> net share
perlbuild    e:\home\src
#!/usr/bin/perl

use strict;
use warnings;

use File::Path qw(make_path);
use File::Slurp;
use Path::Class;

my $top = dir('//Computer/perlbuild');
my @comps = ('0123456789') x 30;

my $path = dir($top, @comps);

make_path $path, { verbose => 1 };

my $file = file($path, 'test.txt');

write_file "$file" => 'This is a test';

print read_file "$file";

Результат:

mkdir \\Computer\perlbuild\0123456789\0123456789\0123456789\0123456789\0123456
789\0123456789\0123456789\0123456789\0123456789\0123456789\0123456789\0123456789
\0123456789\0123456789\0123456789\0123456789\0123456789\0123456789\0123456789\01
23456789\0123456789: No such file or directory; The filename or extension is too
 long at C:\Temp\k.pl line 15
2
ответ дан 30 November 2019 в 04:59
поделиться

У меня было три мысли, все они вроде хаков:

  1. Начать с коротких имен каталогов (C: \ data_directory \ a \ b \ c \ d \ 4 \ 5 \ 6 \ ...), а затем переименуйте каталоги (начиная, конечно, с самого глубокого каталога).

  2. Создать ярлык Windows для умеренно длинного пути и создавать файлы и подкаталоги оттуда? (Или установить Cygwin и использовать символические ссылки?)

  3. Создайте нужные файлы в каталоге с коротким именем, заархивируйте их / tar и распакуйте в каталог с более длинным именем. Или создайте zip / tar-файлы «вручную» и распакуйте их в нужное место.

-1
ответ дан 30 November 2019 в 04:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: