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 FunctionTestaamaton.
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 SubHeippa!
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 SubEDIT: 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 ClassEnsimmä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 SubValmis 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.