| Ver tema anterior :: Ver tema siguiente |
| Autor |
Mensaje |
martinlop2007 Lt JG


Registrado: 20 Feb 2007Mensajes: 67
|
Publicado: Jue 20 Dic, 2007 6:26 pm Asunto: Pasar Archivo CSV separado por comas a tabla DBF |
|
|
Hola Amigos, pues eso... veran necesito pasar los datos de un archivo que me llega en formato CSV a una tbla en DBF, y la verdad es que no tengo ni Put.... idea, ya que soy algo mas que novato en esto.
He buscado en el foro y la verdad es que no saco nada en claro.
Gracias de Antemano.
Un saludo. |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Jue 20 Dic, 2007 7:54 pm Asunto: |
|
|
| En que parte tienes dudas ? que parte sabes hacer y que parte no ? Tienes problemas para leer el archivo en formato CSV ? y si es así que formato exactamente tiene el archivo ? separados por comas ? por punto y coma ? o tienes problemas para grabar los registros en la tabla en formato dBase ? cuantos más detalles o ejemplos mejor.. |
|
| Volver arriba |
|
 |
martinlop2007 Lt JG


Registrado: 20 Feb 2007Mensajes: 67
|
Publicado: Jue 20 Dic, 2007 8:21 pm Asunto: |
|
|
Antes que nada gracias _Leo, y pido disculpas de nuevo por duplicar la consulta.
Y ahora "vamos al turron"
Veras el archivo tiene una extension CSV, con datos separados por punto y coma ( ,
Lo que deseo es poder acceder a los datos, cuando llege a los puntos y comas pasarlos a una tabla,(esto ultimo si lo domino, lo que no sé es como acceder a esos datos y controlar que llego a un punto y coma) y seguir asi hasta recorrer todos los latos linea por linea.
Gracias de Antemano _Leo |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Jue 20 Dic, 2007 9:04 pm Asunto: |
|
|
A ver si te sirve algo así:
| Código: | //Añadimos: #include<fstream> y #include<memory>
std::ifstream file("d:\\prueba.csv");
std::auto_ptr<TStringList> sl(new TStringList);
sl->Delimiter = ';';
std::string line;
while(std::getline(file, line)) {
const TReplaceFlags all = TReplaceFlags() << rfReplaceAll;
sl->DelimitedText = StringReplace(line.c_str(), "\x20", "\xFF", all);
sl->Text = StringReplace(sl->Text, "\xFF", "\x20", all);
// Aquí tienes ahora en cada pasada una línea, y para acceder
// a cada uno de los valores separados por comas usaríamos:
// String primerValor = sl->Strings[0];
// String segundoValor = sl->Strings[1];
// ...
ShowMessage(sl->Text);
// Para saber cuantos campos/valores hay:
// int numValores = sl->Count;
} |
Lo de las líneas "StringReplace" es para prevenir que se corten las líneas al encontrar campos con espacios sin estar entre comillas. Ya que hay programas que exportan a .CSV sin poner comillas:
campo1; campo2 con espacios; campo3
y TStringList espera que sea con comillas:
campo1; "campo2 con espacios"; campo3 |
|
| Volver arriba |
|
 |
martinlop2007 Lt JG


Registrado: 20 Feb 2007Mensajes: 67
|
Publicado: Vie 21 Dic, 2007 1:40 pm Asunto: |
|
|
Muy Buenas _leo, y ante todo gracias por contestarme, pero tengo un problema con tu codigo, me da el siguiente error "'Delimiter' is not a member of 'TStringList''.
Gracias. |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Vie 21 Dic, 2007 1:44 pm Asunto: |
|
|
| Que versión de C++Builder utilizas ? |
|
| Volver arriba |
|
 |
martinlop2007 Lt JG


Registrado: 20 Feb 2007Mensajes: 67
|
Publicado: Vie 21 Dic, 2007 1:47 pm Asunto: |
|
|
| Utilizo la version Professional V5.0 |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Vie 21 Dic, 2007 3:01 pm Asunto: |
|
|
'DelimitedText' y 'Delimiter' solo están disponibles desde el BCB6 en adelante. En versiones anteriores puedes probar de la siguiente manera:
- Creamos la función 'SplitCsv' para sustituir a la funcionalidad de 'DelimitedText':
| Código: | void SplitCsv(String str, TStrings* sl, char delimiter=';', char quoteChar='"')
{
String strTmp = "";
bool flagQuote = false;
sl->BeginUpdate();
sl->Clear();
for (int i = 1; i <= str.Length(); i++) {
if (str[i] == quoteChar)
flagQuote = !flagQuote;
else if (str[i] == delimiter && !flagQuote) {
sl->Append(strTmp.Trim());
strTmp = "";
}
else
strTmp += str[i];
}
if (!strTmp.IsEmpty())
sl->Append(strTmp.Trim());
sl->EndUpdate();
} |
Y ahora el código anterior modificado para usar 'SplitCsv' en vez de 'DelimitedText':
| Código: | //Añadimos: #include<fstream> #include<memory> e #include<string>
std::ifstream file("d:\\prueba.csv");
std::auto_ptr<TStringList> sl(new TStringList);
std::string line;
while(std::getline(file, line)) {
SplitCsv(line.c_str(), sl.get());
// Aquí tienes ahora en cada pasada una línea, y para acceder
// a cada uno de los valores separados por comas usaríamos:
// String primerValor = sl->Strings[0];
// String segundoValor = sl->Strings[1];
// ...
ShowMessage(sl->Text);
// Para saber cuantos campos/valores hay:
// int numValores = sl->Count;
}
|
|
|
| Volver arriba |
|
 |
martinlop2007 Lt JG


Registrado: 20 Feb 2007Mensajes: 67
|
Publicado: Vie 21 Dic, 2007 4:45 pm Asunto: |
|
|
ok._leo Muchisimas gracias, parece que si funciona.
Gracias, de verdad. |
|
| Volver arriba |
|
 |
jacko Master


Registrado: 03 Sep 2005Mensajes: 287Ubicación: Colombia
|
Publicado: Vie 07 May, 2010 3:47 am Asunto: |
|
|
Hola a todos!
Perdón por revivir este hilo tan viejito.
Estoy usando el codigo que nos entregó Leo para abrir archivos CSV, pero tengo una pregunta:
Alguien me podria ayudar por favor a indicarme cómo hago para saber la cantidad de filas que contiene el CSV antes de ingresar al while?
Gracias a todos! _________________ Dios es real... a menos que se declare entero! |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Vie 07 May, 2010 6:05 am Asunto: |
|
|
| jacko escribió: | | cómo hago para saber la cantidad de filas que contiene el CSV antes de ingresar al while? |
Pues tendrías que recorrer el archivo y contar las líneas:
| Código: | // Añadimos: #include<fstream> e #include<string>
int CuentaLineas(String archivo)
{
std::ifstream file(archivo.c_str());
std::string linea;
int lineas = 0;
while(std::getline(file, linea)) ++lineas;
return lineas;
} |
O podemos utilizar un archivo mapeado en memoria y contar todos los '\n':
(este método es un poco más complicado pero es muchísimo más rápido)
| Código: | int CuentaLineas(String archivo)
{
int lineas = 0;
HANDLE file = CreateFileW(WideString(archivo).c_bstr(), GENERIC_READ,
FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
if (file != INVALID_HANDLE_VALUE)
{
HANDLE map = CreateFileMapping(file, 0, PAGE_READONLY, 0, 0, 0);
if (map)
{
LPVOID view = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
if (view)
{
char* buffer = static_cast<char*>(view);
int size = GetFileSize(file, 0);
for (int i = 0; i < size; ++i)
if (buffer[i] == '\n') ++lineas;
UnmapViewOfFile(view);
}
CloseHandle(map);
}
CloseHandle(file);
}
return lineas;
} |
|
|
| Volver arriba |
|
 |
jacko Master


Registrado: 03 Sep 2005Mensajes: 287Ubicación: Colombia
|
Publicado: Vie 07 May, 2010 6:17 am Asunto: |
|
|
Muchas gracias Leo!
Voy a probar los dos metodos y te contaré mis resultados.
Lo que quiero hacer es poner una barra de progreso que avanza a medida que voy cargando el archivo, asi que Bar1->Max no sabría que valor ponerle.
Como no debe ser tan exacto este valor, sino algo aproximado, estaba pensando algo como tomar el tamaño del archivo y como sé que en cada linea deben venir entre 25 a 35 caracteres, hacer una división y de esta forma sacar el total de lineas.. que te parece?
Ya sabrás que por este lado del mundo estamos 7horitas atras de ti... asi que te deseo un buen dia y yo mientras voy a dormir un rato.
Gracias! _________________ Dios es real... a menos que se declare entero! |
|
| Volver arriba |
|
 |
_Leo Site Admin

Registrado: 11 Ago 2002Mensajes: 1875Ubicación: Lanzarote - Islas Canarias (España)
|
Publicado: Vie 07 May, 2010 6:53 am Asunto: |
|
|
| jacko escribió: | | Como no debe ser tan exacto este valor, sino algo aproximado, estaba pensando algo como tomar el tamaño del archivo y como sé que en cada linea deben venir entre 25 a 35 caracteres, hacer una división y de esta forma sacar el total de lineas.. que te parece? |
No quedaría tan exacto, pero por lo menos alguna indicación de lo que va a tardar tiene el usuario..
Con lo que he puesto más arriba podrías hallar el valor máximo exacto. Y si usas el segundo método que he puesto, como referencia, en mi maquina (Q9400+SATA2+Win7+8GB) tarda en contar un archivo con 1 millón de líneas menos de un segundo..
| jacko escribió: | | Ya sabrás que por este lado del mundo estamos 7horitas atras de ti... asi que te deseo un buen dia y yo mientras voy a dormir un rato. |
Que descanses.. |
|
| Volver arriba |
|
 |
|