Delphi5 ja UTF-8

Miten D5:lla saa kirjoitettu merkistön UTF-8 mukaisia tiedostoja?
Ilmianna
Jaa

13 Vastausta



Käsittääkseni Delphi 5 käyttää 8-bittistä windowsin merkkikoodausta. Kyseinen koodaus pohjautuu ASCII-koodaukseen. UTF-8 koodaus käyttää vaihtuvan pituista koodausta mutta sekin pohjautuu ASCII-koodaukseen. Eli kummankin koodauksen pohjalla on ASCII-koodaus.

Katso ascii taulukko
http://wiki.lazarus.freepascal.org/ASCII

Tämä tarkoittaa sitä että 127 "alinta" merkkiä vastaavat toisiaan.

Joudut muuttamaan vain merkit jotka ovat arvoltaan yli 127:n

if ord(muunnettavat_merkit[merkin_paikka]) > 127 then

Eli jos vastaan tulee 8-bittisen merkistön
- Ä niin sen arvo korvautuu kahdella tavulla $C3 ja $84 ($ merkitsee heksa esitystä) eli desimaalisena 195 ja 132
- Å $C3 ja $85 eli 195 ja 133
- Ö $C3 ja $96 eli 195 ja 150
- ä $C3 ja $A4 eli 195 ja 164
- å $C3 ja $A5 eli 195 ja 165
- ö $C3 ja $B6 eli 195 ja 182

Kuten huomasit niin UTF-8 koodaus vie enemmän tilaa kuin 8-bittinen koodaus kun käytössä on muita kuin ASCII merkkejä. UTF-8 etuna on se että sillä pystytään esittämään kaikki merkit.
Kommentoi
Ilmianna
Jaa
1 VASTAUS:
Euron merkki vaatii jo kolme tavua UTF-8 koodauksessa
$E2 $82 $AC on desimaalisena 226, 130 ja 172
Kommentoi
Ilmianna
Jaa
+Lisää kommentti
> Miten D5:lla saa kirjoitettu merkistön UTF-8 mukaisia tiedostoja?

Vähän turhan ylimalkainen oli kysymyksesi. Kannattaisi kertoa _tarkalleen_ että millaista operaatiota olet yrittelemässä. Useinhan nämä liittyvät mm. XML:ään tai johonkin muuhun specifiseen probleemaan, kenties kiinan Kanji-merkistöjen esitykseen jne.

Sait jo yhden vinkin millä handlata simppeline suomalaisten ääkkösmerkkien korvaaminen UTF-vastineilla. Mutta ei tällainen koodaus vaikka johonkin tekstitiedostoon vielä jätä tietoa että tämä tekstitiedosto muuten nyt on sitten UTF-8 koodattua tiedostoa.
Esim.HTML:ssä ja XML:ssä headerit kertovat kulloinkin käytetyn koodaustavan.

Katsele vaikka onko tästä 20 USD hintaisesta toolsetistä mitään apuja ongelmaasi.
http://www.delphipages.com/comp/diunicode_3_2-5050.html

Ja ensi kerralla KERRO PALJON TARKEMMIN mitä oikein olet yrittämässä tehdä.
Ilmianna
Jaa
Tarve olisi tulostaa tiedostoksi sepa-maksuaineisto, joka lähetetään pankkiohjelmalla maksettavaksi. Laitan tämän viestin alle esimerkin viitteellisestä maksusta (kysymyksessä on kuitenkin viestillinen maksuaineisto).

Netistä löysin tällaisen esimerkin:

http://www.delphipages.com/forum/showthread.php?t=200627

const
Utf8ByteOrderMark=#$EF#$BB#$BF;
procedure WriteWideString(FilePath:string;x:WideString);
var
f:TFileStream;
begin
f:=TFileStream.Create(FilePath,fmCreate);
try
f.Write(Utf8ByteOrderMark,3);
f.Write(x[1],Length(x)*2);
finally
f.Free;
end;
end;
Kommentoi
Ilmianna
Jaa
8 VASTAUSTA:
Esimerkin lähde: https://www.op.fi/media/liitteet?cid=150261694&srcpl=3.

Esimerkki.

OP-KESKUS LIITTYMÄKUVAUS 99
Maksuliikepalvelut
__________________________________________________
OPK PIDÄTTÄÄ ITSELLÄÄN OKEUDEN MUUTOKSIIN
10.3. Esimerkkisanomia
10.3.1. SEPA-maksu viitteellä

String
2001-12-17T09:30:47.0Z
false
1
100.5
MIXD

Aineiston tekijän nimi

12354678901234567890
TRF

SEPA

2009-05-13

Maksajan nimi

Osoiterivi 1
Osoiterivi 2
FI

001234567

FI9858499920000101

OKOYFIHH

SLEV

9834894389743987

NORM

100.5

NDEAFIHH

Maksun saajan nimi

Osoiterivi 1
Osoiterivi 2
FI

FI2112345600000785

SCOR

00000000000000001245
Kommentoi
Ilmianna
Jaa
HighwayPatrol kirjoitti:
Esimerkin lähde: https://www.op.fi/media/liitteet?cid=150261694&srcpl=3.

Esimerkki.

OP-KESKUS LIITTYMÄKUVAUS 99
Maksuliikepalvelut
__________________________________________________
OPK PIDÄTTÄÄ ITSELLÄÄN OKEUDEN MUUTOKSIIN
10.3. Esimerkkisanomia
10.3.1. SEPA-maksu viitteellä

String
2001-12-17T09:30:47.0Z
false
1
100.5
MIXD

Aineiston tekijän nimi

12354678901234567890
TRF

SEPA

2009-05-13

Maksajan nimi

Osoiterivi 1
Osoiterivi 2
FI

001234567

FI9858499920000101

OKOYFIHH

SLEV

9834894389743987

NORM

100.5

NDEAFIHH

Maksun saajan nimi

Osoiterivi 1
Osoiterivi 2
FI

FI2112345600000785

SCOR

00000000000000001245
Op:n pdf:n sivulta 99 sivulle 101 löytyy tuo esimerkki.
Kommentoi
Ilmianna
Jaa
> Tarve olisi tulostaa tiedostoksi sepa-maksuaineisto, joka lähetetään pankkiohjelmalla
> maksettavaksi. Laitan tämän viestin alle esimerkin viitteellisestä maksusta (kysymyksessä
> on kuitenkin viestillinen maksuaineisto).

Tuohan on normaalia ASCII-merkistöä sisältävä XML-tiedosto, ei siinä ole ainoatakaan 2:lla bytellä esitettyä UTF-merkkiä joukossa.

Mitä tarkoitat "tulostaa tiedostoksi", kun tuohan on jo valmis XML-tiedosto, jonka pankkiohjelma vain kuskaa PC:ltä pankkiin.
Tietenkin se XML-tiedosto voi olla yhtenä ainoana pötkönä, ilman ainoatakaan rivinvaihtomerkkejä, ja se näyttää aika vaikeaselkoiselta. Ja tämän mahdollisesti haluaisit pätkiä A4:lle mahtuviksi riveiksi?

Vaikkapa IE-selain, tai tarkemmin selaimen sisäisesti kutsuma MSXML.DLL systeemitiedosto osaa avata tällaisen pötkörivisen XML-tiedostonkin, ja esittää sen ruudulla tuon OP-dokumentin esittämässä ihmisen luettavassa muodossa.

Selostuksiasi en täysin tarkkaan ymmärrä, mutta saattaa olla että ongelmasi liittyvät XML-tiedostojen käsittelyyn, eivätkä niinkään UTF-tiedostojen luomiseen.

EU:n SEPA-maksutiedostot on muutenkin määritelty niin, että vaikka otsikossa maailmanlaajuisen yhteensopivuuden vuoksi merkistönä mainitaan UTF-8, niin silti SEPA:ssa käytettävä merkistö on rajoitettu ISO-8859-15 merkkeihin. Joten ei sieltyä XML:stä mitään kummaa abyteristä merkistöä ole vastaan tulossa.
Kommentoi
Ilmianna
Jaa
snaju.2 kirjoitti:
> Tarve olisi tulostaa tiedostoksi sepa-maksuaineisto, joka lähetetään pankkiohjelmalla
> maksettavaksi. Laitan tämän viestin alle esimerkin viitteellisestä maksusta (kysymyksessä
> on kuitenkin viestillinen maksuaineisto).

Tuohan on normaalia ASCII-merkistöä sisältävä XML-tiedosto, ei siinä ole ainoatakaan 2:lla bytellä esitettyä UTF-merkkiä joukossa.

Mitä tarkoitat "tulostaa tiedostoksi", kun tuohan on jo valmis XML-tiedosto, jonka pankkiohjelma vain kuskaa PC:ltä pankkiin.
Tietenkin se XML-tiedosto voi olla yhtenä ainoana pötkönä, ilman ainoatakaan rivinvaihtomerkkejä, ja se näyttää aika vaikeaselkoiselta. Ja tämän mahdollisesti haluaisit pätkiä A4:lle mahtuviksi riveiksi?

Vaikkapa IE-selain, tai tarkemmin selaimen sisäisesti kutsuma MSXML.DLL systeemitiedosto osaa avata tällaisen pötkörivisen XML-tiedostonkin, ja esittää sen ruudulla tuon OP-dokumentin esittämässä ihmisen luettavassa muodossa.

Selostuksiasi en täysin tarkkaan ymmärrä, mutta saattaa olla että ongelmasi liittyvät XML-tiedostojen käsittelyyn, eivätkä niinkään UTF-tiedostojen luomiseen.

EU:n SEPA-maksutiedostot on muutenkin määritelty niin, että vaikka otsikossa maailmanlaajuisen yhteensopivuuden vuoksi merkistönä mainitaan UTF-8, niin silti SEPA:ssa käytettävä merkistö on rajoitettu ISO-8859-15 merkkeihin. Joten ei sieltyä XML:stä mitään kummaa abyteristä merkistöä ole vastaan tulossa.
Nyt tulostan ohjelmasta suoraan LMP-muotoisen tekstitiedoston, jonka lähetän pankkiohjelmalla eteenpäin. Tarkoitus olisi siis muuttaa lähtevä aineisto Sepa-muotoiseksi. Ei kai tagien tulostaminen koodista ole vaikeaa. Ongelmaksi voivat muodostua ääkköset esimerkiksi maksajan tai saajan nimessä.

Osaan siis tulostaa ascii-muotoisen tekstitiedoston. Sitä en tiedä, tuleeko ääkkösistä ongelmaa. Oletan kuitenkin, että olisi parempi tulostaa UTF-8:na.
Kommentoi
Ilmianna
Jaa
HighwayPatrol kirjoitti:
Nyt tulostan ohjelmasta suoraan LMP-muotoisen tekstitiedoston, jonka lähetän pankkiohjelmalla eteenpäin. Tarkoitus olisi siis muuttaa lähtevä aineisto Sepa-muotoiseksi. Ei kai tagien tulostaminen koodista ole vaikeaa. Ongelmaksi voivat muodostua ääkköset esimerkiksi maksajan tai saajan nimessä.

Osaan siis tulostaa ascii-muotoisen tekstitiedoston. Sitä en tiedä, tuleeko ääkkösistä ongelmaa. Oletan kuitenkin, että olisi parempi tulostaa UTF-8:na.
> Osaan siis tulostaa ascii-muotoisen tekstitiedoston. Sitä en tiedä, tuleeko
> ääkkösistä ongelmaa.

Kunhan ISO-8859-15 merkistöä laittelet, lähinnä ääkkösien osalta, etkä sekoa DOS-ajan ääkkösalueelle, niin Sepan XML-tiedoston tosiaan ihan täysin pure-Asciita.

> Oletan kuitenkin, että olisi parempi tulostaa UTF-8:na.

Eikä ole, kun asciita ne Sepan XML:t kuuluu olla. Ulkomaille siirtyvät Sepat enkoodataan omassa pankissasi ennen jatkosiirtoa, jolloin ääkköset korvataan "¨??" tyyppsillä notaatioilla joita HTML:ssäkin käytetään.
Kommentoi
Ilmianna
Jaa
HighwayPatrol kirjoitti:
Nyt tulostan ohjelmasta suoraan LMP-muotoisen tekstitiedoston, jonka lähetän pankkiohjelmalla eteenpäin. Tarkoitus olisi siis muuttaa lähtevä aineisto Sepa-muotoiseksi. Ei kai tagien tulostaminen koodista ole vaikeaa. Ongelmaksi voivat muodostua ääkköset esimerkiksi maksajan tai saajan nimessä.

Osaan siis tulostaa ascii-muotoisen tekstitiedoston. Sitä en tiedä, tuleeko ääkkösistä ongelmaa. Oletan kuitenkin, että olisi parempi tulostaa UTF-8:na.
"Osaan siis tulostaa ascii-muotoisen tekstitiedoston. Sitä en tiedä, tuleeko ääkkösistä
ongelmaa. Oletan kuitenkin, että olisi parempi tulostaa UTF-8:na."

Kannattaa puhua oikeilal termeillä, ei tuo mitään TULOSTAMISTA ole! Vaan ohjelmastasi käsin TALLETAT joksikin tiedostoksi, jotakin ohjelmasi dataa.

Sinänsä LMP tiedostot ja SEPA tiedostot ovat ihan täsmälleen samanlaisella merkkituuballa tehty molemmat. Tässä kohdin nyt ei ole yhtään mitään uutta keksittävänä.

Senkuin talletaa Delphistä Ascii-tiedostoksi ihan samoilla menetelmillä kuin on tehnyt on tehnyt Lmp-tiedostojakin. Notepadissa niitä tuotoksiaan voi sitten katsella.

Uudemmat Notepadit tosin saattavat fuskata, ne yrittävät ymmärtää liikaa ja saattavat tehdä ruudulla näytettäville ääkköstyypin specialmerkeille jotakin mielestään tarpeellisia muunnoksia. Mutta jos testimielessä kertaalleen avaat tuotoksesi vaikka vanhassa MS-DOS:in EDIT-editorissa, tai vaikka Delphin omassa IDE:ssäkin, tms., niin ne ovat siitä hyviä että ne eivät tulkitse mitään, vaan näyttävät kaiken lahjomattomana ulos.
Kommentoi
Ilmianna
Jaa
HighwayPatrol kirjoitti:
Nyt tulostan ohjelmasta suoraan LMP-muotoisen tekstitiedoston, jonka lähetän pankkiohjelmalla eteenpäin. Tarkoitus olisi siis muuttaa lähtevä aineisto Sepa-muotoiseksi. Ei kai tagien tulostaminen koodista ole vaikeaa. Ongelmaksi voivat muodostua ääkköset esimerkiksi maksajan tai saajan nimessä.

Osaan siis tulostaa ascii-muotoisen tekstitiedoston. Sitä en tiedä, tuleeko ääkkösistä ongelmaa. Oletan kuitenkin, että olisi parempi tulostaa UTF-8:na.
Unohtakaa kaikki vanhat paskat, ASCII-merkistöt. UTF-8 on yhteensopiva ASCII:n kanssa ja tästä ylimenevä osuus on sitten Unicodea. UTF-8 on täysin riittävä kaikille merkeille.
Kommentoi
Ilmianna
Jaa
VÄÄRIN tehty !!!

tuo 3-tavuinen os UTF-8 -enkoodattu BOM (Byte Order Mark).

MUTTA:

WideString käyttää UTF16LE -enkoodattua Unicodea.

Siksipä, jos kirjoitat itse merkkijonon näin:

const
Utf8ByteOrderMark=#$EF#$BB#$BF;
procedure WriteWideString(FilePath:string;x:WideString);
var
f:TFileStream;
begin
f:=TFileStream.Create(FilePath,fmCreate);
try
f.Write(Utf8ByteOrderMark,3);
f.Write(x[1],Length(x)*2);
finally
f.Free;
end;
end;

niin luonnollisesti silloin tuon BOM -merkin pitää olla enkoodattu UTF16LE -formaatissa, EIKÄ utf-8 formaatissa !

Jos sellaisenaan käytät ylläolevaa koodia, niin huomaat että jos avaat tiedoston Windowsin NOTEPADilla (suom: muistio), silloin näkyy pelkkää roskaa.

Syy: Alussa olevan BOM:in formaatti ei vastaa itse tietosisällön formaattia.

Tee vaikkapa NOTEPADilla tiedosto, jossa on vain 1 merkki: "A". (ilman lainausmerkkejä).

Tallenna se nimellä "koe1.txt" muodossa "Unicode" (Microsoftin kielenkäytössä
Unicode = UTF-16LE).

Sitten avaa tekstitiedosto "koe1.txt" debug.exe:llä näin:

debug koe1.exe

anna komento r (näyttää rekisterit)

anna komento d (näyttää tiedoston 256 ensimmäistä tavua, tai koko tiedoston ja perässä satunnaista dataa 256 tavuun asti, jos tiedosto on alle 256 tavua).

katso heksadesimaalidatasta 2 ensimmäistä tavua (koska UTF-16LE -muodossa BOM -merkki vie 2 tavua, kuten kaikki muutkin BMP:hen kuuluvat merkit).

nuo 2 ensimmäistä tavua ovat BOM -merkki UTF-16 -esitysmuodossa, ja Delphi -koodissa tulee korvata näillä ylläoleva virheellinen:

const
Utf8ByteOrderMark=#$EF#$BB#$BF;

Tuo ylläoleva ilmeisesti OLISI oikein, jos data olisi UTF-8 -formaatissa, ks. UTF8String sekä AnsiToUTF8 ja UTF8ToAnsi -funktiot.

Mutta WideStringin esitysmuoto on UTF-16LE, eikä UTF-8.

BMP = Basic Multilingual Page = ensimmäiset noin 63000 merkkiä.

Teoreettinen maksimi olisi 65536, mutta

a) osa koodeista on erikoiskäytössä kuten esim. LOW and HIGH surrogates; näiden (käytetään AINA parina) avulla esitetään muut kuin BMP:hen kuuluvat merkit.

b) osa koodeista on eri syistä pysyvästi varattu, eli niitä ei käytetä. Esim: BOM:n byteswapattu esitys on tällainen se on pysyvästi kielletty, jotta ei syntyisi sekaannusta oikean BOM:in kanssa.

Eli jos lukiessasi UTF-16 -enkoodattua tiedostoa alussa on byteswapattu BOM, silloin endianness on väärin, ja sinun täytyy silloin lukea data 2 tavun yksiköissä (Delphissä WORD), ja byteswapata kukin WORD.

esim: $FFFE -> $FEFF.
Kommentoi
Ilmianna
Jaa
+Lisää kommentti
Löytyy täältä! Itse koodailen edelleen Delphi 2006:lla, joka ei ole "Unicode" tuettu, mutta täältä löytyy kirjastot millä handlaat Unicoden (UTF-8) esim.

Olen koodannut sovellusta, jonka pitää käsitellä venäjänkielisiä kyriillisiä merkkejä. Käytä vain Delphissä WideString muuttujia merkkijonoille ja linkin työkalut hoitaa loput :)

http://fundementals.sourceforge.net/unicode.html

Jos tarvitset Unicode-komponentteja Delphiin, eli komponentit jotka tukee unicodea, asenna TNT-komponentit, pitäisi onnistua vaikka kiinalaiset merkit :)

http://www.google.com/search?client=safari&rls=en&q=delphi tnt-control&ie=UTF-8&oe=UTF-8
Ilmianna
Jaa

Vastaa alkuperäiseen viestiin

Delphi5 ja UTF-8

Miten D5:lla saa kirjoitettu merkistön UTF-8 mukaisia tiedostoja?

5000 merkkiä jäljellä

Peruuta