Grafikus C# – Windows Forms tanfolyam › 10.3 lecke Windows Forms · 10.3 lecke · kódolás Egy fájlban nincsenek betűk: csak bájtok (0–255 közötti számok). Hogy a Szövegfájlok és UTF-8 kódolás
ő, ű, á melyik bájt-sorozatot jelenti, azt a kódolás (encoding) dönti el. Ha a fájlt író és az olvasó program más kódolást feltételez, a szöveg tönkremegy: körte, õ az ő helyett, ? jelek. Magyar nyelvű programban ez a legsűrűbb szövegfájl-hiba. Ebben a leckében megérted a bájt és karakter viszonyát, az UTF-8, UTF-16 és Windows-1250 különbségét, a BOM szerepét, a sorvégeket, és hogyan olvasol, írsz és alakítasz át szövegeket biztonságosan.
A lecke végére
- magyarázod, mi a különbség a bájt, a karakter és a kódolás között;
- ismered az UTF-8, UTF-16, Windows-1250 és ISO-8859-2 kódolást, és tudod, melyiket mikor használd;
- érted a BOM jelentését, és megadod a kódolást olvasáskor és íráskor (
Encoding); - felismered a kódolási hibák tüneteit (ö, õ, ?), és az okukat;
- a Windows-1250 kódolást is eléred (
CodePagesEncodingProvider); - kezeled a sorvégeket (
\r\nés\n), és átalakítasz egy fájlt másik kódolásra, veszteség-ellenőrzéssel.
Mielőtt elkezded
Ehhez a leckéhez a 10.1–10.2 lecke (File, StreamReader, StreamWriter) és a 3.3 lecke (char, string) szükséges.
Bájt, karakter és kódolás
A string karakterekből áll (a memóriában UTF-16). A fájlba bájtok kerülnek: a kódolás a karakter → bájtok megfeleltetés. Ugyanaz a szöveg különböző kódolással különböző bájtokat ad:
string szoveg = "őrült";
byte[] utf8 = Encoding.UTF8.GetBytes(szoveg);
byte[] utf16 = Encoding.Unicode.GetBytes(szoveg);
// kiírás hexadecimálisan: BitConverter.ToString(utf8)
// UTF-8: C5-91-72-C3-BC-6C-74 (az ő két bájt: C5 91, az ü két bájt: C3 BC)
// UTF-16: 51-01-72-00-FC-00-6C-00-74-00 (minden karakter 2 bájt, kisvégű)
// vissza: ugyanazt a kódolást kell használni!
string jo = Encoding.UTF8.GetString(utf8); // őrült
string rossz = Encoding.Latin1.GetString(utf8); // körte típusú hiba: Å‘rült| Kódolás | Jellemző | Mikor? |
|---|---|---|
| UTF-8 | Változó hosszúságú (1–4 bájt); az ASCII karakterek 1 bájtosak; minden nyelv betűit tudja. | Az alapértelmezett választás: weben, JSON-ban, XML-ben, új fájlokban. |
UTF-16 (Encoding.Unicode) | Karakterenként 2 (vagy 4) bájt. | Windows belső szövegábrázolása; néhány régi Windows-fájl (Jegyzettömb „Unicode”). |
| Windows-1250 | 1 bájt/karakter, közép-európai betűk (ő, ű is). | Régi magyar Windows-programok fájljai, régi CSV-k. |
| ISO-8859-2 (Latin-2) | 1 bájt/karakter, közép-európai; kismértékben eltér a Windows-1250-től. | Régi Unix/web tartalmak. |
| ASCII | 7 bit: csak angol betűk és jelek. | Ékezetes betűket NEM tud: ? lesz belőlük. |
ő UTF-8-ban 2 bájt. A fájl mérete bájtban ezért nagyobb lehet, mint a karakterek száma. A string.Length a UTF-16 egységeket számolja (az emoji 2 egység).Jósolj!
A program File.WriteAllText(ut, "őrült", Encoding.ASCII) módon ment. Mi lesz a fájl tartalma?
Jóslat ellenőrzése
?r?lt (kérdőjelek az ő és ü helyén): az ASCII nem tudja ábrázolni az ékezetes betűket, és csendben ? karakterre cseréli őket. Az információ visszaállíthatatlanul elveszik: ASCII kódolásba ékezetes szöveget soha ne ments.
UTF-8, BOM és a .NET alapértelmezései
A BOM (byte order mark) a fájl elején álló néhány bájt, amely a kódolást jelzi: UTF-8 esetén EF BB BF, UTF-16 esetén FF FE. Egyes programok (régebbi Jegyzettömb, Excel) a BOM alapján ismerik fel az UTF-8-at. A .NET alapértelmezései:
// ÍRÁS: a File.WriteAllText és a StreamWriter alapértelmezése UTF-8 BOM NÉLKÜL
File.WriteAllText(ut, szoveg);
// kifejezetten BOM-mal (az Excel és a régi programok így ismerik fel az UTF-8-at)
File.WriteAllText(ut, szoveg, new UTF8Encoding(true));
// OLVASÁS: a StreamReader felismeri a BOM-ot, és annak megfelelően dekódol;
// BOM nélkül UTF-8-nak veszi (ezért a Windows-1250 fájl ékezetei elromlanak!)
using (StreamReader olvaso = new StreamReader(ut))
{
string tartalom = olvaso.ReadToEnd();
Encoding felismert = olvaso.CurrentEncoding; // a ReadToEnd után a ténylegesen használt kódolás
}
// konkrét kódolás megadása olvasáskor
string szoveg2 = File.ReadAllText(ut, Encoding.Unicode);
// a fájl első bájtjai: BOM felismerése kézzel
byte[] fej = new byte[3];
using (FileStream fs = new FileStream(ut, FileMode.Open, FileAccess.Read))
{
int db = fs.Read(fej, 0, 3);
bool utf8Bom = db == 3 && fej[0] == 0xEF && fej[1] == 0xBB && fej[2] == 0xBF;
bool utf16Bom = db >= 2 && fej[0] == 0xFF && fej[1] == 0xFE;
}StreamReader a BOM-ból tud felismerni. BOM nélküli Windows-1250 fájlt UTF-8-nak hisz, és az ékezetes betűk helyén ismeretlen karakter (�) jelenik meg. A kódolást ilyenkor a felhasználó kiválaszthatja, vagy a program tippel.� (U+FFFD) azt jelzi, hogy a bájt-sorozat nem érvényes az adott kódolásban. Ha ilyet látsz a beolvasott szövegben, rossz kódolással olvastál.Encoding.Default a .NET Framework alatt a gép ANSI kódlapja (magyar Windows-on Windows-1250), újabb .NET-ben UTF-8: a viselkedése verziófüggő, ezért kerüld; mindig nevezd meg a kódolást.Jósolj!
Az Excel egy BOM nélküli UTF-8 CSV-fájlt nyit meg a magyar Windowson, kettős kattintással. Mit lát a felhasználó az ő és ű betűk helyén?
Jóslat ellenőrzése
Értelmetlen karakterpárokat, például Å‘ az ő helyén: a BOM hiányában az Excel a gép ANSI kódolásával (Windows-1250) olvassa az UTF-8 bájtokat. BOM-mal (new UTF8Encoding(true)) a fájl helyesen jelenik meg.
Windows-1250 és Latin-2 olvasása
Régi magyar programok (és sok CSV-export) Windows-1250 kódolású fájlt írnak. Az újabb .NET (Core, 5+) alapból csak néhány kódolást ismer: a többit (köztük a Windows-1250-et) a CodePagesEncodingProvider teszi elérhetővé (a .NET Framework alatt nem kell, és a regisztráció ártalmatlan):
// egyszer, a program indulásakor (például a Main metódus elején)
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Encoding win1250 = Encoding.GetEncoding(1250); // vagy GetEncoding("windows-1250")
Encoding latin2 = Encoding.GetEncoding("iso-8859-2");
string szoveg = File.ReadAllText(regiFajl, win1250);
File.WriteAllText(ujFajl, szoveg, new UTF8Encoding(false)); // átalakítás UTF-8-ra
// veszteség-ellenőrzés: kivételt dob, ha a szöveg nem ábrázolható a célkódolásban
Encoding szigoru = Encoding.GetEncoding("iso-8859-2", EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback);
try
{
byte[] bajtok = szigoru.GetBytes("Árvíztűrő tükörfúrógép ✓"); // a ✓ nincs a Latin-2-ben
}
catch (EncoderFallbackException ex)
{
lblHiba.Text = "Nem ábrázolható karakter: " + ex.CharUnknown; // a konvertálás előtt figyelmeztetünk
}CodePagesEncodingProvider a System.Text.Encoding.CodePages csomagban van (újabb .NET-ben beépített). Nélküle a GetEncoding(1250) ArgumentException kivételt dob. A regisztráció egyszeri.?-re cseréli, csendben. A ExceptionFallback hibát jelez: így figyelmeztethetsz, mielőtt az adat elvész. UTF-8-ba alakítás sosem veszteséges.DecoderFallback.ExceptionFallback nem dob), (3) különben a gép ANSI kódolása (Windows-1250). A felhasználó mindig kijavíthatja.Jósolj!
Egy Windows-1250 fájlban az ő betű a F5 bájt. A program UTF-8-ként olvassa a fájlt (ReadAllText(ut)). Mit jelenít meg?
Jóslat ellenőrzése
Egy � (helyettesítő karaktert): az F5 bájt önmagában nem érvényes UTF-8 (a többbájtos karakter első bájtja, de nincs folytatása). A beolvasott szöveg „sérült”, a hiba felismerhető a � karakterekről.
Sorvégek
A sor végét a Windows két karakterrel jelzi (\r\n, CRLF), a Linux és a Mac egyel (\n, LF). A StreamReader.ReadLine és a File.ReadAllLines mindkettőt jól kezeli. Gond akkor van, ha a szöveget kézzel bontod (Split('\n'): a \r a sor végén marad), vagy a TextBox.Text és a fájl sorvégei keverednek:
// jó: mindkét sorvéget kezeli
string[] sorok = File.ReadAllLines(ut);
// hibás: az \r a sor végén marad, ha a fájl CRLF
string[] rossz = tartalom.Split('\n');
// helyes kézi bontás
string[] jo = tartalom.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
// egységesítés a rendszer sorvégére
string egyseges = tartalom.Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
// kiíráskor: Environment.NewLine (Windows alatt CRLF)
File.WriteAllText(ut, "egy" + Environment.NewLine + "kettő");Jósolj!
A fájlt Windows-on írták (CRLF), és a program tartalom.Split('\n') hívással bontja sorokra, majd sor == "alma" módon hasonlít. Egyezik-e az első sor?
Jóslat ellenőrzése
Nem: a sor "alma\r" (a CR karakter ott marad). A hasonlítás hamis, a hiba nehezen látható. A ReadAllLines és a ReadLine a CRLF-et jól kezeli, vagy Trim() és a kétféle sorvég szerinti Split kell.
Mit tegyél ide: a kódolás-átalakító: a bal oldalon a rossz kódolással beolvasott szöveg (Å‘), a jobb oldalon a helyes, alatta a hexadecimális nézet és a BOM jelzése.Javasolt fájlnév: winforms-10-3-kodolas.webp · Alt szöveg: A kódolás-átalakító program
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. Az ő és ű betűk helyén � jelek
Egy régi program fájlját olvasod be. A fájl valószínűleg Windows-1250, a program UTF-8-ként olvassa. Add meg a kódolást (Ok és javítás
Encoding.GetEncoding(1250), előbb RegisterProvider), vagy kínálj a felhasználónak kódolás-választót.
2. ArgumentException a GetEncoding(1250) hívásnál
Encoding e = Encoding.GetEncoding(1250); // újabb .NET-ben regisztráció nélkül kivételHiba és javítás
Előbb: Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); (egyszer, induláskor).
3. Az Excel értelmetlen betűket mutat
A program UTF-8 CSV-t ment, az Excelben az ékezetek hibásak. BOM nélküli UTF-8: az Excel ANSI kódolásúnak veszi. Mentsd Ok és javítás
new UTF8Encoding(true) (BOM-os UTF-8) kódolással.
4. Az ékezetes betűk kérdőjellé váltak a mentett fájlban
File.WriteAllText(ut, szoveg, Encoding.ASCII);Hiba és javítás
Az ASCII nem tud ékezetes betűt: ? lesz belőlük, az adat elveszik. Használj UTF-8-at.
5. A sor végén láthatatlan karakter
A beolvasott szöveg hasonlítása nem egyezik, bár a szöveg azonosnak látszik. CRLF fájl Ok és javítás
Split('\n') bontásnál: a \r marad. Használj ReadAllLines metódust, vagy Trim()-et.
6. A fájl két kódolás keveréke
A fájl egyik fele helyes, a másik hibás. Több program írt bele eltérő kódolással (például egy hozzáfűzés más kódolással). Az egy fájlba írt részek ugyanazt a kódolást használják: a Ok és javítás
StreamWriter(ut, true, Encoding.UTF8) kódolását is add meg hozzáfűzéskor.
Mini projekt: kódolás-átalakító
Készíts programot, amely szövegfájlt nyit meg több kódolással, mutatja a bájtokat, és átalakítja:
- Felület: Megnyitás...,
cmbKodolas(UTF-8, UTF-16, Windows-1250, ISO-8859-2, ASCII, Windows-1252), Automatikus jelölő;txtSzoveg(az eredmény),txtHex(az első 64 bájt hexadecimálisan, csak olvasható);lblInfo; Mentés másként...,cmbCel(cél kódolás),chkBom(BOM),cmbSorveg(Windows (CRLF), Unix (LF)). - Regisztráció: a program elején
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance). - Automatikus felismerés: (1) BOM (UTF-8, UTF-16 LE/BE); (2) érvényes UTF-8-e (
ExceptionFallbackdekódolóval); (3) különben Windows-1250. A felismert kódolás a legördülőben beállítódik, és azlblInfomegmondja az okot (BOM alapján / érvényes UTF-8 / feltételezés). - Beolvasás: a fájl bájtjai (
File.ReadAllBytes), a kijelölt kódolással dekódolva (a BOM bájtjait nem kell a szövegben mutatni); a�karakterek száma jelzi a gyanús kódolást (lblInfo: 3 ismeretlen karakter: valószínűleg más a kódolás). - Hexadecimális nézet: az első 64 bájt 16-os sorokban (
BitConverter.ToString), a BOM kiemelve szövegben (UTF-8 BOM (EF BB BF)). - Átalakítás és mentés: a cél kódolás és a BOM választható; a sorvég egységesítve; veszteség-ellenőrzés (
ExceptionFallback): ha a szöveg nem ábrázolható a célban, a program felsorolja az első néhány problémás karaktert, és megkérdezi, folytassa-e (? cserével); a mentés új fájlba (az eredeti nem íródik felül). - Hibatűrés: üres fájl, bináris fájl (sok
�), nagy fájl (> 20 MB figyelmeztetés), zárolt fájl; a program nem omlik össze. - Teszteld: egy UTF-8 BOM-mal, UTF-8 BOM nélkül, Windows-1250 és UTF-16 fájllal (a Jegyzettömb Mentés másként ablakában választható a kódolás); az Árvíztűrő tükörfúrógép mondat mindegyikben; ASCII-ra átalakítás figyelmeztetése; CRLF és LF sorvég.
Megoldás megnyitása (próbáld ki előbb önállóan!)
A központi rész a Felismer metódus (BOM → érvényes UTF-8 → feltételezés) és a veszteség-ellenőrzéses mentés.
private byte[] bajtok = new byte[0];
private void Form1_Load(object sender, EventArgs e)
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
string[] nevek = { "UTF-8", "UTF-16 (LE)", "Windows-1250", "ISO-8859-2", "ASCII", "Windows-1252" };
cmbKodolas.Items.AddRange(nevek);
cmbCel.Items.AddRange(nevek);
cmbKodolas.SelectedIndex = 0;
cmbCel.SelectedIndex = 0;
cmbSorveg.Items.AddRange(new object[] { "Windows (CRLF)", "Unix (LF)" });
cmbSorveg.SelectedIndex = 0;
}
private Encoding KodolasBol(int index, bool szigoru)
{
Encoding e;
switch (index)
{
case 1: e = Encoding.Unicode; break;
case 2: e = Encoding.GetEncoding(1250, szigoru ? EncoderFallback.ExceptionFallback : EncoderFallback.ReplacementFallback, szigoru ? DecoderFallback.ExceptionFallback : DecoderFallback.ReplacementFallback); break;
case 3: e = Encoding.GetEncoding("iso-8859-2", szigoru ? EncoderFallback.ExceptionFallback : EncoderFallback.ReplacementFallback, szigoru ? DecoderFallback.ExceptionFallback : DecoderFallback.ReplacementFallback); break;
case 4: e = Encoding.GetEncoding("us-ascii", szigoru ? EncoderFallback.ExceptionFallback : EncoderFallback.ReplacementFallback, szigoru ? DecoderFallback.ExceptionFallback : DecoderFallback.ReplacementFallback); break;
case 5: e = Encoding.GetEncoding(1252, szigoru ? EncoderFallback.ExceptionFallback : EncoderFallback.ReplacementFallback, szigoru ? DecoderFallback.ExceptionFallback : DecoderFallback.ReplacementFallback); break;
default: e = szigoru ? new UTF8Encoding(false, true) : new UTF8Encoding(false); break; // a második paraméter: hibát dob érvénytelen bájtra
}
return e;
}
// BOM → érvényes UTF-8 → feltételezés (Windows-1250)
private int Felismer(byte[] b, out string ok)
{
if (b.Length >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF) { ok = "BOM alapján (UTF-8)"; return 0; }
if (b.Length >= 2 && b[0] == 0xFF && b[1] == 0xFE) { ok = "BOM alapján (UTF-16 LE)"; return 1; }
try
{
new UTF8Encoding(false, true).GetString(b); // kivételt dob, ha érvénytelen
ok = "érvényes UTF-8 bájtsorozat";
return 0;
}
catch (DecoderFallbackException)
{
ok = "nem érvényes UTF-8, feltételezés: Windows-1250";
return 2;
}
}
private string Dekodol(byte[] b, Encoding kod)
{
int kezd = 0;
// a BOM bájtjait nem mutatjuk a szövegben
if (kod.CodePage == 65001 && b.Length >= 3 && b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF) { kezd = 3; }
else if (kod.CodePage == 1200 && b.Length >= 2 && b[0] == 0xFF && b[1] == 0xFE) { kezd = 2; }
return kod.GetString(b, kezd, b.Length - kezd);
}
private void Mutat()
{
if (bajtok.Length == 0) { return; }
string szoveg = Dekodol(bajtok, KodolasBol(cmbKodolas.SelectedIndex, false));
txtSzoveg.Text = szoveg.Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
int ismeretlen = szoveg.Count(c => c == '\uFFFD');
lblInfo.Text = bajtok.Length + " bájt, " + szoveg.Length + " karakter" + (ismeretlen > 0 ? ", " + ismeretlen + " ismeretlen karakter: valószínűleg más a kódolás" : "");
// hexadecimális nézet: 16 bájt soronként
StringBuilder sb = new StringBuilder();
int db = Math.Min(64, bajtok.Length);
for (int i = 0; i < db; i += 16)
{
sb.AppendLine(BitConverter.ToString(bajtok, i, Math.Min(16, db - i)).Replace('-', ' '));
}
if (bajtok.Length >= 3 && bajtok[0] == 0xEF && bajtok[1] == 0xBB && bajtok[2] == 0xBF) { sb.AppendLine("(UTF-8 BOM: EF BB BF)"); }
txtHex.Text = sb.ToString();
}
private void btnMegnyit_Click(object sender, EventArgs e)
{
if (ofd.ShowDialog(this) != DialogResult.OK) { return; }
try
{
if (new FileInfo(ofd.FileName).Length > 20 * 1024 * 1024 && MessageBox.Show(this, "A fájl nagyobb 20 MB-nál. Betöltsem?", "Nagy fájl", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != DialogResult.Yes) { return; }
bajtok = File.ReadAllBytes(ofd.FileName);
}
catch (IOException ex) { MessageBox.Show(this, "A fájl nem olvasható: " + ex.Message, "Megnyitás", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
catch (UnauthorizedAccessException) { MessageBox.Show(this, "Nincs jogosultság a fájlhoz.", "Megnyitás", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
if (chkAuto.Checked)
{
string ok;
cmbKodolas.SelectedIndex = Felismer(bajtok, out ok);
tsslUzenet.Text = "Felismerés: " + ok;
}
Mutat();
}
private void cmbKodolas_SelectedIndexChanged(object sender, EventArgs e) { Mutat(); }
private void btnMent_Click(object sender, EventArgs e)
{
if (txtSzoveg.TextLength == 0) { return; }
string szoveg = txtSzoveg.Text.Replace("\r\n", "\n");
if (cmbSorveg.SelectedIndex == 0) { szoveg = szoveg.Replace("\n", "\r\n"); }
Encoding szigoru = KodolasBol(cmbCel.SelectedIndex, true);
byte[] ki;
try
{
ki = szigoru.GetBytes(szoveg);
}
catch (EncoderFallbackException ex)
{
if (MessageBox.Show(this, "Nem ábrázolható karakter a célkódolásban: '" + ex.CharUnknown + "'. Ezek ?-re cserélődnek. Folytatod?", "Veszteséges átalakítás", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) != DialogResult.Yes) { return; }
ki = KodolasBol(cmbCel.SelectedIndex, false).GetBytes(szoveg);
}
byte[] bom = chkBom.Checked ? KodolasBol(cmbCel.SelectedIndex, false).GetPreamble() : new byte[0]; // a BOM bájtjai (UTF-8: EF BB BF)
sfd.Filter = "Szöveg (*.txt)|*.txt|Minden fájl (*.*)|*.*";
if (sfd.ShowDialog(this) != DialogResult.OK) { return; }
try
{
File.WriteAllBytes(sfd.FileName, bom.Concat(ki).ToArray());
tsslUzenet.Text = "Mentve: " + Path.GetFileName(sfd.FileName);
}
catch (IOException ex) { MessageBox.Show(this, "A mentés nem sikerült: " + ex.Message, "Mentés", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}Mit tegyél ide: a kész kódolás-átalakító: a felismert kódolás, a szöveg és a hexadecimális nézet.Javasolt fájlnév: winforms-10-3-kesz.webp · Alt szöveg: A kész kódolás-átalakító
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Bájtok száma
Hány bájt az Árvíztűrő szó UTF-8-ban, UTF-16-ban és Windows-1250-ben? A szóban 9 karakter van, ebből 4 ékezetes (Á, í, ű, ő). Az Egy lehetséges megoldás
Encoding.GetByteCount megadja: UTF-8: 9 + 4 = 13 bájt, UTF-16: 18 bájt, Windows-1250: 9 bájt.string s = "Árvíztűrő";int a = Encoding.UTF8.GetByteCount(s);int b = Encoding.Unicode.GetByteCount(s);int c = Encoding.GetEncoding(1250).GetByteCount(s);
2. Ékezet-mentesítés
Készíts függvényt, amely az ékezeteket eltávolítja (árvíztűrő → arvizturo), a kereséshez. Mit használsz? A Egy lehetséges megoldás
string.Normalize(NormalizationForm.FormD) az ékezetes betűt alapbetűre és kombináló ékezetre bontja, a CharUnicodeInfo.GetUnicodeCategory pedig kiszűri az ékezeteket (NonSpacingMark).string Ekezetmentes(string s){ string bontott = s.Normalize(NormalizationForm.FormD); StringBuilder sb = new StringBuilder(); foreach (char c in bontott) { if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) { sb.Append(c); } } return sb.ToString().Normalize(NormalizationForm.FormC);}
3. Tömeges átalakítás
Egy mappa összes .txt fájlját alakítsd UTF-8-ra, új almappába. Mire kell vigyáznod? Az eredetit ne írd felül; a kódolást fájlonként ismerd fel (BOM → UTF-8 érvényesség → feltételezés), és a bizonytalan fájlokat jelentsd; a hibás fájl ne állítsa le a teljes feldolgozást.Egy lehetséges megoldás
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. Mi az UTF-8 BOM?
Hány és milyen bájtok jelzik az UTF-8 BOM-ot? Három bájt: Megoldás megnyitása
EF BB BF, a fájl elején.
2. Melyik kódolás?
Melyiket választod: (a) új JSON fájl; (b) régi magyar program importfájlja; (c) Excelben megnyitandó CSV? (a) UTF-8 BOM nélkül; (b) Windows-1250 (ha a program ezt várja); (c) UTF-8 BOM-mal.Megoldás megnyitása
Közepes szint
3. Az ismeretlen karakter
Hogyan számolod meg a beolvasott szövegben a � karaktereket, és mire jó?Megoldás megnyitása
szoveg.Count(c => c == '\uFFFD'); ha nem nulla, a kódolás valószínűleg rossz: a program figyelmeztetheti a felhasználót, vagy másik kódolást próbálhat.
4. Hozzáfűzés más kódolású fájlhoz
A meglévő fájl Windows-1250, a program hozzáfűz. Mit kell tenned? A Megoldás megnyitása
StreamWriter kódolását is Windows-1250-re állítod (new StreamWriter(ut, true, Encoding.GetEncoding(1250))); más kódolással a fájl két kódolás keveréke lenne.
Kihívás szint
5. Kódolás-tipp fájlrészletből
Készíts egyszerű tippelőt: a Windows-1250 szöveg gyakori betűit (é = Statisztikai tipp: a magyar szövegben az ő és ű (E9, ő = F5) számolva döntsd el, jobban illik-e a fájl Latin-1-hez vagy a Windows-1250-hez. Mi a korlátja?Megoldás megnyitása
F5, FB a 1250-ben) gyakori, Latin-1-ben ezek õ és û. Rövid szövegnél megbízhatatlan; a végső szó mindig a felhasználóé (kódolás-választó).
6. UTF-8 érvényesség kézzel
Mikor érvénytelen egy bájt-sorozat UTF-8-ként? Adj két példát. (1) Egy 11xxxxxx kezdőbájt után hiányzik a 10xxxxxx folytatóbájt (például egyedül álló Megoldás megnyitása
F5); (2) a folytatóbájt kezdőbájt nélkül áll. A .NET dekódoló ezeket � karakterre cseréli (vagy kivételt dob, ha kérsz).
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A karakterek és a bájtok közötti megfeleltetés. Minden nyelv betűit tudja, az ASCII-val kompatibilis, a web és a modern eszközök ezt használják. A fájl elején jelzi a kódolást (például az Excel számára). Helyettesítő karakter: az érvénytelen bájt-sorozatot jelzi (rossz kódolással olvastál). Az újabb .NET a Windows-1250-et csak a A nem ábrázolható karaktereket csendben ?-re cseréli: az adat elvész. A 1. Mi a kódolás?
2. Miért az UTF-8 az alapértelmezett választás?
3. Mire való a BOM?
4. Mi a � jel?
5. Miért kell RegisterProvider?
CodePagesEncodingProvider regisztrálása után ismeri.6. Mi a baj az ASCII-val ékezetes szövegnél?
7. Miért veszélyes a Split('\n') CRLF fájlon?
\r a sor végén marad, a hasonlítás hibás lesz.
Mit tudsz már?
- Érted a bájt, karakter és kódolás viszonyát.
- UTF-8-ban dolgozol, és tudod, mikor kell BOM.
- Windows-1250 és Latin-2 fájlt is beolvasol, és felismered a kódolási hibák tüneteit.
- Kezeled a sorvégeket.
- Veszteség-ellenőrzéssel alakítasz át fájlt másik kódolásra.
Következő lecke: Fájl- és mappaválasztó párbeszédablakok
A 7.8 lecke mélyítése: segédosztály a fájlválasztáshoz, az utoljára használt mappa megjegyzése, útvonal-ellenőrzés és a legutóbbi fájlok listája.



