TMemo.Lines.Delete max length

di il
11 risposte

TMemo.Lines.Delete max length

Ciao,

con il seguente codice (1) carico un file xml in TMemo, (2) cancello le righe contenenti uno specifico nome e risalvo il testo modificato come file xml.

// (1)
  memXml.Lines.LoadFromFile(path, TEncoding.UTF8);
// (2)
var
  i, n: Integer;
begin
   for i := 0 to Length(arrayLibrary) - 1 do
     if arrayLibrary[i, 1] = '1' then
       begin
         for n := 0 to memXml.Lines.Count - 1 do
           if Pos(TPath.GetFileNameWithoutExtension(arrayLibrary[i, 0]), memXml.Lines[n]) > 0 then
             begin
               memXml.Lines.Delete(n);
               Break;
             end;
       end;
   memXML.Lines.SaveToFile(path, TEncoding.UTF8);
end;

Ora, delle volte, accade che TMemo.Lines.Delete cancella una riga solo parzialmente. Ho notato che il punto di interruzione è sempre intorno a Pos 200 (ad es. media Pos 198,89).

Volevo solo chiedervi al volo (1) se c'era un limite di TMemo.Lines.Delete e (2) se conveniva utilizzare TStringList.Delete per questa operazione.

Mille grazie, Ale

11 Risposte

  • Re: TMemo.Lines.Delete max length

    Usa i componenti xml…

    Ci sono pure esempi a corredo con delphi.

  • Re: TMemo.Lines.Delete max length

    Giustamente, perché non provare anche quella via. Grazie del suggerimento, Andrea. : )

    Tornerebbe comunque utile per altre occasioni sapere se c'è un eventuale limite riguardo TMemo.Lines.Delete.

    Ale

  • Re: TMemo.Lines.Delete max length

    Anche se testuale, l'xml ha una struttura. Tmemo va a capo, l'xml ha nodi e valori.

  • Re: TMemo.Lines.Delete max length

    Avevo optato per TMemo (per la visualizzazione) e TStringList (per la ricerca) perché i files xml in questione hanno praticamente un solo tipo di childnode <StateOfSource /> contenente 5 attributes.

    Esempio:

    <?xml version="1.0" encoding="utf-8"?>
    <StateOfSourcesManager xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="SourcesManagerState">
     <Sources>
       <StateOfSource xsi:type="SourceState" ID="uietcg1m4u3xoqxr4mjq2vmunl4c2xdx" FileName="empty-image.png" OriginalPath="C:\Users\Ale\Desktop\Templates\7a73589b-cfd9-5d92-b8f8-c135a2f1fdc6\Resources\empty-image.png" LastEdit="2019-02-25T11:49:40.7443586+01:00" />
       <StateOfSource xsi:type="SourceState" ID="srei07ko1mqll60tx8yoi9ay02q09qrl" FileName="pagetotop_01.png" OriginalPath="C:\Users\Ale\Desktop\Res\PageToTopImages\pagetotop_01.png" LastEdit="2019-02-25T11:57:40.2214787+01:00" />
       <StateOfSource xsi:type="SourceState" ID="q6ngt4kufmh5hjzsxm1mw6fa44wthtsv" FileName="001_add.png" OriginalPath="C:\Users\Ale\Desktop\Res\CartImages\Add\001_add.png" LastEdit="2020-06-24T12:13:59.9248276+02:00" />
       <StateOfSource xsi:type="SourceState" ID="qwikyth3tde2uaz9nlm4xh1zwidpbc8d" FileName="logo.png" OriginalPath="C:\Users\Ale\Desktop\Res\Admin\images\logo.png" LastEdit="2022-02-14T10:54:01.8582949+01:00" />
       <StateOfSource xsi:type="SourceState" ID="vnzbg3y54z960a5k6wkqdpzikicpwnqr" FileName="lvwj56flhy0cljr4gqdgu025vrvsi2es.pdf" OriginalPath="C:\Users\Ale\Desktop\lvwj56flhy0cljr4gqdgu025vrvsi2es.pdf" LastEdit="2022-02-14T10:54:28.6344912+01:00" />
       <StateOfSource xsi:type="SourceState" ID="why0mbhh25dejir4dc9tgu7u447cksax" FileName="World_Time_Zones_Map.png" OriginalPath="C:\Users\Ale\Desktop\Nomus\World_Time_Zones_Map.png" LastEdit="2022-03-03T17:21:09.7828569+01:00" />
       <StateOfSource xsi:type="SourceState" ID="aj4g3jmnm5ve1q4lo7o8m7gk252oihhn" FileName="mummy dark murder, horror.jpg" OriginalPath="C:\Users\Ale\Desktop\mummy dark murder, horror.jpg" LastEdit="2024-04-18T13:14:56.9238094+02:00" />
     </Sources>
    </StateOfSourcesManager>

    Se ora devo eliminare il dataset contenente l'ID "qwikyth3tde2uaz9nlm4xh1zwidpbc8d" eseguo semplicemete:

    for n := 0 to memXml.Lines.Count - 1 do
      if Pos('qwikyth3tde2uaz9nlm4xh1zwidpbc8d', memXml.Lines[n]) > 0 then
        memXml.Lines.Delete(n);
  • Re: TMemo.Lines.Delete max length

    30/05/2024 - al.delphi ha scritto:


    Ora, delle volte, accade che TMemo.Lines.Delete cancella una riga solo parzialmente. Ho notato che il punto di interruzione è sempre intorno a Pos 200 (ad es. media Pos 198,89).

    E' probabile che ci sia un bug nel codice: vedere una cancellazione da una lista di elementi numerando da 0 a N, invece che “a rovescio”, mi fa già sorgere qualche sospetto. Al netto di questo, il codice è un po' farraginoso per quello che devi fare.

    Inoltre, elaborare stringhe usando un TMemo è estremamente lento, a meno di non bloccare gli aggiornamenti sul controllo, in quanto l'azione eseguita sul testo scatena chiamate alle API di Windows e ha ripercussioni sul processo di elaborazione in sé.

    Usa le classi e le funzioni preposte per elaborare i dati nel formato in cui si presentano: per manipolare XML si usa il componente TXMLDocument (e suoi “derivati”).

  • Re: TMemo.Lines.Delete max length

    Ciao Alka,

    individuando il rigo da eliminare mediante un valore “ID” univoco presente in un array dovrebbe rendere indifferente la direzione del loop. Infatti, il rigo viene individuato correttamente, ma non sempre cancellato completamente da TMemo.Lines.Delete[n].

    Domani sostituisco TMemo con TStringList che già uso in tutti gli altri casi perché infatti molto più veloce di TMemo e sto anche facendo delle prove con TXmlDocument per eventualmente accedere più comodamente agli attributi, ma comunque non riesco a capire perché TMemo.Lines.Delete non sempre cancella il completo rigo.

    Ale

  • Re: TMemo.Lines.Delete max length

    31/05/2024 - al.delphi ha scritto:


    non riesco a capire perché TMemo.Lines.Delete non sempre cancella il completo rigo.

    cosa intendi per rigo completo?

    31/05/2024 - al.delphi ha scritto:


    <StateOfSource xsi:type="SourceState" ID="uietcg1m4u3xoqxr4mjq2vmunl4c2xdx" FileName="empty-image.png" OriginalPath="C:\Users\Ale\Desktop\Templates\7a73589b-cfd9-5d92-b8f8-c135a2f1fdc6\Resources\empty-image.png" LastEdit="2019-02-25T11:49:40.7443586+01:00" />

    Non ho fatto altro che copiare la tua riga.. va a capo…

    Un TMemo non fa altro che mostrare un testo. segue le regole della scrittura e va a capo. (come il copia incolla che ho fatto)

    Se devi cancellare un testo che secondo te è:

    “Lorem Ipsum is simply dummy text of the printing and typesetting industry

    ma nel memo risulta:

    Lorem Ipsum is simply dummy text of the  (a capo…)

    printing and typesetting industry.   (resto del testo)

    cancellando il rigo 1 (lines[0]) elimina Lorem Ipsum is simply dummy text of the

    per eliminare “Lorem Ipsum is simply dummy text of the printing and typesetting industry”

    devi cercare nel testo 

    “Lorem Ipsum is simply dummy text of the printing and typesetting industry

    e poi eliminarlo.

    Non sapendo la risoluzione dello schermo, il carattere, e la lunghezza del rigo del file xml di origine, ti ritrovi con un file di testo comune.

    Ecco perchè devi usare strumenti per xml.

  • Re: TMemo.Lines.Delete max length

    31/05/2024 - al.delphi ha scritto:


    individuando il rigo da eliminare mediante un valore “ID” univoco presente in un array dovrebbe rendere indifferente la direzione del loop. Infatti, il rigo viene individuato correttamente, ma non sempre cancellato completamente da TMemo.Lines.Delete[n].

    Come dicevo in un post precedente, agire sul testo di un TMemo coinvolge direttamente l'API di Windows legata a quel controllo visuale (vedi questa risposta su SO per approfondimento), quindi le regole seguite sono quelle della visualizzazione, che potrebbero essere diverse rispetto a quelle applicate a una struttura dati che contiene testo, invece di visualizzarlo.

    Per fare una prova, potresti cambiare la dimensione del TMemo e verificare se il comportamento è diverso ancora: ciò ti farà capire se è la visualizzazione che incide sulla problematica.

    31/05/2024 - al.delphi ha scritto:


    Domani sostituisco TMemo con TStringList che già uso in tutti gli altri casi perché infatti molto più veloce di TMemo e sto anche facendo delle prove con TXmlDocument per eventualmente accedere più comodamente agli attributi, ma comunque non riesco a capire perché TMemo.Lines.Delete non sempre cancella il completo rigo.

    Lavori con un documento strutturato in formato XML, quindi usa solo TXMLDocument.

    Ogni altro strumento in questo contesto non è adatto, perché è sufficiente un piccolo cambiamento al testo per invalidare una logica che tratta un documento strutturato come semplice testo, appunto, e non per quello che è.

    Se usi TStringList o simili, stai solo posticipando un sicuro problema, che sarà difficile da individuare, e quando ciò accadrà ti ritroverai a doverlo risolvere “in emergenza”.

  • Re: TMemo.Lines.Delete max length

    Importi l'xml in una tabella, lavori come si lavora con una tabella e alla fine rigeneri l'xml.

    nella cartella esempi c'è la sezione xml con molti progetti.

    p.s. cartella esempi che hai installato (presumo) insieme a delphi.

  • Re: TMemo.Lines.Delete max length

    Buongiorno Andrea, buongiorno Marco,

    escluderei il “a capo” come causa del trunc perché nella mia applicazione il TMemo non va a capo ma visualizza le scrollbar, esattamente come la seguente visualizzazione codice. Il Pos del trunc inoltre varia (Pos min = 174, Pos max = 210) e, peggior punto, il malfunzionamento è casuale e da me non riproducibile.

    Esempio:

        <StateOfSource xsi:type="SourceState" ID="nwv9v8w1y276zidp97z4wrp64u45ov62" FileName="vero03.jpg" OriginalPath="C:\Users\Cliente\Desktop\vero03.jpg" LastEdit="2022-11-21T16:32:09.9699551+01:00" />
        <StateOfSource xsi:type="SourceState" ID="pc3doh5hrt3f0jhydtfw1rdepz7j6bqc" FileName="vero03.jpg" OriginalPath="C:\Users\Cliente\Desktop\vero03.jpg" LastEdit="2022-11-21T16:34:14.1709718+01:00" />
        <StateOfSource xsi:type="SourceState" ID="wz25gy1m9ovllt06iu7cta3fss7gf74h" FileName="vero04.jpg" OriginalPath="C:\Users\Cliente\Desktop\vero04.jpg" LastEdit="2022-11-21T16:35:56.0513073+01:00" />
        <StateOfSource xsi:type="SourceState" ID="igyddk25mitbckx2m3y7vn4wy16nocnq" FileName="vero02.jpg" OriginalPath="C:\Users\Cliente\Desktop\vero02.jpg" LastEdit="2022-11-21T16:49:48.9090768+01:00" />
        <StateOfSource xsi:type="SourceState" ID="86b7gww5pyswyj7eghfhbffj75jxbqga" FileName="Foresta-Campigna-1920x920-min.jpg" OriginalPath="E:\SITI-WEB\0-giancaforesta\home\Foresta-Campigna-1920x920-min.jpg" LastEdit="2022-11-23T15:56:50.0238031+01:00" />

    Risultato TMemo.Lines.Delete inviatomi dal cliente:

    />
    -min.jpg" LastEdit="2022-11-23T15:56:50.0238031+01:00" />

    Non mi spiego perché su 4 righi di identica lunghezza (201 caratteri), 3 vengono correttamente cancellati e 1 troncato in Pos 199, uno dei motivi perché ho aperto questo post.

    Comunque sia, visto che già immagazzino parte degli attributi Xml in una TStringGrid, ho ora implementato TXmlDocument con versamento di tutti gli attributi nella medesima TStringGrid per poi rigenerare il file Xml dalla TStringGrid, come suggerito da Andrea. Così, come giustamente entrambi dite, i dati Xml vengono gestiti da un componente Xml.

    Inoltre, distribuendo gli attributi di un rigo Xml su 5 colonne della TStringGrid si accorcia la lunghezza della singola String.

    Grazie del vostro feedback!

    Ale

  • Re: TMemo.Lines.Delete max length

    31/05/2024 - al.delphi ha scritto:


    Non mi spiego perché su 4 righi di identica lunghezza (201 caratteri), 3 vengono correttamente cancellati e 1 troncato in Pos 199, uno dei motivi perché ho aperto questo post.

    Credo che l'unica possibilità di individuare cosa accade sia andare in debug del codice che hai scritto e verificare lo stato dell'applicazione nel suo complesso, per capire se è un disguido del controllo visuale oppure di qualcosa che non va nella logica, magari perché ti aspetti una situazione ma in realtà se ne verifica un'altra.

    31/05/2024 - al.delphi ha scritto:


    come giustamente entrambi dite, i dati Xml vengono gestiti da un componente Xml.

    Questa è senz'altro una via imprescindibile: i documenti XML possono contenere entità di caratteri, sezioni CDATA e tante altre peculiarità che - se non gestite nel modo corretto con le apposite classi - rischiano di produrre effetti impredicibili e indesiderati.

    In breve, devi considerare il file XML e il testo che contiene come una mera rappresentazione del documento su cui devi lavorare, una serializzazione in formato testo dei dati che però devi quindi caricare, modificare e risalvare in questo formato alla fine, agendo sul documento, sui suoi nodi, sugli attributi, ecc. invece che sul testo.

Devi accedere o registrarti per scrivere nel forum
11 risposte