Spis treści Skorowidz Poziom główny Poziom nadrzędny Wstecz Dalej Zadania ©

Znakowy zapis informacji. Pliki znakowe

Kody informacyjne i zestawy znaków

Kod informacyjny

W cyfrowym zapisie informacji, nawet przeznaczonej do czytania przez ludzi, nie występują znaki graficzne, tylko ich numery. Przyporządkowanie numer ⟼ znak graficzny lub specjalny ma więc ogromne znaczenie przy komunikacji, zwłaszcza między różnymi systemami. Gdyby danej liczbie w różnych systemach odpowiadały różne znaki, występowałyby na co dzień poważne kłopoty z interpretacją przesyłanej informacji. Do pewnego stopnia tak zresztą jest.

Funkcja φ: numerznak nosi nazwę kodu informacyjnego.

Stosowanie danego kodu informacyjnego w systemie komputerowym wiąże się z jego obsługą przez urządzenia peryferyjne: monitory i drukarki (wyświetlanie i drukowanie znaków), klawiatury (wprowadzanie znaków), oraz funkcje systemu operacyjnego (kolejność znaków w alfabecie, niezbędna np. przy porządkowaniu danych). Dla pojedynczego użytkownika fakt, jakiego kodu używa, nabiera istotnego znaczenia w razie wymiany jakiejkolwiek informacji między systemami albo programami — choćby przez Internet lub pocztę elektroniczną.

Numer znaku a systemy liczbowe

Podając jawnie numery konkretnych znaków kodu informacyjnego (np. w dokumentacji technicznej, ale także jako dane dla programów) stosujemy z reguły system pozycyjny, jednak niekoniecznie dziesiętny. Zapis pojedynczego znaku w pamięci cyfrowej ma postać ciągu bitów, odpowiadającego ciągowi cyfr dwójkowych numeru tego znaku. Programiści chętnie posługują się systemem szesnastkowym (którego każda cyfra grupuje 4 cyfry dwójkowe), czasami można spotkać zapis ósemkowy (każda cyfra grupuje 3 cyfry dwójkowe) i oczywiście dziesiętny. Przykłady notacji zamieszczono w poniższej tabeli:

Notacja dziesiętna, dwójkowa i szesnastkowa liczb całkowitych
Zapis dziesiętnyZapis dwójkowyZapis szesnastkowya
0 '0 x0
1 '1 x1
2 '10 x2
3 '11 x3
9 '1001 x9
10 '1010 xa
11 '1011 xb
15 '1111 xf
16 '10000 x10
17 '10001 x11
122 '1111010 x7a
123 '1111011 x7b
127 '1111111 x7f
128 '10000000 x80
129 '10000001 x81
255 '11111111 xff
256'100000000x100
  1. Oprócz postaci „x21” zapisu szesnastkowego można napotkać również postaci: „$21” oraz „21h”.

Jak wiadomo, w systemach komputerowych preferowanym sposobem zapisu liczb całkowitych jest zapis w systemie dwójkowym (czyli binarnym). Z tego względu pożądane jest, by liczba znaków ujętych kodzie informacyjnym stanowiła pełną potęgę dwójki. Omówione niżej najważniejsze kody informacyjne składają się ze 128, 256 lub 65536 znaków. Liczba bitów przeznaczonych na zapis pojedynczego znaku przechowywanej informacji może być stała, jednak w niektórych kodach bywa różna dla różnych znaków.

Standard ASCII

W obecnej chwili dominującym w świecie kodem informacyjnym jest tzw. rozszerzony kod ASCII (American Standard Code for Information Interchange, czyli Znormalizowany Amerykański Kod do Wymiany Informacji). Dopuszcza on korzystanie z 256 różnych znaków, z czego definiuje jednoznacznie ich połowę, to jest znaki noszące numery od 0 do 127. Stanowią one tzw. podstawowy zestaw ASCII. Jego pierwsze 32 znaki to tzw. znaki specjalne, mające znaczenie przy sterowaniu urządzeniami. Ich postać graficzna nie jest wykorzystywana.

[ Znaki specjalne kodu informacyjnego ASCII ]

Niżej wymieniamy najważniejsze znaki specjalne ASCII.

Wybrane znaki sterujące kodu ASCII
PrzeznaczenieNazwaNumer ASCII
DziesiętnySzesnastkowy
znak pustyNUL0x0
awaryjne przerwanie działania programu (Ctrl+C)ETX = end of text3x3
koniec transmisji danych (Ctrl+D) — systemy UNIXEOT = end of transmission4x4
usunięcie poprzedzającego znaku (Backspace)BSP = backspace8x8
znak tabulacji (Tab)HT = horizontal tab9x9
koniec wierszaLF = line feed10xa
koniec stronyFF = form feed12xc
powrót do początku wiersza CR = carriage return13xd
koniec danych w pliku (Ctrl+Z) — systemy WindowsEOF = end of file26x1a
znak sterujący (Escape): początek rozkazu
lub wycofanie z podejmowania decyzji
ESC = escape27x1b

Zakres znaków o numerach od 32 (spacja) do 127 obejmuje podstawowe znaki graficzne: litery łacińskie duże i małe, cyfry, znaki przestankowe, niektóre symbole działań — z grubsza rzecz biorąc jest to repertuar znaków maszyny do pisania.

[ Znaki zestawu podstawowego ASCII ]

Kilka przykładowych znaków zestawu podstawowego ASCII wymieniono w poniższej tabeli:

Numery dziesiętne, dwójkowe i szesnastkowe wybranych znaków ASCII
ZnakZapis numerycznyUwagi
dziesiętnydwójkowyszesnastkowy
32'0100000x20spacja
!33'0100001x21wykrzyknik
"34'0100010x22cudzysłów techniczny
'39'0100111x27apostrof
-45'0101101x2dłącznik
048'0110000x30cyfra „zero”
149'0110001x31cyfra „jeden”
957'0111001x39cyfra „dziewięć”
@64'1000000x40„atka”, „przy” lub „adres” (nazwa „małpa” jest niepoprawna)
A65'1000001x41
B66'1000010x42
Z90'1011010x5a
[91'1011011x5b
`96'1100000x60odwrócony apostrof
a97'1100001x61
b98'1100010x62
z122'1111010x7a
{123'1111011x7b
127'1111111x7fusunięcie następnego znaku (DEL = delete)

Interesująca jest historia znaku numer 127. Jest to znak sterujący nakazujący usunięcie następującego po nim znaku. W zasadzie wszystkie znaki sterujące ASCII mają numery niższe od 32; ten jeden jest wyjątkiem. Wyjaśnienie tego faktu wiąże się ze sposobem zapisywania znaków na taśmach papierowych w systemach telegraficznych. Na taśmie było 7 ścieżek, z których każda odpowiadała jednej pozycji cyfr dwójkowych. W miejscu zapisania znaku każda ścieżka miała dziurkę lub nie, zależnie od wartości odpowiedniej cyfry dwójkowej w numerze znaku. Wstawienie znaku DEL, z uwagi na jego numer 127 = '1111111, powodowało przedziurkowanie wszystkich 7 ścieżek, czyli skutecznie uniemożliwiało wykorzystanie tego miejsca na taśmie.

Standard ASCII nie określa postaci graficznej znaków o numerach wyższych od 127.

[ Znaki zestawu rozszerzonego ASCII ]

Systemy komputerowe posługujące się kodami 256-znakowymi wykorzystują ten zakres numeracji na różne sposoby, przyporządkowując liczbom postać graficzną liter alfabetów narodowych, symboli matematycznych itp. Te przyporządkowania są standaryzowane jako tzw. strony kodowe (code pages, cp). I tak w Polsce, dla umożliwienia kodowania w plikach znakowych liter polskiego alfabetu, używano różnych standardów, z których większość ma obecnie znaczenie wyłącznie historyczne.

„Standardy” zapisu polskiego alfabetu

Istnieją również kody informacyjne niezgodne z ASCII. Najważniejszym z nich jest kod EBCDIC (Extended Binary Coded Decimal Interchange Code, czyli Rozszerzony Przechowywany Binarnie Dziesiętny Kod Wymiany Informacji), używany w niektórych dużych systemach komputerowych. W skład kodu EBCDIC, tak samo jak rozszerzonego kodu ASCII, wchodzi 256 znaków kodowanych za pomocą jednego bajta, lecz numery tych samych znaków w obu porównywanych kodach nie są zgodne ze sobą.

Standard UNICODE

Istotnym rozszerzeniem standardu ASCII jest standard UNICODE. We wstępie do dokumentacji tego standardu, opracowanej przez zarządzającą nim organizację, czytamy:

What is Unicode?

Unicode provides a unique number for every character,
no matter what the platform,
no matter what the program,
no matter what the language.

Od wydania pierwszej wersji w roku 1991, UNICODE ugruntowuje swoją pozycję jako standard ponadsystemowy i ponadnarodowy nie tylko z nazwy.

Postać graficzna pierwszych 128 znaków UNICODE (o numerach 0–127) pokrywa się ze standardem ASCII. Oprócz liter różnych alfabetów, UNICODE zawiera także obszerny zestaw znaków typograficznych. Niektóre z nich przedstawiamy w poniższej tabeli.

Wybrane znaki typograficzne w zestawie UNICODE
NazwaZnakNumer UNICODE
dziesiętnyszesnastkowy
podwójny cudzysłów otwierający8222x201e
podwójny cudzysłów zamykający 8221x201d
cudzysłów kątowy otwierający » 187xbb
cudzysłów kątowy zamykający « 171xab
spacja zwykła 32x20
spacja niełamliwa  160xa0
wielokropek 8230x2026
półpauza 8211x2013
pauza 8212x2014
znak minus 8722x2212
Znaki UNICODE począwszy od numeru 32 do 65535
(uwaga! plik jest duży, ładowanie i formatowanie może trwać długo)

Szerszy wykaz jest zaprezentowany m.in. w Wikipedii.

We wczesnych wersjach UNICODE myślano o numerowaniu znaków za pomocą liczb 16-bitowych. Pozwoliłoby to na zdefiniowanie 216 = 65536 różnych znaków. Liczba ta starczyłaby z okładem na wszystkie alfabety świata.

Pierwsza edycja UNICODE, ogłoszona w roku 1991, obejmowała 7096 znaków. W edycji 3.1 opracowanej w roku 2001 przekroczono granicę 65536 znaków. Od tej chwili należy myśleć numeracji znaków UNICODE jako o numeracji otwartej. Obecnie, w wersji 15.0 z września 2022 r., obejmuje on 149186 znaków, włączając w to znaki graficzne oraz pewną liczbę symboli pomocniczych (patrz The Unicode Standard version 15.0 — Core Specification. Appendix D).

Organizacja normalizacyjna koordynująca prace nad UNICODE publikuje aktualne tabele znaków zawierające zestawienia ich numerów, nazw, postaci graficznej i przeznaczenia. Przeglądając te tabele zauważymy, że standard obejmuje nie tylko litery różnych alfabetów, ale także bardzo wiele zestawów symboli specjalistycznych. Tym tłumaczy się pozornie niewyobrażalna liczba 100000 znaków.

Szczególnie godne polecenia są części opisowe tabel, zawierające opis przeznaczenia danego znaku i odsyłacze do znaków o zbliżonej postaci graficznej, często mylonych w użyciu. Do ustaleń UNICODE dostosowują się wszyscy zainteresowani — od autorów oprogramowania, przez projektantów układów fontów komputerowych, po autorów i redaktorów dokumentów korzystających z kodu informacyjnego jako nośnika informacji.

W zapisie cyfrowym nie da się bezpośrednio korzystać z otwartej skali liczb. Dlatego reprezentacja cyfrowa znaków UNICODE w systemach komputerowych jest przedmiotem osobnych postanowień. Istnieje wiele szczegółowych standardów zapisu informacji tekstowej, znanych jako UTF (z ang. Unicode Transformation Formats). Znaki zestawu podstawowego ASCII są w większości z nich, z małymi wyjątkami, zapisywane bezpośrednio przy użyciu jednego bajta pamięci. Pozostałe znaki należące do UNICODE są kodowane. W odróżnieniu od stron kodowych, które pozwalają na jednoczesne korzystanie jedynie z 256 znaków, każdy z formatów UTF daje możliwość przechowywania tekstów zawierających dowolne znaki UNICODE.

Dla zgodności wstecznej nadal przewiduje się możliwość korzystania z 256-znakowych zestawów znaków, opisanych międzynarodową normą ISO-8859. Z użytkowego punktu widzenia są one takie same, jak zestawy rozszerzone ASCII. Jednak poprzednio były one interpretowane jako rozszerzenie dostępnego zestawu znaków, teraz zaś — jako 256-elementowy podzbiór szerszej rodziny znaków UNICODE.

Porównajmy poniższe przykłady pod względem treściowym i pod względem objętości przechowujących je plików:

Więcej historycznych materiałów o zapisie informacji w plikach znakowych, o kodach informacyjnych dla języka polskiego i o związanych z nimi zagadnieniach znajdziesz na Polskiej Stronie Ogonkowej. Zachęcam do lektury.

Konwersja wiadomości do innego kodu informacyjnego

Wiadomość zakodowaną w danym kodzie informacyjnym da się bez przeszkód odczytać przy użyciu tego samego kodu (niezależnie od tego, co to jest za kod).

Odczytywanie informacji przekazanej w pewnym kodzie informacyjnym
WiadomośćPójdźże! kiń tę chmurność w głąb flaszy!
Kodowanie ISO-Latin-2
Zapis na nośniku802431061001881911013332107105241321162343299104109117114110111182230321193210317917798321021089711512212133
Odczyt ISO-Latin-2
Wiadomość odczytanaPójdźże! kiń tę chmurność w głąb flaszy!

Jeżeli do odczytywania wiadomości używamy środowiska korzystającego z innego kodu, mogą pojawić się niespodzianki. Oto przykład:

Odczytywanie informacji przekazanej w pewnym kodzie informacyjnym za pomocą innego kodu informacyjnego
WiadomośćPójdźże! kiń tę chmurność w głąb flaszy!
Kodowanie ISO-Latin-2
Zapis na nośniku802431061001881911013332107105241321162343299104109117114110111182230321193210317917798321021089711512212133
Odczyt cp1250
Wiadomość odczytanaPójdĽże! kiń tę chmurnoć w gł±b flaszy!

W takiej sytuacji trzeba albo dopasować sposób czytania do sposobu zakodowania wiadomości, albo przekodować plik przed odczytaniem:

Odczytywanie informacji przekazanej w pewnym kodzie informacyjnym poprzedzone konwersją do kodu używanego przez odbiorcę
WiadomośćPójdźże! kiń tę chmurność w głąb flaszy!
Kodowanie ISO-Latin-2
Zapis na nośniku802431061001881911013332107105241321162343299104109117114110111182230321193210317917798321021089711512212133
Konwersja
ISO-Latin-2 → cp1250
Zapis na nośniku802431061001591911013332107105241321162343299104109117114110111156230321193210317918598321021089711512212133
Odczyt cp1250
Wiadomość odczytanaPójdźże! kiń tę chmurność w głąb flaszy!

Konwersja z jednego kodu informacyjnego do innego nie wydaje się trudnym zadaniem — trzeba tylko zastąpić numery znaków innymi numerami. Ale… rzecz się komplikuje, kiedy dwa kody opisują istotnie różne zestawy znaków graficznych. Wtedy konwersja może wiązać się z częściową utratą informacji, czyli pewnego rodzaju uszkodzeniem wiadomości (jeśli nasza wiadomość zawiera choćby jeden znak, który nie jest opisany w docelowym kodzie). Taka sytuacja jest typowa dla wiadomości zapisanych za pomocą dużego zestawu znaków (np. UNICODE) podczas konwersji do alfabetu uboższego (np. ISO-Latin-2), tak jak w kolejnym przykładzie.

Konwersja wiadomości do innego kodu może się wiązać z utratą informacji (1)
WiadomośćPójdźże! kiń tę chmurność pisał Jan Gwalbert Pawlikowski.
Kodowanie UNICODE
Zapis na nośniku8222802431061003783801013332107105324321162813299104109117114110111347263328230822132821232112105115973223274971103271119971089810111411632809711910810510711111911510710546
Konwersja
UNICODE → ISO-Latin-2
Zapis na nośniku(brak)
−1
80243106100188191101333210710524132116234329910410911711411011118223032(brak)
−1
(brak)
−1
32(brak)
−1
32112105115971793274971103271119971089810111411632809711910810510711111911510710546
Odczyt ISO-Latin-2
Wiadomość odczytana?Pójdźże! kiń tę chmurność ?? ? pisał Jan Gwalbert Pawlikowski.

Podobna sytuacja występuje podczas konwersji do alfabetu zawierającego zupełnie inne znaki.

Konwersja wiadomości do innego kodu może się wiązać z utratą informacji (2)
WiadomośćPójdźże! kiń tę chmurność w głąb flaszy!
Kodowanie ISO-Latin-2
Zapis na nośniku802431061001881911013332107105241321162343299104109117114110111182230321193210317917798321021089711512212133
Konwersja
ISO-Latin-2 → IBM-Latin-1 (cp850)
Zapis na nośniku80162106100(brak)
−1
(brak)
−1
1013332107105(brak)
−1
32116(brak)
−1
3299104109117114110111(brak)
−1
(brak)
−1
3211932103(brak)
−1
(brak)
−1
98321021089711512212133
Odczyt IBM-Latin-1
Wiadomość odczytanaPójd??e! ki? t? chmurno?? w g??b flaszy!

Możliwe jest też rozwiązanie „inteligentne”, stosowane w wielu systemach użytkowych. Konwersja jest w nim rozumiana szerzej, niż zwykła zamiana numerów odpowiadających znakom o tej samej postaci graficznej w kodzie źródłowym i kodzie docelowym. Konwersję „inteligentną” można zdefiniować jako próbę możliwie wiernego przekazania postaci graficznej komunikatu za pośrednictwem alfabetu nie zawierającego kompletu niezbędnych znaków. Na ogół konwersja taka nie jest różnowartościowa, więc również wiąże się ze stratą informacji — czasem nieważnych, ale niekiedy bardzo istotnych. Na pewno zaś nie jest odwracalna, więc wynikowy tekst również jest w pewien sposób zubożony (czyli uszkodzony). Poniższy przykład ilustruje niektóre problemy związane z tym zagadnieniem (w sposób nieco przerysowany, gdyż trudno znaleźć dzisiaj środowisko korzystające bezpośrednio z 7-bitowego kodu ASCII. Jednak konwersje z UNICODE do kodów 256-znakowych zdarzają się na porządku dziennym i prowadzą do tych samych problemów).

Konwersja „inteligentna” nie chroni przed utratą informacji
WiadomośćPójdźże! kiń tę chmurność pisał Jan Gwalbert Pawlikowski.
Kodowanie UNICODE
Zapis na nośniku8222802431061003783801013332107105324321162813299104109117114110111347263328230822132821232112105115973223274971103271119971089810111411632809711910810510711111911510710546
Konwersja
UNICODE →  7-bit ASCII
↙↓↘
Zapis na nośniku34801111061001221221013332107105110321161013299104109117114110111115993246464634324532112105115971083274971103271119971089810111411632809711910810510711111911510710546
Odczyt  7-bit ASCII
Wiadomość odczytana"Pojdzze! kin te chmurnosc ..." - pisal Jan Gwalbert Pawlikowski.

W wielu typowych sytuacjach konwersji dokonują automatycznie programy użytkowe i użytkownik nie uczestniczy w niej czynnie. Niekiedy jednak trzeba przeprowadzić konwersję samodzielnie. Istnieją specjalistyczne programy przeznaczone specjalnie do tego celu. W systemach GNU odpowiedni program systemowy nosi nazwę iconv.

Sposób korzystania z programu iconv jest opisany w jego instrukcji użytkowania.

Przypuśćmy, że w pliku dane.txt mamy wiadomość zapisaną za pomocą kodu informacyjnego ISO-Latin-2, i że chcemy utworzyć plik nowedane.txt z tą samą wiadomością zapisaną w kodzie UTF-8. Możemy to zrobić za pomocą programu iconv, wydając polecenie

iconv -f iso-8859-2 -t utf-8 dane.txt > nowedane.txt

Do konwersji stron kodowych można też wykorzystać programy użytkowe pracujące w oparciu o różne kody informacyjne oraz schowek graficznego środowiska pracy. W wielu przypadkach można sobie poradzić za pomocą graficznej przeglądarki internetowej (im nowsza, tym lepiej).

Jeżeli pracujemy nad plikiem danych zapisanym w pewnym kodzie informacyjnym, a jego nowe fragmenty dopisujemy korzystając z innego kodu, do plik jako całość będzie korzystać z wielu kodów informacyjnych. W rzadkich przypadkach jest to nieuniknione (np. tekst zapisany 8-bitowo, zawierający fragmenty po polsku, po niemiecku i po rosyjsku), lecz na ogół sytuacje takie uniemożliwiają dalsze poprawne wykorzystanie zawartości pliku i trzeba ich unikać (np. konwertując tekst przed rozpoczęciem pracy lub dopasowując swoje środowisko pracy do konkretnego kodu informacyjnego). Dla języków europejskich optymalnym wyborem jest kodowanie UTF-8.

Kody informacyjne — ćwiczenia praktyczne

Pożądane umiejętności praktyczne obejmują znajomość najważniejszych kodów informacyjnych:

Trzeba także umieć zamieniać kodu zapisu informacji z danego na inny:

Formaty zapisu informacji w plikach

Pliki tekstowe

W komunikacie tekstowym (znakowym) do zapisu informacji używa się wyłącznie znaków traktowanych jako graficzne nośniki informacji. Tym samym, ważna jest graficzna postać kolejnych znaków, a nie ich numery. Ściślej, numery znaków są ważne tylko o tyle, że zastosowany kod informacyjny (ASCII, UNICODE lub strona kodowa) definiuje ich postać graficzną. W przypadku znaków zestawu rozszerzonego ASCII na wygląd znaku ma wpływ także wybór strony kodowej (np. ISO-Latin-2).

Plik znakowy można czytać jak maszynopis znak po znaku, bez użycia specjalnych programów (formatujących, dekodujących). Tekst w pliku znakowym może być dzielony na wiersze (znakiem końca wiersza) i na strony (znakiem końca strony). Nie ma możliwości określania kroju pisma, jego wielkości ani barwy itp. Nawet informacja o tym, jakiego kodu informacyjnego użyto do zapisania informacji, pochodzi z zewnątrz, a nie jest przechowywana w samym pliku.

Wybrane znaki specjalne i separatory w plikach znakowych
NazwaWyglądNumer ASCII
znak tabulacji 9
koniec wiersza (UNIX) 10
koniec wiersza (DOS) 13,10
koniec wiersza (MacOS) 13
koniec strony 12
koniec danych (DOS) 26
koniec danych (UNIX) 4
spacja 32
znak cala (w plikach ASCII czasami pełni także rolę cudzysłowu)" 34
apostrof ' 39
przecinek , 44
łącznik (w plikach ASCII pełni także rolę znaku minus)- 45
kropka . 46
średnik ; 59
podkreślenie _ 95
odwrócony apostrof` 96

Końce wierszy w plikach znakowych są oznaczane rozmaicie w różnych systemach operacyjnych. Różnice te ilustrujemy przykładami plików powstałych pod kontrolą systemów:

Znaki separujące, czyli tzw. białe znaki, służą do oddzielania od siebie porcji danych, np. słów w pliku znakowym zawierającym tekst lub pól danych w pliku znakowym zawierającym dane tabelaryczne. Standardowymi separatorami są: znak spacji, znak tabulacji i znak końca wiersza. Rolę tę mogą pełnić także inne znaki. Kilka przykładów umieszczonych poniżej prezentuje rozmaite sposoby oddzielania danych w plikach znakowych:

Oczywiście dany znak może pełnić w pliku rolę separatora tylko pod warunkiem, że nie został użyty do zapisu samych danych.

Pliki binarne

W plikach binarnych informacja jest przechowywana inaczej, niż w plikach znakowych. Do zapisu służą te same układy cyfr binarnych, grupowane w bajty — innych sposobów zapisu przecież nie ma — jednak nie są one rozumiane jako numery znaków o żądanej postaci graficznej (czyli nie są przeznaczone bezpośrednio do czytania), lecz są interpretowane jakimś innym sposobem. Szczegóły techniczne takiego sposobu noszą nazwę formatu zapisu. Żeby informacja zapisana za pomocą danego formatu została właściwie zrozumiana, należy ją odczytać korzystając z odpowiedniego algorytmu, zwykle realizowanego przez pewien program komputerowy.

Bardzo ważnym zastosowaniem binarnego zapisu informacji jest zapis samych programów, czyli poleceń dla maszyny, w sposób zrozumiały dla systemu operacyjnego i procesora.

Postać binarna jest też wygodna do przechowywania informacji graficznej (obrazów) oraz dźwiękowej.

Pliki zawierające sformatowane dokumenty, tworzone za pomocą komercyjnych procesorów tekstu, także na ogół mają postać binarną.

Archiwizacja i kompresja plików

Ważne informacje, w tym dane i programy, powinny być zapisywane w wielu egzemplarzach (kopiach), tak by zmniejszyć ryzyko ich utracenia. Kopie zapasowe mogą być zapisywane za pomocą programów archiwizujących, które operują sposobami zapisu danej informacji za pomocą stosunkowo niewielkiej liczby znaków. Jest to tzw. kompresja danych.

Jak działa kompresja

Istnieje wiele różnych technik kompresji danych. Ich szczegółowe omówienie nie mieści się w ramach tego opracowania. Poprzestaniemy na intuicyjnym przykładzie, opartym na pewnym wynalazku z I połowy XIX wieku.

Rozpatrzmy przykładowe zdanie zapisane w języku polskim:

Ala ma kota.

Dla uproszczenia w dalszej części tego przykładu pominiemy spacje i znaki przestankowe, nie będziemy też rozróżniać wielkości liter. Mamy więc następujący napis:

alamakota

Tekst ten zapisany w kodzie ASCII składa się ze znaków o następujących numerach:

 97 
108 
 97 
109 
 97 
107 
111 
116 
 97

Jego zapis dwójkowy na nośniku cyfrowym składa się z następujących wartości bitowych (każda grupa 8 cyfr dwójkowych odpowiada za numer jednego znaku):

01100001 
01101100 
01100001 
01101101 
01100001 
01101011 
01101111 
01110100 
01100001 

Cały przekaz zajmuje 9 bajtów 8-bitowych, czyli 72 bity pamięci. Jednak objętość zapisu można istotnie skrócić nie tracąc nic ze znaczenia przekazu. W 1840 roku Samuel Morse skonstruował kod telegraficzny, używany później przez wiele dziesięcioleci. Korzysta się w nim jedynie z kropek (.), kresek (-) i odstępów międzyznakowych ( ).

W kodzie tym najkrótszą reprezentację mają litery najczęściej występujące w tekstach anglojęzycznych, to znaczy: E (.), T (-), A (.-), N (-.) oraz I (..).

Nasz tekst zakodowany za pomocą tego alfabetu wygląda następująco:

.- .-.. .- -- .- -.- --- - .- 

Użycie znaku separującego jest niezbędne, gdyż poszczególnym literom tekstu odpowiadają różniące się długością ciągi kropek i kresek. Umówmy się, że w zapisie cyfrowym kropkę będziemy oznaczać cyfrą 1, kreskę — cyfrą 2, odstęp zaś — cyfrą 0. Oto ten sam tekst zakodowany za pomocą cyfr zgodnie z umową:

120121101202201202120222020120

Nie jest to zapis binarny, tylko trójkowy, gdyż na każdym miejscu występować może dowolna spośród trzech cyfr: 0, 1 lub 2. Składa się on z 30 cyfr trójkowych, zatem cały tekst ma po zakodowaniu 30 ⋅ log23 ≈ 48 bitów objętości. Jest to znacznie mniej, niż początkowe 72 bity. Po sprowadzeniu powyższego zapisu z trójkowego do binarnego otrzymamy następujący ciąg 47 cyfr dwójkowych:

11011000011111001110010110101011001011110000100

Ich pogrupowanie w bajty 8-bitowe doprowadzi do następującego zapisu:

11011000
01111100
11100101
10101011
00101111
00001000

(brakujący bit w ostatnim bloku uzupełniono wartością 0). Otrzymanym wartościom liczbowym odpowiada następujący komunikat w rozszerzonym kodzie ASCII:

Ø|å«/

To jest właśnie skompresowany komunikat. Taki lub podobny tekst zobaczyłby użytkownik, przeglądając plik skompresowanego archiwum zwykłym edytorem znakowym.

Przykład jest nieco naciągany: w kodzie rozszerzonym ASCII mamy do dyspozycji 256 różnych znaków, podczas gdy kod Morse’a obejmuje tylko 26 liter i 10 cyfr. Gdyby zamiast kodu rozszerzonego ASCII ograniczyć się do pewnego kodu składającego się wyłącznie z małych liter łacińskich, to każdy znak mógłby zajmować tylko 6 bitów (alfabet łaciński zawiera 26 liter) zamiast 8. Zapis całego tekstu miałby wtedy 9 ⋅ 6 = 54 bity objętości. W tym przypadku kod Morse’a nadal kompresowałby informację, ale nie tak bardzo skutecznie.

Można również postawić sprawę odwrotnie i rozpatrzyć użycie „rozszerzonego kodu Morse’a”, który zawierałby kropkowo-kreskowe reprezentacje wszystkich 256 znaków. Należałoby wybrać taki jego wariant, by znakom najbardziej „egzotycznym”, czyli najrzadziej używanym w danym języku, zostały przydzielone najdłuższe sekwencje kropek i kresek. Wtedy efektywność kompresji typowego komunikatu (jak w naszym przykładzie) zostałaby utrzymana.

Przedstawiony przykład daje tylko ogólny pogląd na ideę kompresji: jeśli coś pojawia się często, to musi mieć krótki zapis. Współczesne profesjonalne metody kompresji działają skuteczniej, niż stary kod Morse’a. Pierwszy użytkowy algorytm kompresji danych został podany w 1952 roku przez Davida Huffmana. Znacznie bardziej efektywne algorytmy opracowali w latach 1977–78 Abraham Lempel i Jacob Ziv.

Skompresowane archiwa danych

Archiwum skompresowane jest plikiem binarnym, którego zawartość opisuje (odpowiednio zakodowane) informacje o zawartości innych plików — tak znakowych, jak binarnych. Po skompresowaniu pliku znakowego otrzymujemy archiwum, którego ciąg znaków nie ma bezpośredniego przełożenia na znaki graficzne za pośrednictwem kodu informacyjnego, tak jak to widać w zademonstrowanym wyżej przykładzie.

Jeden skompresowany plik-archiwum może zawierać dane o całej kartotece plików roboczych. Postać skompresowana jest bezpiecznym, dogodnym i rozpowszechnionym sposobem przechowywania, przesyłania i udostępniania danych.

Do utworzenia oraz do rozpakowania pliku archiwum potrzebne jest specjalne oprogramowanie. Znanych jest wiele algorytmów kompresji; niektóre z nich zostały wdrożone w powszechnie dostępnych programach komputerowych. Niektóre systemy operacyjne są standardowo wyposażone w programy archiwizujące; istnieją też liczne programy tego typu rozpowszechniane na zasadach open source i shareware. Programami takimi można tworzyć i odczytywać m.in. archiwa formatów arj, lzh, rar, tar.gz, tar.bz2 i zip. Archiwa wspomnianych wyżej formatów są przenośne, tzn. można je tworzyć i odtwarzać w wielu różnych środowiskach operacyjnych.

Programom przeznaczonym do zarządzania archiwami plików jest poświęcona galeria ilustracji.

Istniejące oprogramowanie archiwizujące jest w stanie tworzyć także archiwa samorozpakowujące (self-extracting, SFX). Archiwum takie ma postać pliku wykonywalnego, którego uruchomienie powoduje odtworzenie zawartości plików spakowanych. Program taki może być wykonany tylko na komputerze określonego typu i pod nadzorem określonego systemu operacyjnego.

Rozpoznawanie formatu pliku

Po czym rozpoznać, w jakim formacie dany plik przechowuje informację? Odpowiedź nie jest oczywista. Najprościej byłoby posłużyć się rozszerzeniem nazwy pliku. Niektóre środowiska użytkownika (np. środowisko graficzne systemów Windows) przyjmują domniemanie, że rozszerzenie nazwy wskazuje na format zapisu. Niestety, to nie zawsze wystarcza: jak wiemy, związek rozszerzenia z formatem jest wyłącznie umowny; każdy użytkownik ma prawo nadać swojemu plikowi danych dowolną legalną nazwę bez względu na zastosowany format zapisu informacji. Jeżeli faktyczny format jest inny niż deklarowany przez rozszerzenie, środowisko nie wykryje tej sprzeczności.

Jest jeszcze inny powód, dla którego rozszerzenie nazwy nie może stanowić podstawy do wnioskowania o formacie. Wiele programów użytkowych wymaga, by przygotowane dla nich pliki danych nosiły określone rozszerzenia. Może się zdarzyć, że dane rozszerzenie (np. dat) jest wymagane przez dwa niezależne programy, lecz każdy z nich wymaga innego formatu zapisu. Zatem bazowanie na samym rozszerzeniu nazwy nie wystarcza do rozstrzygnięcia, z jakim formatem mamy do czynienia w konkretnej sytuacji.

Jeżeli środowisko ma problem z automatycznym rozpoznaniem formatu, możemy próbować ustalić go ręcznie. W przypadku typowych formatów znanych użytkownikowi, często wystarczy obejrzeć plik za pomocą edytora lub przeglądarki plików znakowych. W przypadku większości formatów użytkowych początkowa sekcja pliku pozwala rozpoznać format.

Nie da się jednak powiedzieć, że format jest zawsze rozpoznawalny. Wyobraźmy sobie następujące sytuacje: w pierwszej pewien szczególny program czyta i tworzy dane w swoim własnym formacie, nie opisanym nigdzie poza instrukcją tego programu. W sytuacji drugiej dane zapisane w pewnym powszechnie znanym formacie są wskutek zbiegu okoliczności bardzo podobne do zupełnie innych danych zapisanych w zupełnie innym formacie. W sytuacji trzeciej mamy do czynienia z kilkoma bardzo podobnymi formatami, zaś zawartość pliku nie pozwala na rozstrzygnięcie, z którym z nich konkretnie mamy do czynienia. W każdym z tych przypadków automatyczne rozpoznanie formatu zapisu jest praktycznie niemożliwe.

Zawsze jednak wykonalna powinna być ocena, czy zawartość danego pliku (to znaczy: przechowywana w nim porcja bajtów) jest, czy nie jest dopuszczalna w myśl definicji ustalonego formatu. Ocena taka nosi nazwę walidacji formatu zawartości pliku.

Powodzenie rozpoznania formatu zależy też od oczekiwań użytkownika. Stosunkowo nietrudno jest sprawdzić, że plik jest w formacie znakowym. Jednak rozpoznanie języka naturalnego, za pomocą którego zapisano wiadomość, choć możliwe, jest o wiele trudniejsze. Jeżeli w poszczególnych fragmentach wiadomości użyto wielu różnych języków, sprawa komplikuje się beznadziejnie.

Inny typowy przypadek, kiedy oczekiwania będą zbyt wysokie w stosunku do możliwości, dotyczy tekstów źródłowych programów komputerowych. Nietrudne będzie stwierdzenie, że plik jest znakowy i że zawiera zapis programu komputerowego. Jednak poszczególne języki programowania zbyt mało różnią się między sobą, by dało się opracować niezawodne wskazówki ich automatycznego rozpoznawania.

Uniksopodobne systemy operacyjne są wyposażone w program narzędziowy o nazwie file, który automatyzuje proces rozpoznawania formatu danych. Programu tego można używać także w innych systemach operacyjnych, ale trzeba go sobie zainstalować.

Program file w ogóle nie zwraca uwagi na rozszerzenie nazwy pliku, tylko analizuje początkowy fragment jego zawartości i dopasowuje go do wzorców formatów przechowywanych w bazie danych. Wynik wyprowadza na terminal w postaci zrozumiałej dla użytkownika.

Algorytm działania programu file i sposób jego użytkowania są opisane w jego instrukcji.

Poniżej zamieszczamy kilka przykładów rozpoznania formatu pliku za pomocą programu file.

Polecenie

file SAMPLES/cplatin2.txt

generuje odpowiedź:

SAMPLES/cplatin2.txt: ISO-8859 text, with LF line terminators

Podobnie:

file SAMPLES/cp1250.txt
SAMPLES/cp1250.txt: Non-ISO extended-ASCII text, with CRLF line terminators

oraz

file SAMPLES/utf8.txt
SAMPLES/utf8.txt: UTF-8 Unicode text, with CRLF line terminators

Były to pliki znakowe korzystające z różnych konwencji kodowania znaków. Za pomocą file można rozpoznać także inne formaty danych:

file IMG/img/alicja.ps
IMG/img/alicja.ps: PostScript document text conforming at level 2.0
file IMG/img/alicja.pdf
IMG/img/alicja.pdf: PDF document, version 1.2
file IMG/img/alicja.gif
IMG/img/alicja.gif: GIF image data, version 89a, 2244 x 3168
file welcome.htm
welcome.htm: XML document text

Jednak nawet przy użyciu programu file nie sposób uniknąć niejednoznaczności. Wiele formatów użytkowych stosuje ogólne schematy kompresji danych, takich jak zip lub gz. Na przykład pliki formatu OpenDocument mają postać archiwów zip zawierających spakowane pliki i kartoteki. Rozpoznanie formatu takiego pliku — czy to ręczne, czy automatyczne — na ogół wykaże, że jest to archiwum zip. Oczywiście jest to prawda, chociaż prawdopodobnie użytkownik życzyłby sobie bardziej precyzyjnej odpowiedzi.

Może też się zdarzyć, że file nie dopasuje żadnego formatu do wskazanego pliku. Zwraca wtedy odpowiedź, która świadczy o niepowodzeniu:

file plik
plik: data

W sytuacjach nietypowych mogą się zdarzyć fałszywe rozpoznania. Na szczęście w praktyce są one rzadkie; najczęściej dotyczą plików o zawartości uszkodzonej np. wskutek nieudanego wypakowania załącznika poczty.

Pytania kontrolne

  1. Co to jest format znakowy informacji i do czego jest przeznaczony?
  2. Co to jest UNICODE i UTF-8? w jaki sposób z nich korzystasz?
  3. Dlaczego czasami „polskie litery” zamieniają się na dziwne znaczki?
  4. Dlaczego dobrze jest unikać „polskich liter” w nazwach plików?
  5. Jaką rolę pełnią znaki spacji, tabulacji, końca wiersza w tekście ciągłym i w zbiorach danych?
  6. Co to jest kompresja danych i do czego się ją wykorzystuje? W jaki sposób możesz kompresować swoje pliki?
  7. Jak rozpoznać format pliku z danymi?
  8. Czym różni się rozpoznanie formatu od walidacji formatu zawartości pliku?
© Copyright 2000–2022 by Jan Jełowicki, Katedra Matematyki Uniwersytetu Przyrodniczego we Wrocławiu
janj@aqua.up.wroc.pl
http://karnet.up.wroc.pl/~jasj