Kodowanie znaków w plikach tekstowych
W artykule przedstawiam informacje na temat stron kodowych oraz kodowania znaków w plikach tekstowych.
Kodowanie plików tekstowych
Kodowanie plików tekstowych polega na przypisaniu określonego kodu znakom używanym w tekście. Kod ten umożliwia poprawne wyświetlanie i przechowywanie znaków.
W pliku tekstowym każdy znak jest reprezentowany za pomocą określonego kodu, którym jest zwykle liczba lub sekwencja liczb binarnych.
Kodowanie plików tekstowych pozwala na poprawne wyświetlanie tekstu z plików, które zawierają znaki specjalne lub pochodzą z różnych języków i zestawów znaków. Dlatego istotne jest, aby pliki tekstowe były kodowane w sposób, który jest zgodny z używanym systemem operacyjnym lub programem, w którym będą wykorzystywane.
Przetwarzanie tekstu w komputerach
Komputery przetwarzają liczby (bajty) a nie znaki tekstowe. Dlatego, aby przechowywać i przetwarzać teksty potrzebujemy przypisać literom kody liczbowe. Encoding to przypisanie kodów liczbowych (bajtów) do znaków, co pozwala reprezentować napisy (ciągi znaków) za pomocą sekwencji liczb.
Aby zapisać treść tekstową (złożoną ze znaków) w pliku lub pamięci RAM, musimy ustalić system kodowania znaków tekstowych za pomocą bajtów. Istnieje kilka systemów kodowania np. ASCII, Unicode, UTF-8, ISO-8859-1, Windows-1250, EBCDIC.
Liczby dziesiętne, binarne, szesnastkowe
Liczby możemy zapisywać w trzech systemach:
- szesnastkowym – system, który wykorzystuje szesnaście cyfr, od 0 do 9 oraz liter A, B, C, D, E i F, aby reprezentować liczby
- dziesiętnym – do zapisu liczb stosuje się 10 cyfr: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
- binarnym (dwójkowym) – do zapisu liczb potrzebne są tylko dwie cyfry: 0 i 1
System dziesiętny | System szesnastkowy | System binarny |
0 | 0x0 | 0b00000000 |
1 | 0x1 | 0b00000001 |
2 | 0x2 | 0b00000010 |
3 | 0x3 | 0b00000011 |
4 | 0x4 | 0b00000100 |
5 | 0x5 | 0b00000101 |
6 | 0x6 | 0b00000110 |
7 | 0x7 | 0b00000111 |
8 | 0x8 | 0b00001000 |
9 | 0x9 | 0b00001001 |
10 | 0xa | 0b00001010 |
11 | 0xb | 0b00001011 |
12 | 0xc | 0b00001100 |
13 | 0xd | 0b00001101 |
14 | 0xe | 0b00001110 |
15 | 0xf | 0b00001111 |
16 | 0x10 | 0b00010000 |
Kodowanie ASCII
ASCII (ang. American Standard Code for Information Interchange) to jeden z najstarszych systemów kodowania znaków, który został opracowany w latach 60-tych XX wieku jako standard kodowania tekstu w systemach komputerowych.
W ASCII każdy znak reprezentowany jest przez 7-bitowy kod, co daje 128 różnych kombinacji, w tym 33 znaki alfanumeryczne, 32 znaki specjalne oraz kilka znaków sterujących. W ASCII zawarte są podstawowe litery alfabetu łacińskiego, cyfry, znaki interpunkcyjne, znaki specjalne, takie jak znak nowej linii i tabulacji, a także kilka znaków sterujących, takich jak znak końca tekstu (End of Text) czy znak powrotu karetki (Carriage Return).
Cechy kodowania ASCII:
- każdy znak kodowany jest tylko jednym bajtem
- tylko bajty z zakresu 0-127 mają zdefiniowany znak, pozostałe wartości nie są zdefiniowane
- kod znaku zajmuje 7 bitów
- obsługuje tylko znaki amerykańskie, cyfry, niektóre znaki interpunkcyjne
Przykładowe kody znaków ASCII:
Znak | Kod (bajt/bajty) | Kod hex (bajt/bajty) |
# | 35 | 0x23 |
1 | 49 | 0x31 |
; | 59 | 0x3b |
A | 65 | 0x41 |
B | 66 | 0x42 |
a | 97 | 0x61 |
b | 98 | 0x62 |
ą | nieobsługiwany | |
ę | nieobsługiwany | |
ä | nieobsługiwany | |
© | nieobsługiwany | |
Ψ | nieobsługiwany | |
Д | nieobsługiwany |
Pełna tabela kodów ASCII:
Dec | Char | Dec | Char | Dec | Char | Dec | Char |
0 | NUL (null) | 32 | SPACE | 64 | @ | 96 | ` |
1 | SOH (start of heading) | 33 | ! | 65 | A | 97 | a |
2 | STX (start of text) | 34 | „ | 66 | B | 98 | b |
3 | ETX (end of text) | 35 | # | 67 | C | 99 | c |
4 | EOT (end of transmission) | 36 | $ | 68 | D | 100 | d |
5 | ENQ (enquiry) | 37 | % | 69 | E | 101 | e |
6 | ACK (acknowledge) | 38 | & | 70 | F | 102 | f |
7 | BEL (bell) | 39 | ’ | 71 | G | 103 | g |
8 | BS (backspace) | 40 | ( | 72 | H | 104 | h |
9 | TAB (horizontal tab) | 41 | ) | 73 | I | 105 | i |
10 | LF (NL line feed, new line) | 42 | * | 74 | J | 106 | j |
11 | VT (vertical tab) | 43 | + | 75 | K | 107 | k |
12 | FF (NP form feed, new page) | 44 | , | 76 | L | 108 | l |
13 | CR (carriage return) | 45 | – | 77 | M | 109 | m |
14 | SO (shift out) | 46 | . | 78 | N | 110 | n |
15 | SI (shift in) | 47 | / | 79 | O | 111 | o |
16 | DLE (data link escape) | 48 | 0 | 80 | P | 112 | p |
17 | DC1 (device control 1) | 49 | 1 | 81 | Q | 113 | q |
18 | DC2 (device control 2) | 50 | 2 | 82 | R | 114 | r |
19 | DC3 (device control 3) | 51 | 3 | 83 | S | 115 | s |
20 | DC4 (device control 4) | 52 | 4 | 84 | T | 116 | t |
21 | NAK (negative acknowledge) | 53 | 5 | 85 | U | 117 | u |
22 | SYN (synchronous idle) | 54 | 6 | 86 | V | 118 | v |
23 | ETB (end of trans. block) | 55 | 7 | 87 | W | 119 | w |
24 | CAN (cancel) | 56 | 8 | 88 | X | 120 | x |
25 | EM (end of medium) | 57 | 9 | 89 | Y | 121 | y |
26 | SUB (substitute) | 58 | : | 90 | Z | 122 | z |
27 | ESC (escape) | 59 | ; | 91 | [ | 123 | { |
28 | FS (file separator) | 60 | < | 92 | \ | 124 | | |
29 | GS (group separator) | 61 | = | 93 | ] | 125 | } |
30 | RS (record separator) | 62 | > | 94 | ^ | 126 | ~ |
31 | US (unit separator) | 63 | ? | 95 | _ | 127 | DEL |
Przykład konwersji tekstu na bajty w Pythonie:
a = "Monty Python's Flying Circus" a.encode(encoding='ascii') # wynik: b"Monty Python's Flying Circus" b = b'\x6b\x6f\x74\x20\x46\x69\x6c\x65\x6d\x6f\x6e' b.decode(encoding='ascii') # wynik: 'kot Filemon'
Strony kodowe
Strona kodowa (ang. code page) to zestaw reguł przypisujących sekwencjom bitów konkretny znak lub zestaw znaków. Strona kodowa definiuje, jak poszczególne znaki są kodowane w postaci binarnej i jak powinny być wyświetlane lub drukowane.
Strony kodowe zostały wprowadzone aby dodać obsługę znaków narodowych. Strona kodowa dodaje definicje dla kodów powyżej 127. Są one stosowane do reprezentowania znaków w różnych językach i zestawach znaków np. alfabetu łacińskiego, cyrylicy, greckiego czy hebrajskiego.
Strona kodowa określa znaczenie kodów z zakresu 128-255 i część z niech przypisuje do określonych znaków narodowych. Istnieje wiele stron kodowych które zawierają różne alfabety narodowe.
Przykłady stron kodowych zawierających polskie znaki:
- Windows-1250 – (cp1250)
- Latin2 – (ISO-8859-2)
- Mazovia (przestarzały i nie wspierany przez język Python)
Strona kodowa Windows-1250 (cp1250)
Cechy strony kodowej Windows-1250 (cp1250):
- każdy znak kodowany tylko jednym bajtem
- używa kodów 0-255
- rozszerzenie kodowania Ascii
- kody 0-127 zdefiniowane tak samo jak w Ascii
- zawiera tylko polskie i niemieckie znaki narodowe
Znak | Kod (bajt/bajty) | Kod hex (bajt/bajty) |
# | 35 | 0x23 |
1 | 49 | 0x31 |
; | 59 | 0x3b |
A | 65 | 0x41 |
B | 66 | 0x42 |
a | 97 | 0x61 |
b | 98 | 0x62 |
ą | 185 | 0xb9 |
ę | 234 | 0xea |
ä | 228 | 0xe4 |
© | 169 | 0xa9 |
Ψ | nieobsługiwany | |
Д | nieobsługiwany |
Przykład konwersji tekstu w Pythonie:
a = 'Jaki dziś dzień?' a.encode(encoding='cp1250') #wynik: b'Jaki dzi\x9c dzie\xf1?' b = b'Jaki dzi\x9c dzie\xf1?' b.decode(encoding='cp1250') #wynik: 'Jaki dziś dzień?' 'ą'.encode(encoding='cp1250') #wynik: b'\xb9' 'ę'.encode(encoding='cp1250') #wynik: b'\xea' 'ä'.encode(encoding='cp1250') #wynik: b'\xe4' '©'.encode(encoding='cp1250') #wynik: b'\xa9' 'Ψ'.encode(encoding='cp1250') # UnicodeEncodeError: 'charmap' codec can't encode character
Strona kodowa Latin2 (ISO-8859-2)
Cechy strony kodowej Latin2 (ISO-8859-2):
- każdy znak kodowany tylko jednym bajtem
- używa kodów 0-255
- jest rozszerzeniem kodowania Ascii
- kody 0-127 zdefiniowane są tak samo jak w Ascii
- zawiera tylko polskie i niemieckie znaki narodowe
Znak | Kod (bajt/bajty) | Kod hex (bajt/bajty) |
# | 35 | 0x23 |
1 | 49 | 0x31 |
; | 59 | 0x3b |
A | 65 | 0x41 |
B | 66 | 0x42 |
a | 97 | 0x61 |
b | 98 | 0x62 |
ą | 177 | 0xb1 |
ę | 234 | 0xea |
ä | 228 | 0xe4 |
© | nieobsługiwany | |
Ψ | nieobsługiwany | |
Д | nieobsługiwany |
Przykład konwersji tekstu w Pythonie:
'ą'.encode(encoding='Latin2') #wynik: b'\xb1' 'ę'.encode(encoding='Latin2') #wynik: b'\xea' 'ä'.encode(encoding='Latin2') #wynik: b'\xe4' '©'.encode(encoding='Latin2') #wynik: UnicodeEncodeError: 'charmap'
Unicode
Unicode to standard kodowania znaków, który został opracowany w celu stworzenia jednoznacznego sposobu reprezentacji znaków dla wszystkich języków i zestawów znaków używanych na całym świecie. Jego celem jest umożliwienie współpracy i wymiany informacji między różnymi systemami i aplikacjami, bez konieczności konwersji między różnymi standardami kodowania.
Unicode jest oparty na 32-bitowej reprezentacji znaków, co pozwala na zakodowanie ponad miliona różnych znaków i symboli, w tym alfabetów różnych języków, znaków specjalnych, ikon i symboli matematycznych. Obejmuje on wiele popularnych zestawów znaków, takich jak ASCII, Latin1, Latin2, oraz zestawy znaków używane w językach azjatyckich, arabskich i hebrajskich.
Kodowanie Ascii nie pozwala kodować znaków narodowych, a różne strony kodowe nie pozwalają spójnie i jednoznacznie kodować znaków narodowych. Plik tekstowy nie ma zapisanej informacji o użytej stronie kodowej, przez co znaki narodowe mogą być niepoprawnie interpretowane.
Kodowanie Unicode rozszerza liczbę dostępnych kodów do ponad 65 tys. co pozwala kodować wszystkie powszechnie używane znaki narodowe. Początkowe 127 kodów Unicode jest przejęte z Ascii.
Funkcja ord() zwraca kod Unicode/Ascii litery:
ord('Ą') #wynik: 260
Kody polskich znaków narodowych:
znak | kod | znak | kod |
Ą | 260 | ą | 261 |
Ć | 262 | ć | 263 |
Ę | 280 | ę | 281 |
Ł | 321 | ł | 322 |
Ń | 323 | ń | 324 |
Ó | 211 | ó | 243 |
Ś | 346 | ś | 347 |
Ź | 377 | ź | 378 |
Ż | 379 | ż | 380 |
Aby zapisać znaki do pliku, jako sekwencję bajtów, musimy wybrać sposób kodowania.
UTF-16 (UCS-2) BE
UTF-16 (UCS-2) BE to jedna z wersji standardu Unicode, która określa sposób kodowania znaków za pomocą 16-bitowych wartości. Wariant BE oznacza, że używa kolejności bajtów „big-endian”, co oznacza, że bardziej znaczący bajt (najstarszy bajt) jest zapisywany jako pierwszy.
UTF-16 (UCS-2) BE zakłada, że każdy znak Unicode jest reprezentowany przez dokładnie 16 bitów, co oznacza, że można zakodować maksymalnie 65 536 różnych znaków. Jednak w przypadku znaków, które wymagają większej liczby bitów, wymagane jest użycie pary tzw. „surrogate code units” (jednostek kodu podporządkowanych), które są zakodowane w dwóch osobnych wartościach 16-bitowych.
Cechy kodowania UTF-16 (UCS-2) BE:
- znak ma kod UNICODE z zakresu 0-65535
- każdy znak kodowany jest tylko dwoma bajtami
- używa kodów 0-65535. Zapis big-endian (BE) czyli kolejność bajtów: bardziej znaczący, mniej znaczący
- rozszerzenie kodowania Ascii. Kody 0-127 zdefiniowane tak samo jak w Ascii
- zawiera polskie znaki narodowe, niemieckie, greckie, rosyjskie, koreańskie itp.
- na początku pliku możne wystąpić znacznik kodowania BOM: 0xfe, 0xff
BOM – opcjonalne bajty na początku pliku tekstowego określające zastosowane kodowanie (encoding).
Znak | Kod (bajt/bajty) | Kod (bajt/bajty) | Kod hex (bajt/bajty) | Kod hex (bajt/bajty) |
# | 0 | 35 | 0x00 | 0x23 |
1 | 0 | 49 | 0x00 | 0x31 |
; | 0 | 59 | 0x00 | 0x3b |
A | 0 | 65 | 0x00 | 0x41 |
B | 0 | 66 | 0x00 | 0x42 |
a | 0 | 97 | 0x00 | 0x61 |
b | 0 | 98 | 0x00 | 0x62 |
ą | 1 | 5 | 0x01 | 0x05 |
ę | 1 | 25 | 0x01 | 0x19 |
ä | 1 | 228 | 0x01 | 0xe4 |
© | 0 | 169 | 0x00 | 0xa9 |
Ψ | 3 | 168 | 0x03 | 0xa8 |
Д | 4 | 20 | 0x04 | 0x14 |
Przykład konwersji tekstu w Pythonie:
'ą'.encode(encoding='UTF-16-BE') #wynik: b'\x01\x05' 'ę'.encode(encoding='UTF-16-BE') #wynik: b'\x01\x19' 'ä'.encode(encoding='UTF-16-BE') #wynik: b'\x00\xe4' '©'.encode(encoding='UTF-16-BE') #wynik: b'\x00\xa9' 'Ψ'.encode(encoding='UTF-16-BE') #wynik: b'\x03\xa8'
UTF-16 (UCS-2) LE
UTF-16 (UCS-2) LE to jedna z wersji standardu Unicode, która określa sposób kodowania znaków za pomocą 16-bitowych wartości. Wariant LE oznacza, że używa kolejności bajtów „little-endian”, co oznacza, że mniej znaczący bajt (najmłodszy bajt) jest zapisywany jako pierwszy.
Cechy kodowania UTF-16 (UCS-2) LE:
- znak ma kod UNICODE z zakresu 0-65535
- każdy znak kodowany tylko dwoma bajtami
- używa kodów 0-65535. Zapis little-endian (LE) czyli kolejność bajtów: mniej znaczący, bardziej znaczący
- rozszerzenie kodowania Ascii. Kody 0-127 zdefiniowane tak samo jak w Ascii
- zawiera polskie znaki narodowe, niemieckie, greckie, rosyjskie, koreańskie itp.
- na początku pliku możne wystąpić znacznik kodowania BOM: 0xff, 0xfe
Znak | Kod (bajt/bajty) | Kod (bajt/bajty) | Kod hex (bajt/bajty) | Kod hex (bajt/bajty) |
# | 35 | 0 | 0x23 | 0x00 |
1 | 49 | 0 | 0x31 | 0x00 |
; | 59 | 0 | 0x3b | 0x00 |
A | 65 | 0 | 0x41 | 0x00 |
B | 66 | 0 | 0x42 | 0x00 |
a | 97 | 0 | 0x61 | 0x00 |
b | 98 | 0 | 0x62 | 0x00 |
ą | 5 | 1 | 0x05 | 0x01 |
ę | 25 | 1 | 0x19 | 0x01 |
ä | 228 | 1 | 0xe4 | 0x01 |
© | 169 | 0 | 0xa9 | 0x00 |
Ψ | 168 | 3 | 0xa8 | 0x03 |
Д | 20 | 4 | 0x14 | 0x04 |
Przykład konwersji tekstu w Pythonie:
'ą'.encode(encoding='UTF-16') #wynik: b'\xff\xfe\x05\x01' 'ę'.encode(encoding='UTF-16') #wynik: b'\xff\xfe\x19\x01' 'ä'.encode(encoding='UTF-16') #wynik: b'\xff\xfe\xe4\x00' '©'.encode(encoding='UTF-16') #wynik: b'\xff\xfe\xa9\x00' 'Ψ'.encode(encoding='UTF-16') #wynik: b'\xff\xfe\xa8\x03'
Kodowanie UTF-8
UTF-8 to popularny standard kodowania znaków, który jest stosowany do reprezentacji znaków z różnych zestawów znaków w sposób kompatybilny z systemami ASCII. UTF-8 jest uważany za jedno z najbardziej wszechstronnych i elastycznych kodowań znaków, ponieważ może reprezentować wszystkie znaki Unicode i jednocześnie zachować kompatybilność z kodowaniem ASCII.
UTF-8 koduje każdy znak Unicode za pomocą 1 do 4 bajtów. Pierwszy bajt każdej sekwencji kodującej zawiera informacje o liczbie bajtów wymaganych do zakodowania danego znaku. Dzięki temu UTF-8 jest w stanie zakodować znaki ASCII za pomocą jednego bajtu, co oznacza, że tekst napisany w samym ASCII jest jednocześnie tekstem napisanym w UTF-8.
Cechy kodowania UTF-8:
- znak ma kod UNICODE z zakresu 0-65535, ale zapisanych w skondensowany sposób
- każdy znak kodowany jednym, dwoma, trzema lub czterema bajtami
- znaki Ascii są kodowane jednym bajtem – każdy dokument Ascii jest poprawnym dokumentem utf-8
- utf-8 jest bardziej oszczędny od utf-16 ponieważ w typowych tekstach znaki w większości zużywają jeden bajt na znak
- współcześnie standardowe (zalecane lub wymagane) kodowanie dokumentów tekstowych (*.html, .css, .json, .xml, .py)
- istnieją nielegalne sekwencje bajtów, dzięki czemu można automatycznie wykryć błędne kodowanie
- wbudowany mechanizm synchronizacji pozwala rozpocząć dekodowanie w środku dokumentu
- na początku pliku możne wystąpić znacznik kodowania BOM: 0xef, 0xbb, 0xbf
Znak | Kod (bajt/bajty) | Kod (bajt/bajty) | Kod hex (bajt/bajty) | Kod hex (bajt/bajty) |
# | 35 | 0x23 | ||
1 | 49 | 0x31 | ||
; | 59 | 0x3b | ||
A | 65 | 0x41 | ||
B | 66 | 0x42 | ||
a | 97 | 0x61 | ||
b | 98 | 0x62 | ||
ą | 196 | 133 | 0xc4 | 0x85 |
ę | 196 | 153 | 0xc4 | 0x99 |
ä | 195 | 164 | 0xc3 | 0xa4 |
© | 194 | 169 | 0xc2 | 0xa9 |
Ψ | 206 | 168 | 0xce | 0xa8 |
Д | 208 | 148 | 0xd0 | 0x94 |
Przykład konwersji tekstu w Pythonie:
'a'.encode(encoding='UTF-8') #wynik: b'a' 'A'.encode(encoding='UTF-8') #wynik: b'A' 'ą'.encode(encoding='UTF-8') #wynik: b'\xc4\x85' 'ę'.encode(encoding='UTF-8') #wynik: b'\xc4\x99' 'ä'.encode(encoding='UTF-8') #wynik: b'\xc3\xa4' '©'.encode(encoding='UTF-8') #wynik: b'\xc2\xa9' 'Ψ'.encode(encoding='UTF-8') #wynik: b'\xce\xa8' 'Д'.encode(encoding='UTF-8') #wynik: b'\xd0\x94' a = 'Jaki dziś dzień?' a.encode() #wynik: b'Jaki dzi\xc5\x9b dzie\xc5\x84?' b = b'Jaki dzi\xc5\x9b dzie\xc5\x84?' b.decode() #wynik: 'Jaki dziś dzień?'
Współczesne edytory tekstowe takie jak: Notepad++, edytor IDLE, Visual Studio obsługują kodowanie UTF-8. Kod programu Python może być zapisany jako plik UTF-8.
Rodzaje formatów plików tekstowych
Moduł csv
Pliki CSV (Comma Separated Values) to proste pliki tekstowe, które są używane do przechowywania danych tabelarycznych w formie tekstowej. Każdy wiersz w pliku CSV reprezentuje jeden rekord tabeli, a każda kolumna reprezentuje konkretny atrybut rekordu.
W plikach CSV dane są oddzielane separatorem np. przecinkiem, średnikiem, tabulacją. Przykładowo, jeśli mamy plik CSV zawierający informacje o użytkownikach, to każdy wiersz może reprezentować jednego użytkownika, a kolumny reprezentować różne informacje o użytkowniku, takie jak: imię, nazwisko, adres e-mail, numer telefonu.
Pliki csv są jednym z najprostszych sposobów zapisu danych tabelarycznych złożonych z wierszy i kolumn. Pliki csv są obsługiwane przez MS Excel. Można do nich eksportować arkusz, a także importować dane w tym formacie.
Dla formatu csv nie ma ścisłej specyfikacji, jest to standard ad hoc. Z tego powodu wczytując dane możemy napotykać problemy związane z formatem konkretnego pliku, który wczytujemy.
W Pythonie jest wbudowana biblioteka csv, która służy do wczytywania i zapisu danych w formacie csv. Bardzo popularna biblioteka Pandas także pozwala operować na tym formacie.
Biblioteka Pandas wymaga jednak zainstalowania – nie jest ona wbudowana w język.
Odczyt pliku – poszczególne wiersze są zwracane jako lista wartości.
import csv with open(r'Dane_do_zadan\csv\waluty.csv', encoding='utf8') as f: spamreader = csv.reader(f, delimiter=';', quotechar='"') for row in spamreader: print(row) # ['Id', 'Kraj', 'Waluta']
Zawartość pliku „waluty.csv”
"Id";"Kraj";"Waluta" 0;"Polska";"PLN" 1;"Niemcy";"EUR" 2;"USA";"USD"
Zapis do pliku:
import csv with open(r'Dane_do_zadan\csv\waluty2.csv', 'w', encoding='utf8') as f: spamwriter = csv.writer(f, delimiter=';', quotechar='"', quoting=csv.QUOTE_NONNUMERIC) spamwriter.writerow(['Id', 'Kraj', 'Waluta']) spamwriter.writerow([0, 'Polska', 'PLN']) spamwriter.writerow([1, 'Niemcy', 'EUR']) spamwriter.writerow([2, 'USA', 'USD'])
Odczyt poszczególnych wierszy możliwy jest także w postaci słowników, co ułatwia późniejsze przetwarzanie. Dane csv można pobrać z Internetu. Wczytując dane należy określić encoding znaków narodowych.
import csv import io import urllib.request url = 'http://www.nbp.pl/kursy/Archiwum/archiwum_tab_a_2017.csv' with urllib.request.urlopen(url) as fp: txt = fp.read().decode('ISO-8859-2') with io.StringIO(txt) as fp: reader = csv.DictReader(fp, delimiter=';') dane = list(reader)
Pliki csv zawierające dane w strukturze tabelarycznej (wszystkie rekordy z tą samą liczbą pól) są bardzo dobrze obsługiwane przez bibliotekę Pandas.
import pandas as pd fn=r'Dane_do_zadan\csv\usa.csv' d = pd.read_csv(fn, sep=';').to_dict(orient='list')
Moduł JSON
JSON (JavaScript Object Notation) to lekki i popularny format wymiany danych, który jest używany do przesyłania i przechowywania danych w postaci tekstowej. JSON został stworzony na bazie składni języka JavaScript, ale jest niezależny od platformy i może być używany w różnych językach programowania.
Format JSON opiera się na dwóch strukturach danych: obiektach i tablicach. Obiekt JSON składa się z pary klucz-wartość, podobnie jak obiekt w języku JavaScript, a tablica JSON jest listą wartości oddzielonych przecinkami, podobnie jak tablica w języku JavaScript. Zarówno obiekt, jak i tablica JSON mogą zawierać zagnieżdżone struktury danych, co umożliwia reprezentowanie bardziej złożonych struktur danych.
Format json, w odróżnieniu od csv, jest precyzyjnie zdefiniowanym formatem. Dzięki temu zawsze możemy jednoznacznie określić czy dany dokument (plik) jest poprawnie sformatowany.
Poprawność formatu JSON można sprawdzić online używając np. walidatora JSON Lint.
Python ma wbudowaną bibliotekę json do odczytu (czyli dekodowania) i zapisu (czyli serializowania) dokumentów. Jeśli odczytywany dokument jest niepoprawnie zapisany, biblioteka zgłosi błąd wczytywania. Nie ma możliwości odczytania choćby fragmentu niepoprawnego dokumentu. Koniecznie cały dokument musi być poprawny.
Dokument json może zawierać następujące elementy:
- lista []
- mapa (słownik) {}
- napis (string) „”
- liczba (float)
- wartość logiczna true oraz false
- wartość pusta null
Przykładowy plik tekstowy w formacie json:
{ "firstName": "John", "lastName": "Smith", "isAlive": true, "age": 27, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021-3100" }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "office", "number": "646 555-4567" } ], "children": [], "spouse": null }
Odczyt pliku json:
import json with open(r'c:\ankieta.json', encoding='utf8') as f: data = json.load(f) wiek = data['age'] numer1 = data['phoneNumbers'][0]['number'] numer2 = data['phoneNumbers'][1]['number']
Zapis pliku json:
import json filename = r'c:\rozkład_jazdy.json' data = {} data['title'] = 'Tytuł' data['stop_name'] = 'Stop name' data['trains'] = [{ 'time': '16:48', 'type' : 'KM' }, { 'time': '16:52', 'type' : 'SKM' }, { 'time': '16:58', 'type' : 'EC' },] with open(filename, 'w', encoding='utf8') as f: json.dump(data, f, ensure_ascii = False, indent = 4, sort_keys = True)
Wynik:
{ "stop_name": "Stop name", "title": "Tytuł", "trains": [ { "time": "16:48", "type": "KM" }, { "time": "16:52", "type": "SKM" }, { "time": "16:58", "type": "EC" } ] }
Klasa StringIO
Funkcja StringIO pozwala przekształcić zawartość zmiennej tekstowej na uchwyt do strumienia, który może być odczytywany jak zwykły plik (powstaje plik w pamięci).
Przekształcenie uchwytu do strumienia odnosi się do procesu przekształcenia obiektu file na obiekt StringIO.
from io import StringIO import json doc='''{ "stop_name": "Stop name", "title": "Tytuł", "trains": [ { "time": "16:48", "type": "KM" }, { "time": "16:52", "type": "SKM" }, { "time": "16:58", "type": "EC" } ] }''' with StringIO(doc) as f: data = json.load(f) print(data['title'])
Jak ustawić kodowanie w Notatniku?
Programy takie jak Notatnik, Notpad++ umożliwiają kodowanie znaków. Aby zmienić ustawienia kodowania w Notatniku:
- kliknij opcję Plik
- wybierz Zapisz jako
- w oknie Kodowanie rozwiń pole wyboru i wybierz opcję kodowania