WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Bestimmte Zeilen aus Textfile einlesen

 

01detlef
Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 14.06.2012, 13:59     Titel: Bestimmte Zeilen aus Textfile einlesen
  Antworten mit Zitat      
Hallo zusammen,

ich habe mir ein Programm geschrieben, dass bestimmte Zeilen aus einem Textfile einliest. Das läuft auch alles, aber das Problem ist bei zu großen Textfiles dauert es sehr sehr lange bis Matlab fertig ist.

In dem Textfile stehen alle möglichen Daten, aber es sollen nur die Zeilen einlesen werden, die mit einem |-Zeichen beginnen:

Text
| 3.8889e-04| 4.729e-03| 2.998e-01|
Text
So sieht eine Zeile aus, die eingelesen werden soll. Mein Code sieht so aus, ist sehr umständlich und dauert zu lange aber läuft:
Code:
fid = fopen('daten.txt'); % öffne Datei
data = [];
while ~feof(fid)
    l = fgetl(fid);  
        if strncmpi(l, '|', 1)
        data = [data; textscan(l, '%s%s%s%s%s%s%s%s')];  
end

i=1;
ID=[];
[a b] = size(data)
for i=1:a
    ID =[ID; data{i,2}];
    cut = strrep(ID,'|','');
    zahl = str2double(cut)
end


Kann man das so programmieren, dass es schneller läuft?

detlef
Private Nachricht senden Benutzer-Profile anzeigen


01detlef
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 14.06.2012, 14:09     Titel:
  Antworten mit Zitat      
Oder auch interessant zu wissen, welcher Teil das ganze so langsam macht bei großen Files?

detlef
Private Nachricht senden Benutzer-Profile anzeigen
 
_Peter_
Moderator

Moderator


Beiträge: 537
Anmeldedatum: 08.12.10
Wohnort: ---
Version: 7.10, 2010a
     Beitrag Verfasst am: 15.06.2012, 07:37     Titel:
  Antworten mit Zitat      
Hallo detlef,
ich denke, was dein Programm langsam macht, ist, dass du nicht Speicher allokierst
Code:

ID=[];
for i=1:a
    ID =[ID; data{i,2}];
    ...
end  
 

Hier wächst deine Matrix und es muss jedesmal Speicher neu allokiert werden, was viel Zeit fressen kann.
Besser ist es vorher den Platz im Speicher zu reservieren:
Code:

ID=nan(length(data{i,2}));   % Beispiel um Speicher allokieren
for i=1:a
    ID(i) = data{i,2};
    ...
end  
 


Ich weiß jetzt nicht was in data{i,2} drin steht, deswegen musst du mal testen ob das so von der Größe passt, oder ob du a als Größenangabe nutzen musst.
_________________

Gruß
Peter
_________________
goMatlab-Knigge - dran gehalten?!
Schon in den FAQ gesucht? Oder der MATLAB Hilfe?
Ist vielleicht bei den Skripten oder den Tutorials was für dich dabei?
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 15.06.2012, 10:26     Titel: Re: Bestimmte Zeilen aus Textfile einlesen
  Antworten mit Zitat      
Hallo 01detlef,

Kannst Du vorher abschätzen oder sogar genau wissen, wieviele Zeilen eingelesen werden? Dann wäre eine Pre-allocation hilfreich. Unter diesem Stichwort findest du viele Beispiele im Forum.
Zur Not ist es besser, zu viel Speicher zu reservieren.

Code:
fid = fopen('daten.txt'); % öffne Datei
if fid == -1, error('Cannot open file for reading.'); end

data = zeros(3, 10000);  % Pre-allocate
cursor = 0;
while ~feof(fid)
    aLine = fgetl(fid);  
    if strncmpi(aLine, '|', 1)
        cursor = cursor + 1;
        data(:, cursor) = sscanf(aLine, '|%g);
    end
end
data = data(:, 1:cursor);  % Crop
 

TEXTSCAN und STR2DOUBLE benötigen beide mehr Zeit als die Daten direkt per SSCANF umzuwandeln.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
01detlef
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 15.06.2012, 14:57     Titel:
  Antworten mit Zitat      
Hallo,

ich habe aber dazu noch eine Frage. Wenn ich den Code probiere von Jan, dann kommt immer:

Subscripted assignment dimension mismatch.

Error in Einlesen_log2 (line 12)
data(:, cursor) = sscanf(aLine, '%g');

Woran kann das liegen? Und wenn ich etwas vorher allokieren möchte, muss das genau die Matrix-Größe haben, die es später einnimmt?

detlef
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 15.06.2012, 21:46     Titel:
  Antworten mit Zitat      
Hallo 01detlef,

Mit dem debugger kannst Du das leicht heraus finden: Setze einen Breakpoint in die entsprechende Zeile oder veranlasse Matlab bei einem Fehler zu stoppen:
Code:

Wenn Matlab dann in der Zeile stehen bleibt, kannst Du die Ausgabe der linken Seite anschauen und testen, ob sie zur rechten Seite passt:
Code:
size(sscanf(aLine, '%g'))
size(data(:, cursor))

Fehle da noch ein | im SSCANF Fomrat-String?

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
01detlef
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 16.06.2012, 15:50     Titel:
  Antworten mit Zitat      
Hallo,

also ich habe das mit der Vektorgröße hinbekommen, aber bisher wird nur die erste Zahl nach dem | eingelesen. Die zweite Zahl usw. wird aber nicht eingelesen, weil dazwischen ja immer noch ein | kommt.

Wie kann ich das ändern, ich habe schon einiges probiert, aber es funktioniert nicht.

Zitat:
| 375| 1.480e-02| 2.950e-01| 4.735e-03| 1.414e+00|


detlef
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 16.06.2012, 16:30     Titel:
  Antworten mit Zitat      
Hallo,

ich würde TEXTSCAN mit '|' als delimiter verwenden.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
01detlef
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 16.06.2012, 17:41     Titel:
  Antworten mit Zitat      
Aber dann muss ich ja wieder in eine Zahl umwandeln und das dauert so lange bei großen DATEIEN.
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 16.06.2012, 17:59     Titel:
  Antworten mit Zitat      
Hallo,

die Zahlen mit %f einlesen, dann müssen sie nicht umgewandelt werden.

Vielleicht hilft es, wenn du ein Beispiel deiner Textdatei anhängst und zeigst, welche Abschnitte eingelesen werden sollen.

Die Frage ist auch: wie lange ist "sehr sehr lange"?
Mit dem Profiler kannst du herausfinden, welche Teile des Codes die meiste Zeit benötigen.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
01detlef
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 16.06.2012, 18:40     Titel:
  Antworten mit Zitat      
Hallo,

also ich habe mal einen Ausschnitt der Datei beigefügt. Die Zeile mit | am Anfang soll eingelesen werden, also die ganze Zeile mit den Werten in den Spalten.

detlef

daten2.txt
 Beschreibung:

Download
 Dateiname:  daten2.txt
 Dateigröße:  5.03 KB
 Heruntergeladen:  422 mal
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 16.06.2012, 22:51     Titel:
  Antworten mit Zitat      
Hallo,

ich würde das so einlesen:
Code:
fid = fopen('daten2.txt');
data = {};
fmt = ['|' repmat('%f', 1, 12)];
while ~feof(fid)
    temp = textscan(fid, fmt, 'delimiter', '|');
    if ~isnan(temp{1})
        data = [data; temp];
    end
    fgetl(fid);
end
fclose(fid);


Bei der Wahl der optimalen Strategie wird es z.B. auch darauf ankommen, ob die gesuchten Zeilen typischerweise als Block kommen oder als einzelne Zeilen.

Wieviele Zeilen hat deine "echte" Datei, und wie lange dauert das Einlesen zur Zeit?

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
01detlef
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 17.06.2012, 08:11     Titel:
  Antworten mit Zitat      
Hallo,

vielen Dank. Aber eine Frage, die Werte sind dann ja alles Cell-Elemente und ich möchte dann mit einigen Daten eine FFT machen. Muss ich die Matrix dann also doch noch umwandeln, weil mit der jetztigen daten-Matrix ist ja eine FFT nicht möglich.

Die ganze Textdatei hat 1-2 Millionen Zeilen und die Blöcke sind recht ähnlich aufgebaut. Was genau meinst du mit Blöcken?

detlef
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 17.06.2012, 09:51     Titel:
  Antworten mit Zitat      
Hallo,

du kannst ja den Code leicht anpassen, z.B. so:
Code:
fid = fopen('daten2.txt');
data = [];
fmt = ['|' repmat('%f', 1, 12)];
while ~feof(fid)
    temp = textscan(fid, fmt, 'delimiter', '|');
    if ~isnan(temp{1})
        data = [data; cell2mat(temp)];
    end
    fgetl(fid);
end
fclose(fid);


Was ich meine ist: Kommen die gesuchten Zeilen einzeln oder kommen davon wenn mehrere am Stück? Um die Struktur der Datei besser zu verstehen und die Zeit abschätzen zu können, wäre eine Datei mit 1000-10000 Zeilen hilfreich.

Wie lange das Einlesen der Originaldatei dauert weiß ich nun leider immer noch nicht.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
01detlef
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 47
Anmeldedatum: 07.05.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 17.06.2012, 12:02     Titel:
  Antworten mit Zitat      
Hallo,

also die Zeilen kommen vereinzelt vor. Es kommen immer so 600 Zeilen irgendetwas und dann wieder eine Zeile mit | am Anfang. Ich habe leider gerade keine große Datei hier.

Die ganze Datei hat 1000000-2000000 Zeilen und mit meinem Code hat es mit der ganzen Datei gar nicht funktioniert. Das Programm lief unendlich lange. Mit der halben Datei war es bestimmt 1h oder so

detlef
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen

Gehe zu Seite 1, 2  Weiter

Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum 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.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.