File és stream kezelés
Dr. Kotsis Domokos Nagy Tibor
Hallgatói tájékoztató A jelen bemutatóban található adatok, tudnivalók és információk a számonkérendő anyag vázlatát képezik. Ismeretük szükséges, de nem elégséges feltétele a sikeres zárthelyinek, illetve vizsgának. Sikeres zárthelyihez, illetve vizsgához a jelen bemutató tartalmán felül a kötelező irodalomként megjelölt anyag, a gyakorlatokon szóban, illetve a táblán átadott tudnivalók ismerete, valamint a gyakorlatokon megoldott példák és az otthoni feldolgozás céljából kiadott feladatok önálló megoldásának képessége is szükséges.
File-ok és elérésük A System.IO névtér szükséges File, FileInfo Fájlok és jellemzőik kezelése Directory, DirectoryInfo Könyvtárak és jellemzőik kezelése Path Fájlnevet és elérési utat tartalmazó sztring részekre bontására használható
A File osztály • Statikus osztály, háttértáron elhelyezkedő fájlok kezelésére • Metódusai: – – – – – – – – – – – – – …
Create(string path, int bufferSize, FileOptions options) Copy(string sourceFileName, string destFileName) Move(string sourceFileName, string destFileName) Delete(string path) Exists(string path) GetAttributes(string path) SetAttributes(string path, FileAttributes attributes) GetCreationTime(string path) Open(String, FileMode, FileAccess, FileShare) Open(string path, FileMode mode, FileAccess access, FileShare share) OpenRead(string path) OpenText(string path) OpenWrite(string path)
A FileInfo osztály Metódusai: – – – – – – – – –
AppendText CopyTo Create CreateText Delete Equals Finalize GetAccessControl GetType
– MoveTo – Open – OpenRead – OpenText – OpenWrite – Refresh – Replace – SetAccessControl
A FileInfo osztály Tulajdonságai: – – – – – – – – – – – – – – –
Attributes CreationTime CreationTimeUtc Directory DirectoryName Exists Extension FullName IsReadOnly LastAccessTime LastAccessTimeUtc LastWriteTime LastWriteTimeUtc Length Name
A Directory osztály • Statikus osztály, háttértáron elhelyezkedő könyvtárak kezelésére • Metódusai: – CreateDirectory(string path) – Exists(string path) – Delete(string path, bool recursive) – GetDirectories(string path) – GetCurrentDirectory(), SetCurrentDirectory(string path) – GetFiles(string path) – GetParent(string path) … • Nem statikus változata a DirectoryInfo osztály
A Path osztály • Statikus osztály, melynek metódusai fájlnevet és elérési utat tartalmazó sztring részekre bontására használhatóak • Metódusai: – GetDirectoryName(string path) – GetFileName(string path) – GetExtension(string path) – GetFileNameWithoutExtension(string path) – …
Kivételek FileNotFoundException IOException
…
Feladat Készítsen programot, a File osztály használatával, mely megadott file-ról másolatot készít megadott helyre, megadott néven!
File másolás … using System.IO; … private void be_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) ki.Focus(); } private void ki_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { try { File.Copy(be.Text, ki.Text); Üzenet.Text = "Kész."; }
Hiba vizsgálat catch (FileNotFoundException) { Üzenet.Text = "Nem létezik az input file!"; } catch (IOException) { Üzenet.Text = "Már létezik a cél file!"; } catch { Üzenet.Text = "Hiba másolás közben!"; } } }
Feladat Készítsen programot, a FileInfo osztály használatával, mely egy file-ról megadja annak méretét, a készítés és az utolsó használat időpontját.
File adatok … using System.IO; … private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { Méret.Text = ""; Készítés.Text = ""; Utolsó.Text =""; FileInfo vizsgálandó = new FileInfo(textBox1.Text); if (vizsgálandó.Exists) { Méret.Text = vizsgálandó.Length.ToString(); Készítés.Text = vizsgálandó.CreationTime.ToString(); Utolsó.Text = vizsgálandó.LastAccessTime.ToString(); } else Üzenet.Text = "Nem létezik az input file!"; …
Stream-ek def. Adatfolyamok: pl. (de nem csak) a file-okból, vagy file-okba történő adatáramlás. Egymáshoz is kapcsolódhatnak.
Stream-ek I. Egy adott médiához kapcsolódnak, onnan/oda írnak/olvasnak byte-okat. • • • • •
Memória Háttértár (fájl) Hálózat Soros port …
System.IO.Stream leszármazottjai: • System.IO.FileStream • System.IO.MemoryStream • System.IO.NetworkStream •…
Stream-ek II. Meghatározott tartalmat írnak, olvasnak: System.IO.StreamReader System.IO.StreamWriter System.IO.StringReader System.IO.StringWriter System.IO.BinaryReader System.IO.BinaryWriter …
(szöveg kódolással) (stringek) (bináris tart.)
Stream-ek megnyitása, zárása •
•
Megnyitás: – A megfelelő stream-osztály példányának létrehozásával pl.: StreamReader sr = new StreamReader("proba.txt"); FileStream fs = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read, FileShare.None); – A File, vagy a FileInfo osztály megfelelő metódusai (Create, Open, OpenRead, OpenWrite, CreateText, OpenText, AppendText) segítségével pl.: StreamReader sr=File.OpenText("proba.txt"); FileStream fs = File.Open(textBox1.Text, FileMode.Open, FileAccess.Read, FileShare.None); Bezárás: – A stream Close() metódusával pl.: sr.Close();
A File ill FileInfo osztályok egyes stream nyitó metódusai FileStream streamet hoz létre: – – – –
Create(…) Open(…) OpenRead(…) OpenWrite(…)
StreamReader streamet hoz létre: – OpenText(…)
StreamWriter streamet hoz létre: – CreateText(…) – AppendText(…)
Pozícionálás streamek-ben – A stream-ek nagy része soros hozzáférésű. A pozícionálás ezeknél az író/olvasó metódusokkal történik. – A közvetlen hozzáférésű stream-ek esetén lehetőség van a pozícionálásra a Seek(long offset, SeekOrigin origin) metódus segítségével. A SeekOrigin { Begin, End, Current } felsorolás konstansaival adható meg, hogy honnan számítva mozduljon el offset byte-tal a fájlpointer. (FileStream, MemoryStream, BufferedStream)
A using utasítás • Szintaxisa using (objektum-létrehozás) { utasítások; } • A paraméterként létrehozott objektum(ok) által foglalt memóriaterület automatikus felszabadítása az utasításblokk végén (nem kell várni a GC-re) • Példa: using (StreamReader sr = new StreamReader("proba.txt")) { string s, s1 = ""; while((s = sr.ReadLine()) != null) s1 += s + "\n"; MessageBox.Show(s1); sr.Close(); }
FileStream konstruktor FileStream(string path, FileMode mode) FileStream(string path, FileMode mode, FileAccess access) FileStream(string path, FileMode mode, FileAccess access, FileShare share) FileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
Felsorolás típusok I. • Fájlmegnyitás módja: FileMode { Append hozzáfűzés (ha nem létezik a fájl, létrehozza) Create új fájl (ha a fájl létezik, akkor felülírja) CreateNew új fájl (ha a fájl létezik, IOException) Open megnyitás (ha a fájl nem létezik, FileNotFoundExc.) OpenOrCreate megnyit, vagy létrehoz Truncate törlés és újra létrehozás }
Felsorolás típusok II. • A fájlhozzáférés módja FileAccess { Read, ReadWrite, Write } • Meghatározza, hogy más streamek milyen módon férhetnek hozzá ehhez a fájlhoz, amíg nyitva van: FileShare { Delete, None, ReadWrite, Write, Read } • Egyéb beállítások FileOptions { Asynchronous, DeleteOnClose, Encrypted, None, RandomAccess, SequentialScan, WriteThrough }
Tulajdonságok CanRead CanWrite Length Position
logikai logikai byte-okban get, set
Metódusok Close() Flush() Seek(long offset, SeekOrigin origin) (origin: { Begin, End, Current } ) Read(byte[] buffer, int offset, int count) ReadByte() (Egésszé alakított byte érték, vagy -1) Write(byte[] buffer, int offset, int count) WriteByte()
Feladat Készítsen programot, mely a FileStream osztály használatával beolvassa egy megadott text file tartalmát egy ListBox-ba. Használja a Read() metódust!
Megoldás private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { FileStream fs = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read, FileShare.None); byte[] byteText = new byte[fs.Length]; string st = ""; fs.Read(byteText, 0, byteText.Length); for (int i=0; i
Feladat Készítsen programot, mely a FileStream osztály használatával beolvassa egy megadott text file tartalmát egy ListBox-ba. Használja a ReadByte() metódust!
StreamWriter I. Karakterek fájlba írása meghatározott kódolás szerint StreamWriter(Stream s) StreamWriter(string filename) StreamWriter(string path, Encoding enc) StreamWriter(string path, bool append) StreamWriter(string path, bool append, Encoding enc) StreamWriter(string path, bool append, Encoding enc, int buffersize)
StreamWriter II. • Metódusai – Write(…) : adott típusú adat kiírása – WriteLine(…) : adott típusú adat kiírása soremeléssel • Tulajdonságai – NewLine : az újsor karakter – AutoFlush : kiíródjon-e minden Write() után a kiírandó adat? • Kódolás – Az Encoding osztály statikus tulajdonságai (pl.: Encoding.UTF8)
Feladat Készítsen programot, ami az Ön által begépelt szöveget beviszi a megadott új file-ba. Használja a StreamWriter-t, és a File osztály metódusait!
Megoldás private void sor_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { StreamWriter szövegem = File.AppendText(file.Text); szövegem.WriteLine(sor.Text); szövegem.Close(); sor.Text = ""; } } private void button1_Click(object sender, EventArgs e) { this.Close(); }
Feladat Készítsen programot, ami az Ön által begépelt szöveget beviszi a megadott új file-ba. Használja a StreamWriter-t, és a StreamWriter konstruktorát!
Megoldás public partial class Form1 : Form { bool nyitott= false; StreamWriter szövegem; … private void sor_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { if (!nyitott) { szövegem = new StreamWriter(file.Text); nyitott = true; } szövegem.WriteLine(sor.Text); sor.Text = ""; } } private void button1_Click(object sender, EventArgs e) { this.Close(); szövegem.Close(); }
StreamReader I. • Adat olvasása szövegfájlból meghatározott kódolás szerint StreamReader(Stream s) StreamReader(string filename) StreamReader(string path, Encoding enc) StreamReader(string path, bool append) StreamReader(string path, bool append, Encoding enc) StreamReader(string path, bool append, Encoding enc, int buffersize)
StreamReader II. • Metódusai – Read() : egy karaktert olvas – Read(char[] buffer, int offset, int count) : tömbbe olvas count darab karaktert – ReadLine() : egy sort olvas – Peek() : egy karakter előreolvasása • Tulajdonságok: – EndOfStream : jelzi a stream végét • Kódolás – Az Encoding osztály statikus tulajdonságai (pl.: Encoding.UTF8)
Feladat Készítsen programot, ami beolvassa egy magadott szöveg file sorait egy ListBox-ba. Használja a StreamReader-t, és a File osztály Opentext() metódusát!
Szöveg beolvasása private void file_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { string buffer; StreamReader szövegem = File.OpenText(file.Text); while ((buffer = szövegem.ReadLine()) != null) listBox1.Items.Add(buffer); szövegem.Close(); } }
BinaryReader / BinaryWriter •
Elemi típusú adatok beolvasását / kiírását teszik lehetővé. Másik stream-re épül!
•
BinaryReader(Stream input) BinaryReader(Stream input, Encoding encoding) BinaryWriter(Stream input) BinaryWriter(Stream input, Encoding encoding)
•
Metódusaik: – ReadX() – Write(data) – X helyére az elemi típus .NET osztálykönyvtárbeli nevét lehet behelyettesíteni pl.: ReadDouble(), ReadSingle(), …
Feladat Készítsen programot, mely kiírja, majd beolvassa egy ListBox-ba az alábbi adatokat: Név (string) Kor (int) Súly (double)
Használja a BinaryWriter/Reader és a FileStream stream-eket!
Kiírás private void button1_Click(object sender, EventArgs e) { string fileName = "f:\\eb.txt"; FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); BinaryWriter wr = new BinaryWriter(fs); wr.Write("Kiss Pál"); wr.Write("Kora: "); wr.Write(23); wr.Write("Súlya: "); wr.Write(85.5); wr.Close(); fs.Close(); button2.Enabled = true; }
Beolvasás private void button2_Click(object sender, EventArgs e) { string fileName = "f:\\eb.txt"; listBox1.Items.Add("File neve: " + fileName); FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None); BinaryReader rd = new BinaryReader(fs); string név = rd.ReadString(); string korString = rd.ReadString(); int kor = rd.ReadInt32(); string súlyString = rd.ReadString(); double súly = rd.ReadDouble(); listBox1.Items.Add(név); listBox1.Items.Add(korString + kor.ToString()); listBox1.Items.Add(súlyString + súly.ToString()); rd.Close(); fs.Close(); }
Feladat Készítsen programot, mely kiírja, majd belovassa egy ListBox-ba az alábbi adatokat: Név (string) Kor (int) Súly (double)
Használja a BinaryWriter/Reader-t és a File osztály metódusait!
Kiírás private void button1_Click(object sender, EventArgs e) { string fileName = "f:\\eb.txt"; BinaryWriter wr = new BinaryWriter(File.Create(fileName)); wr.Write("Kiss Pál"); wr.Write("Kora: "); wr.Write(23); wr.Write("Súlya: "); wr.Write(85.5); wr.Close(); button2.Enabled = true; }
Beolvasás private void button2_Click(object sender, EventArgs e) { string fileName = "f:\\eb.txt"; listBox1.Items.Add("File neve: " + fileName); BinaryReader rd = new BinaryReader(File.Open(fileName, FileMode.Open)); string név = rd.ReadString(); string korString = rd.ReadString(); int kor = rd.ReadInt32(); string súlyString = rd.ReadString(); double súly = rd.ReadDouble(); listBox1.Items.Add(név); listBox1.Items.Add(korString + kor.ToString()); listBox1.Items.Add(súlyString + súly.ToString()); rd.Close(); }
Feladat Készítsen programot, mely az első száz számot kiírja egy bináris file-ba. Használja a BinaryWriter stream-et!
Bináris output private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { FileStream binfájlom = new FileStream(textBox1.Text,FileMode.CreateNew); BinaryWriter bw = new BinaryWriter(binfájlom); for (int i = 0; i < 100; i++) { bw.Write(i); } bw.Close(); binfájlom.Close(); textBox1.Text = "Kész!"; } }
Feladat Készítsen programot, ami beolvassa az előző feladatban kiírt bináris file tartalmát egy ListBox-ba. Használja a BinaryReader stream-et!
Megjegyzések: 1. Használja a PeekChar() metódust, mely -1-et ad vissza, ha nincs több karakter. 2. Használja a ReadInt32() metódust.
Bináris input private void textBox1_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { FileStream binfájlom = new FileStream(textBox1.Text, FileMode.Open); BinaryReader br = new BinaryReader(binfájlom); while (br.PeekChar() != -1) { listBox1.Items.Add(br.ReadInt32().ToString()); } br.Close(); binfájlom.Close(); textBox1.Text = "Kész!"; } }
DeflateStream / GZipStream •
Adatok tömörítésére és kicsomagolására használható. Másik stream használatára épül! DeflateStream(Stream, CompressionMode) GZipStream(Stream, CompressionMode) DeflateStream(Stream, CompressionMode, Boolean) GZipStream(Stream, CompressionMode, Boolean)
•
A tömörítés iránya: CompressionMode { Compress, Decompress }
•
Metódusai: – Read(byte[] buffer, int offset, int count) – ReadByte() – Write(byte[] buffer, int offset, int count) – WriteByte() – Seek(long offset, SeekOrigin origin)
•
Tulajdonságai: – Length – Position
Feladat Készítsen programot, ami tömörít (becsomagol) egy megadott file-ot. A program tömböt használjon pufferként!
Megjegyzés: 1. Használja a GZipStream-ot. 2. Ne feledkezzék meg a using System.IO.Compression direktíváról.
Tömörítés I. private void be_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) ki.Focus(); } private void ki_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { FileStream infile = new FileStream(be.Text, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[infile.Length]; int count = infile.Read(buffer, 0, buffer.Length); infile.Close(); FileStream kimegy = new FileStream(ki.Text, FileMode.CreateNew, FileAccess.Write); GZipStream tömör = new GZipStream(kimegy, CompressionMode.Compress); tömör.Write(buffer, 0, buffer.Length); tömör.Close(); kimegy.Close(); } }
Feladat Készítsen programot, ami visszaállít (kicsomagol) egy tömörített file-t. A program tömböt használjon pufferként!
Megjegyzés: 1. Használja a GZipStream-ot. 2. Ne feledkezzék meg a using System.IO.Compression direktíváról.
Kicsomagolás I. private void ki_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { FileStream infile = new FileStream(be.Text, FileMode.Open,FileAccess.Read); GZipStream tömör = new GZipStream(infile, CompressionMode.Decompress); byte[] buffer = new byte[30000]; /*Nem tudjuk, mekkora!*/ int count = tömör.Read(buffer, 0, buffer.Length); infile.Close(); tömör.Close(); FileStream kimegy = new FileStream(ki.Text,FileMode.CreateNew, FileAccess.Write); kimegy.Write(buffer, 0, count); kimegy.Close(); } }
Feladat Készítsen programot, ami tömörít (becsomagol) egy megadott file-ot. A program byte-okat mozgasson!
Megjegyzés: 1. Használja a GZipStream-ot. 2. Ne feledkezzék meg a using System.IO.Compression direktíváról.
Tömörítés II. private void ki_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { FileStream infile = new FileStream(be.Text, FileMode.Open, FileAccess.Read); byte buffer; FileStream outfile = new FileStream(ki.Text, FileMode.Create, FileAccess.Write); GZipStream tömör = new GZipStream(outfile, CompressionMode.Compress); for (int i = 1; i < infile.Length+1; i++) { buffer = (byte)infile.ReadByte(); tömör.WriteByte(buffer); } tömör.Close(); infile.Close(); outfile.Close(); } }
Feladat Készítsen programot, ami visszaállít (kicsomagol) egy tömörített file-t. A program byte-okat mozgasson!
Megjegyzés: 1. Használja a GZipStream-ot. 2. Ne feledkezzék meg a using System.IO.Compression direktíváról.
Kicsomagolás II. private void ki_KeyPress(object sender, KeyPressEventArgs e) { if (e.KeyChar == (char)(13)) { FileStream infile = new FileStream(be.Text, FileMode.Open, FileAccess.Read); GZipStream tömör = new GZipStream(infile, CompressionMode.Decompress); byte buffer ; FileStream kimegy = new FileStream(ki.Text, FileMode.Create, FileAccess.Write); buffer = (byte)tömör.ReadByte(); while (buffer != 255) { kimegy.WriteByte(buffer); buffer = (byte)tömör.ReadByte(); } kimegy.Close(); infile.Close(); tömör.Close(); } }
MemoryStream • A memóriából tud olvasni / memóriába tud írni MemoryStream(int capacity) MemoryStream(byte[] buffer) MemoryStream(byte[] buffer, bool writable) … • Metódusai: – Read(byte[] buffer, int offset, int count) – ReadByte() – Write(byte[] buffer, int offset, int count) – WriteByte() – Seek(long offset, SeekOrigin origin) – WriteTo(Stream dest) • Tulajdonságai: – Capacity – Length – Position
Feladat Olvasson be két TextBox-ból egy-egy stringet, írja ki, majd olvassa vissza egy harmadik TextBox-ba MemoryStream használatával.
Byte tömbök feltöltése private void button1_Click(object sender, EventArgs e) { int count; byte[] byteArray; byte[] firstString = new byte[textBox1.Text.Length]; for (int i = 0; i < textBox1.Text.Length; i++) firstString[i] = (byte)textBox1.Text[i]; byte[] secondString = new byte[textBox2.Text.Length]; for (int i = 0; i < textBox2.Text.Length; i++) secondString[i] = (byte)textBox2.Text[i];
Kiírás using (MemoryStream memStream = new MemoryStream(100)) { // Az első string kiírása memStream.Write(firstString, 0, firstString.Length); // A második string kiírása byte-ről byte-ra count = 0; while (count < secondString.Length) { memStream.WriteByte(secondString[count++]); }
Beolvasás // A pozíció beállítása memStream.Seek(0, SeekOrigin.Begin); // Az első 20 byte beolvasása byteArray = new byte[memStream.Length]; count = memStream.Read(byteArray, 0, 20); // A maradék beolvasása byte-ről byte-ra. while (count < memStream.Length) { byteArray[count++] = Convert.ToByte(memStream.ReadByte()); }
Az eredmény a textBox3-ba
string s = ""; for (int j = 0; j < byteArray.Length; j++) s = s +(char)byteArray[j]; textBox3.Text = s; } }