Práce se souborem (*.txt ?)   zodpovězená otázka

VB.NET, Architektura, Optimalizace

Dobrý den,

jsem začátečník, jak v programování, tak ve VB.net a potřeboval bych poradit.

Visual Basic 2008 Express

Vytvořil jsem formulář, který obsahuje ComboBox, Button a nějaké labely a textboxy.

V souboru *.txt jsou tři typy dat Jméno, Mód a Částka, vždy po trojicích, které se opakují.

Tyto tři typy dat potřebuji načíst do samostatných proměnných tak, abych s nimi mohl dále pracovat.

Po otevření formuláře se načtou všechna Jména ze souboru do ComboBoxu.

V případě výběru v Comboboxu se mi načtu ještě další dvě hodnoty s tímto spojené do textboxu, v těchto textboxech je budu moci přepsat a znovu uložit do souboru.

Pokoušel jsem se to realizovat pomocí souboru txt. Je to vhodná volba? Šlo by to vyřešit nějak jednodušeji například pomocí tabulky? Samozřejmě bych chtěl, aby data zůstávala zachovaná i po vypnutí programu (proto využívám soubor .txt).

Při svém snažení jsem narazil na problém, že nemůžu zapsat na konkrétní řádek.

Já osobně jsem se pokoušel o velice kostrbaté řešení. Mám deklarované globální proměnné (5*3). Při načítání formuláře načtu do všech proměnných data (co řádek to proměnná). Jména z nich vložim do ComboBoxu (zde mi to ale občas hlásí chybu InvalidArgument=Hodnota 4 není platnou hodnotou pro argument index.)

Podle výběru v ComboBoxu zobrazím příslušené hodnoty do textboxů, zde bych je chtěl mít možnost editovat a po stisknutí tlačítka zapsat, jak do proměnných, tak do souboru.

Public Class hrac
    Dim jmeno0 As String    'deklarace tří typů proměnných
    Dim typhrac0 As String
    Dim penez0 As Integer

    Dim jmeno1 As String    'které se periodicky opakují
    Dim typhrac1 As String
    Dim penez1 As Integer

    Dim jmeno2 As String
    Dim typhrac2 As String
    Dim penez2 As Integer


    Private Sub hrac_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim soubor As New IO.StreamReader("database.txt")

        jmeno0 = soubor.ReadLine()   'nacteni po jednotlivých radcich do proměnných
        typhrac0 = soubor.ReadLine()
        penez0 = soubor.ReadLine()

        jmeno1 = soubor.ReadLine()
        typhrac1 = soubor.ReadLine()
        penez1 = soubor.ReadLine()

        jmeno2 = soubor.ReadLine()
        typhrac2 = soubor.ReadLine()
        penez2 = soubor.ReadLine()

        ComboBox1.Items.Insert(0, jmeno0) 'vloženi do ComboBoxu
        ComboBox1.Items.Insert(1, jmeno1)
        ComboBox1.Items.Insert(2, jmeno2)

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        Dim index As Integer
        index = ComboBox1.SelectedIndex
        If index = 0 Then
            TextBox1.Text = jmeno0      'zobrazení v textboxecech, dle výběru
            TextBox2.Text = typhrac0
            TextBox3.Text = penez0
        ElseIf index = 1 Then
            TextBox1.Text = jmeno1
            TextBox2.Text = typhrac1
            TextBox3.Text = penez1
        ElseIf index = 2 Then
            TextBox1.Text = jmeno2
            TextBox2.Text = typhrac2
            TextBox3.Text = penez2
        

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim cislohrace As Integer
        cislohrace = ComboBox1.SelectedIndex

        If cislohrace = 0 Then
            jmeno0 = TextBox1.Text     'změna hodnot a načtení z proměnných
            typhrac0 = TextBox2.Text
            penez0 = CStr(TextBox3.Text)
        ElseIf cislohrace = 1 Then
            jmeno1 = TextBox1.Text
            typhrac1 = TextBox2.Text
            penez1 = CStr(TextBox3.Text)
        ElseIf cislohrace = 2 Then
            jmeno2 = TextBox1.Text
            typhrac2 = TextBox2.Text
            penez2 = Cstr(TextBox3.Text)

A teď by mělo následovat vypsání do souboru, myslel jsem, že bych to udělal tak, že bych všechny hodnoty vymazal a zapsal vše znovu. Ale za prvé nevím jak a za druhé se mi celkově zdá to řešení strašně kostrbaté.

Předně bych chtěl poděkovat za každou radu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Určitě bych zvolil jinou cestu.

Vytvořil bych třídu clsHrac s proměnnými jmeno, typ, penize

'Třída hráče
Public Class clsHrac
    Public Jmeno As String
    Public TypHrac As String
    Public Penez As Integer

    Protected Overrides Function ToString() As String
        Return Me.Jmeno
    End Function
End Class

db bych načítal do nějaké kolekce př.:

    Private lstOfHrac As List(Of clsHrac)
    Private fileName As String

inicializace

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        'inicializace
        Me.lstOfHrac = New List(Of clsHrac)

        Me.fileName = Application.StartupPath & "\database.txt"

        'bezp. dotaz
        If Not IO.File.Exists(Me.fileName) Then Throw New IO.FileNotFoundException("Soubor nenalezen", "database.txt")

        'načení db souboru
        Using r As New IO.StreamReader(Me.fileName)
            While Not r.EndOfStream
                Dim line As String = r.ReadLine()
                Dim polozky() As String = line.Split(";"c)

                'bezp. dotaz
                If polozky.Length <> 3 Then Throw New ArgumentException("Řádek obsahuje nesprávný počet položek")

                Dim penize As Integer = Convert.ToInt32(polozky(2))

                Dim h As New clsHrac With {.Jmeno = polozky(0), .TypHrac = polozky(1), .Penez = penize}

                Me.lstOfHrac.Add(h)
            End While
        End Using

        'nastavení zdroje dat pro combobox
        'čte hodnotu ToString přidaného objektu
        Me.cbName.DataSource = Me.lstOfHrac
    End Sub

Zobrazení pak bude téměř automatické

   Private Sub cbName_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cbName.SelectedIndexChanged
        'přetypování sendera na konkrétní objekt
        Dim cb As ComboBox = DirectCast(sender, ComboBox)
        'aktuální zvolený item
        Dim hrac As clsHrac = DirectCast(cb.SelectedItem, clsHrac)

        'nastavení proměnných
        Me.tbPenize.Text = hrac.Penez.ToString()
        Me.tbTyp.Text = hrac.TypHrac
    End Sub

Zapsání je jen zpětný postup čtení:

    'zapsání
    Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
        'inicializace stream writeru
        Using w As New IO.StreamWriter(Me.fileName)
            For i As Integer = 0 To Me.lstOfHrac.Count - 1
                'vytvoření řádku
                Dim radek As String = String.Empty
                radek &= Me.lstOfHrac(i).Jmeno
                radek &= ";"c
                radek &= Me.lstOfHrac(i).TypHrac
                radek &= ";"c
                radek &= Me.lstOfHrac(i).Penez.ToString()

                'zapsání
                w.WriteLine(radek)


                'Dim sb As New System.Text.StringBuilder
                'sb.Append(Me.lstOfHrac(i).Jmeno)
                'sb.Append(";"c)
                'sb.Append(Me.lstOfHrac(i).TypHrac)
                'sb.Append(";"c)
                'sb.Append(Me.lstOfHrac(i).Penez.ToString())

                'w.WriteLine(sb.ToString())
            Next
        End Using
    End Sub

Uložení změny

Private Sub btnEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEdit.Click
        dim h as clsHrac = directCast(me.cbName.SelectedItem, clsHrac)
        h.TypHrac = me.tbTyp.text
        h.Penize = me.tbPenize.text
End Sub

Pokud by jste ještě použil databinding tak nebude problém se změnou hodnot objektů Hrac. Způsobů ukládání dat do lokálních souborů je mnoho. Já používám XML a LinqToXml lze se na jednotlivá data dotazovat a při změně jakékoli hodnoty spolu s databindingem se mi bude vše i ukládat do db souboru.

A textbox bych určitě vyměnil za jinou komponentu: NumericUpDown nebo bych si vytvořil textbox na čísla.

Jo a db file vypadá takto:

Jmeno;Typ;Penize

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

A prečo skladáte reťazce cez operátor a nie cez System.Text.StringBuilder ?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Je to příklad.

StringBuilder je samozřejmě také možný.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A viete vôbec ako interne skladá stringy operátor a ako ich skladá StringBuilder ? Operátor naalokuje toľko pamäte, koľko je potrebné na výsledný string, prenesie prvý string, prenesie druhý string a tým to zhaslo. Spravte to niekoľkokrát po sebe na rovnakej premennej a máte pol pamäte použitú. StringBuilder skladá tak, ako by človek chcel, t.j. starý string uvoľní z pamäte a tá bude dostupná pre iné účely.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ježišmarja psal jsem, že je to příklad !!!

A pokud vím tak dotaz nebyl jak funguje StringBuilder, ale na práci s txt daty ;)

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

No je to naozaj iba príklad ale ja som chcel poukázať na jeho slabinu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Zrovna použití StringBuilderu to zas tak nezesložití, není dobré začátečníkům ukazovat, jak se to dělat nemá.

Na druhou stranu to v tomto případě, kdy slučování probíhá pouze párkrát, není tak dramatické, o těch pár objektů se postará GC. Ale je dobré na to pamatovat.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Párkrát? Ak máme napríklad 20 hráčov, to bude 6 * 20, čiže 120 zlučovaní. Jeden string cca. 20 bajtov, to je skoro 2 a pol KB.A možno ešte málo vravím.

Ale v niečom pravdu máte.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Vzhledem k tomu, že dnešní počítače mají běžně 4GB paměti, tak to je zanedbatelná položka.

Netvrdím, že je nepoužívání StringBuilderu dobře, ale někdy je třeba rozlišovat, jestli je to drobný prohřešek nebo katastrofa.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback