Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Búsqueda de archivos ordenada por fecha (https://www.clubdelphi.com/foros/showthread.php?t=69061)

Faust 23-07-2010 17:45:49

Búsqueda de archivos ordenada por fecha
 
Hola compañeros, espero que no hayan tenido mucha bronca por lo de las cervezas que les pasé... les juro que no tenían virus AH1N1 ni HSBC ni CTVS ni nada por el estilo :D :D :D.

Vamos a la duda... tengo una aplicación que lee un directorio con archivos de datos generados por otra aplicación y los procesa, no tenía problema pues eran pocos los archivos así que podía darme el lujo de leer todos los nombres de archivos con su fecha y hora de creación y después ordenarlos para seleccionar los más antiguos y procesarlos de los más antiguos a los más recientes, pero han hecho cambios a la forma en que trabaja el programa que genera los archivos de datos y ahora crea muchísimos archivos de datos que deben ser procesados en el menor tiempo posible, pero mi código tarda muchísimo en leer el directorio completo y después ordenar los nombres de archivo por su fecha de creación, ¿qué me sugieren hacer?

En un principio hacía esto:

Leía los nombres de todos los archivos y su fecha de creación con FindFirst y Findnext, guardándolos en una lista, windows devuelve los nombres de los archivos ordenados alfabéticamente, por lo que debo hacer un proceso para ordenar esta lista por fecha de la menor a la mayor, este proceso es muy rápido si los archivos que hay en el directorio son 100, 200 o incluso 1,000, pero ahora los archivos llegan a ser más de 70,000, incluso ayer eran casi el doble 130,000, por lo que el proceso que les describí anteriormente es muy tardado, he pensado si hay alguna función similar a FindFirst y FindNext pero que devuelva los nombres de los archivos ordenados por fecha de creación o si hay alguna manera de que me devuelva los archivos más viejitos dentro del directorio y asi evitarme el ordenarlos pues ya sería una ayuda...

Bueno, ojalá puedan ayudarme y de antemano les agradezco...

Saludos y buen día :)

manuc 23-07-2010 18:08:41

Hola Faust,

Cuando he tenido que crear procedimientos muy parecidos a lo que comentas, he utilizado ClientsDataset para almacenar en memoria la información de los ficheros y así poder tratarla (ordernarla, locarlizar, comparar, etc).

Un problema que podrías tener al utilizar ClientDataset, como tablas temporales en memoria, es que cuando insertar muchos registros se quedan un poco lentos.

He probado a generar 130.000 registros en memoria y me ha tardado algo menos de un segundo.

En este caso, te diría que podrías utilizar un ClientDataset en memoria para manejar la información de tus ficheros.

Si decides probarlo, Hazle un ".MergeChangeLog", cada 100 insercciones, para que limpie "Basura interna"

Espero que te ayude.

Un saludo.

Faust 23-07-2010 18:17:40

Cita:

Empezado por manuc (Mensaje 371360)
Hola Faust,

Cuando he tenido que crear procedimientos muy parecidos a lo que comentas, he utilizado ClientsDataset para almacenar en memoria la información de los ficheros y así poder tratarla (ordernarla, locarlizar, comparar, etc).

Un problema que podrías tener al utilizar ClientDataset, como tablas temporales en memoria, es que cuando insertar muchos registros se quedan un poco lentos.

He probado a generar 130.000 registros en memoria y me ha tardado algo menos de un segundo.

En este caso, te diría que podrías utilizar un ClientDataset en memoria para manejar la información de tus ficheros.

Si decides probarlo, Hazle un ".MergeChangeLog", cada 100 insercciones, para que limpie "Basura interna"

Espero que te ayude.

Un saludo.


Vaya no sabía que pudiera usarse así un ClientDataSet, creí que solo funcionaban enlazados a bases de datos... perdón por abusar un poco de tu conocimiento, pero podrías poner un ejemplo sobre el uso de él de aunque sea 10 líneas si se puede y aunque no esté relacionado con mi problema...

Gracias :o

Ah, se me olvidaba una pregunta... es necesario instalar el BDE para utilizar el ClientDataSet, es que no quisiera instalarlo donde pongo la aplicación ya que es un servidor

manuc 23-07-2010 18:26:05

Sí, claro. Es muy sencillo.

Agregas un ClientDataset a tu formulario. Le haces doble clic y le agregas los campos que quieras, nombre del fichero, fecha de modificación, etc.

Cada uno con el tipo de dato que te interese y en la propiedad FieldKind, le dejas fkData.

Para inicializarlo:
Código Delphi [-]
ClientDataSet1.CreateDataSet;
ClientDataSet1.Open;

Y a partir de aquí como un Dataset normal que esté conectado a base de datos:

Código Delphi [-]
var
 c:Integer;
 empieza:TDateTime;
begin
empieza := Now;
for c:= 1 to 130000 do
    begin
    if c mod 100 = 0 Then
       ClientDataSet1.MergeChangeLog; //Limpiamos las copias internas que realiza el componente; Para este caso nos sirve de nada y ralentiza una barbaridad. 
    ClientDataSet1.Append;
    ClientDataSet1fichero.AsString := 'fichero '+inttostr(c);
    ClientDataSet1fecha.AsDateTime := Now;
    ClientDataSet1.Post;
    end;
ShowMessage('Ya ' +FormatDateTime('hh:nn:ss:zzz',Now-empieza));

Como ves es muy simple y te da mucha fuerza a la hora de manejar la información.

Si necesitas algo más o tienes alguna duda, coméntame sin problemas.

Un saludo.

Faust 23-07-2010 18:47:41

Muchas gracias, ya estoy trabajando en eso y la verdad es muy rápido, hasta es posible verlo en un DBGrid

Sabes si es necesario instalar el BDE o alguna librería en especial para usar ClientDataSet, DataSource y DBGrid, no quisiera instalarlos, pues esta aplicación debe correr en un servidor.

Muchísimas gracias y aquí estaré molestándote :)...

Ah de paso te invito una cerveza, estas ya no te alertan con el antivirus...


manuc 23-07-2010 18:55:51

jeje, gracias por las cervezas, te las acepto, que aquí, ahora, hace mucha calor!!

Pues no tendrías que instalar nada. Simplemente añade a tus uses la unidad "MidasLib" y ya está.

Ciertamente lo puedes conectar a un dbGrid, pero ten en cuenta una cosa: si el Grid está activo las inserciones irán más lentas. Para evitar este problema, cuando vayas a insertar registros en el clientDataset hazle esto:
Código Delphi [-]
ClientDataset1.DisbleControls;
y cuando termines habilitalo de nuevo así.
Código Delphi [-]
ClientDataset1.EnableControls;

Un saludo.
:)

Faust 23-07-2010 19:16:21

Oh si, eso ya lo he notado, pero al ejecutar me voy a ver los módulos que ocupa mi aplicación y veo que usa midas.dll... ojalá no sea problema y pueda copiarla y usarla sin pormenores.

gracias.

manuc 23-07-2010 19:20:47

Si te refieres al fichero Midas.dll, si incluyes la unidad MidasLib, en los uses (del primer formulario que se cargue) no necesitarás copiar la librería, se embebe en el propio ejecutable.

Saludos.

Faust 23-07-2010 23:46:38

Aquí estoy de nuevo con otra duda... ya puedo usarlo, es muy rápido, pero como le hago para usarlo por segunda vez, simplemente ejecutando ClientDataSet1.Close y volviéndolo a llenar???

Desde ya muchas gracias.

manuc 24-07-2010 09:14:01

Al cerrar y abrirlo: ¿Se te quedan los registros cargados en memoria?

Imagino que sí. Cosas del ClientDataset. Prueba ha hacer esto:

Código Delphi [-]
ClientDataSet1.Close;
ClientDataSet1.ProviderName := '-';
ClientDataSet1.ProviderName := '';
ClientDataSet1.CreateDataSet;
ClientDataSet1.Open;

El ClientDataset lleva una variable interna denominada Data, donde guarda todos los registros que vas cargando en memoria.

Al cambiar la propiedad PoviderName (o RemoteServer) internamente detecta que la información de Data puede haber cambiado y resetea la variable, perdiendo la estructura de datos y los propios datos (al hacer el .close, claro).

De esta forma, lo engañamos y podemos resetear el ClientDataset, para volver a cargarlo de nuevo.

Un saludo.

Faust 26-07-2010 16:43:21

Cita:

Empezado por manuc (Mensaje 371452)
Al cerrar y abrirlo: ¿Se te quedan los registros cargados en memoria?

Imagino que sí. Cosas del ClientDataset. Prueba ha hacer esto:

Código Delphi [-]ClientDataSet1.Close; ClientDataSet1.ProviderName := '-'; ClientDataSet1.ProviderName := ''; ClientDataSet1.CreateDataSet; ClientDataSet1.Open;


El ClientDataset lleva una variable interna denominada Data, donde guarda todos los registros que vas cargando en memoria.

Al cambiar la propiedad PoviderName (o RemoteServer) internamente detecta que la información de Data puede haber cambiado y resetea la variable, perdiendo la estructura de datos y los propios datos (al hacer el .close, claro).

De esta forma, lo engañamos y podemos resetear el ClientDataset, para volver a cargarlo de nuevo.

Un saludo.


Sale... muy buena solución, muchas gracias de nuevo amigo.


La franja horaria es GMT +2. Ahora son las 08:33:46.

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