Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   OOP (https://www.clubdelphi.com/foros/forumdisplay.php?f=5)
-   -   Ayuda otra vez!! (https://www.clubdelphi.com/foros/showthread.php?t=74711)

pelikno 06-07-2011 19:19:31

Ayuda otra vez!!
 
Disculpen pero despues de lograr leer los datos de un txt me encuentro con el problema q el txt tiene mas de 3000000 de lineas !!!! o sea cada vez que cargo en un dbgrid el sistemita se me cuelga.
Queria saber si alguien sabe alguna componente para cargar tantas lineas y mostrarlas en una grilla.
lo que tengo es un RxMemoryData donde cargo las lineas que levanto del txt.
tengo un Datasouce conectado con un dbgrid el cual muestra lo que cargue en el RxMemoryData.
Gracias!!!

oscarac 06-07-2011 19:47:08

has probado usar ClientDataset ?

Casimiro Noteví 06-07-2011 20:20:03

Por favor, recuerda poner títulos descriptivos a tus preguntas, "ayuda otra vez!!" no es ningún título descriptivo. No olvides leer nuestra guía de estilo. Gracias.

Cita:

Empezado por pelikno (Mensaje 405651)
Disculpen pero despues de lograr leer los datos de un txt me encuentro con el problema q el txt tiene mas de 3000000 de lineas !!!! o sea cada vez que cargo en un dbgrid el sistemita se me cuelga.
Queria saber si alguien sabe alguna componente para cargar tantas lineas y mostrarlas en una grilla.
lo que tengo es un RxMemoryData donde cargo las lineas que levanto del txt.
tengo un Datasouce conectado con un dbgrid el cual muestra lo que cargue en el RxMemoryData.
Gracias!!!

El problema que tienes será por la memoria, 3.000.000 de registros son muchos registros para meterlo en memoria, ¿necesitas todos esos registros en memoria?.
Yo uso rxmemorydata y kbmmemtable con muchos registros, pero nunca se me ocurriría cargar en memoria tantos registros. Bueno, mentira, sí lo hago en algunas ocasiones, pero con muy, muy, muy pocos campos.
No es lo mismo tres millones de registros con una tabla de un campo... que 3 millones de registros con una tabla de 20 campos.

wal_laplata 06-07-2011 20:43:20

Hola Casimiro, soy compañero de Pelikno y te agradezco la respuesta. El tema es que son mas de 5 millones de registros (lista de proveedores de la AFIP en todo el pais) y cada registro contiene 6 campos (cuit como principal y mas extenso, y el resto de los campos son estados de 2 o 1 caracter cada uno)

ejemplo :

cuit ganancia iva sociedad monotributo empleador
20201215749 NI NI NI N N

el tema que acortamos el archivo a 1000000 y tambien se re cuelga.

la idea es levantar los datos que estan en un texto plano y pasarlo a SQL, para poder de esa forma, realizar la actualizacion de los estados de los proveedores que posee el sistema con los de la AFIP. Aclaro que el sistema trabaja con base de datos SQL, por eso queremos unificar todo.
Porque un proveedor puede cambiar su situacion frente a la AFIP, pasar de monotributista a responsable inscripto, por ejemplo

pelikno 06-07-2011 20:59:59

Cita:

Empezado por Casimiro Notevi (Mensaje 405660)
Por favor, recuerda poner títulos descriptivos a tus preguntas, "ayuda otra vez!!" no es ningún título descriptivo. No olvides leer nuestra guía de estilo. Gracias.



El problema que tienes será por la memoria, 3.000.000 de registros son muchos registros para meterlo en memoria, ¿necesitas todos esos registros en memoria?.
Yo uso rxmemorydata y kbmmemtable con muchos registros, pero nunca se me ocurriría cargar en memoria tantos registros. Bueno, mentira, sí lo hago en algunas ocasiones, pero con muy, muy, muy pocos campos.
No es lo mismo tres millones de registros con una tabla de un campo... que 3 millones de registros con una tabla de 20 campos.

Si Solamente tiene 5 campos el tema q es la informacion que tengo que usar para mantener la base sqlserver que tengo nada mas que en mi base tengo muchisimos menos, es una tabla de proveedores y la tengo que actualizar con ese archivo.txt de 85 Mb !!!! el tema es que me mandan todos los proveedores en el txt yo solo tengo que actualizar diariamente los que tenga en mi base.

pelikno 06-07-2011 21:01:57

Cita:

Empezado por oscarac (Mensaje 405655)
has probado usar ClientDataset ?


No que diferencia tiene?? no la he usado.

Casimiro Noteví 06-07-2011 21:07:53

De todas formas si no pones el código fuente que lo veamos, no nos dice si sale algún error ni cual es, etc...

wal_laplata 06-07-2011 21:20:35

Código Delphi [-]
begin
  AssignFile(myFile, 'C:\Temp\SELE-SAL-CONSTA.tmp');
  i:=0;
  FileMode := fmOpenRead;
  Reset(myFile);
  Memory.Active:=true;
  while not Eof(myFile) do
  begin
    text:='';
    while length(text) < 21 do
    begin
      Read(myFile, letter) ;   // Read and display one letter at a time
      text:=text + letter ;
    end;
    Read(myFile, letter);
    Memory.Append;
    Memorycuil.Value :=copy(text,1,2)+'-'+copy(text,3,8)+'-'+copy(text,11,1);
    Memoryganancias.Value:=copy(text,12,2);
    Memoryiva.Value:=copy(text,14,2);
    Memorymonotibuto.Value:= copy(text,16,2);
    MemoryintegranteSo.Value:= copy(text,18,1);
    Memoryempleador.Value:=copy(text,19,1);
    MemoryactividadMono.Value:=copy(text,20,2);
    Memory.Post;
    i:=i+1;
    Label1.Caption:=inttostr(i);
  end;
end;

ecfisa 06-07-2011 21:44:12

Hola wal_laplata.

Por favor cuando pongas código Delphi encerralo entre las etiquetas [delphi] codigo [/delphi] para una mejor legibilidad.

Una pregunta: ¿ Cual es la longitud exácta que ocupa cada registro en el formato texto ?
Es decir en referencia a lo dicho más arriba:
Cita:

20201215749 NI NI NI N N
¿ Los últimos campos tienen longitud fija de dos caracteres, de uno ... ? ¿ Tienen algún separador ?



Saludos.

pelikno 07-07-2011 13:34:41

Este es el Formato
 
Cita:

Empezado por ecfisa (Mensaje 405672)
Hola wal_laplata.

Por favor cuando pongas código Delphi encerralo entre las etiquetas [delphi] codigo [/delphi] para una mejor legibilidad.

Una pregunta: ¿ Cual es la longitud exácta que ocupa cada registro en el formato texto ?
Es decir en referencia a lo dicho más arriba:

¿ Los últimos campos tienen longitud fija de dos caracteres, de uno ... ? ¿ Tienen algún separador ?



Saludos.


Casimiro Noteví 07-07-2011 13:48:59

Entonces cuento 21 caracteres más cr+lf = 23 por línea.
Si son 5 millones de registros hacen: 115.000.000 bytes= 109 MB.
No es que sea algo muy abrumador, aunque me pregunto por qué lo cargas en memoria, ¿por qué no usas una tabla para ello?.

maeyanes 07-07-2011 15:53:55

Otra cosa que podrías hacer es ir leyendo los datos en bloques, o sea, lees primero unas 1,000 líneas (o 10,000) y las procesas, luego lees otro bloque de n líneas y lo procesas y así hasta finalizar...


Saludos...

pelikno 07-07-2011 19:04:28

Cita:

Empezado por Casimiro Notevi (Mensaje 405714)
Entonces cuento 21 caracteres más cr+lf = 23 por línea.
Si son 5 millones de registros hacen: 115.000.000 bytes= 109 MB.
No es que sea algo muy abrumador, aunque me pregunto por qué lo cargas en memoria, ¿por qué no usas una tabla para ello?.

El Archivo es de 85 mgb, por lo de la memoria vos decis que lo cargue en un ttable?

pelikno 07-07-2011 19:10:25

Código Delphi [-]
procedure TForm1.Button2Click(Sender: TObject);

var
  Fichero: File of byte;
  Buffer: array[0..21] of Char; // 22 bytes + 1
  Leidos: Integer;
  Str: string;
  b:byte;
  i:integer;
begin
i:=0;
  AssignFile(Fichero,'C:\Temp\SELE-SAL-CONSTA.tmp');
  Filemode:= fmOpenRead;
   Memory.Active:=true;
  {$I-}
    Reset(Fichero);// Reset(Fichero,1);
  {$I+}
  Timer1.Enabled:= true;
  if IOResult = 0 then
  begin

    while not  eof(Fichero) do
    begin
      FillChar(Buffer,Sizeof(Buffer),0);
      BlockRead(Fichero,Buffer,Sizeof(Buffer)-1,Leidos);
      read(fichero,b);
      if Leidos > 0 then
      begin
        Str:= String(PChar(@Buffer));
         i:=i+1;
         Label1.Caption:=inttostr(i);
        CargarGrilla(Str);
      end;
    end;
    Timer1.Enabled:=false;
    CloseFile(Fichero);
  end else
    ShowMessage('No puedo abrir el archivo');
end;

este es el codigo, el tema que tego que actualizar mi base con este txt, como me recomiendan que la cargue o donde, my base es sqlserver.
Gracias!!

maeyanes 07-07-2011 19:33:23

Hola...

¿Es necesario que cargues la información en un grid?


Saludos...

pelikno 07-07-2011 20:32:15

Cita:

Empezado por maeyanes (Mensaje 405778)
Hola...

¿Es necesario que cargues la información en un grid?


Saludos...

No no solamente la ponia para ver como armaba el contenido ... y supongo que eso es lo que me tilda todo el sistema.

ecfisa 07-07-2011 22:35:31

Hola pelikno.

En el código que adjuntas (#14), para recorrer 100000 registros realiza 100000 ciclos de lectura, que es muchisimo mejor que el primer código que leia caracter a caracter(#8), ya que en ese caso eran 100000 x 22 lecturas. Pero creo que se puede optimizar mucho más el código de lectura en bloque.

No tengo acceso a los datos y puede que tengas que cambiar la cantidad de caracteres por registro o algún detalle que se me escape por no tener el archivo origen o el formato requerido.
Código Delphi [-]
...
const
  NCHAR = 22;
  LEER_X = 20000 ;
  TOT_BUFFER = LEER_X * NCHAR;

procedure TForm1.btnACDSClick(Sender: TObject);
var
  F: file of Char;
  Buf: array[1..TOT_BUFFER] of Char;
  c, rl: Integer;
  T1,T2: TTime;
  Ciclos: Integer;
begin
  AssignFile(F, 'C:\Archivo.txt');
  try
    Reset(file(F), 1);
    ClientDataSet.CreateDataSet;
    ClientDataSet.Open;
    ClientDataSet.DisableControls;
    T1:= Time;
    Ciclos:= 1;
    repeat
      BlockRead(file(F), Buf, SizeOf(Buf), rl);
      c:= 0;
      while c < TOT_BUFFER do
      begin
        if c mod 100 = 0 Then 
          ClientDataSet.MergeChangeLog;
        ClientDataSet.Append;
        ClientDataSetCuit.AsString:= Buf[c+1]+Buf[c+2]+Buf[c+3]+
            Buf[c+4]+Buf[c+5]+Buf[c+6]+Buf[c+7]+Buf[c+8]+Buf[c+9]+
            Buf[c+10]+Buf[c+11];
        ClientDataSetD1.AsString:= Buf[c+12]+Buf[c+13];
        ClientDataSetD2.AsString:= Buf[c+14]+Buf[c+15];
        ClientDataSetD3.AsString:= Buf[c+16]+Buf[c+17];
        ClientDataSetD4.AsString:= Buf[c+18];
        ClientDataSetD5.AsString:= Buf[c+19];
        Inc(c, NCHAR);
        ClientDataSet.Post;
      end;
      Inc(Ciclos);
    until rl = 0;
    CloseFile(F);
    T2:= Time;
    Caption:= FormatDateTime('hh:mm:ss:dd',T2-T1)+'  realizando '+IntToStr(Ciclos)+' ciclos.';
    ClientDataSet.EnableControls;
  except
    ShowMessage('Archivo inexistente');
  end;
end;
En este caso, con 100000 registros sólo realiza 7 ciclos en 00:00:05:30 (en mi equipo).

Como no tengo ni conozco el RxMemoryData, usé un TClientDataSet para la prueba. Lo único que tenés que hacer es crear los campos persistentes en él respetando los nombres y el código debería funcionarte.
Cualquier dificultad te adjunto el ejemplo con el generador de datos.

Saludos.

pelikno 08-07-2011 01:42:34

Cita:

Empezado por ecfisa (Mensaje 405797)
Hola pelikno.

En el código que adjuntas (#14), para recorrer 100000 registros realiza 100000 ciclos de lectura, que es muchisimo mejor que el primer código que leia caracter a caracter(#8), ya que en ese caso eran 100000 x 22 lecturas. Pero creo que se puede optimizar mucho más el código de lectura en bloque.

No tengo acceso a los datos y puede que tengas que cambiar la cantidad de caracteres por registro o algún detalle que se me escape por no tener el archivo origen o el formato requerido.
Código Delphi [-]... const NCHAR = 22; LEER_X = 20000 ; TOT_BUFFER = LEER_X * NCHAR; procedure TForm1.btnACDSClick(Sender: TObject); var F: file of Char; Buf: array[1..TOT_BUFFER] of Char; c, rl: Integer; T1,T2: TTime; Ciclos: Integer; begin AssignFile(F, 'C:\Archivo.txt'); try Reset(file(F), 1); ClientDataSet.CreateDataSet; ClientDataSet.Open; ClientDataSet.DisableControls; T1:= Time; Ciclos:= 1; repeat BlockRead(file(F), Buf, SizeOf(Buf), rl); c:= 0; while c < TOT_BUFFER do begin if c mod 100 = 0 Then ClientDataSet.MergeChangeLog; ClientDataSet.Append; ClientDataSetCuit.AsString:= Buf[c+1]+Buf[c+2]+Buf[c+3]+ Buf[c+4]+Buf[c+5]+Buf[c+6]+Buf[c+7]+Buf[c+8]+Buf[c+9]+ Buf[c+10]+Buf[c+11]; ClientDataSetD1.AsString:= Buf[c+12]+Buf[c+13]; ClientDataSetD2.AsString:= Buf[c+14]+Buf[c+15]; ClientDataSetD3.AsString:= Buf[c+16]+Buf[c+17]; ClientDataSetD4.AsString:= Buf[c+18]; ClientDataSetD5.AsString:= Buf[c+19]; Inc(c, NCHAR); ClientDataSet.Post; end; Inc(Ciclos); until rl = 0; CloseFile(F); T2:= Time; Caption:= FormatDateTime('hh:mm:ss:dd',T2-T1)+' realizando '+IntToStr(Ciclos)+' ciclos.'; ClientDataSet.EnableControls; except ShowMessage('Archivo inexistente'); end; end;

En este caso, con 100000 registros sólo realiza 7 ciclos en 00:00:05:30 (en mi equipo).

Como no tengo ni conozco el RxMemoryData, usé un TClientDataSet para la prueba. Lo único que tenés que hacer es crear los campos persistentes en él respetando los nombres y el código debería funcionarte.
Cualquier dificultad te adjunto el ejemplo con el generador de datos.

Saludos.

Muchas Graciasecfisa por tomarte el tiempo de hacer el codigo mañana lo pruebo y veo que pasa.
SALUDOS!!!


La franja horaria es GMT +2. Ahora son las 05:19:15.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi