Не раскодируется utf-8

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Не раскодируется utf-8

Сообщение Antonariy » 14.09.2007 (Пт) 10:25

На почту приходит письмо с темой вида "=?utf-8?B?0JLQsNC8INCe0YLQutGA0YvRgtC60LAh?=".
Получаю из него строку "Вам Открытка!", скармливаю ее функции Convert(s1, 65001, 1251)
Код: Выделить всё
Private Function Convert(ByVal strSrc As String, ByVal nFromCP As Charset, ByVal nToCP As Charset) As String
On Error Resume Next
Dim nLen As Long
Dim strDst As String
Dim strRet As String
Dim nRet As Long
    nLen = Len(strSrc)
    strDst = String(nLen * 2, Chr(0))
    strRet = String(nLen * 2, Chr(0))
    nRet = MultiByteToWideChar(nFromCP, MB_PRECOMPOSED, strSrc, nLen, strDst, nLen)
    nRet = WideCharToMultiByte(nToCP, 0, strDst, nRet, strRet, nLen * 2, ByVal 0, 0)
    Convert = Left$(strRet, nRet)
End Function
однако возвращается пустая строка. В чем проблема?
В поиске находил аналогичную функцию с использованием GlobalAlloc, однако она тоже не сработала.
Лучший способ понять что-то самому — объяснить это другому.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.09.2007 (Пт) 10:41

Строку "Вам Открытка!" нужно для начала перевести из Юникода (или в чём она у тебя физически?) в 1252. Потом из UTF8 в 1251.
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2007 (Пт) 11:09

нужно для начала перевести из Юникода

Это делается той же функцией?
(или в чём она у тебя физически?)
Без понятия. Скопипастенная строка отличается от того, что выдает Debug.Print, могу выложить скриншот.

"Ð’Ð..." -> 1252, utf -> 1251... а как же 1252 -> utf? Не понимаю логики.
Лучший способ понять что-то самому — объяснить это другому.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.09.2007 (Пт) 11:14

"Ð’Ð..." -> 1252 -> сделать вид, что она utf -> 1251
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2007 (Пт) 11:18

А из чего конвертировать "Ð’Ð..."? Какое значение подставить в nFromCP?
У меня уже такой зверинец из разных вариантов...
-0-¦-+ -0-0-¦-0-0-0-¦-¦!
¦Ò¦-¦- ¦ÞT¦¦TÀTËT¦¦¦-!
'ø0 0‘'ó‘0‘<‘'óø!
0'0o00 00‘'0o‘0‘<‘'0o0o!
Лучший способ понять что-то самому — объяснить это другому.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.09.2007 (Пт) 11:39

Из Юникода.
Т.е. чистый WideCharToMultiByte, притом с передачей параметра как StrPtr (иначе он всё равно к 1251 приведётся)
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2007 (Пт) 12:33

:shock:
Чистый, значит без MultiByteToWideChar?
Который из lpWideCharStr и lpMultiByteStr?.. И каким образом StrPtr, если эти параметры as String?

Может просто приведешь пример вызова?.. :roll:
Лучший способ понять что-то самому — объяснить это другому.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.09.2007 (Пт) 13:46

(Положил твою строчку в файл c:\test.txt в Юникоде, вышло 48 байт.)

Код: Выделить всё
Option Explicit
Public Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, lpWideCharStr As Any, ByVal cchWideChar As Long) As Long
Public Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, lpWideCharStr As Any, ByVal cchWideChar As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, ByVal lpDefaultChar As String, ByVal lpUsedDefaultChar As Long) As Long

Sub Main()
Dim w() As Byte, c() As Byte, s As String, l As Long
Open "c:\test.txt" For Binary As 1
ReDim w(1 To LOF(1))
Get #1, , w
Close 1
ReDim c(1 To UBound(w) \ 2)
WideCharToMultiByte 1252, 0, w(1), UBound(c), c(1), UBound(c), vbNullChar, 0
'теперь в c() лежит utf-8
s = Space(UBound(c))
MultiByteToWideChar 65001, 0, c(1), UBound(c), ByVal StrPtr(s), Len(s)
MsgBox s
End Sub


Вам Открытка!
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2007 (Пт) 15:04

Спасибо.
Лучший способ понять что-то самому — объяснить это другому.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2007 (Пт) 15:32

Однако опять не получилось. Вместо файла делаю (уже даже в отдельном проекте):
s = "Вам Открытка!"
w = s
ReDim c(1 To (UBound(w) + 1) \ 2)
и т.д.

w таки содержит 48 байт.
Могу предоставить все байты из массивов до и после.
Лучший способ понять что-то самому — объяснить это другому.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.09.2007 (Пт) 16:08

Antonariy писал(а):s = "Вам Открытка!"

VB тебе не позволит так написать на русской винде. Даже если ты выставишь в редакторе нерусские шрифты, чтобы увидеть нерусские буквы, в строке всё равно будут только символы из 1251.
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2007 (Пт) 17:02

У меня не совсем так. У меня содержимое s получается раскодированием текста из base64, который извлекается из винсока. См. первую строчку из первого поста. Однако результат одинаковый.
Вложения
utf.gif
(12.28 Кб) Скачиваний: 40
Лучший способ понять что-то самому — объяснить это другому.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.09.2007 (Пт) 18:25

Да ты ж мне просто голову морочишь.


Код: Выделить всё
Option Explicit
Public Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, lpMultiByteStr As Any, ByVal cchMultiByte As Long, lpWideCharStr As Any, ByVal cchWideChar As Long) As Long

Sub Main()
Dim c() As Byte, s As String
c() = base64decode("0JLQsNC8INCe0YLQutGA0YvRgtC60LAh")
'теперь в c() лежит utf-8
s = Space(UBound(c) + 1)
MultiByteToWideChar 65001, 0, c(0), Len(s), ByVal StrPtr(s), Len(s)
MsgBox s
End Sub

' Код не мой, я просто разместил объяву.
Private Function base64decode(ByVal base64 As String) As Byte()
Static Base64Reverse() As Byte
   ReDim Preserve Base64Reverse(255)
   If Base64Reverse(0) = 0 Then
       Dim Base64Lookup() As Byte, i As Long
       Base64Lookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
       For i = 0 To 63
          Base64Reverse(Base64Lookup(i * 2)) = i
       Next
   End If
Const Shift2 As Byte = 4, Shift4 As Byte = 16, Shift6 As Byte = 64
Const Mask1 As Byte = 3, Mask2 As Byte = 15, Mask3 As Byte = 63
Const Mask4 As Byte = 192, Mask5 As Byte = 240, Mask6 As Byte = 252
   
   
   Dim Data() As Byte
   Dim EncodedData() As Byte

   Dim DataLength As Long
   Dim EncodedLength As Long

   Dim EncodedData0 As Long
   Dim EncodedData1 As Long
   Dim EncodedData2 As Long
   Dim EncodedData3 As Long

   Dim l As Long
   Dim m As Long

   Dim Index As Long

   Dim CharCount As Long

   EncodedData = StrConv(Replace$(Replace$(base64, vbCrLf, ""), "=", ""), _
   vbFromUnicode)

   EncodedLength = UBound(EncodedData) + 1
   DataLength = (EncodedLength \ 4) * 3

   m = EncodedLength Mod 4
   If m = 2 Then
      DataLength = DataLength + 1
   ElseIf m = 3 Then
      DataLength = DataLength + 2
   End If

   ReDim Data(DataLength - 1)

   For l = 0 To UBound(EncodedData) - m Step 4
      EncodedData0 = Base64Reverse(EncodedData(l))
      EncodedData1 = Base64Reverse(EncodedData(l + 1))
      EncodedData2 = Base64Reverse(EncodedData(l + 2))
      EncodedData3 = Base64Reverse(EncodedData(l + 3))
      Data(Index) = (EncodedData0 * Shift2) Or (EncodedData1 \ Shift4)
      Data(Index + 1) = ((EncodedData1 And Mask2) * Shift4) Or (EncodedData2 \ _
      Shift2)
      Data(Index + 2) = ((EncodedData2 And Mask1) * Shift6) Or EncodedData3
      Index = Index + 3
   Next

   Select Case ((UBound(EncodedData) + 1) Mod 4)
   Case 2
      EncodedData0 = Base64Reverse(EncodedData(l))
      EncodedData1 = Base64Reverse(EncodedData(l + 1))
      Data(Index) = (EncodedData0 * Shift2) Or (EncodedData1 \ Shift4)
   Case 3
      EncodedData0 = Base64Reverse(EncodedData(l))
      EncodedData1 = Base64Reverse(EncodedData(l + 1))
      EncodedData2 = Base64Reverse(EncodedData(l + 2))
      Data(Index) = (EncodedData0 * Shift2) Or (EncodedData1 \ Shift4)
      Data(Index + 1) = ((EncodedData1 And Mask2) * Shift4) Or (EncodedData2 \ _
      Shift2)
   End Select

   base64decode = Data

End Function
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 14.09.2007 (Пт) 20:53

Ничего я не морочу. С самого начала написал как есть. Да, не разжевал, думал, что и так будет понятно, откуда берется строка.
Лучший способ понять что-то самому — объяснить это другому.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Majestic-12 [Bot], Yandex-бот и гости: 91

    TopList