szöveg kódlapja

 ( kaltsi | 2009. szeptember 23., szerda - 11:52 )

hogyan tudnám megmondani egy beolvasott szöveges adatról, hogy milyen karakter kodolású?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Sehogy.

----------------------
"ONE OF THESE DAYS I'M GOING TO CUT YOU INTO LITTLE PIECES!!!$E$%#$#%^*^"

sehogy, ha nem jelölik a fájlban :>

Core2Duo T7100, 4G, Ubuntu 9.04, 2.6.31

Általánosságban: sehogy. Speciális esetben meg a speciális eset jellemzőit kihasználva. Amiről ugye nem írtál semmit.

(hihetetlen néha micsoda építő jellegű hszk vannak)

első lépésben ami egyáltalán lehetséges (tehát a biztos része a dolognak) kb(most így futtában írtam, bash hiba is lehet benne :)):

for i in $(iconv -l|sed 's/ .*//'); do
iconv -f $i -t "ide valami amibe biztos minden mehet, pl UTF-8 (?)" < miez.txt >/dev/null
if [ $? ]; then echo $i; fi
done

aztán jön a tippelős része (mint a betűcserlős titkosításnál a gyakoriságot felhasználva), gondolom ez volt az igazi kérdés amire én sem tudom a választ, biztos van erre eszköz, pl ha tudod hogy magyar akkor csak a kimenetben rá kell keresni hogy az ékezetes betűk vannak-e és hogy az összes lehetséges betűn kívül van-e (ezeket nyilván darabra és ha az egyik sokkal nagyobb a másiknál akkor jó vagy rossz a tipp)

> hihetetlen néha micsoda építő jellegű hszk vannak
> amire én sem tudom a választ

Na, üdvözöllek a csapatban :-)

he?
amit nem tudok az egy vélhetően meglévő eszköz neve, de úgy gondolom hogy az eredeti kérdésre amit írtam egy elég jó kiindulás (sőt egy kis szkiptgyakorlattal max pár perc alatt ez alapján kivitelezhető!), nem pedig rögtön leugatás hogy "mivan, magyarul se tudsz? ha majd hejesírási hiba nélkül kérdel szóba állunk veled"

ps: most nézem hogy c/c++ volt a kérdés, meaculpa, így érthető a reakció legalább egy kicsit :)

Amíg nem lehet tudni, hogy konkrétan mi a probléma, addig a helyes válasz az, hogy: sehogy.

Persze lehet fantáziálni ilyen-olyan speciális esetekről, BOM, UTF-8, UTF-16 detektálásról, meg ilyesmikről, de én az ilyet részletes probléma ismertetés hiányában nem nevezném építő jellegű hozzászólásnak.

azért kíváncsi lennék milyen képet vágnál amikor megkérdeznéd a tűzoltókat mégis miért nem jöttek amikor szóltál hogy ég a házad és azt a választ kapnád hogy nem tudták hogy most a kicsi vagy nagy tűz, helikoptert küldjön vagy egy tucat vegyi anyag oltásár felkészült piros kocsit, legközelebb tessék a tüzet rendesen specifikálni mert nem lehet minden tüzet mindennel oltani
:)

adott egy txt file, benne szövegként értelmezett adat.
ezt utf8-ba kéne alakítani, de a kérdés, hogy miről.
persze, erre tök jó az iconv, de most próbálgassam vévig, amíg azt nem mondja, hogy ok
gondoltam van valamilyen megondás, ami miután vévignyalta a szöveget, kiböki milyen, mint ha a file-al nézném, meg ugyebár az iconv is valahogy hibát dob, hogy nem jó a bemeneti adat

Nem kell ezt ennyire túlmisztikálni, ha nincs akkor marad a favágó módszer :)

> adott egy txt file, benne szövegként értelmezett adat.

Röviden: belenézel a fájlba egy rendes hexa editorral, keresel benne ékezetes szövegrészt, megnézed egy két ékezetes karakter kódját (pld: á, ű), megkeresed a neten a megfelelő kódtáblát.

itt nem a problémáról hanem elvekről (cset vs fórum párbeszédben praktikusan mennyit érdemes visszakérdezni és mire extrapolálni) van (volt!) szó :)

egyébként részemről ha (nálam újra) előkerül a probléma, így fogom megoldani:

egyszer végigolvasva a szöveget bytonkénti előfordulási statisztikát megnézem mire illik legjobban, első lépésben egy kizáró összehasonlítást, másodikban pedig karakterkészletenként nem az összes lehetséges karaktert veszem be hanem csak a betűket

> egyébként részemről ha (nálam újra) előkerül a probléma, így fogom megoldani:

Bonyolult. Nekem ha csak egyszer kell, akkor belenézek és kiderül. Ha rendszeresen kell, akkor szólok a feltöltő(k)nek, hogy UTF-8 legyen a szöveg, különben irgumburgum. :-)

hmm, van pár ezer szövegfájl mindenféle kódolással, se belenézni nincs kedvem, se pár ezer forrás után járni hogy egyáltalán létezik-e

de igazad van, tényleg bonyolult :)

Ezen nem veszünk össze. :-)

Juteszembe: az is lehet, hogy kaltsi email-t akar fájlból beolvasni, abban meg van kódtábla jelölés. Csak hogy építő jellegű hozzászólásom is legyen. :-)

Igen, de ő a címet sem adta meg, hogy hova küldjék a nagy, piros autót...

KisKresz

A nagy piros autónak a localhost jó cím lesz :)

sajnos nem levél, hanem valamilyen módon feltöltött file (web,ftp). Ezt kell feldolgozni, de ki tudja, hogy a készítő hogy mentette el azt, így azt uniformizálni kéne utf8-ra

Ez valamilyen magyar nyelvű szöveg? Vagy ezt sem tudjuk?

KisKresz

a nyelv az miért fontos? lehet magyar is ékezetek nélkül és utf8-ba kódolva vagy akár ucs2-be, semmibe sem fog különbözni pl. egy angol szövetgtól

Az angol szövegben túlnyomórészt 128-nál kisebb kódú karakterek lesznek. Javaslom, hogy tanulmányozd az ascii (7 bit), a kiterjesztett ascii (8 bit), a latinx, a cpxxxx és az utf-8 kódtáblákat, és a kódolás módját.

Kiegészítés: az hogy egyesek ekezetek nelkul irnak magyar szoveget, az meg nem jelenti azt, hogy ezek tenyleg magyar szovegek. Ezekre a szövegekre (2009-ben) a szörnyszülött a legjobb jelző.

De egy japán szövegtől pl. eltér.

KisKresz

Ha nincsenek ékezetek, akkor az ASCII, Latin-1, akármi kódolás ugyanaz mint az UTF-8. UCS-2-ben meg minden második karakter 0. Tehát a feladat megoldása triviális.

Ha vannak ékezetek, és tudod, hogy a szöveg magyar, akkor csak végig kell próbálgatni a kódtáblákat, amíg fura jelek helyett ő-ket meg ű-ket nem találsz. Megintcsak triviális.

Ha nem tudod a nyelvet, akkor meg kell tudnod, különben nem megoldható a probléma...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

A gond az, hogy az "ő", "ű" betukhoz szemileg kell vegigprobalni - es esetleg tobbszaz fajlrol beszelunk, esetlegesen darabonkent eltero kodolasokkal.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Már miért kéne szemmel?

Kigyűjtöd a nem ASCII karaktereket. Majd megnézed, hogy melyik kódlappal lesznek ezek ő-k meg ű-k.
Részletesebben: minden kódlapra megnézed, hogy mik kódolják az ű-ket meg ő-ket, majd párosítod a szövegek nem ASCII karaktereit a kódlap ékezetes betűivel. Minél jobb az egyezés annál biztosabb, hogy jó a kódlap...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

oke, de egy karakterrol rogton nem tudom eldonteni, hogy "ő", "ű", "é", vagy barmi egyeb (a kis-nagy betu elteresrol mar nem is szolva), es elofordulhat olyan eset is, hogy egy szoveg ugyan nem tartalmaz "ő"-t vagy "ű"-t, de esetleg megis van benne olyan karakter, ami csak egy kodlapon ertelmes.
Ha en csinalnam, biztos forditva fognam meg a feladatot: csinalnek tablazatokat, ami az adott kodlapok (127-256) karaktereit tartalmazza, majd minden nem-ascii karaktert vegigmatchelnek rajta. ahol a legutobb match volt, azt allitanam be az adott fajl karakterkeszletenek, es majd ha minden nem-ascii karakterre megvan a match, akkor terek vissza. Itt persze azzal a feltetelezessel elek, hogy a fajlok a) nem lehetnek keleti nyelvuek b) utf8, utf16 kizarva.

Persze ezzel meg az a baj, hogy a) bruteforce b) hosszu ido c) nem teljesen megbizhato.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

> ami az adott kodlapok (127-256) karaktereit tartalmazza, majd minden nem-ascii karaktert vegigmatchelnek rajta

Nem értem. Van egy nem-ascii karakterkódod, mondjuk a 219. Ez a kód nyilván minden kódlapban megtalálható. Mit akarsz ezen match-elni?

Igaz... akkor viszont ugyanazokat a karaktereket tarolom, de eltero kodkeszlettel. A karakterek pedig a nyelvben elofordulhato nem-ascii karakterek listaja.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Ezt magyarázom már vagy 3 hsz óta...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

a 219-es az iconv 142 kódlapjából 61-ben értelmezhetetlen, a maradék 11 csoportra osztható amiben megegyeznek, van amelyikben valami rajzjel, van amelyikben nagy y kettősponttal, van amelyikben kalapos nagy u, ... egy része szinte teljesen kizárható(, pontosabb a teljes vizsgálatba kis pontszámmal számít bele, aminek a végén nagy pontszámú nyer), a többi ahogy testszik nyelvenként más pontozást kap, vagy egymással egyidejűleg való előfordulásukat díjazzuk (pl ö és ű kap pontot de ő és Ł-nek már kicsi a valószínűsége hogy egyszerre fordulna elő)

Látom nem érted. Megpróbálom még egyszer.

Minden szóba jövő kódlapon megcsinálod: kigyűjtöd a magyar nyelv különleges karaktereinek (á, Á, é, É...) kódjait.

Ezt egyszer teszed meg. (Ezt megteheted kézzel, vagy iconv-val).

Utána minden szövegfájlra:
Kigyűjtöd a nem ASCII karaktereket. Találsz benne mondjuk 15 db 161-es kódút, 18 130-asat stb. Utána megnézed, hogy melyik kódlapnál magyar ékezetes karakterek ezek. Amelyik kódlap a legjobban illeszkedik, azt választod.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

man 1 file? legalább indulásnak... az hogy pl latin2 v latin1, értelemszerűen nem fogod _SEHOGY_ megállapítani (eltekintve nagyon spec esetektől), szerintem erre ne is keress megoldást. :)

nem értem miért kell sokadik embernek így lehurrogni, egy szövegről a nyelv sem állapítható meg, mégis a guglitranslate egész jó hogy _gyakorlatilag_ mindig eltalálja, tehát sokkal bonyolultabb esetekre is létezik megoldás

valószínűleg nem véletlen karaktersorozatról akarja megmondani milyen kódolású, senki nem kérdez úgy hogy azzal kezdi a föld nevű bolygón uralkodó fizikai törvényeknek megfelelően...

de most komolyan ennyi végkocka van a hupon az aktív kommentelők közül?

bocs ha úgy tűnt volna, h lehurrogom, nem ez volt a szándékom. :)

szerk: ehh, bocs, benéztem én is a kategóriát :), mea culpa.
Bár a lényegen nem változtat: ansii - latin1|2|... - unicode különbséget fel tudod ismerni, a unicode-on belül még tovább bonthatod, de a 8bites kódolásokon belül nem tudsz különbséget tenni IMHO.

Ha majdnem minden páratlanadik karakter 0, akkor UCS-2, legalábbis európai nyelvek esetén. Ha a szöveg kínai, akkor az bizony szívás...

Ha hiba nélkül értelmezhető UTF-8-ként, akkor lehet, hogy UTF-8-as. Ha nem, akkor biztos nem.

Ha tudod a nyelvet, akkor próbáld végig a szóba jövő kódolásokat, hogy melyik ad értelmes karaktereket.

Ha nem tudod a nyelvet, akkor statisztikai módszerekkel kiderítheted, legalábbis elvileg, ha elég hosszú a szöveg...

Gondolom a kérdés egyébként inkább az, hogy van-e olyan lib, ami megteszi ez helyetted: tudtommal nincs.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

"Ha hiba nélkül értelmezhető UTF-8-ként, akkor lehet, hogy UTF-8-as. Ha nem, akkor biztos nem."

Ez így korán reggel k.rvajó. :D

:: by BRI.
:: config :: Acer TravelMate // Ubuntu Jaunty
:: tothab [a] gmail [pötty] kom
:: black rose immortal's weblog

Ha a fájl (7 bites) ascii kódolású, akkor csak 7 értékes bit van.
Ha a fájl nem ascii és nem* utf-8 kódolású, akkor az uft-8 -> bármi más konverzióra hibát jelez az iconv, és a recode is. Ha ezt a C(++) programból kell megállapítani, akkor tanulmányozd az utf-8 kódkiosztást, és írd meg az ellenőrző rutint (vagy vedd át a fenti programokból).
Ha a fájl latin1(2,3,...), vagy a Microsoft cpxxx(x) kódolású, akkor nincs triviális megoldás.

Még nem csináltam ilyet, de van erre is egy ötletem. Sok munka van vele, de legalább bizonytalan az eredmény :-(. Ha a szövegfájl nyelve egy viszonylag szűk készletre korlátozható (5-10 lehetséges nyelv), akkor meg lehet próbálkozni a nyelvi sajátosságok felismerésével. Gyakorlatilag a szóba jöhető nyelveknél össze kell gyűjteni az ábécéjük karakterkódjait a különböző kódlapok esetén (latinx és cpxxxx). Azok amelyek az angol ábécében is megtalálhatóak, nem lényegesek. Ezután össze kell hasonlítani a 127 feletti kódokat a szabványban és a szóba jöhető nyelvekben. Ahol a legnagyobb a korreláció, vélhetőleg az a kódlap a nyerő. Ha a szöveg elég hosszú, akkor az algoritmus elég pontos -- de nem 100%-osan biztos -- eredményt ad. Ha a szöveg nyelve bármilyen lehet, akkor gyakorlatilag használhatatlan a módszer.

Kiegészítés: úgy látom más már megelőzött.
*: Javítás
Kiegészítés2: Egyébként a probléma elég érdekes, ha lesz rá időm, lehet hogy nekiugrok. Valamilyen plugin-szerű megoldásra gondoltam, ahol az újabb nyelveket plugin-ként lehetne csatolni.
Kiegészítés3: Szintén nem 100%-osan biztos, de támpont lehet a sorvége karakter. Segíthet megsaccolni, hogy latinx vagy cpxxxx kódtábla.

(nem sok de g://"guess codepage" elég sokat segíthet, pl: http://diary.rozsnyo.com/2005/08/25/codepage/ )

Szerintem egyetlen megoldás létezik, de az is csak akkor működik, ha elég hosszú a szöveg.
1. statisztikai módszerekkel sorrendbe rakod a szótáraidat (amelyik a legvalószínűbb, az megy előre)
2. veszed a következő szótárat...
3. ... a következő kódlappal és összehasonlítod a bemenettel
4. ha még van kódlap, goto 3
5. ha még van szótárad, goto 2
6. a legtöbb pontot kapott szótár+kódolás páros a legnagyobb valószínűségű.

Szótárakra azért van szükség, mert sok szó ugyanúgy néz ki több kódlapon is, ezért érdemes szűkíteni. Pl magyar nyelv esetében utf8, iso-latin2, cp852 jöhet szóba, cirill kódlapot felesleges próbálgatni. Megjegyezném, hogy ez sem tuti módszer, pl a "szó" ugyanazokat a biteket tartalmazza cp és iso-latin kódolás esetén is.

Tudtommal ilyen kész opensource implementáció nincs egyébként, neked kell megírnod, és csak speciális esetekben mehetsz biztosra.

erről a "recode --guess"ről van valakinek tapasztalata?
http://www.bugzilla.org/docs/3.0/html/api/contrib/recode.html

Az utf8-at viszonylag konnyu kizarni. Pl egy mezei latin2-es szoveg elhanyagolhato valoszinuseggel fog atmenni egy utf8-as teszten (ez legjobb emlekem szerint jol leirja, hogy miert). De hogy latin1, latin2, iso-8859-pittyputty, azt gyk sehogy (hacsaknem elegge nagy es kuluturalt szoveg, es mindenfele lingv. stat-okat ra nem engedsz). Ha van valami hattered a szovegrol (pl magyar honlapon tolt fel valaki potencialisan magyar szoveget, es ascii, latin1, latin2 ill utf8 kozul valogathat), akkor azert joval egyszerubb a helyzet ;)

igen, sajna a latin2 / iso8859-2 vs windows-1250 szinte csak szemmel, mert az általános karaktereket ugyanoda mappelik... Pont múlt héten szívtam egy régi konfigfájllal, kiderült, hogy windows-1252-es volt (de hogy miért...).

--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.

A kérdés jó és tökéletesen létjogos.

Ha a kódolás nincs explicite meghatározva valamilyen leíró adattal, azaz mindössze egy octet-sorozat áll rendelkezésre, akkor egy válasz (még az is lehet, hogy az egyik legjobb válasz) valahol itt található:

http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html
http://www.mozilla.org/projects/intl/detectorsrc.html
http://www.mozilla.org/projects/intl/chardet.html

(Felteszem, mindenki észrevette már a Firefox-ban a View | Character Encoding | Auto-Detect menüpontot.)

Első benyomás: Még nem olvastam el egyik linket sem (de el fogom olvasni), de az első link azért elég vicces az UniverselCharsetDetection szempontjából :-). Már rég láttam ennyi kérdőjeles pin@t rombuszt.

Igazatok van, és mégsincs igazatok (bár egyáltalán nem az én tisztem, hogy bármit is védelmezzek).

A feladat az volt, hogy van egy octet sorozat, elképzelésünk sincs a kódolásáról, saccoljuk meg, vajon mi lehet.

A legelső link alatti HTML állomány fejében ez szerepel:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

Ellenőrzés:

$ iconv -f UTF-8 -t UTF-8 <UniversalCharsetDetection.html >/dev/null
iconv: (stdin):96:52: cannot convert

A 96. sort megnézve megtaláljuk a "4.7.1." sztringet, amely után a formázott HTML-ben az első kérdőjeles rombusz látható. A firefox kapott egy explicit kijelentést a szöveg kódolásáról, majd a kódolásban nem megengedett sztringbe futott.

A feladat nem az volt, hogy "félrevezető információ esetén is találjuk ki a kódolást". (Egyébként ez is lehetne a feladat, és a firefox-nak is csak annyit kellene hozzá csinálnia, hogy az első EILSEQ-nél nem pár byte-ot ugrik és kérdőjelet rajzol, hanem egyből átvált automatikus felismerésre, és figyelmen kívül hagyja a charset-et (tévesen) megadó meta-elemet. Ha jól sejtem, most a meta-elemnek mindenképpen elsőbbsége van a felderítéssel szemben.)

Igen, mert lehet, hogy egy latin2 szovegbe kerult valamilyen oknal fogva koi8 karakter, peldaul egy nev okan.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

mos hogy így mondod észrevettem, az első linken nekem olyan kockás kérdőjeleket produkál :D

Ami nem is igazi autodetect, hanem a http request header-ben és a head-ben matat charset után. Nem is működik, ha nincs megadva, próbáld csak ki. Olyankor mindig utf-8-at saccol (legalábbis ff 3.5.3, winen, linuxon, macen nekem ezt produkálja)