Avatar billede gulbaek Nybegynder
16. april 2007 - 00:50 Der er 28 kommentarer og
1 løsning

Læsning i flere niveauer med Regex

Hej, vil lige høre om det er muligt at lave en regex sætning som vil være istand til at læse noget data som er delt op i flere niveauer.

f.eks. hvis man har en skole, så vil den bestå af følgende. Skolens navn, Klasse navn, og elev navn med fornavn og efternavn.

og text filen.
Skole: Gauerslund
Klasse: 7.A
Elev: Jens Jensen
Elev: Ole Olesen
Klasse: 7.B
Elev: Mette Hansen
Elev: Ida Nielsen
ovs....

Er det muligt ved hjælp af Regex at lave noget kode der kan læs det data ind, således at jeg kan få placeret eleverne i de rigtige klasser i nogle tilsvarende objekter bagefter.
Avatar billede arne_v Ekspert
16. april 2007 - 00:58 #1
Hvorfor regex ?

Umiddelbart tror jeg da at det nemmeste vil være at læse en linie ad gangen,
kalde Split på kolon, og udføre forskelligt alt efter hvad første del af linien er.
Avatar billede gulbaek Nybegynder
16. april 2007 - 09:29 #2
Det var nu egentlig mest fordi jeg aldrig har brugt regex i mine programmer før, så ville godt lige prøve og se om jeg kunne få noget pænt kode udaf det.

F.eks. hvis jeg nu gerne vil hente For- og Efternavn ud enkeltvis, må det vel blive noget pænere kode med regex, og hvordan vil man tage højde for at et evt. mellemnavn, eller hvad nu hvis jeg vil hente klasse ud som et tal 7 og retningen A
Avatar billede thesurfer Nybegynder
16. april 2007 - 09:48 #3
Du kunne bruge split, som arne_v foreslår..

Split linie ved ":" giver dig f.eks:
[0] = "Skole", [1] = " Gauerslund"
[0] = "Klasse", [1] = " 7.A"
[0] = "Elev", [1] = " Jens Jensen"

Du kan derefter bruge Switch, eller IF-sætninger, til at behandle arrayet der dannes.

Husk at fjerne det første mellemrum i [1].

Hvis [0] er "skole", er det nemt nok

Hvis [0] er "klasse", kan du enten splitte ved "." og få "[0]=7 og [1]=b", eller bruge substring, for at få samme resultat.

Hvis [0] er "elev", kan du splitte [1] ved mellemrum. Antallet af dele du får af det andet split, fortæller dig om der mellemnavne med.
Eksempel:
Antal dele: 2 = fornavn + efternavn
Antal dele: 3 = fornavn + mellemnavn + efternavn

For at få fat på fornavn og efternavn, skal du bruge:
Fornavn: [0]
Efternavn: [max antal dele], dvs: arrayet.length (eller arrayet.length - 1.. kan aldrig huske det)
Avatar billede md_craig Nybegynder
16. april 2007 - 12:18 #4
gulbaek >>

I dit tilfælde vil koden ikke blive pænere med regex, da du skal til at rive fat i mange forskellige ting som Match collections, Group Collections og hvis du i forvejen har en ordnet fil som det der, så er det langt næmmere det andet...

Det er nok er den vigtigste parameter er at flytte funktionelt kode til et regex udtryk kan måske i nogle tilfælde køre koden mere kompakt (nok ikke her), men et regex kan være yderst complext og svært at forstå...

Men som svar til om det kan lade sig gøre, så jow... det kan det som sådan godt...

http://www.regular-expressions.info/
Avatar billede gulbaek Nybegynder
16. april 2007 - 12:42 #5
Hmm, det tyder på jeg må give mig og droppe regex :-)

Så dem der gerne vil have lidt point som tak for hjælp, må gerne lige smide et svar.
Avatar billede thesurfer Nybegynder
16. april 2007 - 19:54 #6
Jeg har bare udpenslet arne_v's kommentar.. ingen points til mig, tak.
Avatar billede arne_v Ekspert
16. april 2007 - 22:05 #7
et hrlt kode eksempel

pointen er at selvom der er en masse linier, så er selve parsningen af linierne
utrolig simpel

using System;
using System.Collections.Generic;
using System.IO;

namespace E
{
    public class Elev
    {
        private string navn;
        public Elev(string navn)
        {
            this.navn = navn;
        }
        public string Navn
        {
            get
            {
                return navn;
            }
        }
    }
    public class Klasse
    {
        private string navn;
        private List<Elev> elever;
        public Klasse(string navn)
        {
            this.navn = navn;
            elever = new List<Elev>();
        }
        public string Navn
        {
            get
            {
                return navn;
            }
        }
        public List<Elev> Elever
        {
            get
            {
                return elever;
            }
        }
    }
    public class Skole
    {
        private string navn;
        private List<Klasse> klasser;
        public Skole(string navn)
        {
            this.navn = navn;
            klasser = new List<Klasse>();
        }
        public string Navn
        {
            get
            {
                return navn;
            }
        }
        public List<Klasse> Klasser
        {
            get
            {
                return klasser;
            }
        }
    }
    public class MainClass
    {
        public static void Main(string[] args)
        {
            Skole skole = null;
            StreamReader sr = new StreamReader(@"C:\skole.txt");
            string line;
            while((line = sr.ReadLine()) != null)
            {
                string[] parts = line.Split(':');
                string key = parts[0].Trim();
                string val = parts[1].Trim();
                if(key == "Skole")
                {
                    skole = new Skole(val);
                }
                else if(key == "Klasse")
                {
                    skole.Klasser.Add(new Klasse(val));
                }
                else if(key == "Elev")
                {
                    skole.Klasser[skole.Klasser.Count-1].Elever.Add(new Elev(val));
                }
                else
                {
                    throw new Exception("Crap in input");
                }
            }
            sr.Close();
            foreach(Klasse k in skole.Klasser)
            {
                Console.WriteLine("Klasse : " + k.Navn);
                foreach(Elev e in k.Elever)
                {
                    Console.WriteLine("Elev: " + e.Navn);
                }
            }
            Console.ReadLine();
        }
    }
}
Avatar billede arne_v Ekspert
16. april 2007 - 22:05 #8
og et svar
Avatar billede thesurfer Nybegynder
16. april 2007 - 22:17 #9
Min erfaring er, at det er hurtigere at læse hele filen og derefter parse den, fremfor at læse 1 linie, parse den, læse næste linie osv..

Dvs:

Skole skole = null;
StreamReader sr = new StreamReader(@"C:\skole.txt");
string indhold = sr.ReadToEnd();
sr.close

string[] linier = indhold.split("\r\n".toCharArray();
for(int i = 0, len = linier.length; i < len; i++)
{
    string line = linier[i];
    string[] parts = line.Split(':');
    ........ resten af koden .......;
}
osv..

Og der bør altid være TryCatch udenom koden.. specielt når man arbejder med filer, der jo kan flyttes mellem mapper..
Avatar billede thesurfer Nybegynder
16. april 2007 - 22:21 #10
Hvis man undrer sig over denne "erfaring", er svaret her:

Jeg skulle lave et program for en ven, der løb en tekstfil igennem, og ændre kommentar til STORE bogstaver..

Min erfaring viste, at ReadToEnd-metoden var meget hurtigere end ReadLine-metoden, specielt ved store tekstfiler..

Jeg testede med filer på et par KB og op til et par MB..
Forskellen var på ca:
ReadToEnd: ~30 sekunder for MB filen
ReadLine: 2-3 minutter for MB filen
Avatar billede thesurfer Nybegynder
16. april 2007 - 22:22 #11
PS: Koden fra 16/04-2007 22:17:05 er ikke testet.. Det er skrevet i en teksteditor, og ikke MS Visual Studio eller ligende..
Avatar billede thesurfer Nybegynder
16. april 2007 - 22:23 #12
Der manglede en slut-parantes i split-linier-linien (og ";" ved "sr.close")... rettelsen:

Skole skole = null;
StreamReader sr = new StreamReader(@"C:\skole.txt");
string indhold = sr.ReadToEnd();
sr.close;

string[] linier = indhold.split("\r\n".toCharArray());
for(int i = 0, len = linier.length; i < len; i++)
{
    string line = linier[i];
    string[] parts = line.Split(':');
    ........ resten af koden .......;
}
Avatar billede arne_v Ekspert
17. april 2007 - 04:45 #13
jeg tror ikke at

string[] linier = indhold.split("\r\n".toCharArray());

gør det du tror den gør
Avatar billede arne_v Ekspert
17. april 2007 - 04:48 #14
ReadToEnd og Split kan måske nok læse hurtigere men den bruger også memory svarende
til det ca. 4 gane filens størrelse, hvilket godt kan blive et problem ved
store filer.

Man kan opnå tilsvarende effekt ved at angive en buffer størrelse til StreamReader
og læse en linie adf gangen.
Avatar billede arne_v Ekspert
17. april 2007 - 04:49 #15
Jeg kan iøvrigt ikke helt genskabe det at ReadToEnd er hurtigere:

using System;
using System.IO;
using System.Text;

namespace E
{
    public class MainClass
    {
        public static void TestStd()
        {
            StreamReader sr = new StreamReader(@"C:\avuarc.ext");
            DateTime t1 = DateTime.Now;
            string line;
            int n = 0;
            while((line = sr.ReadLine()) != null)
            {
                n++;
            }
            DateTime t2 = DateTime.Now;
            GC.Collect();
            Console.WriteLine("one line: " + n + " lines " + (t2 - t1).TotalSeconds + " secs " + GC.GetTotalMemory(false)/1000000 + " MB");
            sr.Close();
        }
        public static void TestOne()
        {
            StreamReader sr = new StreamReader(@"C:\avuarc.ext");
            DateTime t1 = DateTime.Now;
            string all = sr.ReadToEnd();
            string[] lines = all.Split("\r\n".ToCharArray());
            int n = lines.Length/2; // <---- hack because we get a lot of fake empty lines
            DateTime t2 = DateTime.Now;
            GC.Collect();
            Console.WriteLine("all and split: " + n + " lines " + (t2 - t1).TotalSeconds + " secs " + GC.GetTotalMemory(false)/1000000 + " MB");
            sr.Close();
        }
        public static void TestBuf()
        {
            StreamReader sr = new StreamReader(@"C:\avuarc.ext", Encoding.Default, false, 100000);
            DateTime t1 = DateTime.Now;
            string line;
            int n = 0;
            while((line = sr.ReadLine()) != null)
            {
                n++;
            }
            DateTime t2 = DateTime.Now;
            GC.Collect();
            Console.WriteLine("one line with buffer: " + n + " lines " + (t2 - t1).TotalSeconds + " secs " + GC.GetTotalMemory(false)/1000000 + " MB");
            sr.Close();
        }
        public static void Main(string[] args)
        {
            TestStd();
            TestOne();
            TestBuf();
            TestStd();
            TestOne();
            TestBuf();
            TestStd();
            TestOne();
            TestBuf();
            Console.ReadLine();
        }
    }
}

skriver:

one line: 731937 lines 0,390625 secs 0 MB
all and split: 731936 lines 0,78125 secs 124 MB
one line with buffer: 731937 lines 0,28125 secs 0 MB
one line: 731937 lines 0,390625 secs 0 MB
all and split: 731936 lines 0,796875 secs 124 MB
one line with buffer: 731937 lines 0,265625 secs 0 MB
one line: 731937 lines 0,375 secs 0 MB
all and split: 731936 lines 0,796875 secs 124 MB
one line with buffer: 731937 lines 0,265625 secs 0 MB
Avatar billede thesurfer Nybegynder
17. april 2007 - 21:03 #16
Jeg må se, om jeg kan finde programmet jeg lavede, i løbet af de næste par dage.. det kan være at du har ret, og at jeg husker det forkert..

Jeg skriver tilbage med resultatet..
Avatar billede thesurfer Nybegynder
17. april 2007 - 21:06 #17
Angående: string[] linier = indhold.split("\r\n".toCharArray());

Det skulle splitte indholdet op ved linieskift..

Jeg har før oplevet, at hvis man kun splitter ved "\n", vil der stadig være "\r" i linien.. derfor splitter jeg ved "\r\n"..

Men hvis det ikke er det linien gør (som jeg tror at det er), hvad gør den så? Eller, hvordan skal det se ud, for at den gør hvad jeg gerne vil have den til..? :-)
Avatar billede arne_v Ekspert
17. april 2007 - 21:19 #18
den splitter ved baade \r og \n ikkr ved \r\n

using System;

namespace E
{
    public class MainClass
    {
        public static void Main(string[] args)
        {
            string s = "A\r\nBB\r\nCCC";
            string[] parts = s.Split("\r\n".ToCharArray());
            for(int i = 0; i < parts.Length; i++)
            {
                Console.WriteLine("part[" + i + "]=#" + parts[i] + "#");
            }
        }
    }
}

udskriver

part[0]=#A#
part[1]=##
part[2]=#BB#
part[3]=##
part[4]=#CCC#

og det er derfor jeg dividerer med 2 i ovenstaaende kode
Avatar billede arne_v Ekspert
17. april 2007 - 21:25 #19
ovenstaaende = 17/04-2007 04:49:51
Avatar billede thesurfer Nybegynder
17. april 2007 - 21:56 #20
Ahh, ja.. Jeg glemte at C# virkeligt stinker til split.. :-)

I gamle dage, da man programmerede i Microsoft Visual Basic 6, og ikke .Net udgaven, splittede "Split" ved samtlige karakterer på een gang, og ikke "multi-split" ved hvert eneste karakter..


I skolen er vi bl.a. igang med programmering med Java på mobile enheder.. J2ME..
I J2ME har man String[], men man har ikke Split-funktionen.. hvilket jeg synes er underligt..

Så jeg lavede den selv:

    public int getNumberOfSplits(String input, String delimiter)
    {
        int c = 0;
        if (input.indexOf(delimiter) > -1) c = 1;
        while(input.indexOf(delimiter) > -1)
        {
            input = input.substring(input.indexOf(delimiter) + 1);
            c++;
        }
        return c;
    }

    public String[] split(String input, String delimiter)
    {
        int ndx = 0;
        String part = "";
        String[] sTmp = new String[getNumberOfSplits(input, delimiter)];
        while(input.indexOf(delimiter) > -1)
        {
            part = input.substring(0, input.indexOf(delimiter));
            sTmp[ndx] = part;
            input = input.substring(input.indexOf(delimiter) + 1);
            ndx++;
        }
        sTmp[ndx] = input;
        return sTmp;
    }

Denne custom Split-funktion splitter ved samtlige tegn på een gang, i modsætning til standard-Split i C#..


Hvis den kan optimeres, er du velkommen til at skrive en rettelse.. eller skrive det om.. :-)


PS: Custom Split-funktionen må benyttes og modificeres som man lyster..
Offentliggør gerne bedre versioner..
:-)
Avatar billede arne_v Ekspert
17. april 2007 - 22:10 #21
jeg ved ikke om det er en daarlig funktionalitet af Split - man skal bare vide hvad den goer

using System;
using System.Text.RegularExpressions;

namespace E
{
    public class MainClass
    {
        public static void Main(string[] args)
        {
            string s = "A\r\nBB\r\nCCC";
            string[] parts = Regex.Split(s, "\r\n");
            for(int i = 0; i < parts.Length; i++)
            {
                Console.WriteLine("part[" + i + "]=#" + parts[i] + "#");
            }
        }
    }
}

splitter som du vil
Avatar billede arne_v Ekspert
17. april 2007 - 22:15 #22
fra .NET 2.0  boer man ogsaa kunne bruge

string[] parts = s.Split(new string[] { "\r\n" }, int.MaxValue, StringSplitOptions.None);

men jeg kan ikke lige teste
Avatar billede arne_v Ekspert
17. april 2007 - 22:23 #23
JSE fra og med version 1.4 har en indbygget split paa String (som goer hvad du vil
i dette tilfaelde - men man skal vaere opmaerksom paa at det ogsaa er en regex)

JME har ikke naer saa mange features som JSE - ikke overraskende
Avatar billede md_craig Nybegynder
18. april 2007 - 17:38 #24
thesurfer - 17/04-2007 21:56:29 >>

Den kommentar er jeg da helt uenig i... overvej lige hvad det er du ber den om...
Det du fortæller den er: Split på \r OG DEREFTER OGSÅ på \n... så du giver den ikke en Delimiter som er "\r\n" men 2 som er '\r' og '\n'...

Det du leder efter en en som splitter på "\r\n" og derefter på "\r" og så på "\n"... at .NET 1.1 så mangler den funktion til at splitte på strings frem for chars, er en helt anden sag. det var ikke noget super tiltag kan vi godt blive enige om.
Det er der i .NET 2.0... og her er et eksempel...:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main( string[] args )
        {
            string str = "Dette\r\ner\nen\rtekst\r\npå\rflere\nlinier";
            Console.WriteLine( "-------------------------------" );
            Console.WriteLine( "Split på \\n og så på \\r" );
            foreach ( string s in str.Split( '\n', '\r' ) )
            {
                Console.WriteLine( "#" + s + "#" );
            }

            Console.WriteLine( "-------------------------------" );
            Console.WriteLine( "Split på \\r\\n så på \\n og så på \\r" );
            foreach ( string s in str.Split(new string[]{"\r\n", "\n", "\r"}, StringSplitOptions.None) )
            {
                Console.WriteLine( "#" + s + "#" );
            }

            Console.WriteLine( "-------------------------------" );
            Console.WriteLine( "Split på \\r\\n så på \\n og så på \\r" );
            foreach ( string s in str.Split( new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None ) )
            {
                Console.WriteLine( "#" + s + "#" );
            }
        }
    }
}


Resultat:

-------------------------------
Split på \n OG OGSÅ \r
#Dette#
##
#er#
#en#
#tekst#
##
#på#
#flere#
#linier#
-------------------------------
Split på \n\r først så \n OG OGSÅ \r
#Dette#
#er#
#en#
#tekst#
#på#
#flere#
#linier#

og den følger følgende regler:

To avoid ambiguous results when strings in separator have characters in common, the Split operation proceeds from the beginning to the end of the value of the instance, and matches the first element in separator that is equal to a delimiter in the instance. The order in which substrings are encountered in the instance takes precedence over the order of elements in separator.

For example, consider an instance whose value is "abcdef". If the first element in separator was "ef" and the second element was "bcde", the result of the split operation would be "a" and "f". This is because the substring in the instance, "bcde", is encountered and matches an element in separator before the substring "f" is encountered.

However, if the first element of separator was "bcd" and the second element was "bc", the result of the split operation would be "a" and "ef". This is because "bcd" is the first delimiter in separator that matches a delimiter in the instance. If the order of the separators was reversed so the first element was "bc" and the second element was "bcd", the result would be "a" and "def".


Mit eksempel inkluderer i modsætning til det Arne V poster i 17/04-2007 22:15:29 en split på "\r" og "\n" enkeltvis...

Så den prøver først med "\r\n" har den et match så splitter den der, hvis ikke prøver den med "\r" og så til sidst med "\n"...
Avatar billede md_craig Nybegynder
18. april 2007 - 17:47 #25
Et alternativ til hele det her hurlumhej med splits er jo at bruge en StringReader istedet... hvis man nu vil læse hele filen op i hukommelsen...

Nok ser det ikke ud til at det performer bedre i det senarie vi har her hvor man skal indlæse data... men hvis man istedet skulle behandle data, ændre hist og pist og evt. løbende efterhånden som brugeren inteagere med programmet... Så ville man performance vis godt kunne vinde noget i og med at det trods alt er hurtigere at arbejde med ram end med disk IO...

Men der er den åbenlyse downside som Arne understreger at det jo sluger godt på hukommelsen, og når man op hvor der begynder at skulle swappes så taber man evt. det man vinder i det at den skal til det...

Men den interassante pointe her kunne være... hvordan performer ReadToEnd + Split vs. ReadToEnd + StringReader ???....
Avatar billede md_craig Nybegynder
18. april 2007 - 17:54 #26
Det er faktisk et eller andet sted et interassant resultat:

using System;
using System.IO;
using System.Text;

namespace E
{
    public class MainClass
    {
        public static void TestStd()
        {
            StreamReader sr = new StreamReader( @"C:\avuarc.ext" );
            DateTime t1 = DateTime.Now;
            string line;
            int n = 0;
            while ( ( line = sr.ReadLine() ) != null )
            {
                n++;
            }
            DateTime t2 = DateTime.Now;
            GC.Collect();
            Console.WriteLine( "one line: " + n + " lines " + ( t2 - t1 ).TotalSeconds + " secs " + GC.GetTotalMemory( false ) / 1000000 + " MB" );
            sr.Close();
        }
        public static void TestStringRd()
        {
            StreamReader so = new StreamReader( @"C:\avuarc.ext" );
            StringReader sr = new StringReader( so.ReadToEnd() );
            DateTime t1 = DateTime.Now;
            string line;
            int n = 0;
            while ( ( line = sr.ReadLine() ) != null )
            {
                n++;
            }
            DateTime t2 = DateTime.Now;
            GC.Collect();
            Console.WriteLine( "all and reader: " + n + " lines " + ( t2 - t1 ).TotalSeconds + " secs " + GC.GetTotalMemory( false ) / 1000000 + " MB" );
            sr.Close();
        }
        public static void TestOne()
        {
            StreamReader sr = new StreamReader( @"C:\avuarc.ext" );
            DateTime t1 = DateTime.Now;
            string all = sr.ReadToEnd();
            string[] lines = all.Split( "\r\n".ToCharArray() );
            int n = lines.Length / 2; // <---- hack because we get a lot of fake empty lines
            DateTime t2 = DateTime.Now;
            GC.Collect();
            Console.WriteLine( "all and split: " + n + " lines " + ( t2 - t1 ).TotalSeconds + " secs " + GC.GetTotalMemory( false ) / 1000000 + " MB" );
            sr.Close();
        }
        public static void TestBuf()
        {
            StreamReader sr = new StreamReader( @"C:\avuarc.ext", Encoding.Default, false, 100000 );
            DateTime t1 = DateTime.Now;
            string line;
            int n = 0;
            while ( ( line = sr.ReadLine() ) != null )
            {
                n++;
            }
            DateTime t2 = DateTime.Now;
            GC.Collect();
            Console.WriteLine( "one line with buffer: " + n + " lines " + ( t2 - t1 ).TotalSeconds + " secs " + GC.GetTotalMemory( false ) / 1000000 + " MB" );
            sr.Close();
        }
        public static void Main( string[] args )
        {
            StreamWriter sr = new StreamWriter( @"C:\avuarc.ext" );
            for ( int i = 0; i < 5000000; i++ )
                sr.WriteLine( "line {0:D5}" );
            sr.Close();

            TestStd();
            TestOne();
            TestBuf();
            TestStringRd();

            TestStd();
            TestOne();
            TestBuf();
            TestStringRd();

            TestStd();
            TestOne();
            TestBuf();
            TestStringRd();

            Console.ReadLine();

            File.Delete( @"C:\avuarc.ext" );
        }
    }
}


one line: 5000000 lines 0,53125 secs 0 MB
all and split: 5000000 lines 1,96875 secs 374 MB
one line with buffer: 5000000 lines 0,59375 secs 0 MB
all and reader: 5000000 lines 0,375 secs 134 MB
one line: 5000000 lines 0,5 secs 0 MB
all and split: 5000000 lines 1,984375 secs 374 MB
one line with buffer: 5000000 lines 0,59375 secs 0 MB
all and reader: 5000000 lines 0,375 secs 134 MB
one line: 5000000 lines 0,484375 secs 0 MB
all and split: 5000000 lines 1,984375 secs 374 MB
one line with buffer: 5000000 lines 0,578125 secs 0 MB
all and reader: 5000000 lines 0,375 secs 134 MB
Avatar billede gulbaek Nybegynder
18. april 2007 - 22:34 #27
Det var da gevaldigt som I går op i at finde en løsning til mit problem :-)
Sådan skulle det jo være ved alle ens spørgsmål her på eksperten
Avatar billede thesurfer Nybegynder
18. april 2007 - 23:45 #28
Hmm.. Jeg har fået koden frem, som jeg omtalte i 16/04-2007 22:21:02.

Hvis man bruger ReadToEnd, tager den \r\n med.

Hvis man bruger .ReadLine(), tager den ikke \r\n med.

Min loop tilføjede så \n til linie, og tilføjede til variablen der indeholder indholdet...

Eksempel med en tekst fil på 235 KB (240.928 byte)


SR = File.OpenText(filename);
DateTime t1 = DateTime.Now;
indhold = SR.ReadToEnd();
DateTime t2 = DateTime.Now;
SR.Close();
MessageBox.Show("" + (t2 - t1).TotalSeconds); // dette giver mellem 0 og 0,015625 sekunder

SR = File.OpenText(filename);
DateTime t1 = DateTime.Now;
string linie = SR.ReadLine();
while (linie != null)
{
indhold += linie + "\n";
linie = SR.ReadLine();

DateTime t2 = DateTime.Now;
SR.Close();
MessageBox.Show("" + (t2 - t1).TotalSeconds); // dette giver omkring 4,390625 - 4,546875 sekunder


Det var ud fra disse tal, at jeg konkluderede at ReadToEnd var hurtigere end ReadLine..

Der er sikkert en eller anden god forklaring.. :-)


Hvis det kan hjælpe på forklaringen, eller man bare er nysgerrig, er min test-fil her:

http://thesurfer.users.whitehat.dk/e/q/773458/test_235.WAC

Download den, skriv noget læse-kode og test tiderne.. :-)
Avatar billede arne_v Ekspert
19. april 2007 - 04:09 #29
for det første - hvis du alligevel vil have det hele i en enkelt streng, så er
ReadToEnd naturligvis hurtigere end mange ReadLine og Append

for det andet er:

indhold += linie + "\n";

en rigtig performance dræber. Hvis du prøver at akkumulere i en StringBuilder vil du
se en klar forbedret performannce.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester