Publikoval Michal Kočí dňa 22.11.2004 o 22:48 v kategórii .Net
Keďže silne uvažujem nad kúpou stolného DivX prehrávača, začal som preliezať internet krížom krážom a zisťovať si, ako sú na tom prehrávače s podporou titulkov. Na moje sklamanie a počudovanie zároveň, ak niektorý podporuje slovenskú (českú) kódovú stranku, tak iba v ISO štandarde. Na jednej strane rozumiem, že ISO je proste štandard a basta. Na druhej strane, keďže je Microsoft Windows natoľko rozšírený a používá vlastnú kódovú stránku, očakával by som aj jej podporu. Dokonca by mi stačila len jej podpora, na celé ISO (s prepáčením) zvysoka kašlem...
Takže, keďže vačšina titulkov, ktoré mám sú v kódovej stránke windows-1250, potrebujem si ich prekonvertovať do ISO-8859-2. Obe sady sú pre strednú európu. Spomenul som si, že som svojho času mal kódové tabuľky na prevod medzi rôznymi kódovými stránkami pre Delphi (z knihy 1001 topov a trikov pre Delphi), ktoré by som mohol tiež použiť, ale predpokladal som, že Microsoft má prevod medzi rôznymi kódovými stránkami vyriešený. No, a nemýlil som sa. Konverzia textu z jednej kódovej stránky do inej je ozaj podporovaná v .Net Frameworku, čím mi chlapci z Microsoftu ozaj spravili radosť...
Asi najjednoduchší spôsob, ako prekonvertovať súbor z jednej kódovej stránky do druhej, je použitie statickej metódy Convert triedy Encoding. Ako sa však dostať k objektu, predstavujúcemu samotnú kódovú stránku? Aj to je celkom jednodúché. Kódovú stránku predstavuje trieda Encoding. Z nej dedia aj niektoré predpripravené triedy (teda kódovania), napríklad UnicodeEncoding, ASCIIEncoding, atď... Tých je avšak len pár a mňa momentálne zaujímajú hore spomenuté dve kódovania...
Inštancia triedy Encoding sa dá získať aj pomocou opäť statickej metódy GetEncoding triedy Encoding. Tej stačí predať číselný, alebo textový identifikátor požadovaného kódovania. Tu je však zakopaný celý háčik, Váš operačný systém nemusí týmto kódovaním ovplývať a v prípade, že budete chcieť použiť kódovanie, ktorého podporu nemáte nainštalovanú, nedostanete požadované kódovanie, ale dostanete vynímku. Ovšem, keďže používám systém Windows a nachádzam sa v strednej Európe, systém bez tejto podpory by pre mňa nebol moc užitočný. Z toho pramení fakt, že ja túto podporu mám, takisto asi aj väčšina ľudí v našom regióne (strednej Európy) - česť vynímkám, ktoré potvrdzujú pravidlo...
Keď už teda vieme, ako si pripraviť enkodér, potrebujeme ešte poznať alebo číselné, alebo textové kódy. Bohužial som sa nedopátral lepšej metódy na zistenie všetkých enkodérov pre ktoré mám podporu, ako skúsiť si každý zinicializovať a odchytávať vynímky, ktoré budem ignorovať. Ak niekto pozná lepší spôsob, kľudne mi dajte vedieť. Nasledujúca metóda vyskúša získať kódovanie pre každý číselný kód z rozpätia 0 až 65535 a v prípade, že sa jej kódovanie s daným číselným identifikátorom podarí vytvoriť, vypíše do konzoly tento číselný identifikátor, názov kódovania a webový názov, čo je istá skratka, ktorá Vám bude iste z internetového prostredia povedomá a ktorú môžete použiť ako textový indentifikátor pri vytváraní enkodéra.
private static void WriteCodePages() { for(int i=0; i<65536; i++) { Encoding enc = null; try { enc = Encoding.GetEncoding(i); } catch { continue; } Console.WriteLine("{0};{1};{2}", enc.CodePage, enc.EncodingName, enc.WebName); } }
Uvedenou metódou som zistil, že môj systém pozná 65 kódovaní. Takisto som sa dozvedel skratky (ktoré som tak nejak podvedome očakával) kódových stránok, medzi ktorými chcem previesť konverziu. Predpokladám, že v búdúcnosti budem pracovať s nasledovnými stredoeurópskymi kódovými stránkami:
Pri konverzii titulkov budem mať (potrebovať) teda k dispozícii štyri údaje: názov vstupného a výstupného súboru a názov vstupného (windows-1250) a výstupného kódovania (iso-8859-2). Keďže už vopred predpokladám, že neskončím len u týchto konverzií z/do týchto kódovaní, pripravím si metódu, ktorá bude na vstupe očakávať presne tieto štyri parametre, t.j. nebudem očakávať nemennosť kódových stránok. Táto metóda by mohla vyzerať nasledovne:
private static void ConvertFile( string sourceFileName, Encoding sourceEncoding, string destinationFileName, Encoding destinationEncoding) { FileStream fs = null; byte[] ba = null; fs = new FileStream(sourceFileName, FileMode.Open); try { ba = new byte[fs.Length]; fs.Read(ba, 0, ba.Length); } finally { fs.Close(); } ba = Encoding.Convert(sourceEncoding, destinationEncoding, ba); fs = new FileStream(destinationFileName, FileMode.Create); try { fs.Write(ba, 0, ba.Length); } finally { fs.Close(); } }
A je to, keď už viem, ako konvertovať text z jednej kódovej stránky do druhej a mám predpripravenú metódu na túto konverziu, doprogramovanie tejto malej utility nebude problém, ale tým Vás už nebudem zaťažovať. Na čo som však zatiaľ nedošiel, respektíve si zatiaľ myslím, že to nejde - ako úplne odstrániť slovenskú (českú) diakritiku. Ale pevne verím, že až to budem ozaj potrebovať, tak na to prídem. Ak je to môžné. Alebo, žeby niekto z Vás vedel a chcel mi poradiť?
Doplnené 24.11.2004:
Na základe Milanovej rady (viď. komentáre za článkom) som vyskúšal konverziu z windows-1250 do windows-1253 a táto ozaj odstráni diakritiku. Nahradí písmená s diakritikov za tie isté bez diakritiky. T.j. nespraví to čo konverzia do us-ascii, že písmená s diakritikou skonvertuje na otázniky. Ono to ozaj funguje, prečo však, to mi je a asi aj bude záhadou...
Ak nechceš premeškať príspevky ako je tento, sleduj ma na Twitteri, alebo ak máš RSS čítačku, môžeš sledovať môj RSS kanál.