Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Lentitud leer .csv (https://www.clubdelphi.com/foros/showthread.php?t=79231)

ErYcK 18-06-2012 09:49:57

Lentitud leer .csv
 
Mi problema es el siguiente:

Leo un archivo csv. en un RichEdit, lo leo con este componente porque con un Memo me paso del límite de caracteres.

Después de leerlo lo cargo en un StringGrid y comparo los datos con una base de datos en busca de nuevos registros.

El problema esta en la lentitud del proceso de lectura del .csv, no se me ocurre forma de acelerar este proceso ya que tengo que tener en cuenta:
-Que cuando haya mas de un espacio seguido deje de leer la linea del RichEdit.
-Que cuando encuentre un ";" debe meter la variable en la celda del StringGrid.
-Que cuando encuentre algo que no sea ";" rellene la variable con la palabra encontrada.

Mi código es el siguiente, si alguien tiene alguna idea de como podría acelerar el proceso seria de gran ayuda.

Código:

void __fastcall TXPrincipal::ToolButton2Click(TObject *Sender)
{

        if(OpenDialog1->Execute())
        {
              //LECTURA DE CSV
                int col =0;
                int cont=0;
                String referencia ="";
                RichEdit1->Lines->LoadFromFile(OpenDialog1->FileName);
                XCarga->Show();
                XCarga->Caption="Leiendo .CSV...";
                XCarga->ProgressBar1->Min = 0;
                XCarga->ProgressBar1->Max = RichEdit1->Lines->Count;
                for (int i =0; i <= RichEdit1->Lines->Count; i++)
                {
                        XCarga->ProgressBar1->Position = i;
                        col=0;
                        cont=0;
                        for (int j=1; j<= RichEdit1->Lines->Strings[i].Length();j++)
                        {
                                XCarga->Caption="Leiendo .CSV...Linea: "+ IntToStr(i)+ "Columna: "+ IntToStr(j);
                                if (RichEdit1->Lines->Strings[i][j] != ' ')
                                {
                                        cont =0;
                                        if (RichEdit1->Lines->Strings[i][j] == ';')
                                        {
                                        StringGrid1->Cells[col][i] = referencia;
                                        referencia = "";
                                        col++;
                                        }
                                        if (RichEdit1->Lines->Strings[i][j] != ';')
                                        {
                                        referencia = referencia +RichEdit1->Lines->Strings[i][j];
                                        }
                                }
                                if (RichEdit1->Lines->Strings[i][j] == ' ')
                                {
                                        cont++;
                                        if (cont >2)
                                                break;
                                }
                        }

                }

        //COMPARAR CON BD
        XCarga->Close();
        }

        XDatos->TCategorias->Open();
        XDatos->TSubCat1->Open();
        XDatos->TSubCat2->Open();
        XDatos->TSubCat3->Open();
        XDatos->TMarcas->Open();
        XCarga->Close();
        XDatos->TCaracteristicas->Open();
        int cont=0;
        XCarga->Show();
        XCarga->ProgressBar1->Min = 1;
        XCarga->ProgressBar1->Max = RichEdit1->Lines->Count;
        String ref = "";
        for (int f=1;f<=StringGrid1->RowCount;f++)
        {
            if (StringGrid1->Cells[0][f]!="")
            {
            ref = StringGrid1->Cells[0][f];

            XCarga->Caption = IntToStr(f)+ " Productos Nuevos";
            XCarga->ProgressBar1->Position = f;
            XDatos->QExisteProducto->Close();
            XDatos->QExisteProducto->Parameters->ParamByName("PRef")->Value = ref;
            XDatos->QExisteProducto->Open();
            if (XDatos->QExisteProducto->FieldByName("existe")->Value ==0)
            {
                        String categoria ="";
                        XDatos->QProductos->Append();
                        XDatos->QProductosREFERENCIA->Value = StringGrid1->Cells[0][f];
                        XDatos->QProductosESTADO->Value = StringGrid1->Cells[1][f];
                        categoria = StringGrid1->Cells[2][f];
                        XDatos->QExisteCategoria->Close();
                        XDatos->QExisteCategoria->Parameters->ParamByName("PCat")->Value = categoria ;
                        XDatos->QExisteCategoria->Open();
                        if (XDatos->QExisteCategoria->FieldByName("Existe")->Value >0)
                        {
                                XDatos->QCodigoCategoria->Close();
                                XDatos->QCodigoCategoria->SQL->Text = "select * from categorias where categoria = :PCat";
                                XDatos->QCodigoCategoria->Parameters->ParamByName("PCat")->Value = categoria;
                                XDatos->QCodigoCategoria->Open();
                                XDatos->QProductosCATEGORIA->Value = XDatos->QCodigoCategoriaCodCategoria->Value;
                                XDatos->QCodigoCategoria->Close();
                        }
                        else
                        {
                                XDatos->TCategorias->Append();
                                XDatos->TCategoriasCATEGORIA->Value = StringGrid1->Cells[2][f];
                                XDatos->TCategorias->Post();
                                XDatos->QProductosCATEGORIA->Value=XDatos->TCategoriasCodCategoria->Value;
                        }
                        String subcat1 =StringGrid1->Cells[3][f];
                        XDatos->QExisteSubcat1->Close();
                        XDatos->QExisteSubcat1->Parameters->ParamByName("PSubCat1")->Value = subcat1;
                        XDatos->QExisteSubcat1->Open();
                        if (XDatos->QExisteSubcat1->FieldByName("Existe")->Value >0)
                        {
                                XDatos->QCodigoSubCat1->Close();
                                XDatos->QCodigoSubCat1->SQL->Text = "select * from SUBCATS1 where SUBCAT1 = :PSubcat1";
                                XDatos->QCodigoSubCat1->Parameters->ParamByName("PSubcat1")->Value = subcat1;
                                XDatos->QCodigoSubCat1->Open();
                                XDatos->QProductosSUBCAT1->Value = XDatos->QCodigoSubCat1CodSUBCAT1->Value;
                                XDatos->QCodigoSubCat1->Close();
                        }
                        else
                        {
                                XDatos->TSubCat1->Append();
                                XDatos->TSubCat1SUBCAT1->Value = StringGrid1->Cells[3][f];
                                XDatos->TSubCat1CATEGORIA->Value = XDatos->QProductosCATEGORIA->Value;
                                XDatos->TSubCat1->Post();
                                XDatos->QProductosSUBCAT1->Value= XDatos->TSubCat1CodSUBCAT1->Value;
                        }
                        String subcat2 =StringGrid1->Cells[4][f];
                        XDatos->QExisteSubcat2->Close();
                        XDatos->QExisteSubcat2->Parameters->ParamByName("PSubCat2")->Value = subcat2;
                        XDatos->QExisteSubcat2->Open();
                        if (XDatos->QExisteSubcat2->FieldByName("Existe")->Value >0)
                        {
                                XDatos->QCodigoSubCat2->Close();
                                XDatos->QCodigoSubCat2->SQL->Text = "select * from SUBCATS2 where SUBCAT2 = :PSubcat2";
                                XDatos->QCodigoSubCat2->Parameters->ParamByName("PSubcat2")->Value = subcat2;
                                XDatos->QCodigoSubCat2->Open();
                                XDatos->QProductosSUBCAT2->Value = XDatos->QCodigoSubCat2CodSUBCAT2->Value;
                                XDatos->QCodigoSubCat2->Close();
                        }
                        else
                        {
                                XDatos->TSubCat2->Append();
                                XDatos->TSubCat2SUBCAT2->Value = StringGrid1->Cells[4][f];
                                XDatos->TSubCat2SUBCAT1->Value = XDatos->QProductosSUBCAT1->Value;
                                XDatos->TSubCat2->Post();
                                XDatos->QProductosSUBCAT2->Value = XDatos->TSubCat2CodSUBCAT2->Value;
                        }
                        String subcat3 =StringGrid1->Cells[5][f];
                        XDatos->QExisteSubcat3->Close();
                        XDatos->QExisteSubcat3->Parameters->ParamByName("PSubCat3")->Value = subcat3;
                        XDatos->QExisteSubcat3->Open();
                        if (XDatos->QExisteSubcat3->FieldByName("Existe")->Value >0)
                        {
                                XDatos->QCodigoSubcat3->Close();
                                XDatos->QCodigoSubcat3->SQL->Text = "select * from SUBCATS3 where SUBCAT3 = :PSubcat3";
                                XDatos->QCodigoSubcat3->Parameters->ParamByName("PSubcat3")->Value = subcat3;
                                XDatos->QCodigoSubcat3->Open();
                                XDatos->QProductosSUBCAT3->Value = XDatos->QCodigoSubcat3CodSUBCAT3->Value;
                                XDatos->QCodigoSubcat3->Close();
                        }
                        else
                        {
                                XDatos->TSubCat3->Append();
                                XDatos->TSubCat3SUBCAT3->Value = StringGrid1->Cells[5][f];
                                XDatos->TSubCat3SUBCAT2->Value = XDatos->QProductosSUBCAT2->Value;
                                XDatos->TSubCat3->Post();
                                XDatos->QProductosSUBCAT3->Value = XDatos->TSubCat3CodSUBCAT3->Value;

                        }
                        XDatos->QProductosPRODUCTO->Value = StringGrid1->Cells[6][f];
                        XDatos->QProductosKEY->Value = StringGrid1->Cells[7][f];

                        String marca =StringGrid1->Cells[8][f];
                        XDatos->QExisteMarca->Close();
                        XDatos->QExisteMarca->Parameters->ParamByName("PMarca")->Value = marca;
                        XDatos->QExisteMarca->Open();
                        if (XDatos->QExisteMarca->FieldByName("Existe")->Value >0)
                        {
                                XDatos->QCodigoMarca->Close();
                                XDatos->QCodigoMarca->SQL->Text = "select * from MARCAS where MARCA = :PMarca";
                                XDatos->QCodigoMarca->Parameters->ParamByName("PMarca")->Value = marca;
                                XDatos->QCodigoMarca->Open();
                                XDatos->QProductosMARCA->Value = XDatos->QCodigoMarcaCodMARCA->Value;
                                XDatos->QCodigoMarca->Close();
                        }
                        else
                        {
                                XDatos->TMarcas->Append();
                                XDatos->TMarcasMARCA->Value = StringGrid1->Cells[8][f];
                                XDatos->TMarcas->Post();
                                XDatos->QProductosMARCA->Value = XDatos->TMarcasCodMARCA->Value;
                        }
                        XDatos->QProductosDESCRIPCION->Value = StringGrid1->Cells[9][f];
                        XDatos->QProductosFOTOS->Value = StringGrid1->Cells[10][f];
                        XDatos->QProductosCATEGORIAX->Value = StringGrid1->Cells[11][f];
                        XDatos->QProductosCATEGORIAS->Value = StringGrid1->Cells[12][f];
                        XDatos->QProductos->Post();
                        for(int c=13;c<=StringGrid1->ColCount;c++)
                        {
                                if (StringGrid1->Cells[c][f]!="")
                                {
                                        if (c % 2 !=0)
                                        {
                                        XDatos->TCaracteristicas->Append();
                                        XDatos->TCaracteristicasCATEGORIA->Value = XDatos->QProductosCATEGORIA->Value;
                                        XDatos->TCaracteristicasSUBCAT1->Value = XDatos->QProductosSUBCAT1->Value;
                                        XDatos->TCaracteristicasSUBCAT2->Value = XDatos->QProductosSUBCAT2->Value;
                                        XDatos->TCaracteristicasSUBCAT3->Value = XDatos->QProductosSUBCAT3->Value;
                                        XDatos->TCaracteristicasref->Value = XDatos->QProductosREFERENCIA->Value;
                                        XDatos->TCaracteristicasCARACTERISTICA->Value = StringGrid1->Cells[c][f];
                                        XDatos->TCaracteristicasVALOR->Value = StringGrid1->Cells[c+1][f];
                                        XDatos->TCaracteristicas->Post();
                                        }
                                }
                        }

            if (StringGrid1->Cells[0][f]=="")
                        cont ++;
            if (cont > 100)
                        break;
            }
            }
        }
        XCarga->Close();
        XDatos->QRecorreProductos->Close();
        DBGrid1->Refresh();

}

Gracias de antemano por vuestra atención.

Un Saludo.

Casimiro Notevi 18-06-2012 11:00:29

Una pregunta, si quieres leer un fichero y mostrarlo en un stringgrid, ¿por qué lo cargas en el richedit de intermediario?

ErYcK 18-06-2012 11:29:37

Pues en principio lo hice por comodidad, ya que con el LoadFromFile ya leo perfectamente el csv teniendo en cuenta los saltos de linea, y me coloca 1 registro por linea en el RichEdit, lo cual facilita luego la lectura para el StringGrid.

Piensas que la lentitud es a causa de leer el RichEdit? quizás leyendo directamente desde el archivo puede ser mas rápido?
Si es asi como crees que podria leer desde el archivo caracter a caracter para tener en cuenta las mismas cosas?

Gracias por tu interes :)

ecfisa 18-06-2012 21:05:20

Hola ErYcK.

Si no entendí mal lo que deseas hacer, se me ocurre que podrías cambiar el separador ';' por ',' y aprovechar la propiedad CommaText del TStringGrid.

Fijate si de este modo hace mas rápido lo que buscas:
Código:

void __fastcall TForm1::Button1Click(TObject *Sender) {
TStringList *TS = new TStringList;
TStringGrid *SG = static_cast<TStringGrid*> (StringGrid1);

 if (OpenDialog1->Execute()) {
  TS->LoadFromFile(OpenDialog1->FileName);
  for(int i=0; i< TS->Count; i++) {
    StringReplace(TS->Strings[i], ';', ',', TReplaceFlags() << rfReplaceAll);
    SG->Rows[i]->CommaText = TS->Strings[i];
  }
 }
 delete TS;
}

Saludos.

ErYcK 19-06-2012 09:45:33

Gracias por tu aporte ecfisa, el problema es que algunos campos llevan ',' entonces necesito el ';' como separador, sino me crearía conflictos.
Por ejemplo hay un campo fotos en el cual hay 6 nombres de fotos separados con ',' entonces me metería 6 campos distintos donde debe ser solo uno.
Este mismo proceso lo hice en principio utilizando el componente Memo, y lo hacia más rápido pero me vi obligado a cambiarlo porque llegara el límite de caracteres del Memo, no termino de entender porque con el RichEdit se ralentiza tanto, en principio pensé que el problema estaba en que siempre recorría al completo los campos del RichEdit y de por ese motivo utilice el contador para que una vez encuentre 2 espacios seguidos me me salga del bucle, pero no consigo acelerarlo suficiente con eso.

De nuevo gracias por vuestra atención.

ecfisa 19-06-2012 13:24:43

Hola ErYcK.

A ver, proba si te sirve de este modo:
Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  if (OpenDialog1->Execute()) {
    TStringList *TS = new TStringList;
    TS->LoadFromFile(OpenDialog1->FileName);
    for(int i=0; i< TS->Count; i++)
      ExtractStrings(TSysCharSet()<< ';', TSysCharSet() << ' ',
        TS->Strings[i].c_str(), StringGrid1->Rows[i]);
    delete TS;
  }
}

Saludos.

ErYcK 19-06-2012 16:18:03

Buenísimo el aporte ecfisa, me acelera muchísimo el proceso y en principio va bien, el único fallo es que la base de datos de la empresa tiene ciertos fallos, como por ejemplo que algunos de los campos no están, por ejemplo algunos de los registros son algo así:

referencia;estado;producto;categoria;categoria1;categoria2;categoria3; descripción
11234;;producto1;hogar; electrodomésticos;Lavadoras;;lavadora ultimo modelo tal y tal;

Es decir algunos campos vienen vacíos, con lo cual se genera en el csv dos ';' seguidos y lo que hace es meterme en el estado, la categoría.

No se si me he explicado bien, el tema es que cuando se encuentran dos ';' seguidos ha dejar esa celda vacía, estoy dándole vueltas al código que me pusiste
e intento dar con la tecla para tener eso en cuenta pero me da ami que no puede ser de esa forma, aunque no lo se.

Si se te ocurre algo seria de gran ayuda.

Gracias por el esfuerzo.

ecfisa 19-06-2012 20:38:47

Hola de nuevo.
Cita:

el tema es que cuando se encuentran dos ';' seguidos ha dejar esa celda vacía
Entonces, creo que habría que hacer un pequeño cambio a esta línea del código anterior:
Código:

  ExtractStrings(TSysCharSet()<< ';', TSysCharSet() << '\0',
        TS->Strings[i].c_str(), StringGrid1->Rows[i])

Saludos.

ErYcK 19-06-2012 22:14:06

Hola otra vez siento ser tan pesado.

Con ese cambio que me diste me sigue metiendo mal los datos, mete la categoría en el estado en la mayoría de los registros, he probado a mezclar tu idea con la mía, y lo hace bien, el problema es que los registros demasiado largos me los mete en el siguiente registro, entiendo que es porque el TStringList tendrá un límite de caracteres, te muestro el código.

Código:

if(OpenDialog1->Execute())
{
                TStringList *TS = new TStringList;
                TS->LoadFromFile(OpenDialog1->FileName);
                XCarga->Show();
                XCarga->ProgressBar1->Min = 0;
                XCarga->ProgressBar1->Max = TS->Count;
                int cont=0;
                int col=0;
                String referencia="";
                for(int i=0; i< TS->Count; i++)
                {
                cont=0;
                col=0;
                XCarga->ProgressBar1->Position=i;
                XCarga->Caption="Leidno .CSV .. Linea: "+i;
                for (int j=1;j<=TS->Strings[i].Length();j++)
                {
                        if (TS->Strings[i][j]!= ' ')
                        {
                                cont=0;
                                if (TS->Strings[i][j] == ';')
                                {
                                        StringGrid1->Cells[col][i] = referencia;
                                        referencia="";
                                        col++;
                                }
                                else
                                {
                                        referencia = referencia+TS->Strings[i][j];
                                }
                        }
                        if (TS->Strings[i][j] == ' ')
                        {
                                cont++;
                                if (cont>2)
                                        break;
                        }
                }
}

Es algo más lento que la idea que propusiste pero el simple uso del TStringList lo acelera lo suficiente en realidad.

Si sabes alguna forma de solucionar el problema usando el código que antes me mostraste seria genial, si no me gustaría saber si el TStringList tiene límite de caracteres y si se puede ampliar este límite.

Gracias por tu paciencia que ha de ser mucha.

ecfisa 19-06-2012 22:48:19

Hola.

La capacidad de cada línea de TStringList es la que tiene la propiedad vectorial Strings cuyos elementos son de tipo AnsiString y según la ayuda de Builder C++ es:
Código:

Type            Maximum length        Memory required        Used for
AnsiString  ~2^31 characters        4 bytes to 2GB        8-bit (ANSI) characters

Estaría bueno que nos adjuntaras la cabecera (titulos:referencia;estado;producto...) y dos o tres líneas del archivo que estes leyendo (y que te dén problemas), como para hacer algunas pruebas mas.

Saludos.

ErYcK 19-06-2012 23:42:04

1 Archivos Adjunto(s)
Aquí os dejo un ejemplo de csv comprimido, contiene 1 registro demasiado largo, el cual me da conflictos como te he comentado anteriormente.

De nuevo gracias por tu ayuda.
Un Saludo.

ecfisa 20-06-2012 14:07:43

Hola ErYcK.

No me queda muy en claro la definición de la cabecera (columnas) ¿ Conocés cuantas y cuales son ?

Saludos.

ErYcK 20-06-2012 16:30:17

Es que es algo extraño, te comento:

La primera linea del csv guarda los nombres de los campos de una tabla denominada Productos, pero a partir de ahí se guardan los valores de estos campos que son 12 si no me equivoco, seguidos de una característica y el valor de la misma, el tecla esta en que cada producto tiene unas características, algunos más que otros entonces no se sabe cuantas columnas hay hasta que no se lee el csv.

Yo en el StringGrid le tengo puesto un limite de columnas suficientemente alto como para que pudiese entrar el registro mas largo, y después cuando lo paso a la base de datos desde el StringGrid guardo los 12 primeros campos en una tabla y las características que le siguen las voy metiendo en otra tabla relacionada con Productos, pero ese proceso en principio si que esta listo, el problema es que tiene que cargarse correctamente el StringGrid para que funcione.

No se si me he expresado con claridad, el tema es algo rebuscado.

Gracias por el esfuerzo.

Un Saludo.

ecfisa 20-06-2012 18:22:47

Hola ErYcK.

Cita:

La primera linea del csv guarda los nombres de los campos de una tabla denominada Productos, pero a partir de ahí se guardan los valores de estos campos que son 12 si no me equivoco, seguidos de una característica y el valor de la misma, el tecla esta en que cada producto tiene unas características, algunos más que otros entonces no se sabe cuantas columnas hay hasta que no se lee el csv.
Si, lo mismo note yo. Hasta aquí
Código:

00)Referencia                  :19974;
01)Estado;                      :1;
02)Categoría (Español);        :PUERICULTURA;
03)SubCategoría 1 (Español);    :HORA DE JUGAR;
04)SubCategoría 2 (Español);    :GANDULITAS Y COLUMPIOS;
05)SubCategoría 3 (Español);    :;
06)Nombre;                      :HAMACA PLAY BABY;
07)Keywords;                    :;
08)Marca;                      :PLAY BABY;
09)Descripción;                :;
10)Fotos (separadas por ,);    :HAMACA-4.jpg,HAMACA-3.jpg,HAMACA-2.jpg,HAMACA-1.jpg,HAMACA-5.jpg,HAMACA-6.jpg;

hay correspondencia entre campos y contenido, pero luego continua con:
Cita:

CATEGORIAS;PUERICULTURA / HORA DE JUGAR / GANDULITAS Y COLUMPIOS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
...
que descompagina todo y se pierde la congruencia. En un momento llegué a pensar que el archivo pudiera estar dañado, de allí la pregunta.

Con ese formato, no creo posible aplicar los métodos que te sugerí ya que la aparición de los datos no pareciera obedecer a un patrón repetitivo.

Saludos.

ErYcK 20-06-2012 19:47:12

Esos dos campos de los que me hablas son campos que relleno automáticamente, el de CATEGORÍAS, siempre se rellena con eso, y el otro se rellena con la categoría y las subcategorias que tenga el producto separadas con '/'.
Pero claro eso lo hago cuando doy altas aquí simplemente me interesa leerlas.
Respecto a lo que te pregunté sobre los StringList es porque me mete parte de los datos de un registro en el siguiente cuando es demasiado largo y no entiendo el porque, por que dado el tamaño que me dijiste que tenia no tendría sentido que llegase al límite ¿no?.

Un Saludo

ecfisa 20-06-2012 20:30:55

Hola.
Cita:

por que dado el tamaño que me dijiste que tenia no tendría sentido que llegase al límite ¿no?.
No creo que una línea exeda ese límite. Pero lo que sí puede darse es que la propiedad Text del TStrings (también de tipo AnsiString) quede desbordada por la longitud total del archivo, en cuyo caso vas a tener que accederlo secuencialmente como archivo de texto.

Saludos.

ErYcK 24-06-2012 14:04:27

Perdona por la tardanza.

Con acceder al archivo secuencialmente entiendo que debo leer el archivo carácter a carácter, aunque no se exactamente como se haría desde Builder, si pudiese darme una idea seria de gran ayuda.

Gracias

ecfisa 24-06-2012 23:22:26

Hola ErYcK.

Revisá en este enlace: File Processing.

Saludos.

ErYcK 05-07-2012 13:17:30

Gracias por el aporte, he intentando entender la forma de leer el archivo con el enlace que me pusiste pero no consigo entender exactamente como se haría para leer carácter por carácter, de esa forma, si pudieses darme une ejemplo sencillo de como se hace me ayudaría a entenderlo.

Gracias y disculpa por las molestias, pero no consigo entenderlo por mi mismo.

ecfisa 05-07-2012 20:35:34

Cita:

Empezado por ErYcK (Mensaje 436761)
Gracias por el aporte, he intentando entender la forma de leer el archivo con el enlace que me pusiste pero no consigo entender exactamente como se haría para leer carácter por carácter, de esa forma, si pudieses darme une ejemplo sencillo de como se hace me ayudaría a entenderlo.

Gracias y disculpa por las molestias, pero no consigo entenderlo por mi mismo.

Hola ErYcK.

Por ejemplo, este código cuenta los caracteres de un archivo de texto leyéndolos de a uno:
Código:

#include<stdio.h>

void __fastcall TForm1::Button1Click(TObject *Sender)
{
FILE *fp;
char ch;
int char_leidos = 0;

  if ((fp=fopen("C:\\ARCHIVO.TXT","rt")))
    while ((ch = fgetc(fp))!= EOF) char_leidos++;
  fclose(fp);
  ShowMessage("Caracteres leidos: "+IntToStr(char_leidos));
}

La verdad que el ejemplo es tan trivial que no sé si te será de ayuda...

Saludos.


La franja horaria es GMT +2. Ahora son las 13:54:16.

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