Leyendo un archivo CSV
Por ejemplo, imagina que eres achichincle del Jason (el de las películas de terror) y te manda a hacer sus compras, de lo contrario terminarás con tu cabeza y cuerpo en diferentes sectores de la ciudad. El vato hace su "chopin list" en Excel y lo guarda en el siguiente archivo llamado jason.csv:
Entonces, como buen dotnetero, podrías leerlo con una rutina como esta:
El código es bastante sencillo, es el patrón estándar para usar un DataAdapter. Lo único de especial que tiene es que utiliza el OLEDB Data Provider, y que en el connection string le especificamos el directorio donde se encuentra el archivo, así como el formato que tiene. Nota que emites un SELECT de SQL común y corriente, por lo cual podrías agregar una cláusula WHERE si así lo quisieras.
En fin, para comprobar que en realidad funcionara el código, puse un breakpoint e invoqué el DataSet Visualizer desde Visual Studio. El resultado:
Pero, ¿qué tan inteligente es el OLEDB Provider? ¿Adivinó correctamente el tipo de mis datos?
Leyendo un archivo de texto con posiciones fijas
Ahora, asume que el méndigo Jason te la puso más difícil y en lugar de darte un archivo CSV, te da un archivo de texto sencillo como este (jason.txt):
El código sería muy similar al anterior:
De hecho, lo único que cambió fue el parámetro FMT en el connectionString, el nombre del archivo y el directorio donde localizarlo. Sin embargo, para que esto funcione con archivos de posiciones fijas es necesario un paso adicional: especificar el tamaño (y tipo) de las columnas en el archivo.
Esto se hace mediante un archivo schema.ini que debe estar en el mismo directorio que el archivo que vas a leer. Consulta esta página para saber todas las opciones disponibles. En nuestro caso un archivo como el siguiente sería suficiente:
Factorizando códigoSi generalizamos el código un poco, podemos extraer una función sencilla que pueda ser reutilizada en varios de nuestros programas. Esa rutina podría ser como esta, en donde le pasas como parámetros el tipo y archivo a leer y te regresa un DataTable poblado ya con los datos:
De manera que pueda ser llamado así:
Por ejemplo, imagina que eres achichincle del Jason (el de las películas de terror) y te manda a hacer sus compras, de lo contrario terminarás con tu cabeza y cuerpo en diferentes sectores de la ciudad. El vato hace su "chopin list" en Excel y lo guarda en el siguiente archivo llamado jason.csv:
Producto,Cantidad,Precio
Sierra eléctrica,1,250
Máscara de hockey,1,15.50
Machete,5,2.70
Detergente para ropa (con quita-manchas),1,10
Delantal,2,7.25
Afilador,3,5
Entonces, como buen dotnetero, podrías leerlo con una rutina como esta:
// asumiendo que tenemos
// using System.Data.OleDb;
// using System.Data;
// en este connection string:
// HDR=Yes : indica que el primer registro contiene los encabezados
// (nombres) de las columnas, no datos.
// FMT=Delimited : indica que el los campos están delimitados por un caracter
// (coma por default).
string connectionString =
@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\DirectorioDeArchivosCSV;" +
"Extended Properties='text;HDR=Yes;FMT=Delimited'";
DataTable dt = new DataTable("miTabla");
using (OleDbConnection conn = new OleDbConnection(connectionString))
using (OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM jason.csv", conn))
{
da.Fill(dt);
}
// hacer algo con los datos en el DataTable
El código es bastante sencillo, es el patrón estándar para usar un DataAdapter. Lo único de especial que tiene es que utiliza el OLEDB Data Provider, y que en el connection string le especificamos el directorio donde se encuentra el archivo, así como el formato que tiene. Nota que emites un SELECT de SQL común y corriente, por lo cual podrías agregar una cláusula WHERE si así lo quisieras.
En fin, para comprobar que en realidad funcionara el código, puse un breakpoint e invoqué el DataSet Visualizer desde Visual Studio. El resultado:
Pero, ¿qué tan inteligente es el OLEDB Provider? ¿Adivinó correctamente el tipo de mis datos?
Leyendo un archivo de texto con posiciones fijas
Ahora, asume que el méndigo Jason te la puso más difícil y en lugar de darte un archivo CSV, te da un archivo de texto sencillo como este (jason.txt):
El código sería muy similar al anterior:
// asumiendo que tenemos
// using System.Data.OleDb;
// using System.Data;
// en este connection string:
// HDR=Yes : indica que el primer registro contiene los encabezados
// (nombres) de las columnas, no datos.
// FMT=Fixed : indica que el los campos están en posiciones fijas y el tamaño
// de cada campo se especifican con un archivo SCHEMA.INI
// en el mismo directorio donde está el archivo a leer.
string connectionString =
@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\DirectorioDeArchivosTXT;" +
"Extended Properties='text;HDR=Yes;FMT=Fixed'";
DataTable dt = new DataTable("miTabla");
using (OleDbConnection conn = new OleDbConnection(connectionString))
using (OleDbDataAdapter da = new OleDbDataAdapter("SELECT * FROM jason.txt", conn))
{
da.Fill(dt);
}
// hacer algo con los datos en el DataTable
De hecho, lo único que cambió fue el parámetro FMT en el connectionString, el nombre del archivo y el directorio donde localizarlo. Sin embargo, para que esto funcione con archivos de posiciones fijas es necesario un paso adicional: especificar el tamaño (y tipo) de las columnas en el archivo.
Esto se hace mediante un archivo schema.ini que debe estar en el mismo directorio que el archivo que vas a leer. Consulta esta página para saber todas las opciones disponibles. En nuestro caso un archivo como el siguiente sería suficiente:
[jason.txt]
Format=FixedLength
Col1=Producto Char Width 40
Col2=Cantidad Long Width 10
Col3=Precio Double Width 10
Factorizando códigoSi generalizamos el código un poco, podemos extraer una función sencilla que pueda ser reutilizada en varios de nuestros programas. Esa rutina podría ser como esta, en donde le pasas como parámetros el tipo y archivo a leer y te regresa un DataTable poblado ya con los datos:
// asumiendo que tenemos
// using System.Data.OleDb;
// using System.Data;
// using System.IO;
public enum TipoDeArchivoPlano { Delimited, Fixed }
public static DataTable LeerArchivoPlano(
FileInfo archivo, bool tieneEncabezado, TipoDeArchivoPlano tipoDeArchivo )
{
if (!archivo.Exists)
throw new FileNotFoundException(
"No se encontró el archivo especificado");
string conEncabezado = tieneEncabezado ? "YES" : "NO";
string connectionString = String.Format(
@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};" +
"Extended Properties='text;HDR={1};FMT={2}'",
archivo.DirectoryName, conEncabezado, tipoDeArchivo.ToString());
DataTable dt = new DataTable("miTabla");
using (OleDbConnection conn = new OleDbConnection(connectionString))
using (OleDbDataAdapter da =
new OleDbDataAdapter("SELECT * FROM " + archivo.Name, conn))
{
da.Fill(dt);
}
return dt;
}
De manera que pueda ser llamado así:
DataTable dt = LeerArchivoPlano(
new FileInfo(@"C:\DirectorioDeArchivosCSV\jason.csv"),
true, TipoDeArchivoPlano.Delimited);
no entendí xq pones esta parte???
ResponderEliminarDe manera que pueda ser llamado así:
DataTable dt = LeerArchivoPlano(
new FileInfo(@"C:\DirectorioDeArchivosCSV\jason.csv"),
true, TipoDeArchivoPlano.Delimited);