1 (изменено: serzh82saratov, 2013-07-21 18:35:20)

Тема: AHK: Извлечь символы utf-8

Встретил в файле резервной копии телефонных контактов, такие строки:

N;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D1=8C=D1=8F;;;;

Очевидно что в строке

=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D1=8C=D1=8F

содержится имя контакта. Думал извлечь таким кодом:

 
str = D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D1=8C=D1=8F

Loop, parse, str, =
    res .= chr("0x" A_LoopField) 
MsgBox % res 

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

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

2 (изменено: YMP, 2013-07-21 20:34:55)

Re: AHK: Извлечь символы utf-8

Вот так можно:


str = D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D1=8C=D1=8F

VarSetCapacity(buf, StrLen(str) // 3 + 1, 0)

Loop, parse, str, =
    NumPut("0x" A_LoopField, buf, A_Index - 1, "UChar")

MsgBox % StrGet(&buf, "UTF-8") 

3

Re: AHK: Извлечь символы utf-8

YMP
Спасибо!
Не могли бы Вы объяснить построчно? Я совершенно незнаком с VarSetCapacity и NumPut.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

4

Re: AHK: Извлечь символы utf-8

VarSetCapacity создаёт переменную заданного размера. NumPut пишет числа в память. В данном случае эти числа являются кодами символов в кодировке UTF-8, точнее половинками кодов, т.к. русские буквы кодируются двумя байтами. Коды английских букв там такие же, как в ANSI и однобайтные. Так что строка английского текста в перекодировке в UTF-8 и обратно не нуждается.

5 (изменено: serzh82saratov, 2013-07-21 21:19:11)

Re: AHK: Извлечь символы utf-8

VarSetCapacity создаёт переменную заданного размера.

Почему количество символов надо делить на 3 + 1? Что значит FillByte = 0?

NumPut пишет числа в память. В данном случае эти числа являются кодами символов в кодировке UTF-8, точнее половинками кодов, т.к. русские буквы кодируются двумя байтами. Коды английских букв там такие же, как в ANSI и однобайтные. Так что строка английского текста в перекодировке в UTF-8 и обратно не нуждается.

То есть NumPut дописывает в переменную buf числа? А как быть если я незнаю, русские или английские буквы должны быть, и если они вразнобой.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

6

Re: AHK: Извлечь символы utf-8

Вот ещё вопрос, файл видимо бинарный: http://savepic.org/4123391.png и FileRead его нечитает. Как тут быть?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

7

Re: AHK: Извлечь символы utf-8

serzh82saratov пишет:

Почему количество символов надо делить на 3 + 1? Что значит FillByte = 0?

Потому что два символа обозначают один байт, а = — разделитель. Итого 3 символа на байт. А т.к. последняя группа неполная, то она отбрасывается целочисленным делением и я её добавил как +1. FillByte = 0 заполняет переменную двоичными нулями.

serzh82saratov пишет:

А как быть если я незнаю, русские или английские буквы должны быть, и если они вразнобой.

Вам и не надо знать. Строку перекодирует функция StrGet. С английскими буквами ничего не случится. Их перекодировка в UTF-16 заключается только в добавлении нулевого байта.

8

Re: AHK: Извлечь символы utf-8

serzh82saratov пишет:

Вот ещё вопрос, файл видимо бинарный и FileRead его нечитает. Как тут быть?

Можно использовать объект File. Его возвращает функция FileOpen.

9

Re: AHK: Извлечь символы utf-8

а = — разделитель. Итого 3 символа на байт. А т.к. последняя группа неполная, то она отбрасывается целочисленным делением и я её добавил как +1. FillByte = 0 заполняет переменную двоичными нулями.

Спасибо за ответ, но я ничего непонял... Видимо сказывается отсутствие базовых знаний. Если есть возможность, распишите подробно для дилетанта.

С английскими буквами ничего не случится. Их перекодировка в UTF-16 заключается только в добавлении нулевого байта.

Тут тоже туманно, ведь в StrGet указано UTF-8.

Можно использовать объект File. Его возвращает функция FileOpen.

Не понял каким образом.
Чем больше ответов, тем больше глупых вопросов

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

10

Re: AHK: Извлечь символы utf-8

Можно использовать объект File

File := FileOpen(FileName, "r")  

VarSetCapacity(buf, file.length  // 3 + 1, 0)
Loop, parse, ???

Если имелось ввиду взять из него длинну, то что далее парсить?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

11

Re: AHK: Извлечь символы utf-8

serzh82saratov пишет:

Спасибо за ответ, но я ничего непонял... Видимо сказывается отсутствие базовых знаний. Если есть возможность, распишите подробно для дилетанта.

Так вы объясните, что именно не понятно. Фраза "ничего не понял" ни о чём мне не говорит.

serzh82saratov пишет:

Тут тоже туманно, ведь в StrGet указано UTF-8.

Да, указана исходная кодировка. В юникодном АНК строки хранятся в UTF-16, так что перекодирование пойдёт в неё.

Если имелось ввиду взять из него длинну, то что далее парсить?

Парсить пока нечего, т.к. вы файл не прочитали. Для чтения бинарных файлов у объекта есть метод RawRead.

12

Re: AHK: Извлечь символы utf-8

Так вы объясните, что именно не понятно. Фраза "ничего не понял" ни о чём мне не говорит.

Это значит совсем ничего

1. а = — разделитель.
2. Итого 3 символа на байт.
3. А т.к. последняя группа неполная, то она отбрасывается целочисленным делением и я её добавил как +1.
4. FillByte = 0 заполняет переменную двоичными нулями.

Парсить пока нечего, т.к. вы файл не прочитали. Для чтения бинарных файлов у объекта есть метод RawRead.

Пробовал RawRead, но ничего не вышло.
Кстати не понял почему Loop, Read читает файл в отличии от FileRead? С его помощью перевёл файл в текстовый вид. Но конечно хочется увидеть пример с RawRead.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

13

Re: AHK: Извлечь символы utf-8

С VarSetCapacity всё дошло. NumPut я так понял пишет данные в указанный байт A_Index - 1. А что за параметр UChar? Разве можно цифру записать по разному?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

14 (изменено: YMP, 2013-07-22 09:47:01)

Re: AHK: Извлечь символы utf-8

serzh82saratov пишет:

Это значит совсем ничего

Ну, тогда капец.

Пробовал RawRead, но ничего не вышло.

Без конкретики могу только посочувствовать.

Кстати не понял почему Loop, Read читает файл в отличии от FileRead?

Не знаю, это надо смотреть в исходники АНК. Видимо, просто ищет символы перевода строки и считывает то, что между ними. Если там нет нулевых байтов, то всё должно считаться, по идее.

NumPut я так понял пишет данные в указанный байт A_Index - 1. А что за параметр UChar? Разве можно цифру записать по разному?

Она пишет в buf по смещению от его начала на A_Index-1 байтов. Число можно записать по-разному. Если как байт, то это 8 бит займёт в памяти, если как слово (Short, UShort), то 16 бит; если как двойное слово (Int, UInt), то 32 бита, и т.д. Как байт можно записать числа от 0 до 255, т.к. возможных комбинаций из 8 бит, каждый из которых может иметь два значения (0 и 1) — только 256 (2 в 8-й степени).

Вы понимаете разницу между цифрой и числом? Число — это количество чего-то. Цифра — строковый символ, она обозначает число. Одно и то же число можно обозначить разными цифрами или вообще словами: 255, FF, 11111111, двести пятьдесят пять. Так вот, строка D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D1=8C=D1=8F состоит из обозначений чисел. Их нужно перевести в сами числа величиной в байт, чтобы получить строку UTF-8, которую потом прочитать через StrGet .

Если в строке вы видите символ 5, это не значит, что в памяти на этом месте байт со значением 5. Что там реально соответствует этому символу, зависит от кодировки. Этот символ обозначает число 5, а не является им. Чтобы в памяти реально было число 5, нужно использовать NumPut, которая берёт значение символа (а не код символа) и пишет его в память уже непосредственно в бинарном виде.

Строго говоря, число в памяти — это тоже одно из возможных представлений числа, но это то представление, которое понятно процессору, в отличие от символа 5, который понятен человеку.

15

Re: AHK: Извлечь символы utf-8

Парсить пока нечего, т.к. вы файл не прочитали. Для чтения бинарных файлов у объекта есть метод RawRead.

Без конкретики могу только посочувствовать.

В файле есть строки вида:

N;ENCODING=QUOTED-PRINTABLE;CHARSET=utf-8:=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D1=8C=D1=8F;;;;

после них идут номера телефонов которые надо извлечь RegExMatch.

serzh82saratov пишет:

Вот ещё вопрос, файл видимо бинарный и FileRead его нечитает. Как тут быть?

YMP пишет:

Можно использовать объект File. Его возвращает функция FileOpen.

YMP пишет:

Парсить пока нечего, т.к. вы файл не прочитали. Для чтения бинарных файлов у объекта есть метод RawRead.

не  ясно как тут использовать RawRead для получения текста с которым уже можно работать.

Всё остальное по большей части до меня дошло, большое спасибо за разъяснения!

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

16

Re: AHK: Извлечь символы utf-8

Но если Loop, Read работает, то зачем бинарное чтение? Это лишняя морока.

17 (изменено: serzh82saratov, 2013-07-22 15:22:17)

Re: AHK: Извлечь символы utf-8

Мне, для получения знаний исходя из примера. Тем более пригодится в тех случаях когда Loop, Read работать небудет

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

18

Re: AHK: Извлечь символы utf-8

Для получения знаний о бесполезной мороке? Извините, я в этом смысла не вижу.

19

Re: AHK: Извлечь символы utf-8

serzh82saratov пишет:

не  ясно как тут использовать RawRead для получения текста с которым уже можно работать.

Вроде дошло как извлечь текст из бинарного файла:


File := FileOpen(FileName, "r")  
File.Pos := 0
Length := File.Length ; в File.Pos и Length можно задать смещения
file.RawRead(buf, Length) 
Encoding := File.Encoding
file.Close()
 
Loop % Length 
    hex .= NumGet(buf, A_Index - 1, "UChar") " " 

StringReplace, hex, hex, %A_Space%0, , 1

Loop, parse, hex, %A_Space% 
    NumPut(A_LoopField, buf, A_Index - 1, "UChar")

Gui, Add, Edit, r55 w777, % StrGet(&buf, Encoding)
Gui, Show 
Return

И вопрос:
Можно ли как то проще удалить нулевые байты?
Я так понял что StrGet натыкаясь на 0х00 прекращает дальнейшее извлечение.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

20

Re: AHK: Извлечь символы utf-8

Можно ли как то проще удалить нулевые байты?

Проще вместо нулевых записать другие:


File := FileOpen(FileName, "r")  
File.Pos := 0
Length := File.Length
File.RawRead(buf, Length) 
Encoding := File.Encoding 
File.Close()  
    
Loop % Length 
    (!NumGet(buf, A_Index - 1, Encoding)) ? NumPut(32, buf, A_Index - 1, Encoding) : 0
MsgBox % StrGet(&buf, Encoding)

Но вопрос о простоте остаётся.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

21

Re: AHK: Извлечь символы utf-8

Encoding := File.Encoding

Какой может быть encoding у бинарного файла? Никакого. Если в этом файле есть текстовые строки, то их кодировку вы сами должны знать и указать в функции StrGet. Если просто хотите все байты перевести в символы, то учтите, что не для всех возможных значений байта есть какой-то видимый символ, так что некоторые байты вы можете не увидеть. И нет гарантии, что StrGet отобразит вкраплённые в бинарный файл строки правильно. Например, если это строка в utf-16, то там каждый символ кодируется двумя байтами. Если с начала файла до начала строки будет нечётное количество байтов, то первый байт строки (половина первого кода символа) будет спарен с предыдущим (не относящимся к строке) байтом и образует какой-то левый код. Второй байт первого символа строки будет спарен с первым байтом второго символа и т.д., так что получится тарабарщина. Та же проблема с utf-8, т.к. там неанглийские символы обозначаются двумя и более байтами.

22 (изменено: serzh82saratov, 2013-09-19 11:35:59)

Re: AHK: Извлечь символы utf-8

Какой может быть encoding у бинарного файла? Никакого.

Просто это сработало на нескольких файлах, и я подумал что всё правильно. То есть проблемы будут только с utf-8 и utf-16, для остальных достаточно писать "UChar"?

так что некоторые байты вы можете не увидеть.

Ну хоть что то будет.

Если в этом файле есть текстовые строки, то их кодировку вы сами должны знать

Узнать это скриптом никак нельзя?

И нет гарантии, что StrGet отобразит вкраплённые в бинарный файл строки правильно. Например, если это строка в utf-16, то там каждый символ кодируется двумя байтами. Если с начала файла до начала строки будет нечётное количество байтов...

Так панацеи нет?
Какие то алгоритмы ведь эти файлы обрабатывают, или в них заранее все известно про свойства файла.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

23 (изменено: YMP, 2013-09-19 12:29:32)

Re: AHK: Извлечь символы utf-8

serzh82saratov пишет:

Просто это сработало на нескольких файлах, и я подумал что всё правильно.

Что значит сработало? Подозреваю, что для файла без BOM file.Encoding вернёт 0, т.е. будет использована дефолтная ANSI-кодировка. У нас она однобайтная. Если строка в ней, то её будет видно.

То есть проблемы будут только с utf-8 и utf-16, для остальных достаточно писать "UChar"?

Где именно писать?

Узнать это скриптом никак нельзя?

Не представляю как.

Так панацеи нет?
Какие то алгоритмы ведь эти файлы обрабатывают, или в них заранее все известно про свойства файла.

Если это тип файлов, используемый какой-то программой, то естественно разработчик всё знает.

24

Re: AHK: Извлечь символы utf-8

Где именно писать?

В NumGet и NumPut.

Подозреваю, что для файла без BOM file.Encoding вернёт 0

Возвращается CP1251, и код из 20 поста получает нужный текст.

Вообщем я понял что если сам текст в файле в utf-8 или utf-16, то решения как извлечь текст - нет. Но хотя бы есть решение для ANSI.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

25

Re: AHK: Извлечь символы utf-8

serzh82saratov пишет:

В NumGet и NumPut.

Там нет смысла писать что-то другое. Они просто переводят число, представленное байтом, в число, представленное цифрами, и наоборот, а не код символа в символ.

Возвращается CP1251, и код из 20 поста получает нужный текст.

Ну да, это и есть дефолтная кодировка на русской Windows.

26

Re: AHK: Извлечь символы utf-8

Там нет смысла писать что-то другое. Они просто переводят число, представленное байтом, в число, представленное цифрами, и наоборот, а не код символа в символ.

Так зачем тогда вообще нужен этот параметр?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

27 (изменено: YMP, 2013-09-19 14:23:53)

Re: AHK: Извлечь символы utf-8

Он указывает размер читаемых или писомых данных (байт). Ну и по идее в случае чтения ещё может влиять на формат строкового представления числа: если uchar, то будет 255, а если char, то -1.

28

Re: AHK: Извлечь символы utf-8

Спасибо за разъяснения.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui