  | 
					
						Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!   
						
						
					 | 
				 
			 
			 
	
		| Vorheriges Thema anzeigen :: Nächstes Thema anzeigen   | 
	 
	
	
		| Autor | 
		Nachricht | 
	 
	
		Muecke Gast
 
 
 
 
 
  | 
		
			
				 Verfasst am: 06.01.2014, 15:19    Titel: Open Datei auslesen erst ab Zeile i | 
				     | 
			 
			
				
  | 
			 
			
				Hallo miteinander, 
 
 
ich glaube das ich das etwas umständlich mache ich habe aber leider nichts gefunden das mich weiterbringt. 
 
 
ich möchte aus einer Datei eine Bestimmte Zeile (i) auslesen 
 
wie mache ich das am besten? 
 
 
ich habe hier einen Ansatz, glaube aber das ich da suboptimal unterwegs bin mit. 
 
 
 
 	  | Code: | 	 		     Open filename FOR INPUT ENCODING "ASCII" AS #DNr
 
      For i As Integer = 1 To 4
 
         Line INPUT #DNr, Zeile               
 
      Next
 
   Close #DNr | 	 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 06.01.2014, 15:35    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Einfacher als das geht's wirklich nicht, und Performance wird auch nicht dein Problem sein, oder?   _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Muecke Gast
 
 
 
 
 
  | 
		
			
				 Verfasst am: 06.01.2014, 15:40    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				du hast recht die Performance  ist nicht wirklich mein Problem  . 
 
 
dachte nur das es vielleicht die Möglichkeit gibt 
 
 
so was in die Richtung
 
 
 	  | Code: | 	 		  
 
   Open filename FOR INPUT ENCODING "ASCII" AS #DNr
 
         Line INPUT #DNr, 4,  Zeile               
 
   Close #DNr | 	  
 
oder so was: 
 
 	  | Code: | 	 		  
 
   Open filename FOR INPUT ENCODING "ASCII" AS #DNr, 4
 
         Line INPUT #DNr,  Zeile               
 
   Close #DNr | 	  
 
 
die 4 steht dafür welche Zeilen Nr. aufgerufen werden soll. 
 
dann hätte man die lästige For Schleife weg. 
 
 
Doch wenn ich da schon richtig unterwegs bin   perfekt. | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		grindstone
 
 
  Anmeldungsdatum: 03.10.2010 Beiträge: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 06.01.2014, 17:13    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				@Muecke: Wenn du nur eine oder einige wenige Zeilen oder jede Zeile nur einmal brauchst, ist dein erster Ansatz die beste Lösung. Wenn du dagegen häufiger darauf zugreifen willst und/oder in einer anderen Rehenfolge als sie in der Datei stehen, ist es günstiger, vorher die ganze Datei zeilenweise in ein Array zu kopieren und dann über den entsprechenden Index darauf zuzugreifen.
 
 
Gruß
 
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Muecke Gast
 
 
 
 
 
  | 
		
			
				 Verfasst am: 06.01.2014, 23:02    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				OK, ich habe nun entschlossen das ich die Datei vollständig in ein 2D Arrey laden werde, da ich öfter auf die Daten in unterschiedlicher reihen folge zugreifen möchte   
 
 
nur das teil ist extrem langsam   
 
 
meine Datei: 
 
Zeilen: 360
 
Spalten: 1011
 
Größe 1.370 KB
 
 
das Teil ist wirklich extrem langsam   
 
 
und das ist noch eine der Kleinen Datei ich habe noch Daten Sätze hier die Zeilen von über 12652 haben. 
 
die Daten sind dann um die 54.641 KB Groß. 
 
 
 
wie kann ich das denn beschleunigen? 
 
 
das ist der Test Code: 
 
 	  | Code: | 	 		  Declare Sub DateiInArrey (filename As String, Datei_Array() As String)
 
Declare Sub explode (Separator As String, Strg As String, explode_Array() AS String)
 
 
Dim As String filename
 
 
filename = "C:\Users\00\Desktop\Data\Dunlop001.csv"
 
SCREENRES 1024, 768, ,2
 
 
   ReDim As String Daten3D(1)
 
 
Print "Datei Einlesen Starten:"
 
DateiInArrey filename, Daten3D()
 
 
Print "Datei Einlesen ENDE:"
 
Sleep: END
 
 
Sub DateiInArrey (Datei As String, Datei_Array() As String)
 
   Dim DNr As Integer = FreeFile
 
   Dim As String Text, Separator
 
   Dim As Integer x, i, n,  anfptr, endptr
 
   
 
   Open Datei FOR INPUT ENCODING "ASCII" AS #DNr
 
   x=0
 
       DO 
 
          x + = 1
 
          LINE INPUT #DNr, Text
 
          
 
            i      = 0
 
            anfptr = 1                                                                 'pointer auf den anfang des strings setzen
 
            Separator = ","
 
            
 
            Do                                                                         'string zerlegen
 
               i + = 1                                                                 'zähler erhöhen 
 
               ReDim Preserve Datei_Array(x, i)                                        'array vergrößern
 
               endptr = InStr(anfptr, Text, Separator)                                 'endpointer auf nächsten separator setzen
 
               Datei_Array(x, i) = LTrim(RTrim(Mid(Text, anfptr, endptr - anfptr)))     'teilstring in array schreiben
 
               anfptr = endptr + Len(Separator)                                        'anfangspointer hinter den separator setzen (anfang des nächsten teilstrings oder stringende)
 
            
 
            If i>n Then n=i
 
             
 
            Cls
 
            Locate 4, 10: Print "Datei:", Datei
 
            Locate 5, 10: Print "x:", x 
 
            Locate 6, 10: Print "i:", i, "Höchster Wert: ";n
 
            Locate 7, 10: Print "anfptr:", anfptr
 
            Locate 8, 10: Print "endptr:", endptr
 
            Locate 9, 10: Print "Datei_Array(x,i):", Datei_Array(x,i)
 
      screensync                        ' wartet mit der Programmausführung auf eine Bildschirmaktualisierung. Damit wird ein Flimmern des Bildschirms vermieden.   
 
 
            Loop Until endptr <= 0                                                     'weitermachen, bis der string zuende ist (wenn Seperator nict gefunden wierd wir 0 ausgegeben)
 
          
 
          
 
          
 
          
 
          
 
          
 
          
 
       Loop until eof(1)                             ' bis Dateiende erreicht wurde
 
 
 
   Close #DNr
 
End Sub
 
 
Sub explode (Separator As String, Strg As String, explode_Array() AS String)
 
   Dim As Integer anfptr, endptr, x                                        ' Variablen definiren als Zahlen nur für die SUB sonst nirgens
 
 
   x      = 0
 
   anfptr = 1                                                              'pointer auf den anfang des strings setzen
 
 
   Do                                                                      'string zerlegen
 
      x + = 1                                                              'zähler erhöhen 
 
      ReDim Preserve explode_Array(x)                                      'array vergrößern
 
      endptr = InStr(anfptr, Strg, Separator)                              'endpointer auf nächsten separator setzen
 
      explode_Array(x) = LTrim(RTrim(Mid(Strg, anfptr, endptr - anfptr)))  'teilstring in array schreiben
 
      anfptr = endptr + Len(Separator)                                     'anfangspointer hinter den separator setzen (anfang des nächsten teilstrings oder stringende)
 
 
 
   Loop Until endptr <= 0                                                   'weitermachen, bis der string zuende ist (wenn Seperator nict gefunden wierd wir 0 ausgegeben)
 
 
End Sub
 
 | 	 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 06.01.2014, 23:27    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Du hast so ziemlich jede mögliche teure Operation direkt in deiner innersten Schleife, natürlich ist das langsam.
 
 
* ReDim Preserve kopiert in jedem Schleifendurchlauf das komplette (jedes mal wachsende) Array (sofern FB sowas nicht durch Arrays mit Kapazität != tatsächlich benötigter Platz optimiert, was ich nicht glaube). Sinnvoller wäre es beispielsweise, Das Array immer in 100er-Schritten zu vergrößern, sodass das Umkopieren nur noch bei jedem 100. Schleifendurchlauf stattfindet. Selbiges gilt übrigens für das Redim Preserve in der explode-Methode.
 
 
* Ltrim(Rtrim(Mid(...))) erzeugt drei temporäre String-Objekte, das ist ebenfalls teuer. Sinnvoller wäre es, das Ergebnis von Ltrim und Rtrim jeweils "von Hand" zu berechnen (also jeweils ab anfptr und endptr nach Leerzeichen suchen) und dann die gefundenen Stellen an Mid übergeben. Und wenn dir das zu viel Arbeit ist, verwende wenigstens Trim() statt Ltrim(Rtrim()), um ein temporäres Objekt zu sparen.
 
 
* Jegliche Bildschirmausgaben sind immer teuer, die sollten auch nicht nach jeder Zeile gemacht werden.
 
 
* Screensync verlangsamt dein Programm künstlich, da es für jede eingelesene Zeile bis zu 1/60 Sekunde verbrät.
 
 
Die ersten beiden Punkte lassen sich durch besseren Code lösen, die letzten beiden Punkte haben einfach überhaupt nichts in einer inneren Schleife verloren. Versuch erst mal, den Ausgabecode aus der inneren Schleife zu entfernen, evtl reicht das schon und du musst dich gar nicht um die ersten beiden Punkte kümmern - besser wäre es aber. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Muecke Gast
 
 
 
 
 
  | 
		
			
				 Verfasst am: 06.01.2014, 23:42    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				OK das muss ich mir morgen noch mal genauer anschauen, 
 
 
die Ausgabe in der Schleife habe ich eingebaut da ich dachte das mein Programm abgestürzt ist und ich den Fehler finden wollte da es einfach nicht mehr reagierte   
 
 
bei der Ausgabe ist mir dann aufgefallen das es die Verarbeitens Dauer ist, und nicht das Prog abgestürzt ist   
 
 
werde das morgen Optimieren nach deinem vorschlagen. 
 
 
Danke für die hinweise. | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Sebastian Administrator
  
  Anmeldungsdatum: 10.09.2004 Beiträge: 5969 Wohnort: Deutschland
  | 
		
			
				 Verfasst am: 07.01.2014, 00:25    Titel: Verkettete Liste statt Array und REDIM PRESERVE benutzen | 
				     | 
			 
			
				
  | 
			 
			
				Hallo,
 
 
eine große Datei mit sehr vielen Zeilen in ein Array einzulesen, indem man es mit jeder Zeile via REDIM PRESERVE um 1 Element vergrößert, ist auch extrem ineffizient.
 
 
Dazu muss man wissen, wie Arrays und REDIM PRESERVE "unter der Haube" funktionieren.
 
 
Wenn du ein Array erstellst, wird im Speicher ein Block reserviert mit der Größe [Größe eines Elements] X [Anzahl der Elemente] = [Blockgröße].
 
 
Vor und hinter dem Array stehen irgendwelche anderen Daten. Aber für das Array reicht der Platz.
 
 
Wenn du jetzt das Array etwas größer machen möchtest, kann das Programm nicht einfach hintendran weiterschreiben. Weil da höchstwahrscheinlich irgendwas anderes steht, was nicht einfach so überschrieben werden darf.
 
 
D.h. wenn dein Array bisher 100 Byte belegt und du jetzt z. B. einen Integer mit 4 Byte hinzufügen möchtest, fordert das Programm eine neue Speicherlücke mit 104 Bytes an. Anschließend wird das alte Array (100 Byte) in das neue Array kopiert. Das alte Array wird gelöscht.
 
 
Wenn du ein Array 10.000x so vergrößerst, wird 10.000x das gesamte Array in ein neues kopiert und das alte gelöscht.
 
 
Das liegt daran, dass Arrays immer Blöcke "am Stück" sind und nicht gestückelt vorliegen. Daraus ergibt sich folgende Eigenschaft: Wenn ein Array im Speicher an der Adresse 1000 anfängt. Und ein Arrayelement 4 Bytes lang ist (z. B. ein INTEGER), dann steht das 1. Arrayelement an Adresse 1000, das zweite an Adresse 1004, das dritte an 1008 usw. Du kannst dann einfach die Basisadresse mit einem Offset addieren, um zum gewünschten Element zu kommen. Dadurch gehen lesende Zugriffe auf eine beliebige Stelle des Arrays extrem schnell. Wenn ich weiß, wo das Array anfängt im Speicher und wie lang 1 einzelnes Element ist, weiß ich spielend einfach, wo das Element 2384 oder das Element 83930 steht. Das muss man nicht suchen, sondern kann die Stelle einfach ausrechnen.
 
 
Daraus ergibt sich aber auch, dass Array-Inhalte nicht verstreut im Speicher liegen können ("Hier ein bisschen, dann an anderer Stelle ein bisschen usw.").
 
 
Der große Nachteil ist, dass ein Array nicht wachsen kann. Man kann nur ein größeres anlegen und dann das kurze Array in das neue große reinkopieren. Für den Programmierer sieht es so aus, als würde das Array größer, aber in Wirklichkeit entsteht bloß ein neues Array, in das die alten Inhalte hinüberkopiert werden.
 
 
Wenn man eine Datenstruktur braucht, die mit ihren Anforderungen wächst, verwendet man eine verkettete Liste. Die hat den Vorteil, dass Verlängerungen (Einfüge-Operationen) problemlos, ganz schnell und ohne Umkopieren funktionieren. Ihr Nachteil ist, dass du nicht von vornherein weißt, wo das Element 1239 steht. Sondern du musst, wenn du einen bestimmten Index willst, die Liste vom Anfang an durchgehen, bis du beim gewünschten Element landest. Das heißt, das Wachsen geht super. Das Lesen ist, wenn man nicht vom Anfang an loslegen will, etwas langsamer.
 
 
Siehe zum Thema Listen:
 
 
 
Viele Grüße!
 
Sebastian _________________
  
 
Die gefährlichsten Familienclans | Opas Leistung muss sich wieder lohnen - für 6 bis 10 Generationen! | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Muecke Gast
 
 
 
 
 
  | 
		
			
				 Verfasst am: 07.01.2014, 00:56    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				OK es hat mir keine Ruhe gelassen   
 
ich wollte das jetzt doch noch machen. 
 
 
das Prog ist schon deutlich schneller geworden   
 
interessant wäre es eine Leitzeit mal zu messen um zu sehen was man wirklich einspart   
 
 
ich lasse jetzt das 2D Arrey auf der zweiten Ebene Prüfen ob es wirtlich Größer geworden ist oder nicht wenn nicht muss es auch nicht vergrößert werden. 
 
so muss ich das nur noch von ziele zu ziele vergrößern   
 
 
kann ich beim Datei Öffnen auch gleich auslesen wievielte Zeilen eine Datei hat? ohne sie durchlaufen zu müssen? 
 
dann könnte ich das Arrey auch gleich auf die Zeilen von beginn an anpassen. 
 
 
 
das mit dem Leerzeichen von Hand habe ich nicht ganz verstanden   
 
 
 
das ist der Code jetzt: 
 
 	  | Code: | 	 		  
 
#include once "vbcompat.bi"
 
 
Declare Sub DateiInArrey (filename As String, Datei_Array() As String)
 
 
Dim As String filename
 
 
 filename = "C:\Users\00\Desktop\Data\Dunlop001.csv"
 
 filename = "C:\Users\00\Desktop\Data\replay_knete.csv"
 
 
SCREENRES 1024, 768, ,2
 
Locate 4, 10: Print "Datei:", filename
 
 
   ReDim As String Daten3D(1)
 
DateiInArrey filename, Daten3D()
 
Sleep: End
 
 
 
Sub DateiInArrey (Datei As String, Datei_Array() As String)
 
   Dim DNr As Integer = FreeFile
 
   Dim As String Text, Separator
 
   Dim As Integer x, i, n, anfptr, endptr
 
 
   Separator    = ","
 
   Open Datei FOR INPUT ENCODING "ASCII" AS #DNr
 
            n            = 1
 
            x            = 0
 
       DO 
 
          x + = 1
 
         Locate 5, 10: Print "x:", x  ' nur zu überprüfung vorhanden 
 
         ReDim Preserve Datei_Array(x, n)                                           ' array vergrößern
 
          LINE INPUT #DNr, Text
 
            i = 0: anfptr = 1
 
            Do                                                                      ' string zerlegen
 
               i + = 1                                                              ' zähler erhöhen 
 
                If i>n Then 
 
                    n=i 
 
                  ReDim Preserve Datei_Array(x, n)                                  ' array vergrößern
 
                    Locate 5, 33: Print "Hoechster Wert: ";n ' nur zu überprüfung vorhanden 
 
                EndIf
 
               endptr = InStr(anfptr, Text, Separator)                              ' endpointer auf nächsten separator setzen
 
               Datei_Array(x, i) = Trim(Mid(Text, anfptr, endptr - anfptr))           ' teilstring in array schreiben
 
               anfptr = endptr + Len(Separator)                                       ' anfangspointer hinter den separator setzen (anfang des nächsten teilstrings oder stringende)
 
            Loop Until endptr = 0                                                     ' weitermachen, bis der string zuende ist (wenn Seperator nict gefunden wierd wir 0 ausgegeben)
 
       Loop until eof(1)      
 
   Close #DNr
 
End Sub
 
 | 	 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		HorstD
 
 
  Anmeldungsdatum: 01.11.2007 Beiträge: 110
 
  | 
		
			
				 Verfasst am: 07.01.2014, 02:21    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Das mit dem Redim Preserve hast du anscheinend nicht verstanden.
 
 
Hier siehst du, was gemeint ist
 
http://www.vbarchiv.net/tipps/tipp_345-array-dynamisch-vergr-ern.html
 
 
Warum berechnest du jedesmal die Länge des Separators?
 
anfptr = endptr + Len(Separator)  
 
 
 
 	  | Zitat: | 	 		  
 
interessant wäre es eine Leitzeit mal zu messen um zu sehen was man wirklich einspart  | 	  
 
 	  | Code: | 	 		  Dim zeit As Double
 
...
 
zeit = TIMER
 
...
 
...
 
Print "Zeit: ";str$(timer - zeit) | 	 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		grindstone
 
 
  Anmeldungsdatum: 03.10.2010 Beiträge: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 07.01.2014, 07:27    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				@Muecke:
 
 	  | Muecke hat Folgendes geschrieben: | 	 		  | kann ich beim Datei Öffnen auch gleich auslesen wievielte Zeilen eine Datei hat? ohne sie durchlaufen zu müssen?  | 	  Nein, aber unter dem Geschwindigkeitsaspekt kann es sich durchaus lohnen, die Datei zweimal zu durchlaufen. Da der Inhalt der Datei beim ersten Lesen in den Hauptspeicher gecached wird, erfolgt der zweite Zugriff normalerweise deutlich schneller. Ob und inwieweit das in der Praxis funktioniert, hängt von der Dateigröße und der Größe deines Hauptspeichers ab.
 
 
@HorstD:
 
 	  | HorstD hat Folgendes geschrieben: | 	 		  Warum berechnest du jedesmal die Länge des Separators?
 
anfptr = endptr + Len(Separator)  | 	  Das ist meine Schuld, ich habe ihm das als Beispielcode gepostet. In dem Programm, in dem die Sub bei mir werkelt, muß sie mit verschiedenen Separatorlängen zurechtkommen.
 
 
Zur Geschwindigkeitsoptimierung kann die Separatorlänge am Anfang der Sub in eine Variable geschrieben oder -wenn die Separatorlänge feststeht und sich auch niemals ändert- direkt durch die entsprechende Zahl ersetzt werden.
 
Eine dramatische Steigerung der Geschwindigkeit liesse sich durch die von nemored an anderer Stelle schon erwähnte Stringindizierung erreichen, allerdings ist hier die Programmierung etwas komplizierter als mit den vergleichsweise "idiotensicheren" Stringfunktionen. Jeder indizierte Stringzugriff außerhalb des gültigen Indexbereiches führt unausweichlich zu einem Programmabsturz.
 
 
Was ebenfalls viel Zeit kostet, ist die "Line Input"- Funktion. Hier ist es bei größeren Dateien von Vorteil, den Dateiinhalt in Portionen von 30000000 (in Worten: dreißig Millionen, das ist zumindest bei meinem System das Geschwindigkeitsoptimum) Zeichen in einen String einzulesen und anschließend diesen String zu bearbeiten. Aber das können wir besprechen, wenn du den Rest zum Laufen gebracht hast.   
 
 
Übrigens habe ich festgestellt, daß wiederholtes "ReDim Preserve" bei mehrdimensionalen Arrays schnell zu Datensalat führt. Das Erweitern funktioniert offenbar nicht (immer) fehlerfrei.
 
 
Gruß
 
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 07.01.2014, 09:26    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				 	  | Muecke hat Folgendes geschrieben: | 	 		  das mit dem Leerzeichen von Hand habe ich nicht ganz verstanden    | 	  
 
Naja, was Trim() tut, ist ja einfach links und rechts am String nach Leerzeichen zu suchen. Das kannst du auch selbst! Dabei einfach das erste Zeichen nach anfptr bzw letzte Zeichen vor endptr merken, das kein Leerzeichen ist, und dann die Positionen dieser Zeichen an Mid übergeben. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Muecke Gast
 
 
 
 
 
  | 
		
			
				 Verfasst am: 07.01.2014, 12:28    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				
 
 
wenn ich das richtig verstanden habe wir hier ein Größeres Array erzeugt zu beginn wie man wahrscheinlich benötigt. 
 
und am Schluss wenn man fertig ist, wird das Arrey auf die Tatsächliche Größe herunter geschrumpft   
 
dadurch gehen dann auch keine Daten im Arrey verloren  
 
 
 	  | HorstD hat Folgendes geschrieben: | 	 		  Warum berechnest du jedesmal die Länge des Separators?
 
anfptr = endptr + Len(Separator)  | 	  
 
 
 
gute Frage da habe ich nicht dran gedacht   
 
werde das gleich mal in eine Variable Packen. | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Muecke Gast
 
 
 
 
 
  | 
		
			
				 Verfasst am: 07.01.2014, 13:36    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				so jetzt lasse ich zu erst die Anzahl der Zeilen zählen und dann erstelle ich ein zu Großes Arrey:-) das ich später dann wider kleiner mache:-) 
 
 
die Zeiten sind erstaunlich was es bringt. 
 
 
habe es auch mal verglichen mit und Ohne Trim macht auch was aus. 
 
werde das noch mit einer Kleinen abfrage machen (For Schleife) und die Leerzeichen am Anfang zu finden und am Ende, und schauen was dann an Zeiten raus kommt: 
 
 
@grindstone: Das ist nicht Schuld, du hast mir nur ein Beispiel aufgezeigt was ich daraus gemacht habe ist meins nicht deins   ich muss schon selbst das Hirn anschmeißen,  will das ja selber hin bekommen   *hoffe ich zumindest* 
 
 
Das ist der Code bis jetzt   
 
 
 
 
 	  | Code: | 	 		  Declare Sub DateiInArrey (filename As String, Datei_Array() As String)
 
 
 
Dim As String filename, filepfad                                                                        ' Hier kommt der Dateiname rein
 
 
 filepfad = "C:\Users\00\Desktop\Data\"
 
 
 
' filename = "Dunlop001.csv"
 
 filename = "replay_knete.csv"
 
' filename = "Test2.csv"
 
 
SCREENRES 1024, 768, ,2
 
Locate 1, 10: Print "Datei = "; filename
 
 
Dim zeit As Double    ' #### Zeitmessung ####
 
zeit = Timer ' #### Zeitmessung Start ###
 
 
   ReDim As String Daten3D(1)
 
DateiInArrey filepfad+filename, Daten3D()
 
 
Locate 7, 10: Print "Zeit: ";str$(timer - zeit)
 
Locate 30, 10: Print "Druecken sie eine Beliebige Taste zum schliessen...": Sleep: End
 
 
 
Sub DateiInArrey (Datei As String, Datei_Array() As String)
 
      Dim DNr As Integer = FreeFile
 
      Dim As Integer n, endptr, anfptr, i, LenSeparator, SpaltenAnzahl, ZeilenAnzahl
 
      Dim As String Text, Separator
 
 
   n = 0                                                                                       ' n = die anzahl der Zeilen in der Datei
 
 
' --------------------------------------------------------------------------------------------
 
'     Datei Öffnen und Zeilen Zählen 
 
' --------------------------------------------------------------------------------------------
 
   Open Datei FOR INPUT ENCODING "ASCII" AS #DNr
 
      DO 
 
          LINE INPUT #DNr, Text: n + = 1
 
      Loop until eof(1)
 
   Close #DNr
 
   ZeilenAnzahl = n
 
Locate 5, 10: Print "Zeilen anzahl = ";ZeilenAnzahl   
 
 
' --------------------------------------------------------------------------------------------
 
'     2-D Arrey erstellen in der Größe von (Zeilen aus der Datei, 1)
 
' --------------------------------------------------------------------------------------------
 
     ReDim Preserve Datei_Array(ZeilenAnzahl, 5000)                                           ' array erstellen
 
 
' --------------------------------------------------------------------------------------------
 
'     Datei Öffnen Zeilen Lesen und zerlegen dann Speichern 
 
' --------------------------------------------------------------------------------------------
 
   Open Datei FOR INPUT ENCODING "ASCII" AS #DNr
 
   Separator = ",": LenSeparator   = Len(Separator)
 
   n = 0
 
   SpaltenAnzahl = 0
 
      DO 
 
          LINE INPUT #DNr, Text: n + = 1
 
         i = 0 
 
            Do 
 
            i + = 1
 
            If i > SpaltenAnzahl Then SpaltenAnzahl = i                           ' ermitteln des Höchsten Spaltenwertes
 
            endptr = InStr(anfptr, Text, Separator)                              ' endpointer auf nächsten separator setzen
 
            Datei_Array(n, i) = Trim(Mid(Text, anfptr, endptr - anfptr))              ' teilstring in array schreiben
 
            anfptr = endptr + LenSeparator                                        ' anfangspointer hinter den separator setzen (anfang des nächsten teilstrings oder stringende)
 
         Loop Until endptr = 0                                                     ' weitermachen, bis der string zuende ist (wenn Seperator nict gefunden wierd wir 0 ausgegeben)
 
      Loop until eof(1)
 
   Close #DNr
 
 
' --------------------------------------------------------------------------------------------
 
'     2-D Arrey auf die tatsächliche Größe erstellen
 
' --------------------------------------------------------------------------------------------
 
     ReDim Preserve Datei_Array(ZeilenAnzahl, SpaltenAnzahl) 
 
Locate 6, 10: Print "Spalten anzahl = ";SpaltenAnzahl   
 
 
End Sub
 
 | 	 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		grindstone
 
 
  Anmeldungsdatum: 03.10.2010 Beiträge: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 08.01.2014, 02:46    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				@Muecke:
 
Du brauchst die Datei zum zweiten Durchsuchen nicht zu schließen und erneut zu öffnen. Es reicht, vor dem zweiten Durchgang den Dateizeiger mitauf den Anfang der Datei zu setzen.
 
Statt n kannst du im ersten Durchgang direkt die Variable "ZeilenAnzahl" hochzählen, dann sparst du dir das Umkopieren.
 
Beim Anlegen des Arrays ist das Schlüsselwort "Preserve" überflüssig. Du willst ja keine vorherigen Werte erhalten.
 
 
Falls der gesamte Inhalt der Datei in den Arbeitsspeicher passt (was hier ja offensichtlich der Fall ist, denn sie wird ja komplett in ein Array kopiert), ist vom Gesichtspunkt der Geschwindigkeit ein anderes Vorgehen sinnvoller: Zuerst wird die gesamte Datei als ein einziger String ausgelesen. Dann wird dieser String zweimal durchsucht, einmal auf Kennzeichen für Zeilenende ("Chr(13,10)") und ein zweitesmal auf den Separator (","). Die Positionen dieser Trennzeichen innerhalb des Strings (Pointer auf den String) werden in jeweils einem (Integer-)Array gespeichert. Mithilfe dieser Pointer ist ein gezielter Zugriff auf jeden Dateieintrag genausogut möglich wie mit einem Textarray, und man spart sich das gesamte Umkopieren.
 
Mir fehlt im Augenblick die Zeit, ein entsprechendes Programm zu schreiben, ich werde versuchen, es in den nächsten Tagen nachzuliefern.
 
 
Gruß
 
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		grindstone
 
 
  Anmeldungsdatum: 03.10.2010 Beiträge: 1283 Wohnort: Ruhrpott
  | 
		
			
				 Verfasst am: 08.01.2014, 23:47    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				@Mücke: Hier das versprochene Beispielprogramm.  	  | Code: | 	 		  Dim As String filename, filepfad, dateiinhalt
 
Dim As Integer x, zeilenindex, eintragsindex
 
Dim As Double zeitmerken
 
ReDim As Integer eintragspointer(1), zeilenanfangsindex(1)
 
 
 
Declare Function EintragHolen(zeile As Integer, spalte As Integer, ByRef dateiinhalt As String, _
 
                  eintragspointer() As Integer, zeilenanfangsindex() As Integer) As String
 
                        
 
zeitmerken = Timer
 
filepfad = "C:\Users\00\Desktop\Data\"
 
filename = "replay_knete.csv"
 
 
''erzeugen einer testdatei
 
'filename = "test.txt"
 
'Open filepfad + filename For Output As #1
 
'Print #1, "z1 e1, z1 e2, z1 e3"
 
'Print #1, "z2 e1, z2 e2, z2 e3"
 
'Print #1, "z3 e1, z3 e2, z3 e3, z3 e4x"
 
'Close 1
 
 
'datei als string in den hauptspeicher einlesen
 
Open filepfad + filename For Binary Access Read As #1
 
dateiinhalt = Input(Lof(1),#1)
 
Close 1
 
 
ReDim eintragspointer(Len(dateiinhalt) / 2) 'maximal zu erwartende pointeranzahl
 
ReDim zeilenanfangsindex(Len(dateiinhalt) / 2)
 
 
eintragsindex = 1
 
eintragspointer(1) = 0 'ersten pointer auf anfang der datei setzen...
 
zeilenindex = 1
 
zeilenanfangsindex(1) = 1 '...und als ersten zeilenindex speichern
 
 
'separatoren suchen und merken
 
For x = 0 To Len(dateiinhalt) - 1 'die pointer bei stringindizierung beginnen bei 0
 
   Select Case dateiinhalt[x] 'ascii - wert des zeichens an stringposition x
 
      Case 13 'jede zeile wird mit einem Chr(13,10) abgeschlossen
 
         zeilenindex += 1
 
         eintragsindex += 1
 
         eintragspointer(eintragsindex) = x + 2 'pointer auf anfang des nächsten eintrags setzen
 
         zeilenanfangsindex(zeilenindex) = eintragsindex 'index des eintragspointers merken als beginn von zeile <zeilenindex>
 
      Case Asc(",") 'ascii - wert des separators
 
         eintragsindex += 1
 
         eintragspointer(eintragsindex) = x + 1 'pointer auf anfang des nächsten eintrags setzen
 
   End Select
 
Next
 
 
'arrays auf das korrekte maß verkleinern
 
ReDim Preserve zeilenanfangsindex(zeilenindex)
 
ReDim Preserve eintragspointer(eintragsindex)
 
 
Print EintragHolen(3,4,dateiinhalt,eintragspointer(),zeilenanfangsindex())
 
 
Print
 
Print "Rechenzeit "; Timer - zeitmerken; " Sekunden"
 
 
Sleep
 
End
 
 
Function EintragHolen(zeile As Integer, spalte As Integer, ByRef dateiinhalt As String, _
 
                       eintragspointer() As Integer, zeilenanfangsindex() As Integer) As String
 
   Dim As String text
 
   Dim As Integer anfptr, endptr, textlen, x
 
   
 
   If (zeile > UBound(zeilenanfangsindex) - 1) Or (zeile < 1) Or (spalte < 1) Then 'falsche zeilen- oder spaltenangabe
 
      Return "" 'fehler --> leerstring als rückgabewert
 
   EndIf
 
      
 
   anfptr = eintragspointer(zeilenanfangsindex(zeile) + (spalte - 1)) 'pointer auf das erste zeichen des gesuchten eintrags
 
   endptr = eintragspointer(zeilenanfangsindex(zeile) + spalte) - 2 'pointer auf das letzte zeichen des gesuchten eintrags
 
      
 
   If zeilenanfangsindex(zeile + 1) = zeilenanfangsindex(zeile) + spalte Then 'der gesuchte eintrag ist der letzte in der zeile
 
      endptr -= 1 'endpointer korrigieren
 
   ElseIf zeilenanfangsindex(zeile + 1) < zeilenanfangsindex(zeile) + spalte Then 'der angesprochene eintrag gehört schon zur nächsten zeile
 
      Return "" 'fehler --> spaltennummer zu groß --> leerstring als rückgabewert
 
   EndIf
 
   
 
   textlen = endptr - anfptr + 1 'länge des rückgabestrings berechnen
 
   text = String(textlen,Chr(0)) 'leerstring mit der erforderlichen länge erzeugen
 
   For x = 0 To textlen - 1 'eintrag in rückgabestring kopieren
 
      text[x] = dateiinhalt[anfptr + x]
 
   Next
 
   
 
   Return text
 
   
 
End Function | 	  Ich hoffe, die Kommentare im Programm und die Verwendung von möglichst sprechenden Variablennamen reichen aus, um die Funktionsweise zu erklären, besonders die doppelte Indizierung der Zeilenanfänge. Der auskommentierte Block am Anfang dient zum Erzeugen einer kleinen Testdatei, ich habe ihn mal dringelassen.
 
 
Die Arbeitsgeschwindigkeit des Programms dürfte kaum noch zu übertreffen sein, allerdings etwas auf Kosten der Flexibilität:- Die Separatoren sind auf "Chr(13,10)" und "," festgelegt (kann bei Bedarf natürlich geändert werden)
 
- Der gesamte Dateiinhalt und die am Anfang riesengroßen Arrays (sie haben zusammen etwa die achtfache Größe der Datei) müssen gleichzeitig in den Arbeitsspeicher passen
 
- Diese Methode ist nur zum Lesen geeignet. Wenn die Einträge verändert und wieder abgespeichert werden sollen, ist es doch sinnvoller, vorher alles in ein Array zu kopieren 
 
 
Gruß
 
grindstone _________________ For ein halbes Jahr wuste ich nich mahl wie man Proggramira schreibt. Jetzt bin ich einen! | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
  | 
   
 
     |