![]() |
Externer Fehler kurz nach dem öffnen eines OpenDialogs
Hi,
ich wollte mit einer simplen Anwendung meinen CSV-Parser testen. Auf der Form befindet sich lediglich ein Button, eine ListView mit 20 Columns und ein OpenDialog. Nachdem öffnen des OpenDialogs dauert es ein wenig (egal ob ich eine Datei auswähle oder nicht), dann kommt Zitat:
So rufe ich den OpenDialog auf:
Delphi-Quellcode:
Der Code meines Parsers (wird wohl noch nicht ganz funktionieren, habs das grad sozusagen "from scratch" geschrieben:
var
csv: TBcCSVParser; i: Integer; x: Integer; begin if OpenDialog1.Execute then begin csv := TBcCSVParser.Create(nil); try csv.LoadFromFile(OpenDialog1.FileName); for i := 0 to csv.DataSets.Count - 1 do begin with listview1.Items.Add do begin Caption := ''; for x := 0 to csv.DataSets[i].Count - 1 do SubItems.Add(csv.DataSets[i][x]); end; end; finally csv.Free; end; end;
Delphi-Quellcode:
Hier noch eine Test CSV-Datei:
unit BCParsers;
interface uses SysUtils, Classes, ContNrs, {BCUtils}, DateUtils, StrUtils; type TBcCSVParser = class; TBcCSVDataSets = class; TBcCSVDataSet = class; TBcCSVParser = class(TComponent) private FDataSets: TBcCSVDataSets; FFieldSeparator: String; FFieldDefinition: String; FComment: TStrings; protected procedure SetComment(Value: TStrings); procedure SetDataSets(Value: TBcCSVDataSets); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure ParseStrings(Strings: TStrings); procedure LoadFromStream(Stream: TStream); procedure LoadFromFile(const FileName: String); procedure BuildStrings(Strings: TStrings); procedure SaveToStream(Stream: TStream); procedure SaveToFile(const FileName: String); property DataSets: TBcCSVDataSets read FDataSets write SetDataSets; published property FieldSeparator: String read FFieldSeparator write FFieldSeparator; property FieldDefinition: String read FFieldDefinition write FFieldDefinition; property Comment: TStrings read FComment write SetComment; end; TBcCSVDataSets = class(TObjectList) protected procedure SetItem(Index: Integer; Value: TBcCSVDataSet); function GetItem(Index: Integer):TBcCSVDataSet; public function Add:Integer; property Items[Index:Integer]:TBcCSVDataSet read GetItem write SetItem; default; end; TBcCSVDataSet = class(TStrings); implementation { TBcCSVParser } constructor TBcCSVParser.Create(AOwner: TComponent); begin inherited Create(AOwner); FDataSets := TBcCSVDataSets.Create; FComment := TStringList.Create; FFieldDefinition := '"'; FFieldSeparator := ';'; end; destructor TBcCSVParser.Destroy; begin FDataSets.Free; FComment.Free; inherited Destroy; end; procedure TBcCSVParser.SetComment(Value: TStrings); begin FComment.Assign(Value); end; procedure TBcCSVParser.SetDataSets(Value: TBcCSVDataSets); begin FDataSets := Value; end; procedure TBcCSVParser.ParseStrings(Strings: TStrings); var iLine, CommentPos, DefinitionPos: Integer; CurrentDataSet, CurrentValue: String; begin FDataSets.Clear; FComment.Clear; for iLine := 0 to Strings.Count - 1 do begin CommentPos := pos('#', Strings[iLine]); if CommentPos = 1 then Comment.Add(Copy(Strings[iLine], CommentPos + 1, Length(Strings[iLine]) - CommentPos - 1)) else begin with DataSets[DataSets.Add] do begin CurrentDataSet := Strings[iLine]; while CurrentDataSet <> '' do begin DefinitionPos := pos(FFieldDefinition, Strings[iLine]); if DefinitionPos = 1 then begin //extract value from field definition CurrentValue := Copy(CurrentDataSet, DefinitionPos + 1, posEx(FFieldDefinition, CurrentDataSet, DefinitionPos + 1) - DefinitionPos - 1); System.Delete(CurrentDataSet, DefinitionPos, posEx(FFieldDefinition, CurrentDataSet, DefinitionPos + 1) - DefinitionPos); //unescape value if pos(FFieldDefinition + FFieldDefinition, CurrentValue) > 0 then CurrentValue := StringReplace(CurrentValue, FFieldDefinition + FFieldDefinition, FFieldDefinition, [rfReplaceAll, rfIgnoreCase]); end else begin //extract value CurrentValue := Copy(CurrentDataSet, 1, pos(FFieldSeparator, CurrentDataSet) - 1); System.Delete(CurrentDataSet, 1, pos(FFieldSeparator, CurrentDataSet)); end; Add(CurrentValue); end; end; end; end; end; procedure TBcCSVParser.LoadFromStream(Stream: TStream); var Data: TStrings; begin Data := TStringList.Create; try Data.LoadFromStream(Stream); ParseStrings(Data); finally Data.Free; end; end; procedure TBcCSVParser.LoadFromFile(const FileName: string); var Data: TStrings; begin Data := TStringList.Create; try Data.LoadFromFile(FileName); ParseStrings(Data); finally Data.Free; end; end; procedure TBcCSVParser.BuildStrings(Strings: TStrings); var iDataSet, iCommentLine, iValue: Integer; CurrentValue, CurrentDataSet: String; begin Strings.Clear; //add comment line by line for iCommentLine := 0 to Comment.Count - 1 do Strings.Add('#' + Comment[iCommentLine]); //write datasets for iDataSet := 0 to DataSets.Count - 1 do begin CurrentDataSet := ''; for iValue := 0 to DataSets[iDataSet].Count - 1 do begin //prepare current value CurrentValue := DataSets[iDataSet][iValue]; if pos(FFieldSeparator, CurrentValue) > 0 then begin //escape field definition in value if needed if pos(FFieldDefinition, CurrentValue) > 0 then CurrentValue := StringReplace(CurrentValue, FFieldDefinition, FFieldDefinition + FFieldDefinition, [rfReplaceAll, rfIgnoreCase]); //set field definition CurrentValue := FFieldDefinition + CurrentValue + FFieldDefinition; end; //append value to dataset CurrentDataSet := CurrentDataSet + FFieldSeparator + CurrentValue; end; //add dataset Strings.Add(CurrentDataSet); end; end; procedure TBcCSVParser.SaveToStream(Stream: TStream); var Data: TStrings; begin Data := TStringList.Create; try BuildStrings(Data); Data.SaveToStream(Stream); finally Data.Free; end; end; procedure TBcCSVParser.SaveToFile(const FileName: string); var Data: TStrings; begin Data := TStringList.Create; try BuildStrings(Data); Data.SaveToFile(FileName); finally Data.Free; end; end; { TBcCSVDataSets } procedure TBcCSVDataSets.SetItem(Index: Integer; Value: TBcCSVDataSet); begin inherited Items[Index] := Value; end; function TBcCSVDataSets.GetItem(Index: Integer):TBcCSVDataSet; begin Result := inherited Items[Index] as TBcCSVDataSet; end; function TBcCSVDataSets.Add:Integer; var NewDataSet: TBcCSVDataSet; begin NewDataSet := TBcCSVDataSet.Create; Result := inherited Add(NewDataSet); end;
Code:
Kann jemand den Fehler nachvollziehen?
TEST;TEST2;TEST3
"TEST";"TEST2";"TEST3" "Te""st";"TE;ST2";TEST3 |
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Probier mal das:
Delphi-Quellcode:
Wenn das funktioniert liegt der Fehler wo anders. Funktioniert das nicht, probierst du das nochmal mit einem neuen leeren Projekt aus. Funktioniert das dort auch nicht, stimmt was mit deiner IDE/Compiler nicht.
var
csv: TBcCSVParser; i: Integer; x: Integer; begin if OpenDialog1.Execute then begin ShowMessage(OpenDialog1.Filename); end; end; |
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Ok,
Delphi-Quellcode:
geht auch nicht in einem leeren Projekt. Selber Fehler. An was kann das liegen?
if OpenDialog1.Execute then
ShowMessage(OpenDialog1.FileName); |
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Ähm, die Komponente OpenDialog1 hast du aber auf deinem Formular liegen oder? Ich frage nur mal zur Sicherheit. ;)
Woran das liegen kann? Kaputte IDE/Compiler Installation? |
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Zitat:
Zitat:
|
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Mir fällt was auf, worüber ich auch schon mal gestolpert bin:
Delphi-Quellcode:
Du bekommst ja einen Pointer auf das TListItem zurück. Ich bin nicht sicher, ob das so mit dem with verwendet werden kann. Ich musste da auch mal eine Variable TListItem deklarieren und damit arbeiten. Hatte das für einen Bug in den Tnt-Kompos gehalten.
with listview1.Items.Add do
begin Versuch' mal den Umweg über eine Variable. Grüße, Messie |
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Grundsätzlich ja, aber with ist immer gefährlich ( möglicherweise wird falsches Objekt adressiert)
|
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Zitat:
Hab jetzt festgestellt das der Fehler nur aufrtitt wenn ich im OpenDialog am Desktop bin. Und zwar noch bevor die Dateisymbole gelesen werden (sind alles nur weiße Dokumente wie bei unbekannten Dateien). Scheint so als wenn das Symbol einer Verknüpfung nicht ausgelesen werden kann -> Absturz |
Re: Externer Fehler kurz nach dem öffnen eines OpenDialogs
Kontrollier mal, ob bei dir die Debuggeroption "Debug in spawned processes" aktiviert ist. Damit hatte ich auch schonmal Schwierigkeiten wenn eine im Explorer eingeklinkte Shellerweiterung Mist gebaut hat oder auf einen Breakpoint auflief.
In einem solchen Fall kam dann bei mir immer der Debugger mit der CPU-Ansicht hoch sobald der OpenDialog aufging (bei mir allerdings ohne kompletten Absturz - einen Blick in die Debuggeroptinen ist es allemal Wert) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:09 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz