Pliki binarne a struktury i listy

Tym tematem nawiążę do sposobu zachowywania danych i ich odczytywania z pliku. Tym razem dane nie będą zapisywane w pliku tekstowym lecz w pliku binarnym.

Plik binarny, to plik (za wyjątkiem plików tekstowych) o dowolnej zawartości, zapisany ustalonym sposobem kodowania. W naszym przypadku będzie to struktura. Poprawny odczyt takiego pliku wymaga znajomości metody kodowania zapisu. W tym rozwiązaniu będzie to znajomość struktury zapisu.

Przykładowy widok na podgląd zdefiniowanego pliku binarnego

plik binarny Visual Studio C#

Serializacja danych

Proces serializacji danych, to proces zamiany rozbudowanych obiektów (struktur, obiektów) na ciąg (strumień) bajtów, który można zapisać do pliku lub przesyłać przez sieć.

Deserializacja danych

Deserializacja danych jest odwrotnym procesem do serializacji. Deserializacja danych wykonywana jest przy odczycie strumienia bajtów i odtworzeniu do pierwotnej struktury lub pierwotnego obiektu.

Projekt formatki

Układ formatki jak i podstawowy kod tworzonej aplikacji desktopowej jest rozwinięciem aplikacji z tego tematu: Operacje na liście

Do projektu dodamy kolejne komponenty:

plik binarny Visual Studio C#

Do kodu dodamy dwie biblioteki, dzięki którym obsłużymy pliki i binarny strumień danych

Wskazówka:


using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

Serializacja danych

Do naszej struktury dopisujemy dyrektywę serializacji danych. Patrz poniżej

Wskazówka:


[Serializable]
struct Dane
{
    public string nazwisko;
    public string imie;
    public string klasa;
}

Zapis pliku binarnego

Tworzony plik binarny będzie zawierać pełną listę utworzoną w aplikacji. Dla czytelności kodu zapis danych będzie zawsze odbywał się w nowym pliku lub nadpisie już istniejącego pliku.

W pseudokodzie instrukcje zapisu pliku binarnego można podać jak poniżej

Dla naszych binarnych plików zdefiniujemy nowe rozszerzenie. Ja zdefiniowałem rozszerzenie o nazwie: moj. Rozszerzenie zapisałem w filtrze kontrolki okna dialogowego zapisu plików.

W rzeczywistym kodzie w języku C# zorganizujemy to jak poniżej

Wskazówka:


private void zapiszToolStripMenuItem_Click(object sender, EventArgs e)
{
    //ustaw filtr plików
    saveFileDialog1.Filter = "Pliki binarne .moj|*.moj|Wszystkie pliki *.*|*.*";
    //ustaw tytuł okna zapisu dialogowego
    saveFileDialog1.Title = "Zapisz zawartość";
    //narzuć filtr podstawowy
    saveFileDialog1.DefaultExt = "moj";
    //ustaw zapis w katalogu exe'ka
    saveFileDialog1.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath);
    if (saveFileDialog1.ShowDialog() == DialogResult.OK)
    {
        FileStream plikStrumienia = new FileStream(saveFileDialog1.FileName,
                                                   FileMode.Create,
                                                   FileAccess.Write,
                                                   FileShare.None);
        BinaryFormatter buforDanych = new BinaryFormatter();
        buforDanych.Serialize(plikStrumienia, lista);
        plikStrumienia.Close();
        toolStripStatusLabel1.Text = saveFileDialog1.FileName;
    }
}

Skompiluj program. Dodaj do listy kilka elementów i zapisz ją do pliku. Prawidłowo działająca aplikacji utworzy plik, którego zawartość możesz podglądnąć w notatniku.

serialize plik binarny Visual Studio C#

Odczyt danych z pliku binarnego

Odczyt danych z pliku binarnego w pseudokodzie można przedstawić jak poniżej

Otwarcie i odczyt danych z pliku binarnego w rzeczywistym kodzie programu w języku C# można wykonać jak poniżej

Wskazówka:


private void otworzToolStripMenuItem_Click(object sender, EventArgs e)
{
    openFileDialog1.Filter = "Pliki binarne .moj|*.moj|Wszystkie pliki *.*|*.*";
    //ustaw tytuł okna zapisu dialogowego
    openFileDialog1.Title = "Otwórz plik";
    //narzuć filtr podstawowy
    openFileDialog1.DefaultExt = "moj";
    //ustaw w katalogu exe'ka
    openFileDialog1.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath);
    if (openFileDialog1.ShowDialog() == DialogResult.OK)
    {
        textBox4.Clear();
        FileStream plikStrumienia = File.OpenRead(openFileDialog1.FileName);
        BinaryFormatter buforDanych = new BinaryFormatter();
        //int id = 0;
        lista.Clear();
        lista = (List<Dane>)buforDanych.Deserialize(plikStrumienia);
        plikStrumienia.Close();
    }
}

Po wczytaniu danych z pliku do listy, możemy zawartość listy przesłać do kontrolki TextBox pracującej w układzie wielu linii.

deserialize odczyt plik binarny Visual Studio C#

Wczytana lista

deserialize plik binarny Visual Studio C#

Pełny kod aplikacji

Wskazówka:


using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
struct Dane
{
    public string nazwisko;
    public string imie;
    public string klasa;
}

namespace plik_binarny_struktury_listy
{
    
    public partial class Form1 : Form
    {
        private Dane d;
        private List<Dane> lista = new List<Dane>();
        private int idBiezacy = 0;
        public Form1()
        {
            InitializeComponent();
        }
        private void czyscDana()
        {
            d.nazwisko = "";
            d.imie = "";
            d.klasa = "";
        }
        private void dodaj()
        {
            czyscDana();
            d.nazwisko = textBox1.Text; 
            d.imie = textBox2.Text;
            d.klasa = textBox3.Text;
            lista.Add(d);
            idBiezacy = lista.Count - 1;
        }
        private void pokazRekord(int id, TextBox tb)
        {
            if (id < 0 || id>lista.Count-1) return;
            d = lista[id];
            tb.Clear();
            tb.AppendText((id+1).ToString() + Environment.NewLine);
            tb.AppendText(d.nazwisko + Environment.NewLine);
            tb.AppendText(d.imie + Environment.NewLine);
            tb.AppendText(d.klasa + Environment.NewLine);
        }
        private void pokazListe(TextBox tb)
        {
            tb.Clear();
            for(int i = 0; i < lista.Count;i++)
            {
                tb.AppendText((i+1).ToString()+"*******************"+ Environment.NewLine);
                tb.AppendText(lista[i].nazwisko + Environment.NewLine);
                tb.AppendText(lista[i].imie + Environment.NewLine);
                tb.AppendText(lista[i].klasa + Environment.NewLine);
            }
        }
        private void Button1_Click(object sender, EventArgs e)
        {
            dodaj();
            toolStripStatusLabel1.Text = lista.Count.ToString();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            pokazListe(textBox4);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            pokazRekord(idBiezacy, textBox4);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            //pokaz kolejny rekord z lewej
            idBiezacy--;
            if (idBiezacy < 0) idBiezacy = 0;
            pokazRekord(idBiezacy, textBox4);
        }

        

        private void textBox5_KeyUp(object sender, KeyEventArgs e)
        {
            if (textBox5.Text.Length < 1)
            {
                idBiezacy = 0;
                textBox5.Text = "1";
            }
            else
            {
                idBiezacy = Convert.ToInt16(textBox5.Text) - 1;
            }
            pokazRekord(idBiezacy, textBox4);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            //pokaz pierwszy rekord
            idBiezacy = 0;
            pokazRekord(idBiezacy, textBox4);
        }

        private void button7_Click(object sender, EventArgs e)
        {
            //pokaz ostatni rekord
            idBiezacy = lista.Count-1;
            pokazRekord(idBiezacy, textBox4);
        }

        private void button6_Click(object sender, EventArgs e)
        {
            //pokaz kolejny rekord z prawej
            idBiezacy++;
            if (idBiezacy >lista.Count-1) idBiezacy = lista.Count - 1;
            pokazRekord(idBiezacy, textBox4);
        }

        private void button9_Click(object sender, EventArgs e)
        {
            lista.Clear();
            toolStripStatusLabel1.Text = lista.Count.ToString();
        }

        private void button8_Click(object sender, EventArgs e)
        {
            textBox1.Clear();
            textBox2.Clear();
            textBox3.Clear();
        }

        private void button10_Click(object sender, EventArgs e)
        {
            lista.RemoveRange(idBiezacy, 1);
            toolStripStatusLabel1.Text = lista.Count.ToString();
        }


        private void zapiszToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //ustaw filtr plików
            saveFileDialog1.Filter = "Pliki binarne .moj|*.moj|Wszystkie pliki *.*|*.*";
            //ustaw tytuł okna zapisu dialogowego
            saveFileDialog1.Title = "Zapisz zawartość";
            //narzuć filtr podstawowy
            saveFileDialog1.DefaultExt = "moj";
            //ustaw w katalogu exe'ka
            saveFileDialog1.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath);
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                FileStream plikStrumienia = new FileStream(saveFileDialog1.FileName,
                                                           FileMode.Create,
                                                           FileAccess.Write,
                                                           FileShare.None);
                BinaryFormatter buforDanych = new BinaryFormatter();
                buforDanych.Serialize(plikStrumienia, lista);
                plikStrumienia.Close();
                toolStripStatusLabel1.Text = saveFileDialog1.FileName;
            }
        }

        private void otworzToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openFileDialog1.Filter = "Pliki binarne .moj|*.moj|Wszystkie pliki *.*|*.*";
            //ustaw tytuł okna zapisu dialogowego
            openFileDialog1.Title = "Otwórz plik";
            //narzuć filtr podstawowy
            openFileDialog1.DefaultExt = "moj";
            //ustaw w katalogu exe'ka
            openFileDialog1.InitialDirectory = Path.GetDirectoryName(Application.ExecutablePath);
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                textBox4.Clear();
                FileStream plikStrumienia = File.OpenRead(openFileDialog1.FileName);
                BinaryFormatter buforDanych = new BinaryFormatter();
                //int id = 0;
                lista.Clear();
                lista = (List<Dane>)buforDanych.Deserialize(plikStrumienia);
                plikStrumienia.Close();
            }
        }
    }
}
Układ okresowy- kod qr
Układ okresowy

Układ okresowy pierwiastków- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Alkomat- wirtualny test kod qr
Alkomat- wirtualny test

Alkomat- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
Taklarz- olinowanie stałe kod qr
Olinowanie stałe- kalkulator średnic

Olinowanie stałe- darmowa aplikacja na Androida

Pobierz ze sklepu Google Play
przepis na gogfry

Przepis na gofry

zobacz
przepis na bitą śmietanę

Przepis na bitą śmietanę

zobacz