Avatar billede anold Nybegynder
16. maj 2001 - 13:43 Der er 31 kommentarer og
1 løsning

Flytte fra RichEdit til RichEdit

Jeg har en fil på ca 2MB som jeg har indlæst i en RichEdit (Hvilket tager meget lang tid), nu vil jeg gerne flytte noget af teksten over i en anden RichEdit (F.eks fra linje 7 til linje 80)
Første linje som der skal flyttes starter med \'O\'og sidste linje slutter med \'%\' eller \'#\'
Hvorefter at det der er blevet flyttet skal gemmes i en fil

Hvordan gør jeg lige det så det også går stærkt
Avatar billede martinlind Nybegynder
16. maj 2001 - 13:48 #1
RichEdit.FindText()
RichEdit.SelStart;
RichEdit.SelLen;
RichEdit.CopyToClipboard;
RichEdit.CopyFromClipboard;

Det må være disse rutiner du skal bruge find din start pos og sæt SelStart til den find derefter den sidste char og sæt SelLen til antal chars fra startpos til den pos du har nu, og til sidst CopyToClip...


/Martin
Avatar billede ziron Nybegynder
16. maj 2001 - 14:06 #2
prøv dette:

procedure TForm1.Button1Click(Sender: TObject);
var
start, slut, text : String;
begin
start := inttostr(RichEdit1.FindText(\'O\',0,Length(RichEdit1.Lines.Text), [stMatchCase]));
slut := inttostr(RichEdit1.FindText(\'%\',strtoint(start),Length(RichEdit1.Lines.Text), [stMatchCase]));
text := copy(RichEdit1.Lines.Text, strtoint(start), (strtoint(slut) - strtoint(start)));

RichEdit2.Lines.Add(text);

RichEdit2.Lines.SaveToFile(\'c:\\nissebanden.txt\');
end;

/ZIORN
Avatar billede martinlind Nybegynder
16. maj 2001 - 14:10 #3
Ziorn >> Er du sikker på du får #10 og #13 med i den copy ?

/Martin
Avatar billede martinlind Nybegynder
16. maj 2001 - 14:14 #4
Eller sådan

procedure TForm1.Button1Click(Sender: TObject);
begin
  RichEdit1.SelStart := RichEdit1.FindText(\'O\',0,Length(RichEdit1.Lines.Text), [stMatchCase]);
RichEdit1.SelLen := RichEdit1.FindText(\'%\',start,Length(RichEdit1.Lines.Text), [stMatchCase]) - RichEdit1.SelStart;

RichEdit1.CopyToClipBoard;

RichEdit2.CopyFromClipBoard;

RichEdit2.Lines.SaveToFile(\'c:\\nissebanden.txt\');

end;

Avatar billede martinlind Nybegynder
16. maj 2001 - 14:16 #5
ups !

fejl :

RichEdit1.SelLen := RichEdit1.FindText(\'%\',start,Length(RichEdit1.Lines.Text), [stMatchCase]) - RichEdit1.SelStart;

Rettes til :

RichEdit1.SelLen := RichEdit1.FindText(\'%\',RichEdit1.SelStart,Length(RichEdit1.Lines.Text), [stMatchCase]) - RichEdit1.SelStart;


Avatar billede ziron Nybegynder
16. maj 2001 - 14:17 #6
procedure TForm1.Button1Click(Sender: TObject);
var
start, slut, text : String;
begin
start := inttostr(RichEdit1.FindText(\'O\',0,Length(RichEdit1.Lines.Text), [stMatchCase]));
slut := inttostr(RichEdit1.FindText(\'%\',strtoint(start),Length(RichEdit1.Lines.Text), [stMatchCase]));
text := copy(RichEdit1.Lines.Text, strtoint(start), (strtoint(slut) - strtoint(start) +2));

RichEdit2.Lines.Add(text);

RichEdit2.Lines.SaveToFile(\'c:\\nissebanden.txt\');
end;

/ZIRON
Avatar billede borrisholt Novice
16. maj 2001 - 14:18 #7
Ziron og martinlind jeres svar holde ikke vand hjem. Fordi hvis der står et % eller et O inde midt i teksten så stopper FindTeksten det og man får ikke det hele med ....

jens B
Avatar billede ziron Nybegynder
16. maj 2001 - 14:20 #8
borrisholt >> ja det er rigtig nok men der er jo heller ikke talle om at det skal skal med :-)

/ZIRON
Avatar billede borrisholt Novice
16. maj 2001 - 14:21 #9
\"Første linje som der skal flyttes starter med \'O\'og sidste linje slutter med \'%\' eller \'#\' \"

Skrev manden.

Jens B
Avatar billede ziron Nybegynder
16. maj 2001 - 14:23 #10
ja okay skal du bare køre på mig :-)))) lang mund

så kom dog med din syge kode...

/ZIRON
Avatar billede borrisholt Novice
16. maj 2001 - 14:24 #11
skal lige skrive det først ...
Avatar billede ziron Nybegynder
16. maj 2001 - 14:27 #12
okay vi venter...
Avatar billede martinlind Nybegynder
16. maj 2001 - 14:27 #13
Vi kunne jo også lade Anold få en chance til at prøve selv, ellers lærer han det jo aldrig, og da er da kommet nok af foreslag.

/Martin
Avatar billede martinlind Nybegynder
16. maj 2001 - 14:28 #14
Jb >> Du har da helt ret, men vi har ikke lært at læse, vi er kun gode til delphi *GG*
Avatar billede borrisholt Novice
16. maj 2001 - 15:17 #15
prøv det her :

//du bad om noget fart så skal vi lige bruge en ny procedure
//til at finde længden af en Pchar : (omkring 8 gange hurtigere end StrLen)

function StrLenASM(tStr:PChar):integer;
asm
      MOV    EDX,7
      ADD    EDX,EAX
      PUSH    EBX
      MOV    EBX,[EAX]
      ADD    EAX,4
@L1:  LEA    ECX,[EBX-$01010101]
      XOR    EBX,-1
      AND    ECX,EBX
      MOV    EBX,[EAX]
      ADD    EAX,4
      AND    ECX,80808080H
      JZ      @L1
      TEST    ECX,00008080H
      JNZ    @L2
      SHR    ECX,16
      ADD    EAX,2
@L2:  SHL    CL,1
      POP    EBX
      SBB    EAX,EDX
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  i,j,k : Integer;
  p : PChar;
  start,stop : Integer;
  span : Integer;
begin
  i:= 0;
  j:= RichEdit1.Lines.Count;

  repeat //Hurtigere løkke struktur end for sætninger
    with RichEdit1 do
    begin
      p:= pointer(Lines[i]);
      if (bool(p)) and (p[0] = \'O\') then
        break; //grimt hack
      inc(i);
    end;
  until i = j;

  // Når vi er nået her så ved vi følgende :
  // Hvis i = j så fandt vi ingen ting --> skriv fjols til brugeren
  // Ellers Nåede vi aldrig enden af dokumentet og har dermed fundet vores start linje
  // da vores break er sat ind INDEN vi tæller i op ved vi at i er vores start linje.

  if i<> j then
    start := i
  else
  begin
    ShowMessage(\'Fjols !!! Ingen start linje\');
    exit;
  end;

  repeat //Hurtigere løkke struktur end for sætninger
    with RichEdit1 do
    begin
      p:= pointer(Lines[i]);
      if (bool(p)) then //Meget grimt hack men hurtigere end if p <> nil
      begin
        k := StrlenASM(p) -1;
        if (p[k] = \'#\') or (p[k] = \'%\') then
          break; //grimt hack
      end;
      inc(i);
    end;
  until i > j;

  // Når vi er nået her så ved vi følgende :
  // Hvis i >j så fandt vi ingen ting --> skriv fjols til brugeren
  // Ellers Nåede vi aldrig enden af dokumentet og har dermed fundet vores stop linje
  // da vores break er sat ind INDEN vi tæller i op ved vi at i er vores stop linje.

  if j>i then
    stop := i
  else
  begin
    ShowMessage(\'Fjols !!! Ingen stop linje\');
    exit;
  end;
  // Vi er nået forbi vores Exit komando ergo har vi fundet både start og stop

  RichEdit2.Clear;
  k := 0;
  span := stop-start;
  repeat
    p:= pointer(RichEdit1.Lines[start+k]);
    RichEdit2.Lines.Insert(k,p);

    //Ved at kalde Insert og ikke Add sparer vi et procedure kald
    //Vi har kaldt en clear på vores RichEdit2 derfor ved vi at antallet af linjer
    //til en hvertid er det samme som k. Ergo sparer vi et kald til getCount.
    //getCount er en protected procedure der retunerer antallet af linjer på en TStrings;

    inc(k);
  until k > span;
end;


Jens B
Avatar billede martinlind Nybegynder
16. maj 2001 - 15:54 #16
Jb >> Må man have lov at spørge hvad du bygger din hastigheds test på ?? uden at være ekspert i asm, ser deres rutine da meget fornuftig ud, og din looper da også så...

Delphi\'s StrLen :

function StrLen(const Str: PChar): Cardinal; assembler;
asm
        MOV    EDX,EDI
        MOV    EDI,EAX
        MOV    ECX,0FFFFFFFFH
        XOR    AL,AL
        REPNE  SCASB
        MOV    EAX,0FFFFFFFEH
        SUB    EAX,ECX
        MOV    EDI,EDX
end;

/Martin
Avatar billede borrisholt Novice
16. maj 2001 - 16:05 #17
Martin>> Borland bygger deres beregninger på to MEGET dyre instruktioner :

REPNE  og SCASB. Hvis du finder en assembler guide g slår string funktioner op vil det stå at man bør undgå disse.

\"REP LOADS, REP SCAS, and REP CMPS are not optimal, and may be replaced by
loops. See section 16 example 10 for an alternative to REP SCASB.\"

(http://www.neutralzone.org/home/faqsys/docs/p5opt3.txt)

Jens B
Avatar billede borrisholt Novice
16. maj 2001 - 16:06 #18
Min procedure bygger udelukken på billige instruktioner ...

Jens B
Avatar billede martinlind Nybegynder
16. maj 2001 - 19:20 #19
Ok, interessant.

/Martin
Avatar billede anold Nybegynder
17. maj 2001 - 07:32 #20
Hej Borrisholt

Jeg har lige prøvet dit EKS og det virker fint
men jeg glemte vist lige en vigtig detalje, nemlig at der er flere \'O\' i tekstfilen det vil sige at tekst filen skal splittes op i flere filer som får navn efter hvad der står bagefter \'O\' F.eks \'Otest10\' da skal filnavnet være test10

kan du hjælpe mig med det
her er en snip af tekstfilen som har 74120 linjer !!!




Otest10
G90 G53 G0 Z0
G0 X119.8 Y0.
Z2.
G1 X-102.593 Y1.348
X-103.5
Z2.
M99
%
Otest20
G90 G53 G0 Z0
Z2. M8
G1 Z-.8 F1200.
M99
%
Otest30
G90 G53 G0 Z0
G1 Y-5.056
G0 Z2.
M30
Avatar billede borrisholt Novice
17. maj 2001 - 07:36 #21
anold >>

dvs. du har en text der ser således ud :

Otest10
G90 G53 G0 Z0
G0 X119.8 Y0.
Z2.
G1 X-102.593 Y1.348
X-103.5
Z2.
M99
%
Otest20
G90 G53 G0 Z0
Z2. M8
G1 Z-.8 F1200.
M99
%
Otest30
G90 G53 G0 Z0
G1 Y-5.056
G0 Z2.
M30
%

samt en masse mere ...

Den vil du gerne have splitter op i flere bider :

Otest10
G90 G53 G0 Z0
G0 X119.8 Y0.
Z2.
G1 X-102.593 Y1.348
X-103.5
Z2.
M99
%

Otest20
G90 G53 G0 Z0
Z2. M8
G1 Z-.8 F1200.
M99
%

Otest30
G90 G53 G0 Z0
G1 Y-5.056
G0 Z2.
M30
%

disse bider skal de så gemt i hver sin fil ? I så fald er der ingen grund til at komme dem over i et nyt RichEdit ...

Jens B
Avatar billede anold Nybegynder
17. maj 2001 - 07:50 #22
ja de skal gemmes i hver sin fil hvor filnavnet er det som står efter \'O\'

men du skal være opmærksom på at efter M30 kommer der ikke noget % tegn men M30 er altid den sidste linje i programmet
Hilsen anold
Avatar billede borrisholt Novice
17. maj 2001 - 08:11 #23
anold >>

Må jeg ikke have lov til bare tilføje det % i enden hvis bare jeg sletter den igen ?

Jens B
Avatar billede anold Nybegynder
17. maj 2001 - 08:53 #24
det må du gerne
Avatar billede borrisholt Novice
17. maj 2001 - 10:27 #25
Så nu har jeg en version der virker. Der er lavet en del om. Det hele er trukket ud i en ny procedure, og algoritmen er ændret lidt. Men det går stærkt.

Hvis du ikke forstår koden helt må du spørge. Sådan noget optimeret kode er ikke ret nemt at læse, secielt fordi der bliver brugte nogle beskidte tricks i den :-)

Her er koden :

//du bad om noget fart så skal vi lige bruge en ny procedure
//til at finde længden af en Pchar : (omkring 8 gange hurtigere end StrLen)

function StrLenASM(tStr:PChar):integer;
asm
      MOV    EDX,7
      ADD    EDX,EAX
      PUSH    EBX
      MOV    EBX,[EAX]
      ADD    EAX,4
@L1:  LEA    ECX,[EBX-$01010101]
      XOR    EBX,-1
      AND    ECX,EBX
      MOV    EBX,[EAX]
      ADD    EAX,4
      AND    ECX,80808080H
      JZ      @L1
      TEST    ECX,00008080H
      JNZ    @L2
      SHR    ECX,16
      ADD    EAX,2
@L2:  SHL    CL,1
      POP    EBX
      SBB    EAX,EDX
end;

procedure TForm1.DoTheTrick(StringList : TStringList;  Start : Integer = 0);
//StringList er en buffer vi bruger til at stoppe den blok af teksen over i som
//senere skal gemmes i en fil. Frodelen ved at overføre den som arameter er at den
//ikke skal oprettes og nedlægges hver gang.
//Start er en Index for hvor i listen vi skal starte vores søgning.
var
  i,j,k : Integer;
  p : PChar;
  stop : Integer;
  span : Integer;
begin
  i:= Start;
  j:= RichEdit1.Lines.Count;

  repeat //Hurtigere løkke struktur end for sætninger
    with RichEdit1 do
    begin
      p:= pointer(Lines[i]);
      //Hvis du overstyrer en String til en pointer, få du adgang direkte til
      //de bogstaver strengen består af der hvor de ligger.
      //Det har samme efekt som at overstyre det

      if (bool(p)) and (p[0] = \'O\') then
        break; //grimt hack
      inc(i);
    end;
  until i >= j;

  // Når vi er nået her så ved vi følgende :
  // Hvis i = j så fandt vi ingen ting --> Exit proceduren eller
  // Hvis i > j så er vi rendt ud over enden af vores liste --> Exit proceduren
  // Ellers Nåede vi aldrig enden af dokumentet og har dermed fundet vores start linje
  // da vores break er sat ind INDEN vi tæller i op ved vi at i er vores start linje.

  if i < j then
    start := i
  else
    exit;

  repeat //Hurtigere løkke struktur end for sætninger
    with RichEdit1 do
    begin
      p:= pointer(Lines[i]);
      if (bool(p)) then //Meget grimt hack men hurtigere end if p <> nil
      begin
        k := StrlenASM(p) -1;
        if (p[k] = \'#\') or (p[k] = \'%\') then
          break; //grimt hack.
      end;
      inc(i);
    end;
  until i > j;

  // Når vi er nået her så ved vi følgende :
  // Hvis i >j så fandt vi ingen ting --> Exit proceduren
  // Ellers Nåede vi aldrig enden af dokumentet og har dermed fundet vores stop linje
  // da vores break er sat ind INDEN vi tæller i op ved vi at i er vores stop linje.

  if j>i then
    stop := i
  else
    exit;
  // Vi er nået forbi vores exit komando ergo har vi fundet både start og stop

  //Ryd vores buffer
  StringList.Clear;
  //Nulstil vores Index
  k := 0;

  //Beregn antal linjer der skal kopieres
  span := stop-start;
  repeat
    p:= pointer(RichEdit1.Lines[start+k]);
    StringList.Insert(k,p);

    //Ved at kalde Insert og ikke Add sparer vi et procedure kald
    //Vi har kaldt en clear på vores StringList derfor ved vi at antallet af linjer
    //til en hvertid er det samme som k. Ergo sparer vi et kald til getCount.
    //getCount er en protected procedure der retunerer antallet af linjer på en TStrings;

    inc(k);
  until k > span;

p := @RichEdit1.Lines[start][2];
//Smid det første 0 væk
//Igen et grimt hack, men det virker :-)

//Dette er en beregning vi skal bruge flere gange kan der spares
//ved at stoppe det over i en variabel
k:= Start+span;

//Hvis vi er ved den sidste blok .. Så ryd op efter os selv
if k  = j-1 then
begin
  RichEdit1.Lines.Delete(k);
  StringList.Delete(span);
end;

StringList.SaveToFile(p+\'.txt\');

DoTheTrick(StringList,Stop+1);
//Vi kalder os selv igen med vores Stop+1 fordi vi skal fortsætte søgningen
//Fra tidligst fra næste linje, i froholt til vores stop linje fra før.
end;

procedure TForm1.Button1Click(Sender: TObject);
var
StringList : TStringList;
p : PChar;
k,j : Integer;
begin
  j:= RichEdit1.Lines.Count;
  p:= pointer(RichEdit1.Lines[j-1]);
  k := StrlenASM(p) -1;

  //Hvis vores tekst ikke er termineret \"ordenligt\" simder vi selv
  //en terminator på. Det har den fordel at vi ikke hele tiden skal teste
  //for om vi er nået enden, men det i mod vi kan koncentrerer os om at finde
  //den næste terminator. Og der af følgende hvis vi ingen finder så stop
  //vores rekusion
  if (p[k] <> \'#\') and (p[k] <> \'%\') then
    RichEdit1.Lines.add(\'%\');

  StringList := TStringList.Create;
  DoTheTrick(StringList);
  StringList.Free;
end;

Jens B http://fotx.net/borrisholt

Orv ja Lad mig lige slå et slag for at Delphi grupper bliver godt repræsenteret ved Eksperten festen (http://www.ekspertenfest.dk)
Avatar billede martinlind Nybegynder
17. maj 2001 - 10:45 #26
anold >> Er det en tekst fil til et printudlægnings program eller hvor har du fået den fil fra.
Forøvrigt når der ikke er brug for at formatere teksten, så brug en TStringList istedet for lines på RichEdit, jeg har rigtig gode erfaringer med LoadFromFile på en StringList, den var faktisk Lyn hurtig, hurtigere end noget andet jeg kunne finde.

/Martin
Avatar billede borrisholt Novice
17. maj 2001 - 10:48 #27
Martin >> tror du ikke man kunne skrive en selv der var hurtigere. Hvis du byffer den uddelukkende på pointere, og su aldrig fik fat i en \"rigtig\" string. Den ville selv følgelig ikke være så brugervenlig ... Men MÅSKE hurtigere !!?

Jens B
Avatar billede borrisholt Novice
17. maj 2001 - 10:51 #28
hov byffer = bygger :-)

Jens B
Avatar billede anold Nybegynder
17. maj 2001 - 11:51 #29
Hej Borrisholt
Jeg har nu prøvet dit nye program og det virker fint
der er dog den hage ved det at det tager ca 4,5 min at dele filen på 1.3MB  op i 3 filer og det er jo temlig lang tid at vente.

Jeg tænkte om det ikke var muligt at lave et program hvor man finder start(O) og slut(%) på \'første fil\'og kopiere det til clipboard hvorefter at man saver det som er på clipbord til fil OSV til man er i bunden af tekstfilen
Avatar billede borrisholt Novice
17. maj 2001 - 11:56 #30
Det skal IKKE via Clipbordet. Det tager for lang tid. Martin havde en god pointe med at ikke at brug en RichEdit, med mindere det skal \"farves\". Lad være med at vise det på skærmen hvis du kan undgå det.

Prøv ar zippe det hele og send det ilt mig. Så skal jeg lige prøve at kige på det. EJg kan ikke gøre det bedere uden at have hele programmet.

Jens B
Avatar billede martinlind Nybegynder
17. maj 2001 - 12:11 #31
Jb >> prøv at læse en text fil med en masse liner end med din egen kode og så prøv med loadfromfile, jeg sad selv og prøvede en gang, jeg blev vildt overrasket, den læser ca. 2mb ind så hurtigt at man næsten ikke nåede at bemærke det.

/Martin
Avatar billede borrisholt Novice
17. maj 2001 - 12:14 #32
Det der med at loade en fil kan jeg gøre lige så hurtigt som Borland kan. Jeg ville også benytte mig af en FileStream, som en TStringList også bacere sig på ... Det jeg tror jeg kunne gøre hurtigere var alt det der med tilgang til indholdet, ved at lukke op for de rå bits.

Jens B
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
Kurser inden for grundlæggende programmering

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