Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[c#] file sluiten na uitlezen?

Pagina: 1
Acties:

  • Ruben314199
  • Registratie: Juli 2002
  • Laatst online: 06-04 21:08
Als c# newbie probeer ik op een nette manier een textfile uit te lezen.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
StreamReader s;
            
            try
            {
                s = File.OpenText(filename);

                string read = null;
                while ((read = s.ReadLine()) != null)
                {
                   // do something
                } // while


             } // try
            finally
            { 
                s.Close();
            }


als ik dit probeer krijg ik echter de foutmelding dat "s" niet beschikbaar is in het finally blok.

Nu vroeg ik me dus af: is het uberhaupt nodig om een file weer vrij te geven? Gebeurt dat in dit geval niet automatisch bij het het disposen van de locale variabele "s" na het einde van de functie?
Maw: kan ik vanavond nog rustig slapen als ik gewoon deze code gebruik:

C#:
1
2
3
4
5
6
7
8
9
10
11
StreamReader s;
            
 s = File.OpenText(filename);

    string read = null;
    while ((read = s.ReadLine()) != null)
                {
                   // do something
                } // while

} // einde functie


in voorbeelden op internet vond ik vanalles, dus daar werd ik niet echt wijzer van.

De gaafste watergekoelde pc ter wereld


  • Viper®
  • Registratie: Februari 2001
  • Niet online
Als je de streamreader niet vrijgeeft zal deze niet door de garbage collector worden opgeruimd. Dit resulteert in memoryleakage, en uiteindelijke tot problemen.

Tevens hebben andere processen eventueel geen toegang meer tot het bestand.
Als je weet dat je bewerking klaar is en je niets meer met het bestand of de stream doet zal je deze moeten sluiten.
Kijk wel eerst of deze niet null is. Kijkend naar je voorbeeld, als de try op de eerste regel al verkeerd gaat zal s geen instantie bevatten en valt deze dus ook niet te 'closen'

Aan de andere kant, in dit voorbeeld van msdn doen ze het ook niet:

http://msdn2.microsoft.com/en-us/library/xtd0s8kd.aspx

[ Voor 10% gewijzigd door Viper® op 01-08-2007 11:14 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
Ben je zeker dat je de juiste code gepost hebt ?
Als je s declareert in je try block, dan krijg je idd de melding dat s niet beschikbaar is in het finally block. Echter, ik zie in jouw code voorbeeld dat je s gedeclareerd hebt buiten je try block, dus dat zou gewoon moeten werken. Volgens mij is die code in jouw eerste code-voorbeeld gewoon goed.
Wel beter om in je finally nog eens te checken of s niet null is, want hij wordt pas in je try geassigned. Als je OpenText method bv een exceptie gooit, dan zal de finally clause ook uitgevoerd worden, maar s zal null zijn.
edit:
ik moet blijkbaar rapper typen.


Het is zeker nodig om je file te sluiten als je 'm niet meer gebruikt; anders blijft die file gelocked.
Wat je ook kan doen, is gebruik maken van het using statement.
code:
1
2
3
4
5
6
using( StreamReader s = File.OpenText (fileName)
{
     while( ... )
     {
     } 
}

Als de scope van het using statement bereikt wordt, zal de Dispose method van de StreamReader automatisch gecalled worden (wat in dit geval equivalent is aan de Close method).

https://fgheysels.github.io/


  • Viper®
  • Registratie: Februari 2001
  • Niet online
whoami schreef op woensdag 01 augustus 2007 @ 11:12:
Ben je zeker dat je de juiste code gepost hebt ?
Als je s declareert in je try block, dan krijg je idd de melding dat s niet beschikbaar is in het finally block. Echter, ik zie in jouw code voorbeeld dat je s gedeclareerd hebt buiten je try block, dus dat zou gewoon moeten werken. Volgens mij is die code in jouw eerste code-voorbeeld gewoon goed.
Wel beter om in je finally nog eens te checken of s niet null is, want hij wordt pas in je try geassigned. Als je OpenText method bv een exceptie gooit, dan zal de finally clause ook uitgevoerd worden, maar s zal null zijn.
edit:
ik moet blijkbaar rapper typen.


Het is zeker nodig om je file te sluiten als je 'm niet meer gebruikt; anders blijft die file gelocked.
Wat je ook kan doen, is gebruik maken van het using statement.
code:
1
2
3
4
5
6
using( StreamReader s = File.OpenText (fileName)
{
     while( ... )
     {
     } 
}

Als de scope van het using statement bereikt wordt, zal de Dispose method van de StreamReader automatisch gecalled worden (wat in dit geval equivalent is aan de Close method).
Inderdaad :Y)
StreamReader.Dispose always closes stream EdBall | Edit | Show History (1)

Please Wait
Disposing a StreamReader closes the underlying stream when it is disposed, even if you use a constructor where you explicitly provide the stream. Sometimes you want to keep the stream open, but this class doesn't currently provide a mechanism to do that, except to not call Dispose.
Uiteraard icm een try zodat fouten afgevangen worden
(http://msdn2.microsoft.co...stem.io.streamreader.aspx)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Test 
{
    public static void Main() 
    {
        try 
        {
            // Create an instance of StreamReader to read from a file.
            // The using statement also closes the StreamReader.
            using (StreamReader sr = new StreamReader("TestFile.txt")) 
            {
                string line;
                // Read and display lines from the file until the end of 
                // the file is reached.
                while ((line = sr.ReadLine()) != null) 
                {
                    Console.WriteLine(line);
                }
            }
        }
        catch (Exception e) 
        {
            // Let the user know what went wrong.
            Console.WriteLine("The file could not be read:");
            Console.WriteLine(e.Message);
        }
    }
}


oid

[ Voor 26% gewijzigd door Viper® op 01-08-2007 11:20 ]


  • barfieldmv
  • Registratie: Maart 2004
  • Laatst online: 10-10 12:36
Ruben314199 schreef op woensdag 01 augustus 2007 @ 11:04:
Nu vroeg ik me dus af: is het uberhaupt nodig om een file weer vrij te geven? Gebeurt dat in dit geval niet automatisch bij het het disposen van de locale variabele "s" na het einde van de functie?
Maw: kan ik vanavond nog rustig slapen als ik gewoon deze code gebruik:

C#:
1
2
3
4
5
6
7
8
9
10
11
StreamReader s;
            
 s = File.OpenText(filename);

    string read = null;
    while ((read = s.ReadLine()) != null)
                {
                   // do something
                } // while

} // einde functie


in voorbeelden op internet vond ik vanalles, dus daar werd ik niet echt wijzer van.
Nee je kan dan niet rustig slapen :z
Value types zoals integers worden bij het verlaten van de scope direct verwijderd.
Reference types zoals Streams worden pas opgeruimd bij een garbage collection die OOIT een keertje langs komt. Verder behoud je de lock op je bestand zoland de stream niet geclosed is.

Even een s.close meegeven of de using statement gebruiken.

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
De garbage collector ruimt enkel de managed resources op; een streamreader bevat (zoals alle Disposable types) unmanaged resources en die worden niet door de GC opgeruimd.
Vandaar dat je 'm zelf moet closen of disposen.

https://fgheysels.github.io/


  • DrDelete
  • Registratie: Oktober 2000
  • Laatst online: 30-11 21:50
whoami schreef op woensdag 01 augustus 2007 @ 11:28:
De garbage collector ruimt enkel de managed resources op; een streamreader bevat (zoals alle Disposable types) unmanaged resources en die worden niet door de GC opgeruimd.
Vandaar dat je 'm zelf moet closen of disposen.
dat is niet helemaal waar, de garbage collector ruimt uiteindelijk wel de unmanaged resources op (anders heb je leaks), echter niet altijd op het moment dat het de ontwikkelaar uitkomt. Door de disposable pattern (IDispose interface) biedt .NET de mogelijkheid om op elk moment de unmanaged resources op te ruimen door zelf Dispose te callen of via een using block.

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
Hmm, idd, my mistake.

https://fgheysels.github.io/


  • Ruben314199
  • Registratie: Juli 2002
  • Laatst online: 06-04 21:08
Bedankt voor alle reacties.

Ik denk dat de oplossing met using { } de mooiste is.

Wil ik als afsluiter nog even terug te komen op de variabele s die niet beschikbaar is in het "catch" blok is hier de gehele sourcecode:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            StreamReader s;
            // s = null;            

            try
            {
                s = File.OpenText("c:\temp\test.txt");

                string read = null;
                while ((read = s.ReadLine()) != null)
                {
                    Console.WriteLine(read);
                } // while 


            } // try 
            finally
            {
                if (s!=null) s.Close();
            }

        }
    }
}


Ik krijg de foutmelding: Use of unassigned local variable 's'.
Hetgeen op zich logisch is omdat niet gegarandeerd kan worden dan s een waarde heeft. Eventueel op te lossen door s=null te geven voor het try-blok.

De gaafste watergekoelde pc ter wereld


  • Viper®
  • Registratie: Februari 2001
  • Niet online
Dat is correct.

Op zich een logische foutmelding. Je declareert variable s als een StreamReader. Maar mocht regel 1 in het try block fout gaan, dan is van variabele s nooit een instantie aangemaakt. In dat geval zou je dus ook nooit s.Close aan kunnen roepen.
Het buiten de scope declareren en initialiseren (s = null) is de oplossing.

  • whoami
  • Registratie: December 2000
  • Laatst online: 14:05
Viper® schreef op donderdag 02 augustus 2007 @ 09:33:
Dat is correct.

Op zich een logische foutmelding. Je declareert variable s als een StreamReader. Maar mocht regel 1 in het try block fout gaan, dan is van variabele s nooit een instantie aangemaakt. In dat geval zou je dus ook nooit s.Close aan kunnen roepen.

Het buiten de scope declareren en initialiseren (s = null) is de oplossing.
Niet helemaal; je krijgt dan wel geen errormelding meer van de compiler, maar, in het finally block zal je nog altijd moeten checken of s geen null is voor je de Close aan roept.

https://fgheysels.github.io/

Pagina: 1