Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: bonmario - Dicembre 14, 2018, 04:33:26 pm

Titolo: Gestione files di testo con codifiche differenti
Inserito da: bonmario - Dicembre 14, 2018, 04:33:26 pm
Ciao a tutti,
a breve dovrò fare un programma che:
- cerca all'interno di più files di testo una parola
- ogni volta che la trova, la sostituisce con un'altra parola

Da notare che:
- Sia la parola "vecchia" che quella "nuova", sono composte da caratteri che vanno dalla "A" alla "Z", quindi nessun carattere "speciale".
- Le parole che devo sostituire non hanno caratteri speciali, ma nel resto di ogni file, ci possono anche essere lettere accentate o altri caratteri speciali.

La difficoltà deriva dal fatto che, seppure tutti i files siano di testo, questi vengono "scritti" da persone che lavorano su PC diversi, con codifiche diverse. Alcuni files arrivano in formato UTF8, altri  ANSI, e via dicendo.

Avevo pensato di leggere i files come stream, portando il contenuto in una stringa, e poi riscriverlo sempre come stream, ma ho paura che così facendo mi cambi comunque la codifica, visto che userei una stringa come appoggio per poi fare uno StringReplace.

Qualcuno ha qualche consiglio?

Grazie in anticipo, Mario
Titolo: Re:Gestione files di testo con codifiche differenti
Inserito da: nomorelogic - Dicembre 14, 2018, 07:54:10 pm
Qualcuno ha qualche consiglio?

utilizza sed!  :D
non so se ci sia per Win, forse nel progetto cygwin ma il programma che ti serve è già scritto ;)

https://www.linuxtechi.com/20-sed-command-examples-linux-users/ (https://www.linuxtechi.com/20-sed-command-examples-linux-users/)
Titolo: Re:Gestione files di testo con codifiche differenti
Inserito da: nomorelogic - Dicembre 15, 2018, 01:10:15 am
scherzi a parte,
quello che mi viene in mente ora è di ereditare da TFileStream ed implementare un 2 nuovi metodi tipo ReadDelimited e ReadDelimiters

ReadDelimited  dovrebbe funzionare leggendo un byte alla volta (ReadByte) fino al raggiungimento di un delimitatore, tipo ExtractDelimited
https://www.freepascal.org/docs-html/rtl/strutils/extractdelimited.html (https://www.freepascal.org/docs-html/rtl/strutils/extractdelimited.html)

ReadDelimiters dovrebbe invece leggere in un buffer stringa tutti i delimitatori

in questo modo la sostituzione potrebbe avvenire con del codice tipo:

Codice: [Seleziona]
var filein, fileout: TMyFileStream; // la tua classe
    letti:integer;
    s: string;
begin
   filein:=TMyFileStream.Create(...., read);   
   fileout:=TMyFileStream.Create(...., write);
   repeat
      letti:=filein.ReadDelimited(s, [' ', #10, #13, ','];
      if letti >0 then begin
         // sostituzione
         if s='hello' then s:= 'ciao';
        // scrittura
        fileout.WriteBuffer(s[1], length(s));
     end;
     // ora leggiamo i delimitatori
     letti:=filein.ReadDelimiters(s, [' ', #10, #13, ','];
     if letti>0 then
        fileout.WriteBuffer(s[1], length(s));

   until letti=0; 
end


Edit:
in questo modo occupi pochissima memoria anche processando file di grandi dimensioni
Titolo: Re:Gestione files di testo con codifiche differenti
Inserito da: bonmario - Dicembre 15, 2018, 09:34:27 am
Ok, grazie, appena parto col progetto, ci provo.
Fortunatamente i files sono sì tanti, ma sono piccoli, credo che nessuno passi i 5 mega ...

Grazie, Mario