1

Тема: дешифровка Unicode

Добрый день, возникла необходимость декодировать текст из unicode. Выглядит это так:
"\u0412\u0435\u0434\u0443\u0449\u0438\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440".
Уже попробовал StrConv, Спрашивать посимвольно AskW, а также

With CreateObject("ADODB.Stream")
        .Type = 2
        If Len(sDecode) Then .Charset = sDecode    ' указываем исходную кодировку
        .Open
        .LoadFromFile sFileName    ' загружаем данные из файла
        sFileContent = .ReadText   ' считываем текст файла в переменную FileContent$
        .Close
        .Charset = sDecodeTo    ' назначаем новую кодировку
        .Open
        .WriteText sFileContent
        .SaveToFile sFileName, 2   ' сохраняем файл уже в новой кодировке
        .Close
    End With

В первых случаях получаются иероглифы, в последнем - "файл повреждён" и открыть его не представляется возможным. Декодирование онлай-ресурсами позволяет декодировать текст. Буду рад вашему совету, как это разрешить. (П.С.: Просто заменить макросом все символы, зная код и его значение можно, но хочется более программно выполнить задачу). Спасибо

Спасибо можно перевести на WebMoney-кошелёк R378231864568 или на Яндекс-деньги 410015093172871

2

Re: дешифровка Unicode

Fck_This пишет:

Добрый день, возникла необходимость декодировать текст из unicode.

Как-то наткнулся на одном сайте на функцию чтения файла в unicode. Попробовал - вроде работает (глубоко не тестировал). Попробуйте (см. в прицепе к сообщению).

Post's attachments

ReadAnyTextFile_VBA.txt 4.29 Кб, 3 скачиваний с 2017-01-25 

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

3

Re: дешифровка Unicode

yshindin пишет:
Fck_This пишет:

Добрый день, возникла необходимость декодировать текст из unicode.

Как-то наткнулся на одном сайте на функцию чтения файла в unicode. Попробовал - вроде работает (глубоко не тестировал). Попробуйте (см. в прицепе к сообщению).

Спасибо, буду тестить и разбираться.
У вас файл повреждён - не хватает знаков сравнения. Вот этот код со всеми знаками:

Function ReadAnyTextFile(sFilePath$, Optional fGetRowsArray As Boolean) As Variant
'Функция читает файлы в формате:
' Обычный (ANSI/OEM и т.п. с однобайтовой кодировкой)
' Unicode (UTF-16 LE, UTF-16 BE)
' UTF-8
'Формат файла определяется по маркеру BOM (первые 2-3 байта в начале файла)
' или анализом.
'Лишние завершающие символы vbCr и/или vbLf исключаются.
'Если fGetRowsArray=0, возвращает содержимое файла.
'Если fGetRowsArray=1, возвращает массив строк (разделитель vbCrLf, vbCr или vbLf).
On Error Resume Next
Dim i&, j&, k%, s$, arr() As Byte, iUtf8%, iUtf16%
    
    i = FreeFile: Open sFilePath$ For Binary Access Read Shared As i
 If Err.Number <> 0 Then Err.Clear: Exit Function
    
    j = LOF(i): If j = 0 Then Close i: GoTo Finish
 If j >= 4 Then
    ReDim arr(1 To 4): Get i, , arr
'Проверяется наличие признака кодировки (первые 2-3 байта).
  If arr(1) = &HFF And arr(2) = &HFE And arr(3) <> 0 Then
'Есть признак Unicode(UTF-16 LE). Читаем с 3-го байта.
    k = 2: iUtf16 = 1
  ElseIf arr(1) = &HFE And arr(2) = &HFF And arr(4) <> 0 Then
'Есть признак Unicode(UTF-16 BE). Читаем с 3-го байта.
    k = 2: iUtf16 = 2
  ElseIf arr(1) = &HEF And arr(2) = &HBB And arr(3) = &HBF Then
'Есть признак UTF-8. Читаем с 4-го байта.
    k = 3: iUtf8 = 1
  End If
 End If
    j = j - k: ReDim arr(1 To j): Get i, 1 + k, arr
    Close i

 If iUtf16 = 0 And iUtf8 = 0 And (UBound(arr) Mod 2) = 0 Then
'Проверка Unicode. Контролируется значение старшего байта в первом и последнем символе.
'Этого достаточно, если эти символы не "№" и не специальные знаки
' (например - математические или химические).
  If arr(2) <= 5 And arr(UBound(arr)) <= 5 Then
    iUtf16 = 1
  ElseIf arr(1) <= 5 And arr(UBound(arr) - 1) <= 5 Then
    iUtf16 = 2
  End If
 End If
 If iUtf16 = 2 Then
'Для UTF-16 BE в цикле меняем местами парные байты.
  For i = 1 To j - 1 Step 2
    k = arr(i): arr(i) = arr(i + 1): arr(i + 1) = k
  Next
 End If
 If iUtf16 > 0 Then s = arr: GoTo Finish

'Проверка UTF-8
 For i = 1 To j - 1
  Select Case arr(i)
  Case Is <= 127
  Case &HC2 To &HDF
'В UTF-8 после байта с таким кодом должен стоять байт с кодом &H80-&HBF
   If arr(i + 1) < &H80 Or arr(i + 1) > &HBF Then iUtf8 = 0: Exit For
    iUtf8 = 3: i = i + 1
  Case &HE0 To &HFF
'В UTF-8 после байта с таким кодом должны стоять 2 байта с кодом &H80-&HBF
   If i = j - 1 Then iUtf8 = False: Exit For
   If arr(i + 1) < &H80 Or arr(i + 1) > &HBF Then iUtf8 = 0: Exit For
   If arr(i + 2) < &H80 Or arr(i + 2) > &HBF Then iUtf8 = 0: Exit For
    iUtf8 = 3: i = i + 2
  Case Else
    iUtf8 = 0: Exit For
  End Select
 Next
'Если в массиве найдены недопустимые для UTF-8 коды или все коды <=127
 If iUtf8 < 3 Then s = StrConv(arr, vbUnicode): GoTo Finish

'Преобразование UTF-8 -> Unicode
 For i = 1 To j
'Переменная "k" (код символа) - Integer (2 байта или 16 битов с весом 0-15)
  Select Case arr(i)
  Case Is <= 127
    k = arr(i)
  Case &HC2 To &HDF
'6 младших битов 2-го байта переносятся в код с тем же весом (0-5)
    k = (arr(i + 1) And &H3F)
'5 младших битов 1-го байта переносятся в код с весом 6-10
    k = k + (arr(i) And &H1F) * &H40        'Биты смещаются на 6 позиций влево.
    i = i + 1
  Case &HE0 To &HFF
'6 младших битов 3-го байта переносятся в код с тем же весом (0-5)
    k = (arr(i + 2) And &H3F)
'6 младших битов 2-го байта переносятся в код с весом 6-11
    k = k + (arr(i + 1) And &H1F) * &H40    'Биты смещаются на 6 позиций влево.
'4 младших бита 1-го байта переносятся в код с весом 12-15
    k = k + (arr(i) And &HF) * &H1000       'Биты смещаются на 12 позиций влево.
    i = i + 2
  End Select
  If k <= 127 Then s = s & Chr(k) Else s = s & ChrW(k)
 Next

Finish:
'Исключаются лишние завершающие символы vbCr и/или vbLf
    j = Len(s): Erase arr
 For i = j To 1 Step -1
    k = Asc(Mid$(s, i, 1))
  If k <> 13 And k <> 10 Then Exit For
 Next
 If i < j Then s = Left(s, i)
 
 If Not fGetRowsArray Then ReadAnyTextFile = s: Exit Function
 If i <= 1 Then ReadAnyTextFile = Split(s): Exit Function
'Преобразование текста в массив строк.
 If InStr(s, vbCrLf) > 0 Then
    ReadAnyTextFile = Split(s, vbCrLf)
 ElseIf InStr(s, vbLf) > 0 Then
    ReadAnyTextFile = Split(s, vbLf)
 Else
    ReadAnyTextFile = Split(s, vbCr)
 End If
End Function
Спасибо можно перевести на WebMoney-кошелёк R378231864568 или на Яндекс-деньги 410015093172871

4

Re: дешифровка Unicode

Fck_This пишет:

У вас файл повреждён - не хватает знаков сравнения.

У меня код работает. Текст я копировал через буфер Windows и для того, чтобы сохранить русские комментарии, мне пришлось дополнительно прогнать этот текст через программу tcode = м.б., что-то испортилось. oO))

5

Re: дешифровка Unicode

yshindin пишет:
Fck_This пишет:

У вас файл повреждён - не хватает знаков сравнения.

У меня код работает. Текст я копировал через буфер Windows и для того, чтобы сохранить русские комментарии, мне пришлось дополнительно прогнать этот текст через программу tcode = м.б., что-то испортилось. oO))

При русской раскладке комментарии на русском сохраняются. А вы какой текст декодили? Буду пробовать ещё, но что-то у меня не вышло ничего путного.

Спасибо можно перевести на WebMoney-кошелёк R378231864568 или на Яндекс-деньги 410015093172871

6

Re: дешифровка Unicode

Fck_This пишет:

А вы какой текст декодили?

Я проверял функцию на примере чтения html-текста в кодировке UTF-8. Вроде все прочиталось.

7

Re: дешифровка Unicode

Всё. Намучался с разными чужими кодами, перерыл интернет, попробовал функцию

Selection.InsertSymbol

Сначала не понимал, почему вставялет какую-то шляпу по номеру unicode-символов. Получалось так: Символ в Unicode выглядит как "043B", а при записи макрорекордером - выводит "1083" в указанной выше функции. Потом дошло до меня, что это в десятичной системе счисления он так выглядит. Плюнув на поиск готовых решений углубился в суть систем счисления и нашёл как перекодировать число из шестнадцатеричной системы в двоичную и десятичную. Короче вот код, который может перевести символы UTF-16 в привычный нам русский язык windows-1251, может кому пригодится:

Sub s_election()
Dim sText$, iFour&, iThree&, iTwo&, iOne&, iTenCodeSystem&
'Перевод Unicode из шестнадцатеричной системы в десятичную
sText = Selection.Range.Text
iOne = Замещение(Right(sText, 1))
iTwo = Замещение(Left(Right(sText, 2), 1))
iThree = Замещение(Right(Left(sText, 2), 1))
iFour = Замещение(Left(sText, 1))
iTenCodeSystem = (iOne * 1) + (iTwo * 16) + (iThree * 256) + (iFour * 4096)
sChar = ChrW(iTenCodeSystem)
Selection.Collapse direction:=wdCollapseEnd
Selection.InsertAfter ("-")
Selection.InsertSymbol Font:="TimesNewRoman", CharacterNumber:=iTenCodeSystem, Unicode:=True
End Sub
Private Function Замещение(ByVal InputText As String)
If IsNumeric(InputText) Then Замещение = CInt(InputText): GoTo LineOut
If InputText Like "[a-f]" Then
    Замещение = CInt(Replace(Replace(Replace(Replace(Replace(Replace(InputText, "a", "10"), "b", "11"), "c", "12"), "d", "13"), "e", "14"), "f", "15"))
ElseIf InputText Like "[A-F]" Then
    Замещение = CInt(Replace(Replace(Replace(Replace(Replace(Replace(InputText, "A", "10"), "B", "11"), "C", "12"), "D", "13"), "E", "14"), "F", "15"))
End If
LineOut:
End Function

В программу можно дописать код, который будет делить текст в формате UTF-16 по 4 необходимых символа по разделителю и через цикл, для каждого слова, организовать замену или сразу внести всё в массив по разделителю и цикл формировать уже для содержимого массива.

Спасибо можно перевести на WebMoney-кошелёк R378231864568 или на Яндекс-деньги 410015093172871

8

Re: дешифровка Unicode

Fck_This пишет:

текст из unicode...u0412\u0435\u0434...ADODB.Stream...получаются иероглифы

У вас Юникод-символы из какого-то программного кода. ADODB.Stream служит для перекодировки текста. Надо сначала конвертировать ваш код в текст, а потом уж использовать ADODB.Stream, или сразу перекодировать в текст нужной кодировки.

Макросы под заказ и готовый пакет - mtdmacro.ru

9

Re: дешифровка Unicode

Fck_This пишет:

Добрый день, возникла необходимость декодировать текст из unicode. Выглядит это так:
"\u0412\u0435\u0434\u0443\u0449\u0438\u0439 \u0438\u043d\u0436\u0435\u043d\u0435\u0440".

Для текста такого вида работает макрос:

Sub Uni_To_Char()
Dim oRng As Range
    Set oRng = ActiveDocument.Content
    ResetFRParameters oRng 
    With oRng.Find
        .Text = "\\u[0-9A-Fa-f]{4}"
        .Forward = True
        .MatchWildcards = True
        While .Execute
            With oRng
                .End = .Start + 2
                .Text = ""
                .End = .Start + 4
                .Select
                Selection.ToggleCharacterCode 'ALT+X на клавиатуре
                .Collapse wdCollapseEnd
            End With
        Wend
  End With
End Sub

Sub ResetFRParameters(oRng As Range)
  With oRng.Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Text = ""
    .Replacement.Text = ""
    .Forward = True
    .Wrap = wdFindStop
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchWildcards = False
    .MatchSoundsLike = False
    .MatchAllWordForms = False
    .Execute
  End With
End Sub

Кроме того для перевода Unicode из шестнадцатеричной системы в десятичную можно воспользоваться функцией Val(string), например: ChrW(Val(&H0424)) --> Ф

10

Re: дешифровка Unicode

Boris_R пишет:

Кроме того для перевода Unicode из шестнадцатеричной системы в десятичную можно воспользоваться функцией Val(string), например: ChrW(Val(&H0424)) --> Ф

Спасибо. Где ж вы раньше-то были?! Столько было перелопачено инфы...  Важен даже не то, как перевести в число данный формат, а как должен выглядеть текст. У меня было "\u4535": пробовал брать полностью, пробовал брать "u4535" и "4535". А вот в виде &H#### - нет... А перевести в число десятичного формата можно и через CInt - работает идентично, нареканий на выполнение нет. Ещё раз спасибо.

Спасибо можно перевести на WebMoney-кошелёк R378231864568 или на Яндекс-деньги 410015093172871