LINUX.ORG.RU

Vim: корректное определине кодировки файла

 ,


2

2

Иногда попадаются файлы в кодировках cp1251, cp866, koi8r. Как заставить Vim определять их кодировку автоматически?

Пробовал такое:

set fileencodings=utf8,cp1251,cp866,ucs-2le,koi8r

Результаты неудовлетворительные:

Съешь ещё этих мягких французских булок, да выпей же чаю.

файл в cp1251 - кодировка определяется верно
файл в cp866  - кодировка определяется как cp1251
файл в koi8r  - кодировка определяется как cp1251

Предположим, у Вас есть байты:

00000000: f3df c5db d820 c5dd a320 dcd4 c9c8 20cd
00000010: d1c7 cbc9 c820 c6d2 c1ce c3d5 dad3 cbc9
00000020: c820 c2d5 cccf cb2c 20c4 c120 d7d9 d0c5
00000030: ca20 d6c5 20de c1c0 2e0a

Как определить, в какой кодировке этот текст? Это не UTF-8 (в нём есть некорректные многобайтовые последовательности), но любой однобайтовой кодировкой, которая задаёт значения для всех используемых здесь байтов, его можно раскодировать. Да хоть CP-1252: каждому байту соответствует какой-то code point. Почему нет?

(Ответом, наверное, будет частотный анализ и мягкая классификация, но не факт, что Vim будет её делать. Плюс, нужен корпус текстов с известной кодировкой и языком.)

anonymous ()
Ответ на: комментарий от temp_account_123

Задача не решаема.

Кодировка определяется как трактовать коды символов. Например, если в файле записан один байт с кодом 208, то в кодировке CP1251 это должно трактоваться (в частности «рисоваться на экране») как «Р», а в кодировке CP1251 как «Ð». При этом содержимое файла абсолютно идентично.

В некоторых кодировках есть «запрещённые» коды, тогда еще как-то можно угадать. И то, это вариант удачи. Еще учти, что сделано так, что первые 128 кодов почти во всех кодировках значат одно и то же (цифры, буквы латинского алфавита, пунктуация, основные управляющие символы). Здесь кодировку вообще никак не различить.

Kroz ★★★★★ ()
Ответ на: комментарий от Kroz

Но можно немного упростить себе жизнь :)

map <F8> :execute RotateEnc()<CR>

let b:encindex=0
function! RotateEnc()   " сменить кодировку
    let y = -1
    while y == -1
        let encstring = "#8bit-cp1251#8bit-cp866#ucs-2le#utf-8#koi8-r#"
        let x = match(encstring,"#",b:encindex)
        let y = match(encstring,"#",x+1)
        let b:encindex = x+1
        if y == -1
            let b:encindex = 0
        else
            let str = strpart(encstring,x+1,y-x-1)
            return ":e ++enc=".str
        endif
    endwhile
endfunction

function! Mytabtag()

В результате по F8 перебираются кодировки, если автоопределение не помогло. Код народный, ещё с линуксфорума, пока он был жив

ну и до кучи:

set statusline=%<%f%h%m%r%=%({%{&fileformat},%{&fileencoding},%{&encoding}}%)\ %-6(0x%B%)\ %-10(%l,%c%V%)\ %7P

"
" *********
" кодировки
" *********
"
" кодировка _всех_ внутренних буферов
set encoding=utf8
" кодировка для сохранения нового файла
set fileencoding=utf8
" кодировки, перебираемые при автоопределении кодировки
set fileencodings=utf8,koi8-r,cp1251,cp866
" кодировка терминала
"set termencoding=utf8
" кодировка этого скрипта ;o)
scriptencoding utf8

router ★★★★★ ()