Давайте посмотрим, вы указали второй аргумент открытой функции следующим образом:
open my $fh, ">:via(File::BOM):encoding(UTF-8)", $file or die "Cannot open $file: $!";
Здесь вы указываете сначала :via(File::BOM) и :encoding(UTF-8)",
Затем выходная строка будет обрезана посередине.
Следующий сценарий пытается вывести текстовый файл UTF-8 со спецификацией: Содержимое должно представлять собой объединение строк от «xxx yyyy1» до «xxx yyyy100» с увеличением конечного номера и разделением символами «/».
#!/usr/bin/perl
# bomTest.pl
use strict;
use warnings;
use File::BOM;
use feature 'say';
my $file = '/home/cf/Desktop/foo.txt';
open my $fh, ">:via(File::BOM):encoding(UTF-8)", $file or die "Cannot open $file: $!";
say $fh 'xxx yyyy1 / xxx yyyy2 / xxx yyyy3 / xxx yyyy4 / xxx yyyy5 / xxx yyyy6 / xxx yyyy7 / xxx yyyy8 / xxx yyyy9 / xxx yyyy10 / ' .
'xxx yyyy11 / xxx yyyy12 / xxx yyyy13 / xxx yyyy14 / xxx yyyy15 / xxx yyyy16 / xxx yyyy17 / xxx yyyy18 / xxx yyyy19 / xxx yyyy20 / ' .
... snip ...
'xxx yyyy71 / xxx yyyy72 / xxx yyyy73 / xxx yyyy74 / xxx yyyy75 / xxx yyyy76 / xxx yyyy77 / xxx yyyy78 / xxx yyyy79 / xxx yyyy80 / ' .
'xxx yyyy81 / xxx yyyy82 / xxx yyyy83 / xxx yyyy84 / xxx yyyy85 / xxx yyyy86 / xxx yyyy87 / xxx yyyy88 / xxx yyyy89 / xxx yyyy90 / ' .
'xxx yyyy91 / xxx yyyy92 / xxx yyyy93 / xxx yyyy94 / xxx yyyy95 / xxx yyyy96 / xxx yyyy97 / xxx yyyy98 / xxx yyyy99 / xxx yyyy100';
close $fh;
Выходной файл foo.txt будет представлять собой файл UTF-8 со спецификацией (0x EF BB BF) в верхней части файла, но строка будет завершена в середине, как показано ниже:
xxx yyyy1 / xxx yyyy2 / xxx yyyy3 / xxx yyyy4 / xxx yyyy5 / xxx yyyy6 / xxx yyyy7 / xxx yyyy8 / xxx yyyy9 / xxx yyyy10 / xxx yyyy11 / xxx yyyy12 / xxx yyyy13 / xxx гггг14 / ххх гггг15 / ххх гггг16 / ххх гггг17 / xxx yyyy18 / xxx yyyy19 / xxx yyyy20 / ...snip... xxx yyyy71 / xxx yyyy72 / xxx yyyy73 / xxx yyyy74 / xxx yyyy75 / xxx yyyy76 / xxx yyyy77 / xxx yyyy78 / xxx 79 / ххх гг
Вывод останавливается в середине «xxx yyyy80».
Теперь, если вы измените скрипт следующим образом:
open my $fh, ">:encoding(UTF-8):via(File::BOM)", $file or die "Cannot open $file: $!";
Измененная точка — это порядок уровня ввода-вывода. Вы указали :encoding(UTF-8) первым и :via(File::BOM) последним.
Затем сценарий полностью запускается до «xxx yyyy100».
Что это за явление?
Это ошибка кодировки Perl?
Или еще модуль File::BOM?
Или это их разумная спецификация?





Ответ уже в вопросе: Вы использовали ">:via(File::BOM):encoding(UTF-8)" тогда, когда следовало использовать ">:encoding(UTF-8):via(File::BOM)".
Из документов,
Добавьте слой via(File::BOM) поверх слоя кодировки Юникода, чтобы напечатать спецификацию в начале выходного файла. Это необходимо сделать до записи каких-либо данных. Спецификация записывается как часть первой команды печати в дескрипторе, поэтому, если вы ничего не печатаете в дескрипторе, вы не получите спецификацию.
Непонятно, какой слой находится поверх другого слоя, но пример проясняет это.
# Writing little-endian UTF-16 file with BOM: open(HANDLE, '>:encoding(UTF-16LE):via(File::BOM)', $filename)
Ошибка ваша. Это случай ГИГО.
Во всех примерах в документации сначала задается кодировка, и там говорится, что слой перехода должен быть поверх одного.