Autor Beitrag
Siluro
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 74

Win XP Prof., Win XP64 Prof., Win 7 Prof.
Delphi 7 Ent., Delphi XE, Delphi XE5
BeitragVerfasst: Do 04.06.15 17:23 
Hi Leute,

ich habe ein merkwürdiges Problem in meiner Anwendung in Delphi XE5. Eine Funktion gibt mir einen extrem langen String zurück. Den Rückgabewert schreibe ich in die Text-Property eines Edit-Feldes. Zur Laufzeit bleibt das Feld in der Anzeige jetzt aber komischerweise leer, während Text beim Debuggen aber gefüllt ist.

Das Gleich passiert, wenn ich den Wert Label.Caption zuweise. Beim Versuch den Rückgabewert an ein Memo zu übergeben, friert sogar das komplette Programm ein (ohne Fehlermeldung).

Bei Google hab ich leider nichts gefunden (oder einfach nicht die richtigen Worte gefunden). Hat hier vielleicht jemand ne Idee?

Schon mal vielen Dank im Voraus.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Do 04.06.15 18:42 
Hallo,

gibt doch einfach mal die Länge aus/an, damit man das abschäten kann, was da schief geht.
EIn Memo braucht viel Zeit um alle Zeilen daraus zu extrahieren.

Gruß Horst
Perlsau
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 04.06.15 19:49 
user profile iconSiluro hat folgendes geschrieben Zum zitierten Posting springen:
Eine Funktion gibt mir einen extrem langen String zurück. Den Rückgabewert schreibe ich in die Text-Property eines Edit-Feldes. Zur Laufzeit bleibt das Feld in der Anzeige jetzt aber komischerweise leer, während Text beim Debuggen aber gefüllt ist. Das Gleich passiert, wenn ich den Wert Label.Caption zuweise. Beim Versuch den Rückgabewert an ein Memo zu übergeben, friert sogar das komplette Programm ein (ohne Fehlermeldung).

  1. Welchem Zweck sollte es dienen, einen String anzeigen zu wollen, der ob seiner Länge niemals vollständig angezeigt werden kann?
  2. Wie hast du überprüft, ob das Edit-Feld bzw. die Label-Caption leer bleiben?
  3. Wie übergibst du den überlangen String an das Memo?
  4. Hast du vor der String-Übergabe an das Memo BeginUpdate und nach der Übergabe EndUpdate ausgeführt?
  5. Wie lang ist er String?

user profile iconSiluro hat folgendes geschrieben Zum zitierten Posting springen:
Hat hier vielleicht jemand ne Idee?

In der Tat hätte ich da eine Idee: Zeig mal deinen Code her :)
Oder wie sollen wir als hilfsbereite User wissen, was du da fabriziert hast?
hathor
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 04.06.15 20:43 
TRIM ?
Siluro Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 74

Win XP Prof., Win XP64 Prof., Win 7 Prof.
Delphi 7 Ent., Delphi XE, Delphi XE5
BeitragVerfasst: Fr 05.06.15 09:48 
Moin,

erstmal danke für die Rückmeldungen. Vielleicht muss ich dann doch ein bisschen weiter ausholen. Bei meinem Projekt handelt es sich um einen WYSIWYG-Designer. Dafür benutze ich die Vektor-Komponente von ImageEn und male mir Bilder auf die Zeichenfläche. Diesen Platzhaltern sollen dann Inhalte zugewiesen werden (Bilder, Videos, RTF-Text). Bilder und Videos lasse ich mal außen vor, da hier keine Probleme auftreten.
Für RTF-Text benutze ich die WPTools und lasse mir den Inhalt dann als String ausgeben. Das war bisher auch kein Problem. Allerdings ist nun die Anforderung hinzugekommen, dass im RTF-Text Bilder enthalten sein können. So komme ich also zu meinen ewig langen Strings (6 – 7 Stellig).

Die entscheidenden Stellen im Code sehen dann Folgendermaßen aus:

RichText Inhalt auslesen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
case pcDialogs.ActivePageIndex of
    0: FResult := edImageFileName.Text;
    1: FResult := edVideoFileName.Text;
    2begin
      DeletePages;
      FResult := string(rtContent.AsANSIString('RTF-nobinary'));
    end;
  end;


Inhalt an Hauptformular zurückgeben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
function TfrmContentDlg.GetResult: string;
begin
  Result := FResult;
end;


Und hier der Code vom Hauptformular:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
if ContentDlg.ShowModal = mrOk then begin
      edContent.Text := ContentDlg.GetResult;
      {für test}
      label1.Caption := AnsiReplaceStr(edContent.Text, #13#10'');
      text := edContent.Text;
      showmessage(inttostr(length(ContentDlg.GetResult)));
      showmessage(inttostr(length(edContent.Text)));
      showmessage(inttostr(length(label1.Caption)));
      showmessage(inttostr(length(trim(label1.Caption))));
      application.ProcessMessages;
      {für test}
      if LoadContent(ievArea.SelObjects[0] ,ievArea.ObjID[ievArea.SelObjects[0]], edContent.Text) then
        try
        //ievArea.ObjText[ievArea.SelObjects[0]] := edContent.Text; //auskommentiert wegen freeze
        except
          on e:exception do showmessage(e.Message);
        end;
    end;


Kurz zu den Fragen von Perlsau:

user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Welchem Zweck sollte es dienen, einen String anzeigen zu wollen, der ob seiner Länge niemals vollständig angezeigt werden kann?

Es geht nur darum dass das Feld nicht leer ist (wäre für den Benutzer wohl ganz schön verwirrend)

user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Wie hast du überprüft, ob das Edit-Feld bzw. die Label-Caption leer bleiben?

Weil kein Inhalt angezeigt wird.

Die Memo-Fragen überspringe ich mal, da ich die Komponente eigentlich nicht verwenden möchte. Hatte das nur zum Testen mal verwendet.

user profile iconPerlsau hat folgendes geschrieben Zum zitierten Posting springen:
Wie lang ist er String?

Die Länge des Strings liegt halt im oberen 6-stelligen bis untern 7-stelligen Bereich.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Fr 05.06.15 10:07 
Hallo,

lass mal auf die Schnelle AnsiStringReplace weg und teste dann die Laufzeit.
Für Deinen speziellen Fall, wo 2 Zeichen durch etwas kürzeres ersetzt werden, kann man eventuell schneller vorgehen.

Gruß Horst
EIn String mit 10e6 Zeichen war in 330 Sekunden noch nicht fertig.
ein String mit 1e6 Zeichen war in 1,5 Sekunden fertig.
Siluro Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 74

Win XP Prof., Win XP64 Prof., Win 7 Prof.
Delphi 7 Ent., Delphi XE, Delphi XE5
BeitragVerfasst: Fr 05.06.15 12:05 
Sorry für die Verzögerung. Ich bin gerade dabei mich um das Problem mit dem Freeze zu kümmern und wollte mal versuchen das über einen Pointer zu lösen. Dabei hatte ich unter anderem folgenden Code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
sContent := ContentDlg.GetResult;
      if (ievArea.ObjID[hObj] = 2and (Length(sContent) > 200then begin
        edContent.Text := copy(sContent, 1200);
        ievArea.ObjUserData[hObj] := @sContent;
      end else
        edContent.Text := sContent;
      {für test}
      label1.Caption := string(ievArea.ObjUserData[hObj]^);

      showmessage(inttostr(length(ContentDlg.GetResult)));
      showmessage(inttostr(length(label1.Caption)));
      showmessage(inttostr(length(trim(label1.Caption))));
      application.ProcessMessages;


Wenn ich Label1.Caption über den Pointer hole, wird es mir auf dem Formular angezeigt. Verstehe nur nicht, wo der Unterschied ist.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Fr 05.06.15 12:40 
Hallo,

wie denn? Wo denn? Was denn?
Einmal willst 10e6 Byte mit replaceString beackern, das andere mal beschränkst Du Dich auf 200 Byte.
Hast Du vielleicht das Edit nicht gesehen?
Zitat:
EIn String mit 10e6 Zeichen war in 330 Sekunden noch nicht fertig.
ein String mit 1e6 Zeichen war in 1,5 Sekunden fertig.


Gruß Horst
Ein kleines Test Programm mit einem alternativem Replacestring aus www.delphipraxis.net/457239-post1.html für eine 10 Mio Zeichen String, mit CRLF alle 60 Zeichen aka 166666 Zeilen mit einem Rest.
ausblenden volle Höhe Delphi-Quelltext
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:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
program test;
{$MODE DELPHI}
uses
  sysutils, strutils;

const
  gesLen = 10*1000*1000;
  rowLen = 60// incl #13#10
var
  s : AnsiString;
  p : longInt;

//Aus http://www.delphipraxis.net/457239-post1.html  von Matze
function StringReplaceMultiple(const Source: AnsiString;
   const OldPatterns, NewPatterns: array of AnsiString;
   CaseSensitive: Boolean = True): AnsiString;
// Replace every occurrence

type
   TFoundPos = record
     Position: Integer;
     PatternNum: Integer;
   end;

var
   C: Integer;
   FoundCount: Integer;
   SourcePosition: Integer;
   PatternCount: Integer;
   Positions: array of TFoundPos;
   PositionLength: Integer;

   PatternNum: Integer;
   SourceLength: Integer;
   OldLengths, NewLengths: array of Integer;
   DeltaOld: Integer;

   Delta: Integer;

   PSource, PDest, PNew: PAnsiChar;

   SearchSource: AnsiString;
   CasePatterns: array of AnsiString;

begin
   if (Source = ''or (Length(OldPatterns) <> Length(NewPatterns)) then
   begin
     Result := Source;
     Exit;
   end;

   try
     // Initialize some variables
     PatternCount := Length(OldPatterns);
     SourceLength := Length(Source);
     SetLength(OldLengths, PatternCount);
     SetLength(NewLengths, PatternCount);
     Delta := 0;
     DeltaOld := 0;
     for C := 0 to PatternCount - 1 do
     begin
       OldLengths[C] := Length(OldPatterns[C]);
       NewLengths[C] := Length(NewPatterns[C]);
       Inc(DeltaOld, OldLengths[C]);
     end;
     DeltaOld := Round(DeltaOld / PatternCount);

     SetLength(CasePatterns, PatternCount);
     if CaseSensitive then
     begin
       SearchSource := Source;
       for C := 0 to PatternCount - 1 do
         CasePatterns[C] := OldPatterns[C];
     end else
     begin
       SearchSource := AnsiLowerCase(Source);
       for C := 0 to PatternCount - 1 do
         CasePatterns[C] := AnsiLowerCase(OldPatterns[C]);
     end;

     FoundCount := 0;

     // ----------------------------------
     // Check the amount of replaces
     // ----------------------------------

     // We *should* range check here, but who has strings > 2GB ?
     PositionLength := SourceLength div DeltaOld + 1;
     SetLength(Positions, PositionLength);

     C := 1;
     while C <= SourceLength do
     begin
       for PatternNum := 0 to PatternCount - 1 do
       begin
         if (SearchSource[C]) = (CasePatterns[PatternNum][1]) then // Check first char before we waste a jump to CompareMem
         begin
           if CompareMem(@SearchSource[C], @CasePatterns[PatternNum][1], OldLengths[PatternNum]) then
           begin
             if FoundCount >= PositionLength then
             begin
               Inc(PositionLength, 4);
               SetLength(Positions, PositionLength);
             end;

             Positions[FoundCount].Position := C; // Store the found position
             Positions[FoundCount].PatternNum := PatternNum;
             Inc(FoundCount);
             Inc(C, OldLengths[PatternNum] - 1); // Jump to after OldPattern
             Inc(Delta, NewLengths[PatternNum] - OldLengths[PatternNum]);
             Break;
           end;
         end;
       end;
       Inc(C);
     end;

     SetLength(CasePatterns, 0);

     // ----------------------------------
     // Actual replace
     // ----------------------------------

     if FoundCount > 0 then // Have we found anything?
     begin
       // We know the length of the result
       // Again, we *should* range check here...
       SetLength(Result, SourceLength + Delta);

       // Initialize some variables
       SourcePosition := 1;
       PSource := PAnsiChar(Source);
       PDest := PAnsiChar(Result);

       // Replace...

       for C := 0 to FoundCount - 1 do
       begin
         // Copy original and advance resultpos
         PNew := PAnsiChar(NewPatterns[Positions[C].PatternNum]);

         Move(PSource^, PDest^, Positions[C].Position - SourcePosition);
         Inc(PDest, Positions[C].Position - SourcePosition);

         // Append NewPattern and advance resultpos
         Move(PNew^, PDest^, NewLengths[Positions[C].PatternNum]);
         Inc(PDest, NewLengths[Positions[C].PatternNum]);

         // Jump to after OldPattern
         Inc(PSource, Positions[C].Position - SourcePosition + OldLengths[Positions[C].PatternNum]);
         SourcePosition := Positions[C].Position + OldLengths[Positions[C].PatternNum];
       end;

       // Append characters after last OldPattern
       Move(PSource^, PDest^, SourceLength - SourcePosition + 1);
     end else
       Result := Source; // Nothing to replace

     // Clean up
     Finalize(Positions);
   except
   end;
end;
var
  Pat,Rpl : array of AnsiString;
Begin
  setlength(s,gesLen);
  fillchar(s[1],length(s),'A');
  p := (length(s) DIV rowLen) *rowLen-1;
  while p > 2 do
  begin
    s[p]:= #13;
    s[p+1]:= #10;
    dec(p,60);
  end;
  setlength(Pat,1);
  setlength(Rpl,1);
  Pat[0] := #13#10;
  Rpl[0] := ' ';

  writeln(length(s));
  s:=StringReplaceMultiple(s,Pat,Rpl);
//  s := AnsiReplaceStr(s,#13#10,' ');// dauerte über 330 Sekunden-> Abbruch
  writeln(length(s));
end.


Laufzeit bei mir 66ms.
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
10000000
9833334

real  0m0.066s
user  0m0.062s
sys  0m0.003s