1 (изменено: Resager, 2012-10-18 13:22:10)

Тема: AHK: Как определить кодировку?

Скачиваю файл с HTTP, не знаю почему, но время от времени кодировка файла меняется (ссылка на файл одна и та же, кодировка то CP1251, то UTF-8). Собственно возникла проблема, как определить кодировку файла?
Такие методы не помогают:

FileEncoding, UTF-8
FileRead, VAR, ...

потому как если файл в CP1251, то при попытке открыть его как UTF-8 и потом ещё и сохранить в cp1251, символы русские просто пропускаются.

2 (изменено: Александр_, 2012-10-18 13:26:11)

Re: AHK: Как определить кодировку?

У UTF-8 есть специальная сигнатура(BOM)- 0xEF-0xBB-0xBF.

3 (изменено: Resager, 2012-10-18 14:10:45)

Re: AHK: Как определить кодировку?

Александр_ пишет:

У UTF-8 есть специальная сигнатура(BOM)- 0xEF-0xBB-0xBF.

Файл этот UTF-8 без BOM. Даже Filec.Encoding возвращает CP1251. Однако при чтении, как только дело до русских букв доходит, то появляются кракозябры.

Хм... так. Зато можно встретить эту сигнатуру посередине файла. Теперь проблема с кодировкой решена.

4 (изменено: Александр_, 2012-10-18 14:16:35)

Re: AHK: Как определить кодировку?

Resager пишет:

Файл этот UTF-8 без BOM. Даже Filec.Encoding возвращает CP1251. Однако при чтении, как только дело до русских букв доходит, то появляются кракозябры.

Это плохо, тогда только по косвенным признакам. Можно проверить файл на неиспользуемые UTF-8 байты, но на этот тест я бы полагаться не стал. Надёжнее будет частотный анализ, исходя из предполагаемого содержимого файла(русско-английский текст, xml-файл, tex-документ и т.д.) можно оценить вероятность каждой из кодировок. Правда это не самый быстрый путь, но универсальный.

Resager пишет:

Хм... так. Зато можно встретить эту сигнатуру посередине файла.

Может там несколько файлов, склеенных в один или перед файлом идёт какой-то пролог?

5

Re: AHK: Как определить кодировку?

Александр_ пишет:

Написал небольшой скрипт (впрочеим он не находит нужного)

#Include consolesender.ahk 

testUTFSignatyre(teststring)
{
    flagIsPreUTF := 0
    flagIsUTF := 0    
    Loop, parse, teststring
    {
        Transform, CharCode, Asc, %A_LoopField%
        console(CharCode . A_Tab . A_LoopField)
        if (CharCode=239)
        {
            flagIsPreUTF := 0
            ;msgbox, %A_LoopField%
        }
        if (flagIsPreUTF=1)
            if (CharCode=187)
                flagIsPreUTF := 1
        if (flagIsPreUTF=2)
            if (CharCode=191)
                flagIsUTF := 1
        if (flagIsUTF=1)
            return 1
    }
    return 0
}
filename := "catpage.html"
    console("====Читаем файл")
    FileRead, file, % filename
    console("=====Проверяем кодировку на UTF-8")
    rezulcode := testUTFSignatyre(file)
    if(rezulcode=1)
        console("UTF-8")
    else
        console("CP1251")
    msgbox, %rezulcode%

На строку:

<title>Основные темы для контакта -  это оформления,  которым не нашлось место в других категориях</title>

Начал выводить это (моя консолька, корявая выводит так)

[17:53:51:437] ====Читаем файл
[17:53:51:921] =====Проверяем кодировку на UTF-8
[17:53:52:359] 60 <
[17:53:53:093] 116 t
[17:53:53:562] 105 i
[17:53:54:156] 116 t
[17:53:54:625] 108 l
[17:53:55:093] 101 e
[17:53:55:640] 62 >
[17:53:56:156] 208 Р
[17:53:56:625] 158 ћ
[17:53:57:125] 209 С
[17:53:57:593] 129 Ѓ
[17:53:58:078] 208 Р
[17:53:58:515] 189 Ѕ
[17:53:59:093] 208 Р
[17:53:59:578] 190 ѕ
[17:54:00:062] 208 Р
[17:54:00:484] 178 І
[17:54:01:031] 208 Р
[17:54:01:546] 189 Ѕ
[17:54:02:062] 209 С
[17:54:02:484] 139 ‹
[17:54:02:937] 208 Р
[17:54:03:406] 181 µ

Как видим, БОМ нет Как определить такой файл и не знаю (поторопился, скзав что нет пробем)

6

Re: AHK: Как определить кодировку?

Resager пишет:
Александр_ пишет:

Написал небольшой скрипт (впрочеим он не находит нужного)

я этого не писал .

Resager пишет:

Как видим, БОМ нет Как определить такой файл и не знаю (поторопился, скзав что нет пробем)

Есть возможно прикрепить к сообщению пример тестируемого файла? А лучше несколько примеров .

7

Re: AHK: Как определить кодировку?

Resager пишет:

Скачиваю файл с HTTP...

Кстати говоря, там в поле "Content-Type" заголовка кодировка не указана?

8 (изменено: Resager, 2012-10-19 11:50:58)

Re: AHK: Как определить кодировку?

Александр_ пишет:
Resager пишет:

Скачиваю файл с HTTP...

Кстати говоря, там в поле "Content-Type" заголовка кодировка не указана?

Указана, text/html; charset=UTF-8 но как это глянуть то? Скачиваю я через UrlDownloadToFile

Александр_ пишет:

я этого не писал

Рабочий день заканчивался, меня с работы выгоняли. Торопился


Александр_ пишет:

Есть возможно прикрепить к сообщению пример тестируемого файла? А лучше несколько примеров

Прикрепил.

Нашел вот такую информацию в википедии:

Текст, состоящий только из символов Юникода с номерами меньше 128, при записи в UTF-8 превращается в обычный текст ASCII. И наоборот, в тексте UTF-8 любой байт со значением меньше 128 изображает символ ASCII с тем же кодом. Остальные символы Юникода изображаются последовательностями длиной от 2 до 6 байт (реально только до 4 байт, поскольку использование кодов больше 221 не планируется), в которых первый байт всегда имеет вид 11xxxxxx, а остальные — 10xxxxxx.
Проще говоря, в формате UTF-8 символы латинского алфавита, знаки препинания и управляющие символы ASCII записываются кодами US-ASCII, a все остальные символы кодируются при помощи нескольких байтов со старшим битом 1. Это приводит к двум эффектам.

Значит, вероятно можно запускать проверку старших битов каждого байта/кода символа. (что однако проблематично, с точки зрения быстродействия). Можно однако после первого найденого такого символа сразу конвертировать файл.
К примеру, символ скобки, закодированный как 0x3C ("<") в двоичной выглядит так: 00111100
А символ (кирилица) ("О")/UTF-8 или ("Рћ")/ASCII с кодом 0xD0 & 0x9E имеет двоичный код такой 11010000 & 10011110
А символ (кирилица) ("с")/UTF-8 или ("СЃ")/ASCII с кодом 0xD1 & 0x81 имеет двоичный код такой 11010001 & 10000001
Как можно заметить, первый байт есть ни что иное, как русские символы "Р" и "С". Так что на них ориентироваться нельзя, можно попробовать отслеживать "кроказябры", идущие после Наших "Р" и "С" (коды их 208 и 209 DEC).
...
Все же необходимо знать кодировку.
Узнать Http заголовок можно с помощью функции, ОТСЮДА
Ну Регулярное выражение что бы достать кодировку, можно задать как-то так:

Content-Type\:(?!charset).*?charset=(.*?)$
Post's attachments

example.zip 7.95 kb, 3 downloads since 2012-10-19 

You don't have the permssions to download the attachments of this post.

9 (изменено: Александр_, 2012-10-19 14:59:13)

Re: AHK: Как определить кодировку?

Здесь мы уже работали с сокетами, в данном случае можно тоже воспользоваться.
Из приложенного примера:
1) 16-ая строка закомментирована, т.е. скорее всего тупо забыта и будет присутствовать постоянно "// // alert("Нехватает "+(themeCost-money)+" рейтинга");", там есть русские буквы, можно по ним проверить кодировку. Там много строк, которые кажутся постоянными.
2) Строка 27- "<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">".

Как можно заметить, первый байт есть ни что иное, как русские символы "Р" и "С". Так что на них ориентироваться нельзя, можно попробовать отслеживать "кроказябры", идущие после Наших "Р" и "С" (коды их 208 и 209 DEC).

Нужно искать константы, которые занимают несколько байт в юникоде или исследовать частоты. Если в строке на русском языке много крокозябр(неалфавитных символов) или слишком много букв "С" и "Р"(гласные "о", "а", "е", "и" и согласные "н", "т" встречаются чаще чем любая из них).

10

Re: AHK: Как определить кодировку?

Александр_ пишет:

Здесь мы уже работали с сокетами, в данном случае можно тоже воспользоваться.
Из приложенного примера:
1) 16-ая строка закомментирована, т.е. скорее всего тупо забыта и будет присутствовать постоянно "// // alert("Нехватает "+(themeCost-money)+" рейтинга");", там есть русские буквы, можно по ним проверить кодировку. Там много строк, которые кажутся постоянными.
2) Строка 27- "<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">".

Как можно заметить, первый байт есть ни что иное, как русские символы "Р" и "С". Так что на них ориентироваться нельзя, можно попробовать отслеживать "кроказябры", идущие после Наших "Р" и "С" (коды их 208 и 209 DEC).

Нужно искать константы, которые занимают несколько байт в юникоде или исследовать частоты. Если в строке на русском языке много крокозябр(неалфавитных символов) или слишком много букв "С" и "Р"(гласные "о", "а", "е", "и" и согласные "н", "т" встречаются чаще чем любая из них).

Благодарю за помощь.