Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 12-04-2006
Avatar de halcon_rojo
halcon_rojo halcon_rojo is offline
Miembro
 
Registrado: abr 2006
Posts: 14
Poder: 0
halcon_rojo Va por buen camino
Post Cual la capacidad de un TStringList?

Hola a todos mi duda es si el TStringList tiene alguna limitacion en cuanto al tamaño (o numero de lineas) del archivo con el que trabaja. Mi problema es que tengo una rutina que carga datos desde un archivo de texto a una tabla DBF y hasta ahora el archivo de texto no pasaba los 1.3 MB (como 29mil registros que tarda mas de 10 min) asi que mi rutina funciona bien, pero se presento que el archivo que necesito cargar es de aprox. 6MB con algo mas de 80mil registros. Mi rutina a parte de que tarda un monton, se corta a medias y no se por que.
este es mi codigo (algo resumido):
Código Delphi [-]
begin
  Archivo:= TStringList.Create;
  Linea:= TStringList.Create;
  linea.Te
  try
    Linea.Delimiter:= chr(124); // Caracter pipe
    Linea.QuoteChar:= ' ';
    Archivo.LoadFromFile(filetxt);
    progressbar1.Min := 0;
    progressbar1.Max := Archivo.Count - 2;
    for i:= 0 to Archivo.Count - 1 do
    begin
      // uso lo siguiente para capturar sin problemas datos con espacios en blanco        
      Linea.DelimitedText:= StringReplace(Archivo[i],chr(32),'(_)',[rfReplaceAll]);
           with datamodule1.datos do
           begin 
                    compras.Append;
                    compras.edit;
                    comprasNIT.AsString      := Linea[1];
                    comprasRSOCIAL.AsString  := StringReplace(Linea[2],'(_)',chr(32),[rfReplaceAll]);
                    comprasNFACTURA.AsString := Linea[3];
                    // etc....
                    compras.Post;
            end; // with
        if i <= progressbar1.Max then progressbar1.Position := i;
        Application.ProcessMessages;
    end; //for
  finally
    Archivo.Free;
    Linea.Free;
 end;
se puede hacer esto de otra manera cosa que acepte archivos de texto bastante grandes y que el proceso no tarde mucho?
Responder Con Cita
  #2  
Antiguo 12-04-2006
Avatar de halcon_rojo
halcon_rojo halcon_rojo is offline
Miembro
 
Registrado: abr 2006
Posts: 14
Poder: 0
halcon_rojo Va por buen camino
Cool para quien le entienda

>Hello,
>>Someone knows the exact limits of TStringList.LoadFromFile ?
>>- file size ?
>- max lines ?
>- ctrl_Z in file ?
>>(I know it stops on nulls).

I don't think there should be specific filesize or maxline limits other
than those that are imposed by the
process. LoadFromFile calls LoadFromStream which calls Read which calls
HandleStream.Read which
calls FileRead which returns a pointer to a buffer and a count of the bytes
read ( a DWORD so there is a 2gb or is it 4gb limit there).

the Tstrings.LoadFromStream
looks like
Size := Stream.Size - Stream.Position;
SetString(S, nil, Size);
Stream.Read(Pointer(S)^, Size);
SetTextStr(S);
so it is clear that there is a 1 hit read of all the data on that file
until the end of file (which might not be what
you want if you have other stuff on the file). Anyway, all the data goes
into an ansistring S (which is local and will be deallocated on exit) but
afaik the memory for the underlying buffer is never freed until the
handle is finally freed .. this seems wasteful (as in, as soon as we have
finished the load we could release
the file buffer .. but I may have misread the code).

Next we have SetTextStr which is a loop that looks like so

P := Pointer(Value);
if P <> nil then
while P^ <> #0 do
begin
Start := P;
while not (P^ in [#0, #10, #13]) do Inc(P);
SetString(S, Start, P - Start);
Add(S);
if P^ = #13 then Inc(P);
if P^ = #10 then Inc(P);
end;

(I am sure Borland will forgive me for publishing this code snippet, in the
interests of science).

So, there are some possibilities of some oddities here particularly wrt
#0,#10,#13.
The #10 and #13 were put there by GetTextStr .. but you might have had
them embedded in
your original source strings. The #0 .. again, you may have had a reason
for having one or more
consecutive empty strings in your original list.

Note also the call to Add .. depending upon your settings of Sorted and, if
sorted, Duplicates this can end up
with another call to the bsearch find and Insert (even if you KNOW you are
restoring a sorted list), and some locale dependencies.


My point is that TstringList.SaveToFile and LoadFromFile are not the simple
mirror image dump and
restore of blocks of characters that one might expect. There is quite a
lot of looping and comparison and memory management going on under the
hood, so if your strings have unusual content or you need to do a lot of
this ,you might be better off considering alternative structures.

fwiw
Responder Con Cita
  #3  
Antiguo 12-04-2006
alapaco alapaco is offline
No confirmado
 
Registrado: jun 2003
Ubicación: Buenos Aires
Posts: 287
Poder: 0
alapaco Va por buen camino
Acabo de probar de cargar un archivo de 10Mb en un TStringList y no tuve ningún problema.

EDIT: Vos lo explicaste mejor.
Responder Con Cita
  #4  
Antiguo 12-04-2006
Avatar de halcon_rojo
halcon_rojo halcon_rojo is offline
Miembro
 
Registrado: abr 2006
Posts: 14
Poder: 0
halcon_rojo Va por buen camino
otro tip

gracias Alvaro por tu interes, tal vez se deba a algun 'error' en el archivo de texto, de todos modos mi pregunta es si cargaste el archivo de 10Mb en el TStringList y lo recorriste? o solo lo cargaste?
acerca de mi otra duda de por que me demora tanto la carga y al tener en mi codigo una llamada repetitiva del ProcessMessages encontre este comentario:

In your loop you need to add a call to the Application.ProcessMessages method. This will allow your application to process Windows messages, including those generated by user actions. There are two significant caveats. First, since Windows messages often translate into calls to event handlers your program may begin to do things at inappropriate times. Make sure that the user can't initiate actions that will interfere with the loop while the loop is active. In particular, note the following sentence, taken from Delphi 3's help file on TApplication.Terminated: "For applications using calculation-intensive loops, call Application.ProcessMessages periodically, and also check Application.Terminated to determine whether or not to abort the calculation so that the application can terminate." The second caveat is that calling Application.ProcessMessages can be relatively expensive and may slow the program. In a fast (tight) loop you may not want to call the method on each iteration. If you only want to update the display and not handle user input you can use the Update method (Delphi 3 and up) of the control covering the part of the display you want to update. Remember that this will also slow down the loop!

Última edición por halcon_rojo fecha: 12-04-2006 a las 22:02:33.
Responder Con Cita
  #5  
Antiguo 12-04-2006
alapaco alapaco is offline
No confirmado
 
Registrado: jun 2003
Ubicación: Buenos Aires
Posts: 287
Poder: 0
alapaco Va por buen camino
Exacto, eso que remarcaste en rojo es correcto, tal vez sería mejor llamar a Application.ProcessMessages cada X cantidad de registros procesados, no cada 1.
Responder Con Cita
  #6  
Antiguo 16-05-2006
JCarlosas JCarlosas is offline
Miembro
 
Registrado: abr 2006
Ubicación: Habana. Cuba
Posts: 103
Poder: 19
JCarlosas Va por buen camino
Hola.
Me estuve leyendo el fragmento que esta en ingles pues casualmente soy uno de los que tiene el problema con el caracter #0.
Me estaba ocurriendo que cuando leia el archivo con
LoadFromFile
y dicho archivo contenia en algun lugar el caracter #0 se me cortaba ahi el archivo no seguia cargando.
Quizas la solucion del problema le sea util a alguien y aqui se las dejo.
En el fuente solamente lo que hice fue cambiar el caracter #0 que venia por un caracter A, quizas en otras aplicaciones se deba hacer otra cosa pero creo que el ejemplo vale.


Código Delphi [-]
unit UCustomTStrings;
{$R-,T-,X+,H+,B-}
{$IFDEF MSWINDOWS}
{ ACTIVEX.HPP is not required by CLASSES.HPP }
(*$NOINCLUDE ActiveX*)
{$ENDIF}
{$IFDEF LINUX}
{$DEFINE _WIN32}
{$ENDIF}
{$IFDEF MSWINDOWS}
{$DEFINE _WIN32}
{$ENDIF}

interface
{$IFDEF MSWINDOWS}
uses Windows, Messages, SysUtils, Variants, TypInfo, ActiveX, classes;
{$ENDIF}
{$IFDEF LINUX}
uses Libc, SysUtils, Variants, TypInfo, Types, classes;
{$ENDIF}
 type
  TCustomTStrings = class(TStringList)
  Public
   procedure LoadFromStream(Stream: TStream);Virtual;
   procedure LoadFromFile(const FileName: string);Virtual;
  end;
implementation
uses strutils;
procedure TCustomTStrings.LoadFromFile(const FileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
  try
    LoadFromStream(Stream);
  finally
    Stream.Free;
  end;
end;
 
procedure TCustomTStrings.LoadFromStream(Stream: TStream);
var
  Size: Integer;
  S : string;
  i: integer;
  StringSize : integer;
begin
  BeginUpdate;
  try
    Size := Stream.Size - Stream.Position;
    SetString(S, nil, Size);
    Stream.Read(Pointer(S)^, Size);
    StringSize := Length(S);

//Este for es solamente para cambiar el caracter #0 por otro.
    for i:= 1 to StringSize do
      Begin
         if S[i] = #0 then S[i] := 'A'; //Sustituyendo el #0 por  una "A"
      end;

 
    SetTextStr(S);
  finally
    EndUpdate;
  end;
end;
end.

Ah y la llamada y creacion del nuevo componente muy facil.

Código Delphi [-]
var
  tsArchivo : TCustomTStrings;
Begin
 tsArchivo := TCustomTStrings.create;
 tsArchivo.LoadFromFile(LoteFileName);

Otra variante pudo ser redefinir el metodo
SetTextStr
en lugar de loadfromstream

Por cierto he cargado archivos de mas de 100MBytes con ese codigo

Espero que sea de utilidad a alguien.
Saludos
Juan Carlos

Última edición por JCarlosas fecha: 16-05-2006 a las 01:47:44.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Capacidad de Paradox irvingcm Tablas planas 3 13-04-2005 00:41:59
Cual es el limite de capacidad de Paradox? URBANO Tablas planas 1 15-03-2005 09:54:12
Saber exactamente cual es cual en un DBLookUpComboBox bustio OOP 3 03-02-2005 23:16:58
Capacidad del QReport marila Impresión 2 22-04-2004 16:02:47
Capacidad No soportada con BDE GIVO Conexión con bases de datos 3 27-08-2003 03:10:09


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


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
Copyright 1996-2007 Club Delphi