Italian community of Lazarus and Free Pascal

Programmazione => Databases => Topic aperto da: sergio - Luglio 25, 2012, 12:12:49 am

Titolo: estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 25, 2012, 12:12:49 am
Saluti a tutti , ho un problemino che mi sta assillando ! Devo estrarre dei dati da un file di testo che hanno come separatore (|). Alla fine della riga ci sono 3 separatori. Sono dati che non hanno sempre la stessa lunghezza , quindi io dovrei fare contare i separatori. Vi faccio un esempio ; 20|1010100|prova|12,10||| ; Dovrei poi inserirli in un database (Mysql o di qualsiasi altro tipo, anche DB).Potete darmi una dritta ? Vi ringrazio .  :) :-[
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: Maverich - Luglio 25, 2012, 08:25:40 am
sOrigine := '20|1010100|prova|12,10||| ';

dovresti immagazzinare la stringa senza i separatori
sOrigine, sDestinazione: String;
i: integer;

potresti usare StringReplace per sostituire ! con spazio
Codice: [Seleziona]
 sDestinazione  := StringReplace(sOrigine, ' ! ', '  ', [rfReplaceAll, rfIgnoreCase]);
oppure fare un ciclo per eliminare un separatore alla volta,
una volta che hai le stringe senza separatori, non ci saranno problemi per inserirle in un db.
qualcosa di simile
Codice: [Seleziona]
 i := Pos( '!', sOrigine,)
 if i > 0 then
 begin
  sDestinazione := Copy(sOrigine, 1, i-1);
  sOrigine := Copy(sOrigine, 1 , i-1);
 end;
oppure cercare gli ultimi 3 sapratori
Codice: [Seleziona]
 i := Pos( '!!!', sOrigine,)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: xinyiman - Luglio 25, 2012, 08:52:16 am
Guarda questo spezzone di codice, è un esempio di come affronto io il problema in questione!



var
   appfile: TStringList;
begin


appfile:=TStringList.Create();

     appfile.LoadFromFile(FileDati);
     appFile.SaveToFile(FileControllo);
     for i:=0 to AppFile.Count-1 do
     begin
          MyQuery.SQL.Text:='';
          MyQuery.SQL.Add('INSERT INTO T_Dati(Articolo,CodSerie,DescSerie,Img,DataCons,TitoloRep)VALUES("' + StringReplace(EstrapolaValoreNumero(appFile.Strings,0),'''','''''', [rfReplaceAll]) + '","' + StringReplace(EstrapolaValoreNumero(appFile.Strings,1),'''','''''', [rfReplaceAll]) + '","' + StringReplace(EstrapolaValoreNumero(appFile.Strings,2),'''','''''', [rfReplaceAll]) + '","' + StringReplace(EstrapolaValoreNumero(appFile.Strings,3),'''','''''', [rfReplaceAll]) + '","' + StringReplace(EstrapolaValoreNumero(appFile.Strings,4),'''','''''', [rfReplaceAll]) + '","' + StringReplace(TitoloRep,'''','''''', [rfReplaceAll]) + '");');
          MyQuery.ExecSQL;
     end;
     appfile.Free;
end;


function TForm1.EstrapolaValoreNumero(stringa: string; pos: integer): string;
var
   MiaStringa: TStringList;
   ret: string;
begin
     ret:='';
     MiaStringa := TStringList.Create;
     MiaStringa.Delimiter := '|';
     MiaStringa.QuoteChar := '';
     MiaStringa.DelimitedText := stringa;

     if ((pos>=0) AND (pos<MiaStringa.Count)) then
     begin
          ret:=MiaStringa[pos];
     end;
     MiaStringa.Free;
     EstrapolaValoreNumero:=ret;
end;



Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 25, 2012, 03:25:56 pm
Grazie , ci provo e poi ti dico , penso che la soluzione di xinyiman
 vada meglio . Grazie Mille , per ora !!!! :) ;)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: nomorelogic - Luglio 25, 2012, 03:44:20 pm
io sono più pigro...

farei una StrToStrings indicando '|' come separatore per avere in una TStringList d'appoggio tutti i campi già separati su ogni riga
poi hai:
campo1 = lista[0]
campo2 = lista[1]
campo3 = lista[2]
campo4 = lista[3]

il tutto dentro un loop che fa la scansione di tutte le righe del file di testo
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 25, 2012, 04:25:34 pm
Scusa Nomore , come intendi ? Mi puoi fare un esempio , non ho capito!!! :-[
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: nomorelogic - Luglio 25, 2012, 05:55:07 pm
qualcosa del genere:

Codice: [Seleziona]
var
   slSrc, slFields: TStringList;
   scan: integer;
   SQL: string;
begin
   slSrc := TStringList.Create;
   slFields := TStringList.Create;
   try
      slSrc.LoadFromFile('...filename...');
      for scan := 0 to slSrc.Count - 1 do
         begin
            slFields.Clear;
            StrToStrings(slSrc[scan], '|', slFields, False);
            SQL := Format('INSERT INTO TABLE (CAMPO1, CAMPO2, CAMPO3, CAMPO4) VALUES (''%s'', ''%s'', ''%s'', ''%s'');',
                                     [ slFields[0], slFields[1], slFields[2], slFields[3] ]);
         end;
   finally
      slFields.Free;
      slSrc.Free;
   end;

end;


il problema è che StrToStrings la trovi nelle jedi (JCL per l'esattezza, unit JclStrings)... e emh... sembra che usarle in fpc non sia così immediato :(
però ho trovato una implementazione che secondo me si adatta facilmente e se ci perdi tempo (pochissimo, ad occhio per compilarla non ci vorrà molto) hai una ottima funzione che riuserai sicuramente...


Codice: [Seleziona]
procedure StrToStrings(const S, Sep: String; const List: TStringList; const AllowBlank: Boolean);
var
  I, J, L, M: Integer;
  Left: String;
begin
  if List <> nil then
    List.Clear;

  if (List = nil) or (S = '') or (Sep = '') then
    Exit;

  L := Length(Sep);
  M := Length(S);
  I := 1;
  J := PosEx(Sep, S, 1);
  while (J > 0) do begin
    Left := Copy(S, I, J - I);
    if (Left <> '') or AllowBlank then
      List.Add(Left);
    I := J + L;
    J := PosEx(Sep, S, I);
  end;
  if I < M then begin
    Left := Copy(S, I, M - (I - 1));
    if (Left <> '') or AllowBlank then
      List.Add(Left);
  end;
end;


Edit:
come sento la mancanza delle jedi...
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: bonmario - Luglio 25, 2012, 06:34:27 pm
Ciao,
se non ricordo male:

Codice: [Seleziona]
var
obje: TStringList;
begin
  obje := TStringList.Create;
  obje.Delimiter := '|';
  obje.DelimitedText := '20|1010100|prova|12,10|||';

  Arrivati qui:
  obje[0] sarà = a 20
  obje[1] sarà = a 1010100
  e così via
end;

Ciao, Mario
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 25, 2012, 06:39:34 pm
Grazie a tutti , questa sera ci provo e vedo cosa esce . grazie a tutti !!!!!! :D
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: Stilgar - Luglio 26, 2012, 01:08:43 am
Provare questo?
http://wiki.freepascal.org/CsvDocument#Download (http://wiki.freepascal.org/CsvDocument#Download)
E modificare il separatore di campo da "," o ";" e metterlo "|"?
Nessuno si è accordo che è un CSV come formato? ( ;D )

EDIT:
Bonmario è andato su una soluzione rapida :D
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: Stilgar - Luglio 26, 2012, 01:12:14 am
Interessante anche questo http://wiki.freepascal.org/CSV#CSV_and_SDF
Verso la fine dice che c'è già tutto pronto ... o quasi ;)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 26, 2012, 01:00:04 pm
Grazie Stilgar , questa sera ci provo , visto che il metodo proposto da xinyiman
mi da un errore nella valutazione dei dati '' StringReplace(EstrapolaValoreNumero(appFile.Strings,0)'' . Ma devo rinominare in '.csv il file ?
 :)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: Stilgar - Luglio 26, 2012, 01:34:48 pm
Non lo so.
So solo che gli articoli che ti ho indicato possono aiutarti a risolvere il problema.
;)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 26, 2012, 06:58:42 pm
Grazie  :D
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 27, 2012, 11:35:03 am
Scusate , il componente CSV mi richiede la LCL 1.0.1 . Sapete dove posso trovarla ? Grazie  :-[
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 27, 2012, 12:16:44 pm
Xinyman, la  '''StringReplace(EstrapolaValoreNumero(appFile.Strings,0),'''','''''', [rfReplaceAll]) '''' mi da un errore di dato . !  :-[
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: xinyiman - Luglio 27, 2012, 12:34:59 pm
Prova a stampare quei dati senza la stringreplace. Dimmi cosa ti ritorna! Oppure metti dei brackpoint all'interno della funzione e dimmi il punto esatto in cui va in errore!
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 27, 2012, 12:51:02 pm
OK , ci provo ! Sai comunque dove si puo' trovare la LCL 1.0.1?  Grazie
 :)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: xinyiman - Luglio 27, 2012, 01:22:14 pm
Sinceramente no, perchè non mi è ancora servita!
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: nomorelogic - Luglio 28, 2012, 10:37:36 am
OK , ci provo ! Sai comunque dove si puo' trovare la LCL 1.0.1?  Grazie
 :)

LCL dipende dal compilatore free pascal e difficilmente la potrai installare in quanto la LCL 1.0.1 credo di ricordare che sia nella trunk (versione in fase di sviluppo per la quale non esiste un installer).

Se non ho detto una castroneria :D e vuoi provare la trunk hai due strade:
1) http://wiki.freepascal.org/Getting_Lazarus (http://wiki.freepascal.org/Getting_Lazarus)
2) http://www.lazarus.freepascal.org/index.php/topic,15919.0.html (http://www.lazarus.freepascal.org/index.php/topic,15919.0.html)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: bonmario - Luglio 28, 2012, 12:26:37 pm
Confermo: io mi aggiorno tramite SVN ed ho la LCL 1.0.1

Ciao, Mario
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: sergio - Luglio 31, 2012, 10:38:20 pm
Grazie ragazzi , ci provo !!!! il package CSV funziona solo con la 1.0.1 . Per ora grazie , poi vi faccio sapere !! ;)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: brunello - Agosto 02, 2012, 05:03:00 pm
fedele alla filosofia del pane e salame ho queste due funzioni che adopero da delphi 2 e non mi hanno mai dato problemi
la prima serve per sapere il numero dei separatori presenti all'interno della stringa
mentre la seconda per estrarre la n. sottostringa dalla stessa usale così eviti versioni di più o meno aggiornate repositary e amenità varie, ciao Brunello

function StrTokenCount(S: String; Seperator: Char): Integer;
var i: integer;
begin
  Result := 0;
  for i := 1 to Length(s) do
    if s = Seperator then Inc(Result);
end;

function StrTokenAt(const S:String; Seperator: Char; At: Integer): String;
var
  j, i: Integer;
begin
  Result := '';
  j := 1;
  i := 1;
  while (i <= At ) and (j <= Length(S)) do
    begin
      if S[j] = Seperator then
        Inc(i)
      else
        if i = At then Result := Result + S[j];
      Inc(j);
    end;
end;       
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: Stilgar - Agosto 03, 2012, 03:03:33 pm
Le hai modificate al volo o il forum le ha modificate?
Codice: [Seleziona]
function StrTokenCount(S: String; Seperator: Char): Integer;
var i: integer;
begin
  Result := 0;
  for i := 1 to Length(s) do
    if s[i] = Seperator then Inc(Result);
end;
Mai pensato di usare i puntatori? Sono un pelino più veloci ;)
Codice: [Seleziona]
var
  c : PChar;
begin
   Result := 0;
  C := PChar(S);
   while C^ <> #0 do
  begin
     if C^=separator then inc(result);
    inc(C);
  end;
end;
 
il codice l'ho modificato al volo ;)
Titolo: Re:estrarre dati da file.txt per inserirli in un db
Inserito da: Stilgar - Agosto 03, 2012, 03:10:36 pm
Codice: [Seleziona]
function StrTokenAt(const S:String; Seperator: Char; At: Integer): String;
var
  C, Start : PChar;
begin
  Result := '';
  C := PChar(S);
  Start := C;
  inc (C, at);
  if (C-Start) > Length(S) then 
    // controllo di non essere uscito dai margini della memoria assegnata.
    raise Exception.Create('indici mauchi'); // <- Magari un messaggio più serio
  Start := C;
  while (C^ <> #0) and (C^<>Separator) do
    begin
      inc(C);
    end;
  SetString(Result, Start, C-Start);
end;