Słów kilka o stronach kodowych (Code Page).
7-bitowy kod ASCII
Dawno, dawno temu zestaw znaków kodowany był jako 7-bitowy kod ASCII, który przyporządkowywał liczby z zakresu 0−127 literom alfabetu angielskiego, cyfrom, znakom przestankowym i innym symbolom oraz poleceniom sterującym.
8-bitowy kod ASCII
Ponieważ kod ASCII był 7-bitowy, a już od dawna komputery operują na 8-bitowych bajtach, dodatkowy (ósmy) bit został wykorzystany na powiększenie zbioru kodowanych znaków ze 128 znaków do 256 znaków. W ramach 256 znaków nie było możliwości stworzenie uniwersalnego zestawu obejmującego znaki wszystkich alfabetów. Powstało więc wiele różnych rozszerzeń ASCII wykorzystujących ósmy bit, które zostały nazywane stronami kodowymi (Code Page) i którymi w jakiś sposób trzeba było zarządzać.
Unicode
Próbą rozwiązania problemu stron kodowych było wprowadzenie zestawu znaków Unicode, obejmującego ponad milion znaków wszystkich alfabetów świata, nawet takich jak hieroglify. Unicode jest jednak tylko zestawem samych znaków, więc aby go zastosować, korzysta się z systemów ich kodowania, do których należą m.in. UTF8, UTF16 i UTF32 Również kodowanie UTF8 można uważać za rozszerzenie ASCII, tutaj jednak dodatkowe znaki są kodowane na 2 i więcej bajtach.
Częściej używane inne strony kodowe
- • Windows 1250
- strona kodowa używana w systemie Microsoft Windows do reprezentowania tekstów w językach Europy środkowej i wschodniej, które używają alfabetu łacińskiego, takich jak polski, czeski, słowacki, węgierski, słoweński, bośniacki, chorwacki, serbski (alfabet łaciński), rumuński i albańskim. Może być również używana do tekstów w języku niemieckim, gdyż teksty niemieckojęzyczne zakodowane w Windows-1250 i Windows-1252 są identyczne.
- • ISO 8859-2
-
znany jako ISO Latin-2, bądź alfabet łaciński dla Europy środkowej i wschodniej, składa się ze 191 znaków łacińskiego pisma,
z czego każdy znak zapisywany jest przy pomocy ośmiu bitów.
Używając tego zestawu znaków da się zapisać teksty w językach bośniackim, chorwackim, czeskim, węgierskim, polskim, rumuńskim, serbskim, serbsko–chorwackim, słowackim, słoweńskim. Dodatkowo nadaje się do przedstawienia kilku zachodnioeuropejskich języków takich jak język niemiecki, czy też angielski, choć dla tych języków powinno się zastosować stronę kodową ISO 8859-1.
Dawniej większość polskich stron internetowych (poprawnie wyświetlanych)☺ zapisywanych było w formacie ISO 8859-2. - • UTF8
-
system kodowania Unicode, wykorzystujący od 1 do 6 bajtów do zakodowania pojedynczego znaku, w pełni kompatybilny z ASCII.
Jest najczęściej wykorzystywany do przechowywania tekstu w plikach i w komunikacji sieciowej.
Standard ten, rozwiązuje problemy jakie stwarzały wcześniej opisane strony kodowe Windows 1250 oraz ISO 8859-2 gdyż obsługuje wiele języków i wszystkie nowoczesne aplikacje obsługują ten format kodowania tekstu. Bogactwo znaków UTF8, nie tylko diakrytycznych, umożliwia stosowanie przeróżnych znaków i symboli np. ⊗ ⊥ ⊄ ♠ ♣ ♥ ♦ ≅ ∴ ∫ ∑ ∉
Obecnie strony internetowe są najczęściej zapisywane w formacie UTF8. - • 852
-
Strona kodowa 852 używana jest w wierszu poleceń cmd.exe.
Po wywołaniu polecenia Dir i przekierowaniu zwracanego strumienia do pliku tekstowego:
Dir C:\Test\* /A:D /B /S > C:\Test\~Dir2File.txt
otrzymamy plik wynikowy zawierający tekst zgodny ze stroną kodową 852. Testowy podfolder o nazwie „Gżegżółka” zapisany będzie jako „Gľegľ˘ka” a podfolder „Pójść” jako „P˘j†”
Tekst pliku wymaga więc konwersji na format Unicode, bądź wcześniejszej zmiany strony kodowej interpretatora poleceń cmd.exe na Windows 1250. - • Inne strony kodowe
-
Pełny wykaz stron kodowych MS Windows znajduje się na stronie:
Code Page Identifiers
Zestawienie najczęściej używanych stron kodowych: Code Page Nazwa Typ Opis 852 ibm852 OEM Latin 2 Środkowoeuropejski (DOS) Standard ANSII Windows 1250 Windows-1250 ANSI Środkowoeuropejski (Windows) 1251 Windows-1251 ANSI Cyrylica (Windows) 1252 Windows-1252 ANSI Zachodnia Europa (Windows) 1253 Windows-1253 ANSI Grecki (Windows) 1254 Windows-1254 ANSI Turecki (Windows) 1255 Windows-1255 ANSI Hebrajski (Windows) 1256 Windows-1256 ANSI Arabski (Windows) 1257 Windows-1257 ANSI Baltic (Windows) 1258 Windows-1258 ANSI Wietnamski (Windows) Standard ISO 8859 28591 iso-8859-1 Latin 1 alfabet łaciński dla Europy zachodniej 28592 iso-8859-2 Latin 2 alfabet łaciński dla Europy środkowej i wschodniej 28593 iso-8859-3 Latin 3 alfabet łaciński dla Europy południowej 28594 iso-8859-4 Latin 4 alfabet łaciński dla Europy północnej (bałtyckie) 28595 iso-8859-5 - cyrylica 28596 iso-8859-6 - alfabet arabski 28597 iso-8859-7 - alfabet grecki 28598 iso-8859-8 - alfabet hebrajski ISO-Visual (porządek wizualny) 28599 iso-8859-9 - alfabet turecki Standard Unicode 65000 utf-7 - Unicode (UTF-7) 65001 utf-8 - Unicode (UTF-8)
Funkcje konwertujące tekst z ASCII na UTF8 oraz z UTF8 na ASCII
Na stronie ASCII »» UTF8 przedstawiłem funkcję konwertującą ciąg znaków z formatu Unicode na ciąg znaków zgodny z określoną stroną kodową ASCII, w tym także na format wielobajtowy np. UTF8, a na stronie UTF8 »» ASCII. przedstawiłem odwrotną funkcję, konwertującą ciąg znaków z formatu ASCII na format Unicode (domyślną stroną kodową ASCII).
A może uniwersalna funkcja konwertująca tekst na dowolną stronę kodową
Po tak długim wstępie pozostało tylko napisać funkcję konwertującą tekst z jednej strony kodowej na inną, w tym również konwersja z ASCII » UTF8 oraz z UTF8 » ASCII.
• Użyte funkcje API
- Funkcja MultiByteToWideChar(...) która konwertuje tekst wejściowy ze strony kodowej ASCII, lub UTF8 na format Unicode (ciąg znaków UTF-16). Konwertowany tekst wejściowy nie musi być zestawem znaków wielobajtowych.
- Funkcja WideCharToMultiByte(...) która konwertuje ciąg znaków z formatu Unicode na jednobajtowy ciąg znaków zgodny z określoną stroną kodową ASCII lub na ciąg znaków w formacie wielobajtowym np. UTF8.
- funkcja GetACP() która zwraca bieżący identyfikator strony kodowej ANSI Windows (ACP) dla systemu operacyjnego
Konwersja tekstu pomiędzy stronami kodowymi, także wielobajtowymi np. UTF8
⊗ Funkcja tekstCodePageToCodePage( _ sStrIn As String, _ lFromCP As Long, _ lOutCP As Long) As String
- Konwertuje ciąg znaków (tekst) z jednej strony kodowej, na drugą stronę kodową. Konwersja tekstu nie ogranicza się do konwersji pomiędzy jednobajtowymi zestawami znaków ASCII, lecz możliwa jest również konwersję tekstu zgodnego z wielobajtowym zestawami np. UTF8
- argumenty:
- sStrIn
- ciąg znaków który ma zostać przekonwertowany na docelową stronę kodową
- sStrIn
- identyfikator strony kodowej ANSI Windows (ACP), określający format tekstu wejściowego sStrIn
- sStrIn
- identyfikator strony kodowej ANSI Windows (ACP), na którą ma zostać przekonwertowany ciąg wejściowy sStrIn
- zwraca:
-
Zwraca ciąg znaków w formacie zgodnym z identyfikatorem lOutCP docelowej strony kodowej ANSI Windows (ACP) . Przy niepowodzeniu zwraca ciąg zerowej długości "".
- autor: Zbigniew Bratko
- data: 03.02.2018
Option Compare Database Option Explicit #If VBA7 Then Private Declare PtrSafe Function WideCharToMultiByte Lib "kernel32" ( _ ByVal CodePage As Long, _ ByVal dwFlags As Long, _ ByVal lpWideCharStr As LongPtr, _ ByVal cchWideChar As Long, _ ByVal lpMultiByteStr As String, _ ByVal cchMultiByte As Long, _ ByVal lpDefaultChar As LongPtr, _ ByVal lpUsedDefaultChar As LongPtr) As Long Private Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" ( _ ByVal CodePage As Long, _ ByVal dwFlags As Long, _ ByVal lpMultiByteStr As String, _ ByVal cchMultiByte As Long, _ ByVal lpWideCharStr As LongPtr, _ ByVal cchWideChar As Long) As Long Private Declare PtrSafe Function GetACP Lib "kernel32" () As Long #Else Private Declare Function WideCharToMultiByte Lib "kernel32.dll" ( _ ByVal CodePage As Long, _ ByVal dwFlags As Long, _ ByVal lpWideCharStr As Long, _ ByVal cchWideChar As Long, _ ByVal lpMultiByteStr As String, _ ByVal cchMultiByte As Long, _ ByVal lpDefaultChar As Long, _ ByVal lpUsedDefaultChar As Long) As Long Private Declare Function MultiByteToWideChar Lib "kernel32.dll" ( _ ByVal CodePage As Long, _ ByVal dwFlags As Long, _ ByVal lpMultiByteStr As String, _ ByVal cchMultiByte As Long, _ ByVal lpWideCharStr As Long, _ ByVal cchWideChar As Long) As Long Private Declare Function GetACP Lib "kernel32" () As Long #End If Public Function tekstCodePageToCodePage( _ sStrIn As String, _ lFromCP As Long, _ lOutCP As Long) As String Dim lLenStrOut As Long Dim sAscii As String Dim lLenAscii As Long Dim lCurrentCP As Long ' pobierz aktualna stronę kodową lCurrentCP = GetACP If lFromCP = lCurrentCP Then ' nie konwertuj, ciąg wejściowy jest zgodny z aktualną stroną kodową sAscii = sStrIn Else lLenAscii = MultiByteToWideChar(lFromCP, 0&, sStrIn, Len(sStrIn), 0&, 0&) ' przygotuj bufor na przyjęcie ciągu po konwersji sAscii = String$(lLenAscii, vbNullChar) ' konwertuj wejściowy ciąg na ASCII (bieżącą stronę kodową) lLenAscii = MultiByteToWideChar(lFromCP, 0&, sStrIn, Len(sStrIn), _ StrPtr(sAscii), lLenAscii) End If If lOutCP = lCurrentCP Then ' nie konwertuj, ciąg wyjściowy sAscii jest zgodny z aktualną stroną kodową tekstCodePageToCodePage = sAscii Else ' pobierz wielkość potrzebnego buforu na wyjściowy ciąg znaków (strona kodowa lOutCP) lLenStrOut = WideCharToMultiByte(lOutCP, 0&, StrPtr(sAscii), Len(sAscii), 0&, 0&, 0&, 0&) ' przygotuj bufor na przyjęcie ciągu po konwersji tekstCodePageToCodePage = String$(lLenStrOut, vbNullChar) ' konwertuj ciąg na ASCII na określoną stronę kodową lOutCP lLenStrOut = WideCharToMultiByte(lOutCP, 0&, StrPtr(sAscii), Len(sAscii), _ tekstCodePageToCodePage, lLenStrOut, 0&, 0&) End If End Function
Test funkcji
Do testów weźmiemy tekst zawierający dość dużo polskich znaków diakrytycznych i spróbujmy przekonwertować ten tekst ze strony kodowej Windows-1250 (ANSI Środkowoeuropejski Windows) na format UTF8 (65001), potem na stronę kodową 852 (ibm852 Środkowoeuropejski DOS), natępnie na iso-8859-2 (Latin 2, alfabet łaciński dla Europy środkowej i wschodniej) i z powrotem na Windows-1250 (ANSI Środkowoeuropejski Windows).
Private Const cMyString As String = _ "Rzekł pajączek do pajączki:" & vbNewLine & _ "Popatrz, ja mam złote rączki!" & vbNewLine & _ "Już uprzędłem dla was nową" & vbNewLine & _ "Pajęczynę własnościową." & vbNewLine & _ "Będziesz pewnie bardzo rada," & vbNewLine & _ "Bo to cud, mucha nie siada!" & vbNewLine & _ "Na to ona z gniewem wrzaśnie:" & vbNewLine & _ "A ma, durniu, siadać właśnie!" & vbNewLine & _ " (Bogdan Brzeziński)" Public Function testCP() As String testCP = tekstCodePageToCodePage( _ tekstCodePageToCodePage( _ tekstCodePageToCodePage( _ tekstCodePageToCodePage( _ cMyString, 1250, 65001), 65001, 852), 852, 28592), 28592, 1250) End Function
Po wywołaniu w oknie „Immediate” funkcji testCP(), która wykonuje cztery kolejne konwersje tekstu cMyString na następujące strony kodowe 1250 » 65001 » 28592 » 1250, otrzymujemy tekst taki sam jak tekst wejściowy cMyString przekazany do funkcji testCP(). Można powiedzieć, że funkcja konwertująca w tych przypadkach działa poprawnie ☺.
Tekst wynikowy po czterokrotnej konwersji.
Konwersja tekstu ASCII na format UTF8.
Funkcję tekstCodePageToCodePage(...) możemy wykorzystać zamiast przedstawionej na stronie ASCII »» UTF8 funkcji konwertującej tekst ASCII (1250) na format UTF8.
Jeżeli funkcję tekstCodePageToCodePage(...) wywołamy z argmentami lFromCP = 1250 oraz lOutCP = 65001, to możemy funkcję tą wykorzystać do konwertowania tekstu ze strony kodowej ASCII (1250) na format UTF8 zamiast przedstawionej na stronie ASCII »» UTF8 funkcji konwertującej tekst.
Public Function AsciiToUTF8(sStrIn As String) As String AsciiToUTF8 = tekstCodePageToCodePage(sStrIn, 1250, 65001) End Function
Konwersja tekstu UTF8 na domyślną stronę kodową ASCII.
Jeżeli funkcję tekstCodePageToCodePage(...) wywołamy z argmentami lFromCP = 65001 oraz lOutCP = 1250, to możemy funkcję tą możemy wykorzystać do konwertowania tekstu z formatu UTF8 na domyślną stronę kodową ASCII (1250) zamiast przedstawionej na stronie UTF8 »» ASCII funkcji konwertującej tekst.
Public Function UTF8ToAscii(sStrIn As String) As String UTF8ToAscii = tekstCodePageToCodePage(sStrIn, 65001, 1250) End Function