Гость
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как определить, что кодировка txt-файл Unicode (UTF-16) / 8 сообщений из 8, страница 1 из 1
17.03.2015, 19:05
    #38907490
Unicode (UTF-16)
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как определить, что кодировка txt-файл Unicode (UTF-16)
Всем здрасьте!

Есть два txt-файла - один в ANSI кодировке, другой - в UTF-16.
Первый (ANSI) открываю и читаю так
Код: vbnet
1.
2.
3.
4.
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oTXT = oFSO.OpenTextFile(FileName1, ForReading)
    Debug.Print "ansi", oTXT.ReadLine
    oTXT.Close


Второй (UTF-16) так
Код: vbnet
1.
2.
3.
4.
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    Set oTXT = oFSO.OpenTextFile(FileName2, ForReading, , TristateTrue)
    Debug.Print "unicode", oTXT.ReadLine
    oTXT.Close


Вопрос: как, во время выполнения программы, определить какой из файлов Unicode (UTF-16)?

Notepad же как-то "умеет" это делать! ))
...
Рейтинг: 0 / 0
17.03.2015, 20:22
    #38907542
VSVLAD
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как определить, что кодировка txt-файл Unicode (UTF-16)
Unicode (UTF-16),

Обычно, так скажем как правило, вначале файла содержится заголовок из байтов: &HFF и &HFE или &HFE и &HFF, говорит что файл у нас в Unicode.

Другой вариант, собрать статистику использования символов, если текст достаточный и можно догадаться что у нас Unicode (например, если текст латиницей, то каждый 2-ой байт у символа будет нулевой &H0)
...
Рейтинг: 0 / 0
17.03.2015, 23:17
    #38907662
Казанский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как определить, что кодировка txt-файл Unicode (UTF-16)
Если FF, FE, то блокнот открывает. Как и без этих байтов. Если FE, FF, то нет.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
Sub bb()
Dim b() As Byte
b = " У Мери был барашек. Mary had a little lamb."
Open "c:\temp\u0.txt" For Binary As #1: Put 1, , b: Close #1
b(0) = &HFF: b(1) = &HFE
Open "c:\temp\u1.txt" For Binary As #1: Put 1, , b: Close #1
b(0) = &HFE: b(1) = &HFF
Open "c:\temp\u2.txt" For Binary As #1: Put 1, , b: Close #1
End Sub
...
Рейтинг: 0 / 0
17.03.2015, 23:57
    #38907686
Unicode (UTF-16)
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как определить, что кодировка txt-файл Unicode (UTF-16)
VSVLAD ,

Спасибо! Вообщем, через анализ этого BOM пока и сделал
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Function IsUnicodeTXT(ByVal sFileName As String) As Boolean
    Dim k As Integer
    Dim buf(0 To 3) As Byte
    Dim lLOF As Long
    
    k = FreeFile
    Open sFileName For Binary Access Read As #k
    lLOF = LOF(k)
    Get #k, , buf()
    Close #k
    
    Select Case True
        Case lLOF >= 4 And Hex(buf(0)) = "FF" And Hex(buf(1)) = "FE" And Hex(buf(2)) = "0" And Hex(buf(3)) = "0"
            IsUnicodeTXT = True ' UTF-32LE
        Case lLOF >= 4 And Hex(buf(0)) = "0" And Hex(buf(1)) = "0" And Hex(buf(2)) = "FE" And Hex(buf(3)) = "FF"
            IsUnicodeTXT = True ' UTF-32BE
        Case lLOF >= 3 And Hex(buf(0)) = "EF" And Hex(buf(1)) = "BB" And Hex(buf(2)) = "BF"
            IsUnicodeTXT = True ' UTF-32LE
        Case lLOF >= 2 And Hex(buf(0)) = "FF" And Hex(buf(1)) = "FE"
            IsUnicodeTXT = True ' UTF-16LE
        Case lLOF >= 2 And Hex(buf(0)) = "FE" And Hex(buf(1)) = "FF"
            IsUnicodeTXT = True ' UTF-16BE
    End Select
End Function


VSVLAD Обычно, так скажем как правило , вначале файла содержится заголовок из байтов: &HFF и &HFE или &HFE и &HFF, говорит что файл у нас в Unicode.
"Попроверял" свои файлы, вроде бы, проблемы нет - у всех, первые два байта : FF FE
Но вот нашёл сходную проблему и там тоже об этом пишут:
авторА "фишка" вот в чем. Текстовые файлы, записанные в Unicode (точнее, в UTF-16) должны, по-хорошему, начинаться с BOM (Byte Order Mask) — двухбайтового флага, говорящего о том, как трактовать идущие за ним данные. Предполагается так же, что эти два байта навряд ли окажутся в начале ASCII файла.
Однако же, не все приложения пишут BOM в начале UTF-16-файла. Так как же поступить бедному блокноту?
В Windows API есть функция IsTextUnicode(), позволяющая с определенной долей вероятности узнать, в Unicode ли переданный ей текст или нет.
И вот где порылась собака. Данная функция применяет эвристические алгоритмы и статистические тесты и выдает лишь свою догадку:

These tests are not foolproof. The statistical tests assume certain amounts of variation between low and high bytes in a string, and some ASCII strings can slip through. For example, if lpBuffer points to the ASCII string 0x41, 0x0A, 0x0D, 0x1D (A\n\r^Z), the string passes the IS_TEXT_UNICODE_STATISTICS test, though failure would be preferable.
и предлагается использовать API функцию IsTextUnicode()
Код: vbnet
1.
Private Declare Function IsTextUnicode Lib "advapi32" (ByVal lpBuffer As String, ByVal cb As Long, lpi As Long) As Long


и тут у меня уже "мозгов нехватило" ))
В функцию нужно передавать строку, которая будет проверятся, но что бы передать эту строку - её нужно считать из файла,
а для того, что бы считать - нужно знать "как считывать" - как ANSI или Unicode ... замкнутый круг какой-то ))
...
Рейтинг: 0 / 0
18.03.2015, 01:06
    #38907710
Shocker.Pro
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как определить, что кодировка txt-файл Unicode (UTF-16)
Полагаю, считывать надо в двоичном (бинарном) режиме
...
Рейтинг: 0 / 0
18.03.2015, 02:10
    #38907722
Unicode (UTF-16)
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как определить, что кодировка txt-файл Unicode (UTF-16)
Shocker.ProПолагаю, считывать надо в двоичном (бинарном) режимеДа, считать в массив байт - не проблема, непонятно как потом этот массив передать как параметр lpBuffer As String в функцию.

Но идея, в целом та. Нашёл, что есть ещё одна подобная функция (IsTextPointerUnicode), которой нужно передавать указатель на строку, вот ей можно указатель на массив байт и "подсунуть".
Вот такое что-то вышло (в правильности выбора константы не очень уверен)
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
Private Const IS_TEXT_UNICODE_ASCII16 = &H1
Private Const IS_TEXT_UNICODE_CONTROLS = &H4
Private Const IS_TEXT_UNICODE_DBCS_LEADBYTE = &H400
Private Const IS_TEXT_UNICODE_ILLEGAL_CHARS = &H100
Private Const IS_TEXT_UNICODE_NOT_ASCII_MASK = &HF000
Private Const IS_TEXT_UNICODE_NOT_UNICODE_MASK = &HF00
Private Const IS_TEXT_UNICODE_NULL_BYTES = &H1000
Private Const IS_TEXT_UNICODE_ODD_LENGTH = &H200
Private Const IS_TEXT_UNICODE_REVERSE_ASCII16 = &H10
Private Const IS_TEXT_UNICODE_REVERSE_CONTROLS = &H40
Private Const IS_TEXT_UNICODE_REVERSE_MASK = &HF0
Private Const IS_TEXT_UNICODE_REVERSE_SIGNATURE = &H80
Private Const IS_TEXT_UNICODE_REVERSE_STATISTICS = &H20
Private Const IS_TEXT_UNICODE_SIGNATURE = &H8
Private Const IS_TEXT_UNICODE_STATISTICS = &H2
Private Const IS_TEXT_UNICODE_UNICODE_MASK = &HF

Private Declare Function IsTextUnicode Lib "advapi32" (ByVal lpBuffer As String, ByVal cb As Long, lpi As Long) As Long
Private Declare Function IsTextPointerUnicode Lib "advapi32" Alias "IsTextUnicode" (ByVal lpBuffer As Long, ByVal cb As Long, lpi As Long) As Long


Function IsUTF16TXT(ByVal sFileName As String) As Boolean
    Dim k As Integer
    Dim buf() As Byte
    Dim lLOF As Long
    
    k = FreeFile
    Open sFileName For Binary Access Read As #k
    lLOF = LOF(k)
    ReDim buf(lLOF)
    Get #k, , buf()
    Close #k

Debug.Print Hex(buf(0)), Hex(buf(1))

'    IsUTF16TXT = IsTextPointerUnicode(StrPtr(buf), UBound(buf) + 1, IS_TEXT_UNICODE_STATISTICS + IS_TEXT_UNICODE_SIGNATURE + IS_TEXT_UNICODE_REVERSE_SIGNATURE)
    IsUTF16TXT = IsTextPointerUnicode(StrPtr(buf), UBound(buf) + 1, IS_TEXT_UNICODE_UNICODE_MASK)
End Function


Все три файла отсюда 17397008 определяет как Unicode
(правда u2.txt если читать через OpenTextFile(FileName2, ForReading, , TristateTrue) выводит "?")

Описание констант, вдруг кому понадобится
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
This parameter can be one or more of the following values. Value Meaning
IS_TEXT_UNICODE_ASCII16            The text is Unicode, and contains onlyzero-extended ASCII values/characters.
IS_TEXT_UNICODE_REVERSE_ASCII16    Same as the preceding, except that the Unicode text is byte-reversed.
IS_TEXT_UNICODE_STATISTICS         The text is probably Unicode, with the determination made by applying statistical analysis. Absolute certainty is not guaranteed. See the following Remarks section.
IS_TEXT_UNICODE_REVERSE_STATISTICS Same as the preceding, except that the probably-Unicode text is byte-reversed.
IS_TEXT_UNICODE_CONTROLS           The text contains Unicode representations of one or more of these nonprinting characters: RETURN, LINEFEED, SPACE, CJK_SPACE, TAB.
IS_TEXT_UNICODE_REVERSE_CONTROLS   Same as the preceding, except that the Unicode characters are byte-reversed.
IS_TEXT_UNICODE_BUFFER_TOO_SMALL   There are too few characters in the buffer for meaningful analysis (fewer than two bytes).
IS_TEXT_UNICODE_SIGNATURE          The text contains the Unicode byte-order mark (BOM) 0xFEFF as its first character.
IS_TEXT_UNICODE_REVERSE_SIGNATURE  The text contains the Unicode byte-reversed byte-order mark (Reverse BOM) 0xFFFE as its first character.
IS_TEXT_UNICODE_ILLEGAL_CHARS      The text contains one of these Unicode-illegal characters: embedded Reverse BOM, UNICODE_NUL, CRLF (packed into one WORD), or 0xFFFF.
IS_TEXT_UNICODE_ODD_LENGTH         The number of characters in the string is odd. A string of odd length cannot (by definition) be Unicode text.
IS_TEXT_UNICODE_NULL_BYTES         The text contains null bytes, which indicate non-ASCII text.
IS_TEXT_UNICODE_UNICODE_MASK       This flag constant is a combination of IS_TEXT_UNICODE_ASCII16, IS_TEXT_UNICODE_STATISTICS, IS_TEXT_UNICODE_CONTROLS, IS_TEXT_UNICODE_SIGNATURE.
IS_TEXT_UNICODE_REVERSE_MASK       This flag constant is a combination of IS_TEXT_UNICODE_REVERSE_ASCII16, IS_TEXT_UNICODE_REVERSE_STATISTICS, IS_TEXT_UNICODE_REVERSE_CONTROLS, IS_TEXT_UNICODE_REVERSE_SIGNATURE.
IS_TEXT_UNICODE_NOT_UNICODE_MASK   This flag constant is a combination of IS_TEXT_UNICODE_ILLEGAL_CHARS, IS_TEXT_UNICODE_ODD_LENGTH, and two currently unused bit flags.
IS_TEXT_UNICODE_NOT_ASCII_MASK     This flag constant is a combination of IS_TEXT_UNICODE_NULL_BYTES and three currently unused bit flags.

...
Рейтинг: 0 / 0
18.03.2015, 10:40
    #38907965
Казанский
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как определить, что кодировка txt-файл Unicode (UTF-16)
Наверно лучше
Код: vbnet
1.
IsUTF16TXT = IsTextPointerUnicode(VarPtr(buf(0)), ...

, потому что для функции StrPtr массив будет скопирован в новую строку - лишняя операция.
...
Рейтинг: 0 / 0
25.09.2015, 14:51
    #39061365
Как определить, что кодировка txt-файл Unicode (UTF-16)
Unicode (UTF-16)Shocker.ProПолагаю, считывать надо в двоичном (бинарном) режимеДа, считать в массив байт - не проблема, непонятно как потом этот массив передать как параметр lpBuffer As String в функцию.

Но идея, в целом та. Нашёл, что есть ещё одна подобная функция (IsTextPointerUnicode), которой нужно передавать указатель на строку, вот ей можно указатель на массив байт и "подсунуть".
Вот такое что-то вышло (в правильности выбора константы не очень уверен)
[/src]

[/src][/spoiler]

Добрый день!
подскажите что есть результатирущим в данном примере. тоесть по какому признаку, возвращаемому значению вы определяете результат?
...
Рейтинг: 0 / 0
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Как определить, что кодировка txt-файл Unicode (UTF-16) / 8 сообщений из 8, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]