Mostrando las entradas con la etiqueta CSV. Mostrar todas las entradas
Mostrando las entradas con la etiqueta CSV. Mostrar todas las entradas

miércoles, 18 de julio de 2018

Conferencia CEPS UNI - Aplicaciones Web en Tiempo Real con WebSockets

Conferencia sobre Aplicaciones Web en Tiempo Real con WebSockets

Comparto con ustedes la conferencia que di el Martes 17 de Julio del 2018 en el CEPS UNI por su 50 Aniversario. Gracias a Cesar Oceda por la invitación y a mis alumnos que asistieron.

En esta conferencia muestro algunos de mis utilitarios desarrollados en .NET como Generadores de Código, Compresores de Imágenes, Manejadores de Archivos de Office: xlsx, docx, pdf, etc.

También muestro la aplicación de búsqueda de RUCs de la SUNAT con Archivos de texto y ejemplos de WebSockets como Chats, Paint, Sheets, Mantenimientos de Tablas y Gráficos en Tiempo Real.

Al final se ve un ejemplo con Google Maps y una Carga Masiva de archivos CSV en Base de Datos de SQL Server (genérico).



miércoles, 29 de noviembre de 2017

Preguntas y Respuestas de Desarrollo Web en ASP.NET & JavaScript

A partir de este momento estaré inaugurando una nueva sección de videos en mi canal de youtube que consistirá en responder las dudas sobre desarrollo web, para lo cual los interesados deberán enviarme un correo con el siguiente formato:

Para: Luis.duenash@gmail.com
Asunto: Preguntas y Respuestas de Desarrollo Web .NET
Nombre Completo: Apellidos y Nombres
Ubicación Geográfica: Ciudad y País
Tipo de Perfil: Estudiante o Profesional
Lugar de: Estudio o Trabajo
Categoria de la Pregunta: Descrita mas abajo
Pregunta:
Lo mas detalla posible.....

Las Categorías pueden ser entre otras:

Lenguajes
- C#
- Visual Basic

.NET Framework
- ADO.NET
- Serialización
- Cifrado
- Reflection
- Programación Asíncrona
- Programación Paralela

ASP.NET
- Web Forms
- MVC

Servicios
- Servicios Web XML
- Servicios WCF
- Servicios Web API

Formatos de Datos
- Binario
- XML
- JSON
- CSV

Manejo de Archivos
- De Texto: TXT, CSV
- Office Open XML: XLSX, DOCX, PPTX
- Contenedores Comprimidos: OpenXPS y PDF
- Imagenes: Mapa de Bits (BMP, PNG, JPG, GIF) y Vectoriales (SVG)

Protocolos
- HTTP
- TCP
- Web Sockets

Front End
- JavaScritpt
- HTML
- CSS

Arquitecturas
- Orientada a Servicios (SOA)
- Distribuida con Capas (LDA)
- Ligera Sin Capas, etc.

Performance
- Lectura y Escritura de Archivos
- Concatenación de gran cantidad de datos
- Presentación en Pantalla de miles de registros o cientos de páginas
- Exportación e Importación de miles de registros
- Velocidad de Carga de una Página Web, etc.

Las preguntas No pueden ser sobre:
- Frameworks, como por ejemplo Entity Framework, LINQ, MyBatis, Hibernate, etc.
- Librerías, como por ejemplo jQuery, Angular, Bootstrap, Ember, React, DevExpress, etc.
En caso de preguntar sobre estos les explicaré porque no se debe usar (desventajas).

miércoles, 21 de diciembre de 2016

Presentación - Desarrollo de Software Ligero y Desconectado

Desarrollo de Software Ligero y Desconectado

Introducción

Comparto con ustedes una de mis presentaciones de este año sobre la Necesidad de una Nueva Arquitectura de Software de Alto Rendimiento (ASAR): Ligera, Desconectada, Segura y Disponible (LDSD) que busca cambiar el paradigma del desarrollo que actualmente esta orientado a la Reusabilidad (N-Capas, Servicios, Frameworks, Librerías, Plantillas, etc) y No a la Performance (que es algo que se necesita Urgente).

La actual arquitectura y los temas que se aprenden en todas partes del mundo solo llevan a que las Aplicaciones sean demasiado lentas ya que se conectan constantemente y ocupan todo el ancho de banda con los formatos existentes (XML, JSON), por lo cual es necesario desconectarse y usar un formato mas ligero (CSV).

En estos últimos años vengo trabajando mucho en este tema y mi intención es compartir con la mayor cantidad de personas mi visión sobre lo que debería corregirse en los Sistemas sino los problemas continuaran, es por eso comparto esta Presentación donde comento los Problemas de los Sistemas, las Causas y la Solución.

Presentación

Diapositiva 1

Diapositiva 2

Diapositiva 3

Diapositiva 4

Diapositiva 5

Diapositiva 6

Diapositiva 7

Diapositiva 8

Diapositiva 9

Diapositiva 10

Diapositiva 11

Diapositiva 12

Diapositiva 13

Diapositiva 14

Diapositiva 15

Diapositiva 16

Diapositiva 17

Diapositiva 18

Diapositiva 19

Comentario Final

Si su objetivo principal es que las aplicaciones sean rápidas, nada de lo que se enseña te va a ayudar en dicho objetivo, es decir, si aprendes el uso de Frameworks, Librerías, Plantillas, Patrones, etc, más el enfoque conectado, solo conseguirán que sus páginas sean mas lentas.

Mi aporte para resolver estos problemas los puedo resumir en lo siguiente:
1. Enviar la menor cantidad de archivos: La página, un solo JS, un solo CSS y un solo paquete con las imágenes.
2. Trabajar en forma desconectada para reducir el número de conexiones.
3. Usar CSV como formato de datos para el transporte y así reducir el ancho de banda.
4. Eliminar el uso de capas y bucles en el Back-End
5. Serializar los datos en el Servidor de Datos (SQL Server, Oracle, etc).
6. Trabajar con JavaScript la presentación, búsquedas, filtros, ordenaciones, paginaciones, exportaciones, importaciones, previews de archivos, etc.
7. Actualizar en tiempo real usando Sockets y no Servicios ni llamar constantemente al servidor, etc.

Este breve resumen es la implementación de mi Arquitectura Ligera y Desconectada que considero la alternativa mas eficiente para resolver el problema de la performance que es el "Gran Problema" y el más urgente de resolver.

La mayoría de desarrolladores solo piensan en "Crear" y aprenden muchas cosas que No servirán de nada y solo contribuirán a los problemas descritos en la presentación, los cuales pueden evitarse si uno entiende como funciona una aplicación.

Solo me queda aconsejar a los más jóvenes, sobre todo que recién empiezan, que no se dejen guiar por la moda y las "nuevas formas de desarrollar" que al final cuando trabajen se darán cuenta de que todo lo que estudiaron y las plantillas de arquitectura que les dieron para seguir No fueron las mejores.

En el colmo de la ignorancia, mucha gente que sigue el "Modelo Equivocado" y todavía se pregunta "Pero si ya aumentamos las características del Servidor (CPU, RAM, Disco, etc), porque las Aplicaciones siguen Lentas". La respuesta es simple: "NO es problema de Hardware, pero si de Software, en este caso de Aplicación" y la capacitación que seguiste, la arquitectura que elegiste y todo lo que aprendiste "No resolverá dicho problema".

Los que han visto mi trabajo en este último año y basta como prueba lo que hicimos este Domingo en el Seminario de JavaScript saben que en todos los extremos desde el Back-End hasta el Front-End mejoramos el tiempo de respuesta convirtiendo a la aplicación en "Super Rápida".

Para finalizar, quiero agradecer a todos mis alumnos que durante este año me permitieron mostrar mi trabajo y compartir muchos momentos de reflexión los cuales dieron sus frutos creando una arquitectura sólida en cuanto a performance, la cual vamos a mejorar al próximo año aumentando la seguridad, que son los principales problemas al cual debemos enfocarnos y en el cual trato de aportar algo.

martes, 2 de agosto de 2016

Videos - Carrito de Compras en ASP.NET MVC & JavaScript

Videos del Carrito de Compras en ASP.NET MVC & JavaScript

Quiero compartir con los que No asistieron a mi último taller y con los visitantes del Blog de otros países los videos de una aplicación completa en ASP.NET MVC & JavaScript que tiene un 20% de código en el servidor (C#) y un 80% de código en el cliente (JavaScript).

Partes de la Aplicación

La aplicación es un Carrito de Compras que trabaja con la BD Northwind a la cual se le aumento la tabla de Usuarios asociados a cada Cliente (para el Login y ordenar el Pedido).
Esta consta de 4 vistas o páginas:

- Login: Esta página permite el ingreso de un usuario y su clave, mas un código de Captcha.

- Categorias: Página que lista las Categorías de Productos.

- Productos: Página que lista los Productos de una cierta Categoría y permite agregar una cantidad al Carrito y también ir a ver.

- Pedidos: Página que permite mostrar los pedidos y cambiar su cantidad o eliminar un producto del pedido. También permite grabar el pedido al cliente.

Características Técnicas

Este Carrito de Compras tiene las siguientes características:

- Los controladores están protegidos por un Filtro de Autenticación usando una Sesión para el Cliente, es decir no se puede ir a ningún controlador o vista sino te autenticas (Login).

- Todas las llamadas al servidor son asíncronas con XHR (No jQuery, No Angular, etc)

- Todos los datos enviados al cliente se serializan a CSV (No XML ni JSON que son mas grandes por tener metadata).

- El Login usa un Captcha y cifrado en el cliente con WebCryptoAPI (No Librerías Externas JS)

- Todas las imágenes vienen en un solo viaje (No Sprite sino Serializado en Conjunto).

- Los datos del pedido se almacenan en el cliente con SessionStorage (No Session en el servidor).

- La grabación de la cabecera detalle es muy rápida ya que se pasa una cadena desde el cliente hasta el servidor web y de datos consumiendo una sola conexión y ejecutando un solo comando.

Videos del Carrito de Compras

Carrito de Compras Parte 1



Carrito de Compras Parte 2


Carrito de Compras Parte 3


Carrito de Compras Parte 4


Comentario Final

Este Carrito de Compras es totalmente distinto al que ven en la mayoría de sitios web que enseñan ASP.NET, ya que tiene muy poco código y trabaja casi desconectado donde toda la funcionalidad se construye con JavaScript y es 100% asíncrono con XHR.

No es un Carrito de Compras tradicional, es un "Formula 1" pura Performance usando JavaScript nativo que se ejecuta en cualquier Browser moderno.

Lástima que solo unos pocos pudieron apreciar esta interesante demostración de un nuevo tipo de aplicaciones. Para los que están en Lima y se atreven a pedir el código fuente, la respuesta es "hubieras participado en el taller" y para los del exterior pronto veremos la forma de que estos cursos se hagan virtuales (primero vería si tienen demanda, para lo cual están sus comentarios).

domingo, 31 de julio de 2016

Entrenamiento - Fin del Taller de ASP.NET MVC & JavaScript

Fin del Taller de ASP.NET MVC & JavaScript

Este post es para agradecer a los participantes de mi último taller de ASP.NET MVC & JavaScript de los Domingos. Como no hay certificados, la mejor constancia que han culminado el entrenamiento en técnicas desconectadas usando JavaScript nativo es publicar sus nombres para que las Empresas conozcan al grupo de personas que está preparada con una visión diferente del desarrollo.

Gracias a todos ustedes por compartir momentos educativos cada fin de semana. La lista de participantes por orden alfabético es la siguiente:

01 Aranda Rosales, Jaime Jesús
02 Beteta, Antonio
03 Cabrera Otoya, Jimmy
04 Chávez Córdova, Billy Herbert
05 Ciudad, Brayan
06 Condor Castillo, Edgar
07 Gaspar Chumpitaz, Oscar Michael
08 Huamaní García, Eduardo Felipe
09 Llontop Caballero, Jhony Frank
10 Marquez Redhead, Jorge Manuel
11 Miraya Anamaría, Edgar
12 Moreno Gomez, Juan Carlos
13 Palacios, Mario
14 Paredes Urbano, Gary W.
15 Palomino Oliva, Alan Francesco
16 Rengifo Ocrospoma, Joseph
17 Reyes Espinoza, Ray
18 Reyes, Alex
19 Rivera Molina, Pool
20 Saavedra Mejia, Miguel
21 Schwarz Moreno, Edward
22 Silva, Madeleyne
23 Tasayco Trigozo, José
24 Tito Fernandez, Erick
25 Vallejo Aguilar, Fernando
26 Vera Morocho, Edinson
27 Zambrano Pérez, Rolando José

Suerte a todos ustedes y éxito para salir a conquistar el mercado que están muy bien preparados, quizás en un nivel que todavía tomará tiempo que otros exploren.

miércoles, 4 de mayo de 2016

Entrenamiento - Nuevas Vacantes Segundo Taller de ASP.NET MVC & JavaScript

Nuevas Vacantes para el Segundo Taller de ASP.NET MVC & JavaScript

A todos los interesados en seguir el Taller que iniciamos este Domingo, les comunico que debido a que varias personas que se registraron y no llegaron a asistir, hay varias vacantes para poder seguir el entrenamiento que va a ser extremo.

Este Domingo (Día de la Madre) si habrá clases y los temas en homenaje a la madres de todos los desarrolladores serán:

1. Creación de Serializadores (desde DataTables y Listas de Objetos)
- Serializador XML
- Serializador JSON
- Serializador CSV

2. Llamadas Asíncronas al Servidor con XmlHttpRequest (XHR2)
- Textos
- Blob
- ArrayBuffer

Además presentaremos los Utilitarios de la Semana (como les prometí ese día):
- Convertidor MP3 (basado en Lame)
- Lector de Tablas de Páginas Web (incluyendo si están con Login o Seguridad de Formularios)

Finalmente, les copiaré mas de 100 Libros de .NET, HTML, JavaScript, CSS, etc.

Los interesados, ya saben que el costo para ex-alumnos que hubieran llevado conmigo un curso no hace mas de 5 años es de 200 soles, para los demás es de 300 soles. Solo tienen que enviar un mail a Luis.duenash@gmail.com para registrarlos y enviarles la dirección exacta que esta cerca a ISIL de Salaverry.

jueves, 12 de junio de 2014

El Demo del Día: Leer y Escribir Archivos de Texto usando Lista de Objetos

Leer y Escribir Archivos de Texto usando Lista de Objetos

Requerimiento
Se desea leer un archivo con registros separador por un carácter, por ejemplo por comas, punto y coma o por el símbolo "|".
Luego el usuario podrá modificar los registros existentes y al final debería grabar en el mismo archivo o si desea en otro archivo todo los registros.

Solución
La mejor solución es usar una Lista de Objetos debido a que esta consume menos memoria que el DataTable (exactamente la tercera parte) y se procesa mas rápido (la quinta parte aproximadamente), luego lo enlazamos a una grilla, en este caso el control DataGridView de WinForms y luego podemos grabar nuevamente el contenido de la Lista de Objetos en un archivo de texto.

Paso 1: Crear una Clase Genérica para crear los Métodos que usen la Lista de Objetos
using System.Reflection;
using System.IO;

namespace LeerCrearArchivoTextoLista
{
    public class ucTextoLista<T>
    {
    }
}

Paso 2: Función Genérica para Leer un Archivo de Texto en una Lista de Objetos
        public static List<T> TextoALista(string archivo, char separador)
        {
            List<T> lista = new List<T>();
            Type tipo = typeof(T);
            if (File.Exists(archivo))
            {
                using (StreamReader sr = new StreamReader(archivo))
                {
                    string[] cabeceras = sr.ReadLine().Split(separador);
                    if (cabeceras != null && cabeceras.Length > 0)
                    {
                        string[] campos = null;
                        object obe = null;
                        string tipoDato;
                        while (!sr.EndOfStream)
                        {
                            obe = Activator.CreateInstance(tipo);
                            campos = sr.ReadLine().Split(separador);
                            if (campos != null && campos.Length > 0)
                            {
                                for (int i = 0; i < campos.Length; i++)
                                {
                                    tipoDato =obe.GetType().GetProperty(cabeceras[i]).PropertyType.
                                                      ToString().ToLower();
                                    if (tipoDato.Contains("int16"))
                                    obe.GetType().GetProperty(cabeceras[i]).SetValue
                                      (obe, short.Parse(campos[i]));
                                    else
                                    {
                                        if (tipoDato.Contains("int32"))
                                        obe.GetType().GetProperty(cabeceras[i]).SetValue
                                          (obe, int.Parse(campos[i]));
                                        else
                                        {
                                            if (tipoDato.Contains("decimal"))
                                                obe.GetType().GetProperty(cabeceras[i]).SetValue
                                                  (obe, decimal.Parse(campos[i]));
                                            else obe.GetType().GetProperty(cabeceras[i]).
                                              SetValue(obe, campos[i]);
                                        }
                                    }
                                }
                            }
                            lista.Add((T)obe);
                        }
                    }
                }
            }
            return (lista);
        }

Paso 3: Función Genérica para Crear un Archivo de Texto desde una Lista de Objetos
        public static void ListaATexto(List<T> lista, string archivo, char separador)
        {
            using(FileStream fs = new FileStream(archivo, FileMode.Create, FileAccess.Write,
                    FileShare.Write))
            {
                using(StreamWriter sw = new StreamWriter(fs, Encoding.Default))
                {
                    PropertyInfo[] propiedades = lista[0].GetType().GetProperties();
                    for (int i = 0; i < propiedades.Length; i++)
                    {
                        sw.Write(propiedades[i].Name);
                        if (i < propiedades.Length - 1) sw.Write(separador);
                    }
                    sw.WriteLine();
                    for(int j = 0;j< lista.Count;j++)
                    {
                        propiedades = lista[j].GetType().GetProperties();
                        for (int i = 0; i < propiedades.Length; i++)
                        {
                            sw.Write(propiedades[i].GetValue(lista[j],null).ToString());
                            if (i < propiedades.Length - 1) sw.Write(separador);
                        }
                        sw.WriteLine();
                    }
                }
            }
        }

Paso 4: Archivo de Texto separados por un caractér (csv)
Crear un archivo de texto llamado "Productos.txt" con los siguientes datos:
ProductID,ProductName,SupplierID,CategoryID,UnitPrice,UnitsInStock
1,Chai,2,1,10.0000,76
2,Chang,7,4,3.0000,22
3,Chicha,10,1,10.0000,35
4,Chef Anton's Cajun Seasoning,2,2,22.0000,80
5,Chef Anton's Gumbo Mix,2,2,21.3500,31
6,Grandma's Boysenberry Spread,2,3,25.0000,50
7,Uncle Bob's Organic Dried Pears,3,7,30.0000,98
8,Northwoods Cranberry Sauce,3,2,40.0000,99
9,Mishi Kobe Niku,4,6,97.0000,96
10,Ikura,4,8,31.0000,93
..............................................................................

Paso 5: Crear una Clase Entidad para Almacenar los Productos
    public class beProducto
    {
        public int IdProducto { get; set; }
        public string Nombre { get; set; }
        public int IdProveedor { get; set; }
        public int IdCategoria { get; set; }
        public decimal PrecioUnitario { get; set; }
        public short Stock { get; set; }
    }

Paso 6: Crear un  Formulario con una Grilla que pueda usar las 2 Funciones
Asumiendo que las 2 funciones estáticas fueron creadas en una clase llamada "ucTextoLista" y hemos creado un formulario llamado: "frmPrueba" conteniendo un control DataGridView llamado: "dgvTexto" y 2 botones llamados: "btnLeerArchivoTxt" y "btnCrearArchivoTxt", tal como se muestra en la siguiente imagen:


Escribir el siguiente código en el formulario:
    public partial class frmPrueba : Form
    {
        List<beProducto> lista;

        public frmPrueba()
        {
            InitializeComponent();
        }

        private void btnLeerArchivoTxt_Click(object sender, EventArgs e)
        {
            lista = ucTextoLista<beProducto>.TextoALista("Productos.txt", ',');
            dgvTexto.DataSource = lista;
        }

        private void btnCrearArchivoTxt_Click(object sender, EventArgs e)
        {
            ucTextoLista<beProducto>.ListaATexto(lista,"Productos2.txt", ',');
            MessageBox.Show("Archivo de Texto creado");
        }
    }

Paso 7: Ejecutar la aplicación y Probar
Para ejecutar la aplicación se tiene que tener el archivo: "Productos.txt" en la carpeta bin/debug donde corre la aplicación con los datos descritos en el paso 4.
Primero dar clic al primer botón: "Leer Archivo Txt" y se cargarán los datos de los productos desde el archivo; luego ingresar nuevos registros, modificar los existentes y finalmente dar clic al botón "Crear Archivo Txt" y observar que se ha creado en la carpeta bin/debug el archivo "Productos2.txt".


Comentario:
Esta forma de leer y crear archivos de texto es mas rápida pero necesita conocer Reflection para trabajar con una Lista de Objetos y poder deducir sus propiedades, recuperar valores y asignar valores a cualquier tipo de objeto. Como pocos desarrolladores conocen el poder de Reflection se van por el "lado oscuro" (ineficiente pero fácil) y terminan trabajando con el DataSet, DataTable, DataView, XML, etc.

Descarga:
Demo02_LeerCrearArchivoTextoLista

miércoles, 11 de junio de 2014

El Demo del Día: Leer y Escribir Archivos de Texto usando DataTable

Leer y Escribir Archivos de Texto usando DataTable

Requerimiento
Se desea leer un archivo con registros separador por un carácter, por ejemplo por comas, punto y coma o por el símbolo "|".
Luego el usuario podrá modificar los registros existentes y al final debería grabar en el mismo archivo o si desea en otro archivo todo los registros.

Solución
Una alternativa sería leer el archivo y almacenarlo en un DataTable de ADO .NET (aunque no es lo mejor), luego lo enlazamos a una grilla, en este caso el control DataGridView de WinForms y luego podemos grabar nuevamente el contenido del DataTable a un archivo de texto.

Paso 1: Función Genérica para Leer un Archivo de Texto en un DataTable
        public static DataTable TextoATabla(string archivo, char separador)
        {
            DataTable tabla = new DataTable();
            if (File.Exists(archivo))
            {
                using (StreamReader sr = new StreamReader(archivo))
                {
                    string[] cabeceras = sr.ReadLine().Split(separador);
                    if (cabeceras != null && cabeceras.Length > 0)
                    {
                        for (int i = 0; i < cabeceras.Length; i++)
                        {
                            tabla.Columns.Add(cabeceras[i], Type.GetType("System.String"));
                        }
                        DataRow fila = null;
                        string[] campos = null;
                        while (!sr.EndOfStream)
                        {
                            fila = tabla.NewRow();
                            campos = sr.ReadLine().Split(separador);
                            if (campos != null && campos.Length > 0)
                            {
                                for (int i = 0; i < campos.Length; i++)
                                {
                                    fila[i] = campos[i];
                                }                              
                            }
                            tabla.Rows.Add(fila);
                        }
                    }
                }
            }
            return (tabla);
        }

Paso 2: Función Genérica para Crear un Archivo de Texto desde un DataTable
        public static void TablaATexto(DataTable tabla, string archivo,char separador)
        {
            using(FileStream fs = new FileStream(archivo, FileMode.Create, FileAccess.Write, 
                    FileShare.Write))
            {
                using(StreamWriter sw = new StreamWriter(fs, Encoding.Default))
                {
                    for(int i = 0;i< tabla.Columns.Count;i++)
                    {
                        sw.Write(tabla.Columns[i].ColumnName);
                        if(i<tabla.Columns.Count - 1) sw.Write(separador);
                    }
                    sw.WriteLine();
                    for(int j = 0;j< tabla.Rows.Count;j++)
                    {
                        for(int i = 0;i< tabla.Columns.Count;i++)
                        {
                            sw.Write(tabla.Rows[j][i].ToString());
                            if(i<tabla.Columns.Count - 1) sw.Write(separador);
                        }
                        sw.WriteLine();
                    }
                }
            }
        }
Nota: Ambas funciones usan el Namespace System.IO y System.Data

Paso 3: Archivo de Texto separados por un caractér (csv)
ProductID,ProductName,SupplierID,CategoryID,UnitPrice,UnitsInStock
1,Chai,2,1,10.0000,76
2,Chang,7,4,3.0000,22
3,Chicha,10,1,10.0000,35
4,Chef Anton's Cajun Seasoning,2,2,22.0000,80
5,Chef Anton's Gumbo Mix,2,2,21.3500,31
6,Grandma's Boysenberry Spread,2,3,25.0000,50
7,Uncle Bob's Organic Dried Pears,3,7,30.0000,98
8,Northwoods Cranberry Sauce,3,2,40.0000,99
9,Mishi Kobe Niku,4,6,97.0000,96
10,Ikura,4,8,31.0000,93
..............................................................................

Paso 4: Crear un  Formulario con una Grilla que pueda usar las 2 Funciones
Asumiendo que las 2 funciones estáticas fueron creadas en una clase llamada "ucTextoTabla" y hemos creado un formulario llamado: "frmPrueba" conteniendo un control DataGridView llamado: "dgvTexto" y 2 botones llamados: "btnLeerArchivoTxt" y "btnCrearArchivoTxt", tal como se muestra en la siguiente imagen:


Escribir el siguiente código en el formulario:
    public partial class frmPrueba : Form
    {
        DataTable tabla;

        public frmPrueba()
        {
            InitializeComponent();
        }

        private void btnLeerArchivoTxt_Click(object sender, EventArgs e)
        {
            tabla = ucTextoTabla.TextoATabla("Productos.txt", ',');
            dgvTexto.DataSource = tabla;
        }

        private void btnCrearArchivoTxt_Click(object sender, EventArgs e)
        {
            ucTextoTabla.TablaATexto(tabla,"Productos2.txt", ',');
            MessageBox.Show("Archivo de Texto creado");
        }
    }

Paso 5: Ejecutar la aplicación y Probar
Para ejecutar la aplicación se tiene que tener el archivo: "Productos.txt" en la carpeta bin/debug donde corre la aplicación con los datos descritos en el paso 3.
Primero dar clic al primer botón: "Leer Archivo Txt" y se cargarán los datos de los productos desde el archivo; luego ingresar nuevos registros, modificar los existentes y finalmente dar clic al botón "Crear Archivo Txt" y observar que se ha creado en la carpeta bin/debug el archivo "Productos2.txt".


Espero les guste el primer Demo y este fue un pedido. Ya saben que cualquier solicitud o requerimiento es bienvenida. No se olviden sus comentarios.

Descarga:
Demo01_LeerCrearArchivoTexto