Skip to content

Instantly share code, notes, and snippets.

@mjlassila
Created November 5, 2012 14:07
Show Gist options
  • Save mjlassila/4017345 to your computer and use it in GitHub Desktop.
Save mjlassila/4017345 to your computer and use it in GitHub Desktop.
ITIA41 - Viikkoharjoitusten esimerkkiratkaisuja 7
## Tehtävä 1 ##
### ASCII
'''ASCII on 7-bittinen eli 128 merkkiä käsittävä merkistö, joka sisältää
amerikanenglannin suur ja pienaakkoset, numerot, välilyönnin sekä joitain väli-
ja erikoismerkkejä. Merkkien järjestys perustuu englantilaiseen aakkostoon.'''
### UTF-8, hyötyjä ja haittoja
#### Hyviä puolia ####
'''- Yksinomaan Unicode-merkistön 128 ensimmäistä merkkiä sisältävät UTF-8
-esitysmuotoa noudattavat tiedostot ovat indenttisiä vastaavien
ASCII-tiedostojen kanssa. Tämä säästää tilaa ja parantaa yhteensopivuutta
vanhojen ASCII-standardia noudattavien järjestelmien kanssa.
- UTF-8 riittää ilmaisemaan kaikki tämänhetkisen Unicode-merkistön sisältämät
noin 110 000 merkkiä. Jos samassa tekstissä tarvitaan eri kirjoitusjärjestelmistä
peräisin olevia merkkejä -- kuvitellaan vaikkapa asiakirjaa, jossa on sekä
suomen, ruotsin ja venäjänkielistä tekstiä -- UTF-8 mahdollistaa näiden
esittämisen rinnakkain saman dokumentin sisällä.'''
#### Huonoja puolia ####
'''- Aasialaisia merkkejä käyttäessä UTF-8 esitysmuoto vie enemmän tilaa kuin
UTF-16. UTF-8 muotoa käytettäessä yhtä merkkiä vastaa kolme tavua, kun taas
UTF-16 -koodaus vaatii merkkiä kohti kaksi tavua
Unicode-merkistön kohdassa joka on varattu aasialaisille merkeille.
- Merkkien vaihtelevamittaisuus (1-4 tavua) voi tehdä niiden käsittelystä
monimutkaisempaa. Harvinaisessa virhetilanteessa merkkiä ilmaiseva tavujen
yhdistelmä voi katketa väärästä kohtaa, jolloin tuloksena merkki näytetään
väärin. Mikäli UTF-8 käsittely on toteutettu oikein, tällaisten tilanteiden
syntyminen on estetty.'''
### ISO 8859-1 ###
'''ISO 8859-1 (Latin1) on 8-bittinen merkistö, joka sisältää Unicode-merkistön
256 ensimmäistä koodipistettä, kattaen muun muassa suomea kirjoitettaessa
tarvittavat merkit. Se ei kuitenkaan kata kaikkia eurooppalaisia kieliä ja
erikoismerkkien (kuten typografisten lainausmerkkien) tuki on puutteellinen.
Windowsin käyttämä Windows-1252 -merkistökoodaus perustuu ISO 8859-1
-standardiin. Mikäli todellisuudessa Windows 1252 -standardia noudattava
tiedosto avataan ISO 8859-1 -muodossa, jotkut erikoismerkeistä -- kuten
heittomerkit ja lainausmerkit, näkyvät väärin.'''
## Tehtävä 2 ##
'''Tässä tehtävässä tarkoitus oli tutustua Python-ympäristössä hyödylliseen
työskentelytapaan, jossa kaikki käsiteltävät merkkijonot muutetaan
mahdollisimman varhaisessa vaiheessa Unicode-muotoon. Vastaavasti muunnos
Unicodesta haluttuun tallennusmuotoon on viisasta tehdä vasta lopuksi,
tallennettaessa tiedostoa.
Tehtävä demonstroi myös Pythonin käytäntöä esittää Unicode-muotoiset
merkkijonot ASCII-merkkien yhdistelminä. Näytöllä erikoismerkit näkyivät
merkkijonon \xe1szl\xf3 -kaltaisena siansaksana.
Jos Pythonissa haluaa tulostaa Unicode-merkkejä puretussa esitysmuodossaan
(l. erikoismerkit sellaisenaan), voidaan käyttää komentoa print().
Tällöin SSH-ohjelman tulee noudattaa UTF-8 koodausta, jotta merkit tulostuivat
näytölle oikein.'''
### Esimerkki:
# UTF-8 koodausta noudattava merkkijono Pythonin ASCII-esitysmuodossa
>>> utf8_text
'L\xc3\xa1szl\xc3\xb3 Moholy-Nagy'
# Tulostetaan merkkijono UTF-8 koodausta noudattavassa SSH-ohjelmassa.
>>> print(utf8_text)
László Moholy-Nagy
'''Jos kokeilemme tulostaa UTF-16 esitysmuodossa olevan merkkijon UTF-8
ympäristössä, saamme seuraavan tuloksen:'''
# Aluksi UTF-16-koodattu merkkijono Pythonin ASCII-esitysmuodossa
>>> unicode_in_utf16
'\xff\xfeL\x00\xe1\x00s\x00z\x00l\x00\xf3\x00 \x00M\x00o\x00h\x00o\x00l\x00y\x00
-\x00N\x00a\x00g\x00y\x00 \x00o\x00n\x00 \x00u\x00n\x00k\x00a\x00r\x00i\x00l\x00
a\x00i\x00n\x00e\x00n\x00 \x00v\x00a\x00l\x00o\x00k\x00u\x00v\x00a\x00a\x00j\x00
a\x00.\x00'
# Koitetaan tulostaa näytölle
>>> print(unicode_in_utf16)
??L?szl? Moholy-Nagy on unkarilainen valokuvaaja.
# ==> Huomataan merkkien tulostuvan väärin.
## Tehtävä 3 ##
'''Tehtävä demonstroi Unicode-merkistön kattavuutta. Charbase.com -sivusto on
mainio apu merkistön selailuun - sivustolta voi tarkistaa muun muassa jokaisen
Unicode-merkin Python-esitysmuodon, nimen, sijainnin merkistössä sekä
merkistöryhmän.'''
# Merkit charbase-sivustolla
# http://www.charbase.com/0f00-unicode-tibetan-syllable-om
# http://www.charbase.com/263a-unicode-white-smiling-face
# http://www.charbase.com/2603-unicode-snowman
# http://www.charbase.com/2615-unicode-hot-beverage
# http://www.charbase.com/2638-unicode-wheel-of-dharma
# Eräs ratkaisu:
>>> import unicodedata
>>> import chardet
>>> unknown_characters = open('/home/courses/itima41/erikoismerkit.txt', 'r').read()
{'confidence': 0.96906250000000005, 'encoding': 'utf-8'}
>>> unicode_characters = unknown_characters.decode('utf8')
>>> characters_as_tokens = unicode_characters.split('\n')
>>> characters_as_tokens
[u'\u263a', u'\u0f00', u'\u2603', u'\u2615', u'\u2638']
>>> for token in characters_as_tokens:
... print(unicodedata.name(token))
...
WHITE SMILING FACE
TIBETAN SYLLABLE OM
SNOWMAN
HOT BEVERAGE
WHEEL OF DHARMA
## Tehtävä 4 ##
'''Tämän tehtävän tarkoituksena oli havainnollistaa merkistön ja merkistön
esityskoodauksen käsitteellistä eroa.
Unicode on merkistö -- sopimus joka määrittelee vastaavuuden merkin symbolin ja
Unicode-koodipisteen välillä. Koodipiste on merkin sijainti Unicode-merkistössä.
Unicode-merkistön voi mieltää valtavaksi taulukoksi, jossa kullakin merkillä
on oma paikkansa, johon koodipiste viittaa.
UTF-8, UTF-16, UTF-32 ovat taas Unicode-merkistön esityskoodauksia, tapoja
esittää nämä merkit bittijonoina. On varsin yleistä että käsitteitä merkistö,
merkistökoodaus ja esityskoodaus käytetään toistensa synonyymeinä, vaikka
kyseessä ovat eri asiat. Jukka K. Korpela on laatinut tästä erinomaisen
esityksen, joka selventää käsitteiden eroja selkokielellä:
Jukka K. Korpela: A tutorial on character code issues
<http://www.cs.tut.fi/~jkorpela/chars.html>
Python-ympäristössä - ja myös tekstinkäsittelyohjelmassa - työskentelyä
helpottaa jos työnkulun hahmottaa seuraavalla tavalla:
1) Levyllä on tallennettu teksti, jonka merkit on enkoodattu (encode) levylle
tiettyä esitystapaa noudattaen
2) Teksti avataan ja se dekoodataan (decode) ohjelman sisäiseen esitysmuotoon.
Jos tämä vaihe menee pieleen, tavallisesti näytöllä näkyy merkkiroskaa.
3) Kun teksti tallennetaan, se enkoodataan (encode) haluttuun muotoon.
Tallennusmuoto voi olla sama, kuin tekstiä avattaessa tai tarvittaessa se
voidaan tallentaa jotain muuta esityskoodausta käyttäen. Tärkeää on kuitenkin
muistaa, että esityskoodauksen on tuettava tekstin sisältämiä merkkejä.
Esimerkiksi, jos yrittää tallentaa skandinaavisia merkkejä sisältävää
tekstiä ASCII-muotoon, merkistöenkoodaus tulee menemään pieleen jos
tallentaminen ylipäätänsä onnistuu.
Esimerkkiratkaisussa kyrillisten merkkien KOI-8 -esitysmuodossa tallennetun
tekstin lataaminen ja tallentaminen UTF-8 -muotoon:'''
text1 = open('/home/courses/itima41/enkoodausharjoitus-01.txt').read()
text2 = open('/home/courses/itima41/enkoodausharjoitus-02.txt').read()
text3 = open('/home/courses/itima41/enkoodausharjoitus-03.txt').read()
text4 = open('/home/courses/itima41/enkoodausharjoitus-04.txt').read()
text5 = open('/home/courses/itima41/enkoodausharjoitus-05.txt').read()
>>> chardet.detect(text1)
{'confidence': 0.98756803475891264, 'encoding': 'KOI8-R'}
>>> chardet.detect(text2)
{'confidence': 0.91635421768622582, 'encoding': 'ISO-8859-2'}
>>> chardet.detect(text3)
{'confidence': 0.85359795046648712, 'encoding': 'ISO-8859-2'}
>>> chardet.detect(text4)
{'confidence': 0.98999999999999999, 'encoding': 'utf-8'}
>>> chardet.detect(text5)
{'confidence': 1.0, 'encoding': 'UTF-16BE'}
# Dekoodataan KOI8-muotoon tallennettu teksti Unicodeksi.
text1_unicode = text1.decode('KOI8-R')
# Enkoodataan Unicode-teksti UTF-8 esitysmuotoon
text1_utf8 = text1_unicode.encode('utf8')
# Avataan tiedosto kirjoittamista varten
file = open('enkoodausharjoitus-01.txt', 'w')
# Kirjoitetaan tiedostoon
file.write(text1_utf8)
# Suljetaan tiedosto
file.close()
## Tehtävä 5 ##
'''Aiemmissa tehtävissä käytettiin chardet-työkalua, joka helpottaa tuntemattomassa
muodossa tallennettujen tiedostojen käsittelyä. Chardet ei ole kuitenkaan erehtymätön.
Tehtävässä käytetyt enkoodausharjoitus-06.txt ja enkoodausharjoitus-08.txt
tiedostot olivat nimittäin merkistökoodaukseltaan identtiset (ISO 8859-15),
vaikka chardet-työkalun mukaan tiedostot noudattaisivat ISO 8859-2 -muotoa
85% todennäköisyydellä. Mikäli ISO 8859-15 merkistökoodausta noudattava tiedosto
avataan ISO 8859-2 muodossa, näkyvin muutos on merkistökoodauksen kohdassa
0xA4 olevan € -merkin korvautuminen valuuttamerkillä ¤ .
SSH-ohjelmassa ja shellissä käytössä oleva merkistöjen esitysmuoto saattoi
aiheuttaa tässä tehtävässä hankaluuksia. Koska tiedostot tallennettiin UTF-8
-muotoon, niiden katseleminen cat-komennolla jotain muuta merkistökoodausta
noudattavassa ympäristössä saa aikaan erikoismerkkien tulostumisen väärin.
Windows käyttää oletusarvoisesti Windows-1252 -koodausta, joka on muunnos
ISO 8859-1 -standardista. Jos Windows-ohjelmissa haluaa käyttää UTF-8 koodausta,
se tulee tyypillisesti kytkeä erikseen päälle.
Esimerkiksi Putty SSH-ohjelmassa UTF-8 -koodauksen saa otettua käyttöön
valitsemalla valikoista:
Window → Translation → Character set → UTF-8'''
## Tehtävä 6 ##
'''Tehtävässä annettua merkkijonoa "väisälä" vastaava sana luonnollisessa
kielessä on todennäköisesti (suuraakkosella kirjoitettu) vastaava erisnimi Väisälä.
Merkkijonon "vaisala" ilmentymä lähdetekstissä on myös todennäköisesti
erisnimi (yrityksen nimi). Myös merkkijono "visala" assosioituu todennäköisesti
erisnimeen. Tiedonhaun näkökulmasta annetut kolme samaa eivät välttämättä tuntuisi ole
kovinkaan "lähellä toisiaan" (toisin kuin esimerkiksi
merkkijono "vaisala" ja sen tarkoitettu generiivimuoto "vaisalan").
Kehiteltäessä samankaltaisuuden laskentaa voidaan pohtia samuuden
mittauksen käyttötarkoitusta ja esim. seuraavia aspekteja:
-kieli: vertaillaanko merkkijonoja yksikielisessä tilanteessa vai
eri kielten välillä (vrt. "Chechnya"/"Tshetshenia"/"Tshetshenian#)
-kuinka tokenisaatio on toteutettu vertailtavana oleville merkkijonoille
-ortografia kielten välillä ("ks"/"x", "oo"/"o" jne.?)
-kielen ortografia, esim.
--yhdyssanat ("vero"/"tulovero")
--sanojen taipuminen ("tulovero"/"tuloveron")
--derivatiivit ("vero"/"verottaminen"/"verottaa")
--suuraakkoset ("suomalainen"/"suomalaisten"/"Suomalainen"; "US" vrt."us")
--välimerkit ("u.s."/"us"/"1000"/"1,000"/"1,0"/"10"/"1.0" - eri tulkintoja
esim. suomen- vs. englanninkielisessä tekstissä).
Matemaattisesti merkkijonojen samankaltaisuutta kuvataan tavallisesti nk.
etäisyysmetriikoiden avulla. Tunnettuja ovat esimerkiksi
Levenšteinin etäisyys, Jaccardin etäisyys sekä Jaro-Winklerin etäisyys.
Erinomainen englanninkielinen esitys etäisyysmetriikoista löytyy osoitteesta
http://alias-i.com/lingpipe/demos/tutorial/stringCompare/read-me.html
johon kannattaa tutustua, jos aihe herätti syvempää mielenkiintoa.
UTF-8 ja ISO 8859-1 -merkistöillä koodatut merkkijonot voivat tuottaa erilaisia
samankaltaisuustuloksia.
Jos tietty sana koodataan eri merkistöjä käyttäen,
syntyvät esitysmuodot (bittijonot) saattavat olla erilaiset, vaikka
abstraktissa mielessä sanat ovatkin identtiset. Merkkijonojen
pituuden laskennassa on erityisesti vaihtelevamittaisissa merkistöissä
otettava huomioon mahdolliset monitavuiset merkit.'''
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment