Сообщение об ошибке довольно расплывчато, но я думаю, что его огорчает тот факт, что в строке найдено нечетное число байтов, поскольку каждый символ в UTF-16 равен двум (или иногда четырем)байт.И я думаю, что причиной того, что является использование вами gets
- строки в вашем файле разделены символом новой строки UTF-16le, который равен 0x0a 0x00
, но gets
разделяется на (и strip
удаляет) 0x0a
только.
Для иллюстрации: предположим, что файл содержит
ab
cd
, закодированный в UTF-16le.Это
0x61 0x00 0x62 0x00 0x0a 0x00 0x63 0x00 0x64 0x00 0x0a 0x00
a b \n c d \n
gets
читает до первого 0x0a
, который strip
удаляет, поэтому первое чтение строки равно 0x61 0x00 0x62 0x00
, которое iconv с радостью принимает и кодирует в UTF-8 как 0x61 0x62
- «ab».gets
затем читает до следующего 0x0a
, который strip
снова удаляет, поэтому во второй раз line
получает 0x00 0x63 0x00 0x64 0x00
, и теперь все облажается - мы синхронизированы на один байт, и естьнечетное количество байтов для преобразования, и iconv
взрывается, потому что это несовместимо с тем, что вы просили его сделать.
В отсутствие фактического рабочего слоя кодирования / декодирования файлов, я думаю, что вы хотите изменить *Разделитель 1031 * от "\n"
("\x0a"
) до "\x0a\x00"
, откажитесь от любого использования strip
, поскольку он не является чистым для кодирования, и используйте print
вместо puts
, чтобы не добавлять лишнюю строку-концы (поскольку вы будете конвертировать уже имеющиеся).
Если вы работаете с файлами Windows, CRLF для Windows в UTF-16le будет "\x0d\x00\x0a\x00"
.