Konvertointi UTF-8 to Ansi vb:ssä?
Miten onnistuu siten että merkistö menee oikein?
Kiitos,
-Jarmo-
Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long Declare Function WideCharToMultiByte Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long, ByVal lpMultiByteStr As Long, ByVal cchMultiByte As Long, ByVal lpDefaultChar As Long, lpUsedDefaultChar As Long) As Long
Function UTF8decode(ByRef Text As String) As String Dim bytText() As Byte, bytOut() As Byte, lngOut As Long ' muunna tavutaulukoksi bytText = StrConv(Text, vbFromUnicode) ' varataan tilaa lngOut = LenB(Text) * 2 ReDim bytOut(lngOut - 1) ' suoritetaan muunnos lngOut = MultiByteToWideChar(65001&, 0&, ByVal VarPtr(bytText(0)), Len(Text), ByVal VarPtr(bytOut(0)), lngOut) ' lopputuloksen pituus If lngOut > 0 Then ReDim Preserve bytOut(lngOut * 2 - 1) UTF8decode = bytOut End If End Function
Testaamaton.
Moikka ucsjsa!
tässä olis samaa jutskaa ilman API-vääntöä...
'Testi: avaa muistiolla uusi tekstitiedosto 'kirjoittele jotain jossa on ääkkösiä seassa 'tallenna työpöydälle nimellä testi.txt / UTF-8 muodossa Private Sub Command1_Click() Dim tiedosto As String, pituus As Long, tavut() As Byte, teksti As String tiedosto = Environ$("userprofile") & "\Työpöytä\testi.txt" pituus = FileLen(tiedosto) ReDim tavut(1 To pituus) Open tiedosto For Binary Access Read As #1 Get #1, 4, tavut: Close #1 For i = 1 To UBound(tavut) Select Case Val(Format$(tavut(i))) Case 32 To 127 teksti = teksti + Chr(Val(Format$(tavut(i)))) 'ääkköset Case 132 teksti = teksti + "Ä" Case 133 teksti = teksti + "Ö" Case 150 teksti = teksti + "Å" Case 164 teksti = teksti + "ä" Case 165 teksti = teksti + "å" Case 182 teksti = teksti + "ö" End Select Next i MsgBox teksti End Sub
Heippa!
Sorry, ajatus näköjään kulkee kun väsyttää...
teksti = teksti + Chr(tavut(i))
Kiitokset,
Käytössä on Visual Studio 2005 ja se ei ainakaan suoraan syönyt
kumpaakaan noista malleista. Ihmetyttää ettei tuohon ole kätevämpää
muunnosta olemassa...voisi kuvitella että olisi valmis mokkula kun
notepadikin jopa osaa käännön.
Onpas hankala tehdä tätä tuolla visuaalin 2005 versiolla pikku koodia...
Tai sitten oon vaan... =)
-Jarmo-
Kannattaa kertoa mitä versiota käyttää, molemmat koodinpätkät olivat perinteiselle VB:lle, eivät .NETille.
Moikka ucsjsa!
testaa - tutki - analysoi...
testi.txt:
abcdefghijklmnopqrstuwxyzåäö ABCDEFGHIJKLMNOPQRSTUVXYZÅÄÖ 1234567890/+-=*"'$%&()[]{}?!
Imports System Imports System.IO Imports System.Text Imports System.Drawing Imports System.Windows.Forms Imports Microsoft.VisualBasic '...valmiiksi generoidut jutskat Private Sub Button1Click(sender As System.Object, e As System.EventArgs) Dim tiedosto As String = Environ("userprofile") + "\Työpöytä\testi.txt" Dim readeri As New StreamReader(tiedosto) Dim teksti As String = readeri.ReadToEnd() Dim koodaus As String = readeri.CurrentEncoding.EncodingName Dim koodisivu As String = readeri.CurrentEncoding.WindowsCodePage.ToString() messagebox.Show("koodaus: " + koodaus + " koodisivu: " + koodisivu) readeri.Close() readeri = Nothing messagebox.Show("StreamReaderilla: " + Environment.NewLine + teksti) teksti = Nothing FileSystem.FileOpen(1, tiedosto, OpenMode.Binary, OpenAccess.Read) Dim tavut As New String(" ", LOF(1) - 3) 'tiedoston pituus -3 'välilyönti' FileSystem.Seek(1, 4) 'siirtää osoittimen tiedoston 4. merkkiin & 'ottaa merkit tiedoston 4. merkistä -> loppuun FileSystem.FileGet(1, tavut) FileSystem.FileClose(1) Dim i As Integer For i = 0 To Len(tavut) -1 Select Case Asc(tavut.Substring(i, 1)) Case 32 To 127: teksti += tavut.Substring(i, 1) 'ääkköset Case 132: teksti += "Ä" Case 133: teksti += "Ö" Case 150: teksti += "Å" Case 164: teksti += "ä" Case 165: teksti += "å" Case 182: teksti += "ö" End Select Next messagebox.Show("Binary FileOpen'lla: " + Environment.NewLine + teksti) End Sub
EDIT: Case 10, 13, 32 to 127 ...
Nea, tämä auttoi!
Olen pystyssä kaffeet! =)
-Jrmo-
Hei!
Mitähän teen väärin kuin tuolla konvertoitaessa häviää rivin vaihdot?
-Jarmo-
Dummy me...
Toimii hienosti! KIITOKSET!!!! Tai no...
Tuo luettava tiedosto on noin 10mt, jääpi jumiin....
-Jarmo-
Imports System Imports System.IO Imports System.Text Public Class MainClass Shared Sub Main() Dim file_stream As New FileStream("test.txt", FileMode.Create) Dim bytes As Byte() = New UTF8Encoding().GetBytes("Hello world!") file_stream.Write(bytes, 0, bytes.Length) file_stream.Close() End Sub End Class
Ensimmäinen hakutulos sanoilla VB.NET UTF-8 encode
Heitän arvauksen että tämä toimii varmasti ja nopeasti :)
Heippa taas!
tässä olis aiheesta vielä hieman VB4/5/6-vinkkelissä, ilman API-vääntöä
testi.txt:
1234567890ABCDEFGHIJKLMNOPQRSTUVXYZÅÄÖ abcdefghijklmnopqrstuvxyzåäö !"#¤%&/()=?½§'*~¨^{}[]\.:;,-_+=|<>@£$
Private Sub Form_Load() Dim bstr As String, fStr As String Open Environ("userprofile") & "\Työpöytä\testi.txt" For Binary Access Read As #1 bstr = String(LOF(1), " ") Get #1, 1, bstr: Close #1 Select Case AscB(LeftB(bstr, 1)) Case 49 'ANSI For i = 1 To LenB(bstr) Step 2 fStr = fStr & Chr(AscB(MidB(bstr, i, 1))) Next i fStr = Replace(fStr, Chr(255), "") Case 239 'UTF-8 For i = 1 To LenB(bstr) Step 2 Select Case Asc(Chr(AscB(MidB(bstr, i, 1)))) Case 10, 13, 32 To 127 fStr = fStr & Chr(AscB(MidB(bstr, i, 1))) Case 132: fStr = fStr & "Ä" Case 133: fStr = fStr & "Ö" Case 150: fStr = fStr & "Å" Case 164: fStr = fStr & "ä" Case 165: fStr = fStr & "å" Case 182: fStr = fStr & "ö" End Select Next i Case 254 'Unicode Big endian For i = 1 To LenB(bstr) Step 2 Select Case Asc(Chr(AscB(MidB(bstr, i, 1)))) Case 10, 13, 32 To 253 fStr = fStr + Chr(AscB(MidB(bstr, i, 1))) End Select Next i Case 255 'Unicode For i = 1 To LenB(bstr) Step 4 fStr = fStr & Chr(AscB(MidB(bstr, i, 1))) Next i fStr = Replace(fStr, Chr(255), "") End Select Text1.Text = fStr End Sub
Valmis nopsakasti toimiva UTF-8 koodaaja ja dekoodaaja, sekä tarkistusfunktio jolla voi katsoa onko tekstinpätkä UTF-8:aa vaiko ei. Toimii huomattavasti nopeammin kuin Nean yläpuoliset ratkaisut (mutta todennäköisesti hitaammin kuin API).
Heippa taas!
tässä vähän terapiaa:
jos tyydytään vain lukemaan niin tämä riittää mainiosti...
testasin ~6MB tiedostolla ja toimii mielestäni aika kivasti
Private Sub Command1_Click() ReDim bstr(0) As String Open Environ("userprofile") & "\Työpöytä\testi.txt" For Binary Access Read As #1 '** eli siis: ei mitän byteArrayta vaan... bstr(0) = String(LOF(1), " ") If LOF(1) = 0 Then MsgBox "Tyhjä tiedosto!", vbInformation, "Viestiloota" Close #1: Erase bstr: Exit Sub End If '** lykätään tavut suoraan stringiin... Get #1, 1, bstr(0): Close #1 Select Case AscB(LeftB(bstr(0), 1)) Case 49 'ANSI '** napataan alusta pois muutama merkki bstr(0) = Right(bstr(0), Len(bstr(0)) - 3) '** ja rtfBoxi nielee kaiken mukisematta RichTextBox1 = bstr(0): Erase bstr Exit Sub Case 239 'UTF-8 bstr(0) = Right(bstr(0), Len(bstr(0)) - 3) For i = 128 To 255 Select Case i 'jos halutaan esim. à yms niin lista venyy... ' (tämä "¤" on tässä tapauksessa syvältä) Case 132, 133, 150, 164, 165, 182 If InStr(bstr(0), CStr(Chr(i))) > 0 Then bstr(0) = Replace(bstr(0), CStr(Chr(i)), CStr(Chr(i + 64))) End If Case 194, 195 If InStr(bstr(0), CStr(Chr(i))) > 0 Then bstr(0) = Replace(bstr(0), CStr(Chr(i)), "") End If End Select Next i RichTextBox1 = bstr(0): Erase bstr Exit Sub Case 254 'Unicode Big endian bstr(0) = Right(bstr(0), Len(bstr(0)) - 3) bstr(0) = Replace(bstr(0), CStr(Chr(10)), "") RichTextBox1 = bstr(0): Erase bstr Exit Sub Case 255 'Unicode Dim xstep As Integer bstr(0) = Right(bstr(0), Len(bstr(0)) - 1) xstep = 244 For i = 10 To 255 Step xstep If InStr(bstr(0), CStr(Chr(i))) > 0 Then bstr(0) = Replace(bstr(0), CStr(Chr(i)), "") End If If i = 244 Then xstep = 1 Next RichTextBox1 = bstr(0): Erase bstr Exit Sub End Select End Sub
-Nea-
Heippa taas!
EDIT: Case Else' ANSI
Aihe on jo aika vanha, joten et voi enää vastata siihen.