none
Manipular archivos texto plano TXT (lectura, escritura) y luego filtrar cadenas de texto Windows Phone 8 RRS feed

  • Pregunta

  • Hola,

    Sinceramente no estoy a gusto con todos los ejemplos que he visto de base de datos por la web, ya que no he visto que se pueda hacer consultas digamos selectivas como si lo podría hacer en SQL Server o MySQL. (Claro que un txt no es un motor de base de datos) Es por esto que un poco me canse y decidi crear mi propia base de datos con simples archivos planos txt. Ya tengo experiencia de como hacerlo y crear mis clases para tener un mayor acceso y manipular la BD a mi gusto.

    Pero me estoy iniciando con aplicaciones en WP8 y obviamente tengo muchas dudas y dificultades.

    Tengo un problemita con el tema de abrir un archivo .txt (lectura y escritura)

    Tengo este código simple para abrir el archivo usuarios.txt:

    privatevoidbtnLeer_Click(objectsender, RoutedEventArgse)

    {

    // Obtener instancia del Almacenamiento Aislado

    IsolatedStorageFileisolatedStorage =IsolatedStorageFile.GetUserStoreForApplication();

    // Verificar si el archivo existe para evitar errores

    if(isolatedStorage.FileExists("BD/usuarios.txt"))

    {

    // Instancia de StreamReader para obtener y leer archivo almadenado

    using(StreamReaderreader =newStreamReader(isolatedStorage.OpenFile("BD/usuarios.txt", FileMode.Open, FileAccess.Read)))

    {

    // Lectura del archivo linea por linea, escribiéndolo en el control en pantalla.

    while(!reader.EndOfStream)

    {

     this.txtLista.Text +=reader.ReadLine();

    }

    }

    }

    else

    {

    MessageBox.Show("El archivo a leer no existe!");

    }

    }

    Pero no encuentra el archivo txt y por lo tanto muestra el mensaje del messagebox(El archivo a leer no exite). Ya he probado con diferentes rutas: "ms-appx///BD/usuarios.txt", o "ms-appx:///AppSetup/usuarios.txt" y ninguno funciona.

    Luego tengo este código para guardar:

    privatevoidbtnGuardar_Click(objectsender, RoutedEventArgse)

    {

    //Se obtiene instancia de almacenamiento aislado

    IsolatedStorageFileisolatedStorage =IsolatedStorageFile.GetUserStoreForApplication();

    //Instancia de StreamWriter para crear el archivo

    using(StreamWriterwriter =newStreamWriter(newIsolatedStorageFileStream

    ("BD/usuarios.txt", FileMode.Append, FileAccess.Write, isolatedStorage)))

    {//FileMode.Append hace que siempre se acumulen los datos al archivo

    //copiado de datos al archivo

    writer.WriteLine(string.Format("Nombre: {0}", "Nombre1"));

    writer.WriteLine(string.Format("Ciudad: {0}", "Ciudad1"));

    writer.Close();

    }

    }

    En este caso me muestra una excepción con el siguiente error en la primera línea del using:

    An exception of type 'System.IO.IsolatedStorage.IsolatedStorageException' occurred in mscorlib.ni.dll but was not handled in user code
    Additional information: Operation not permitted on IsolatedStorageFileStream.

    No se donde puede estar el problema. También imagino que deben existir otras formas de codificación de leer o escribir en archivos txt.

    Mi idea es que cuando se abre por primera vez la aplicación pueda tener acceso a dicho archivo txt para obtener los datos contenidos, como también tener acceso cuando la aplicación se esta ejecutando, tanto lectura como escritura.

    Desde ya agradezco sus opiniones y ayuda al respecto.

    Saludos

    Fabián

    viernes, 20 de noviembre de 2015 19:52

Todas las respuestas

  • El problema es que en cada compilación tu archivo txt no existe o está vacío y el Windows Phone no lo puede encontrar. Nuevamente, te recomiendo que utilices SQLite como motor de base de datos local para tus dispositivos Windows Phone.

    Aquí tienes un buen ejemplo. Uno que resulta un poco viejito está aquí.

    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile
    My code samples

    lunes, 23 de noviembre de 2015 11:26
  • El problema es que en cada compilación tu archivo txt no existe o está vacío y el Windows Phone no lo puede encontrar. Nuevamente, te recomiendo que utilices SQLite como motor de base de datos local para tus dispositivos Windows Phone.

    Aquí tienes un buen ejemplo. Uno que resulta un poco viejito está aquí.

    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile
    My code samplesTomaré en cuenta tu consejo en cuanto a usar SQLite. Aprovecho para preguntarte si en SQLite puedes hacer búsquedas de un registro solo con su ID o nombre de usuario, o que me devuelva los registros dada una fecha inicial y final (suponiendo que tengo una tabla en la cual tiene por ejemplo las columnas, ID, NomUsuario,FechaRegistro, etc...).  El archivo .txt si existe y no esta vacío. Yo lo agregue a mi proyecto. Es mas, ya encontré la solución. Ya instalé la aplicación en mi equipo WP con el archivo txt el cual contiene un texto como para probar y al abrir la aplicación por primera vez, al final lee perfectamente el archivo txt, como también pude guardar texto en el archivo. Ahora mi duda es como puedo hacer para que al guardar una cadena de texto no me remplace el ya existente y lo guarde en una siguiente línea. Este es mi código actual que guarda en el archivo pero elimina el texto existente:

    StorageFilefile =awaitStorageFile.GetFileFromApplicationUriAsync(newUri("ms-appx:///usuarios.txt"));

    using(StreamWritersWrite =newStreamWriter(awaitfile.OpenStreamForWriteAsync()))

    sWrite.WriteLine(this.txtTexto.Text);


    martes, 24 de noviembre de 2015 2:51
  • Tomaré en cuenta tu consejo en cuanto a usar SQLite. Aprovecho para preguntarte si en SQLite puedes hacer búsquedas de un registro solo con su ID o nombre de usuario, o que me devuelva los registros dada una fecha inicial y final (suponiendo que tengo una tabla en la cual tiene por ejemplo las columnas, ID, NomUsuario,FechaRegistro, etc...). 

    El archivo .txt si existe y no esta vacío. Yo lo agregue a mi proyecto. Es mas, ya encontré la solución. Ya instalé la aplicación en mi equipo WP con el archivo txt el cual contiene un texto como para probar y al abrir la aplicación por primera vez, al final lee perfectamente el archivo txt, como también pude guardar texto en el archivo. Ahora mi duda es como puedo hacer para que al guardar una cadena de texto no me remplace el ya existente y lo guarde en una siguiente línea. Este es mi código actual que guarda en el archivo pero elimina el texto existente:

    StorageFilefile =awaitStorageFile.GetFileFromApplicationUriAsync(newUri("ms-appx:///usuarios.txt"));

    using(StreamWritersWrite =newStreamWriter(awaitfile.OpenStreamForWriteAsync()))

    sWrite.WriteLine(this.txtTexto.Text);

    martes, 24 de noviembre de 2015 2:55
  • Hola FASA, me parece genial lo de SQLite y sí se puede realizar la búsqueda. Cualquier operación de base de datos se puede hacer con SQLite.

    En cuanto a tu código, puedes utilizar True en el constructor de la clase StreamWriter para adjuntar.

    StorageFilefile =await StorageFile.GetFileFromApplicationUriAsync(newUri("ms-appx:///usuarios.txt"));
    
    using(StreamWriter sWrite = new StreamWriter(awaitfile.OpenStreamForWriteAsync(), true))
    {
        sWrite.WriteLine(this.txtTexto.Text);
    }
    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile
    My code samples

    martes, 24 de noviembre de 2015 11:23
  • Hola FASA, me parece genial lo de SQLite y sí se puede realizar la búsqueda. Cualquier operación de base de datos se puede hacer con SQLite.

    En cuanto a tu código, puedes utilizar True en el constructor de la clase StreamWriter para adjuntar.

    StorageFilefile =await StorageFile.GetFileFromApplicationUriAsync(newUri("ms-appx:///usuarios.txt"));
    
    using(StreamWriter sWrite = new StreamWriter(awaitfile.OpenStreamForWriteAsync(), true))
    {
        sWrite.WriteLine(this.txtTexto.Text);
    }
    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile
    My code samples

    Hola Christian,

    Le puse el TRUE pero me sale un error. Adjunto un screenshot para que veas el error que muestra.

    Te quería preguntar si tienes algún ejemplo de como hacer una búsqueda usando SQLite por ID y entre dos fechas

    según lo comentado en el anterior mensaje.

    Como siempre gracias y saludos

    martes, 24 de noviembre de 2015 19:19
  • Hola FASA, lo puedes hacer de la siguiente manera:

    StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(@"ms-appx:///usuarios.txt"));
    
    await FileIO.AppendTextAsync(file, txtTexto.Text, UnicodeEncoding.Utf8);

    Con esto lograrás tu objetivo.

    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    MCP Profile
    My code samples

    jueves, 26 de noviembre de 2015 11:34
  • Que tal Christian...

    Al poner dicha instrucción me da un error y no encuentra el FileIO. No es un tema de referencias ya que contiene el using Windows.Storage. Pero luego de probar con un proyecto en WP 8.1, veo que si lo reconoce el FileIO, pero no para la versión 8.0.
    Lo que si me dio error ya sea para la versión 8.0 u 8.1 es al agregarle el UnicodeEncoding.UTF8, pero simplemente quitándolo funciona correctamente. Entonces el código me quedo de esta forma para la versión 8.1:

    StorageFilefile =awaitStorageFile.GetFileFromApplicationUriAsync(newUri("ms-appx:///usuarios.txt"));

    awaitFileIO.AppendTextAsync(file, "Probando Texto ");//, UnicodeEncoding.UTF8);

    En cuanto al proyecto con la versión 8.0, este es el error:

    Sinceramente mi idea era intentar hacer un proyecto pero para WP 8.0 ya que entiendo que es mas conveniente ya que abarca mayor cantidad de usuarios, todos los que tengan 8.0 mas todas las siguientes versiones.

    No se si estoy equivocado en pensar de esta forma, o me conviene iniciarme con las aplicaciones con WP 8.1...?

    Tu que me recomiendas?

    De todas formas si tienes algún ejemplo que funcione sobre la duda que venimos charlando sobre añadir texto en un archivo txt sin borrar lo que ya contiene pero que funcione para la versión 8.0 te lo voy a agradecer.

    Gracias y saludos

    jueves, 26 de noviembre de 2015 22:52
  • Fabianuy, pues recomiendo pasarte a Windows Phone 8.1 por funcionalidad y ahora que sale Windows 10 será 8.1 la plataforma estándar. En cuanto a lo de Windows Phone 8.0 aquí hay un ejemplo que puede servirte:

    private async System.Threading.Tasks.Task WriteToFile()
            {
                // Obtienes los datos desde un TextBox o donde sea. 
                byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes("Aquí va el texto".ToCharArray());
    
                // Obtienes la carpeta actual.
                StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
    
                // Obtienes la carpeta de datos del dispositivo.
                var dataFolder = await local.CreateFolderAsync("DataFolder",
                    CreationCollisionOption.OpenIfExists);
    
                // Creas un nuevo archivo usuarios.txt. Si existe lo abre.
                var file = await dataFolder.CreateFileAsync("usuarios.txt",
                CreationCollisionOption.OpenIfExists);
    
                // Escribes los datos obtenidos desde el TextBox.
                using (var s = await file.OpenStreamForWriteAsync())
                {
                    s.Seek(0, SeekOrigin.End);
                    s.Write(fileBytes, 0, fileBytes.Length);
                }
            }

    Espero resulte útil. 

    Saludos


    Christian Amado
    Software Engineer | MCPD: Windows Phone Developer | MCTS: Silverlight Developer
    Don't forget to mark the right answer and vote up if helps you.
    My Blog
    My code samples

    viernes, 27 de noviembre de 2015 11:42
  • Hola Christian

    Lamento decirte que tampoco funciono este ejemplo que me pasaste.

    Si bien no tira error pero creo que el problema es que no encuentra el archivo usuarios.txt entonces crea uno nuevo y lo guarda en otra dirección. Es como si tuviera dos archivos usuarios.txt.

    La única forma que por ahora puedo lograr guardar en mi archivo txt anexado en el proyecto previo a la depuración, y que luego la aplicación pueda guardar cadenas de texto en una siguiente línea dentro del archivo sin eliminar su contenido original es:

    Al darle "GuardarTXT", primero leo y obtengo todo su contenido y lo cargo ya sea en una variable tipo string o una array, etc.., luego simplemente agrego el texto al final de la variable string. Luego simplemente vuelvo a rescribir el archivo txt.

    Sinceramente intentaba no hacer este procedimiento ya que es mas código, mas cantidad de procesos y mayor uso de recursos (claro que en txt pequeño no hay problema, pero si tienes miles y miles de líneas es diferente). A parte no queda nada prolijo sabiendo que pueden existir herramientas que solo tendrían que anexar texto en la siguiente línea sin eliminar el existente.

    Aunque no resulte no quiero molestar mas, claro que si tu quieres puedes chequearlo y ver si encuentras alguna solución, de todas formas muchas gracias

    viernes, 27 de noviembre de 2015 19:31
  • Estimado:

    Para trabajar con archivos en Windows Phone Silverlight, tengo estos métodos que uso en todas mis apps:

    public bool ExisteArchivo(string fname)
            {
                var store = IsolatedStorageFile.GetUserStoreForApplication();
                
                return (store.FileExists(fname));
            }
    
    public string LeerArchivo(string fname)
            {
                var store = IsolatedStorageFile.GetUserStoreForApplication();
                string salida;
    
                try
                {
                    using (var f = store.OpenFile(fname, FileMode.Open))
                    {
                        using (var sr = new StreamReader(f))
                        {
                            salida = sr.ReadToEnd();
                        }
                    }
                }
                catch (Exception e)
                {
                    Debug.WriteLine("LeerArchivo: " + fname + ": " + e.Message);
                    return null;
                }
    
                return salida;
            }
    
    public void GuardarArchivo(string fname, string contenido)
            {
                var store = IsolatedStorageFile.GetUserStoreForApplication();
    
                try
                {
                    using (var f = store.OpenFile(fname, FileMode.OpenOrCreate))
                    {
                        using (var sr = new StreamWriter(f))
                        {
                            sr.Write(contenido);
                            sr.Flush();
                        }
                        //f.Flush();
                    }
                }
                catch (Exception e)
                {
                    Debug.WriteLine("GuardarArchivo: " + fname + ": " + e.Message);
                }
            }

    Este código funciona sin problemas. Los nombres de archivo que usan NO tienen ms-appx ni nada parecido. Te recomiendo leer lo siguiente para tener claro en qué versiones del sistema operativo (y con qué APIs) te funcionarán los protocolos ms-appx, appdata, y otros:

    https://msdn.microsoft.com/en-us/library/windows/apps/ff402541%28v=vs.105%29.aspx

    miércoles, 2 de diciembre de 2015 16:02
  • Estimado Ivan,

    Primero gracias por tu respuesta.

    También lamento decir que la función de leer el archivo tampoco funciono, teniendo en cuenta una aplicación para WP8.0 con Silverlight.

    public bool ExisteArchivo(string fname)

    {

    var store = IsolatedStorageFile.GetUserStoreForApplication();

    return (store.FileExists(fname)); }

    Le he pasado como parámetro mi archivo .txt de las dos formas: "usuarios.txt" y "ms-appx:///usuarios.txt" y de ninguna de las dos formas lo lee.

    Ten en cuenta que mi idea es que lea el archivo desde que se instala la aplicación en el simulador, no que crea el archivo luego que abra la aplicación. O sea, ya tengo un archivo usuarios.txt en mi proyecto con datos.

    una de las formas que me ha funcionado para leer archivos es la siguiente:

    stringfileContent;

    StorageFilefile =awaitStorageFile.GetFileFromApplicationUriAsync(newUri(@"ms-appx:///usuarios.txt"));

    using(StreamReadersRead =newStreamReader(awaitfile.OpenStreamForReadAsync()))

    fileContent =awaitsRead.ReadToEndAsync();

    this.txtLista.Text =fileContent;

    return;

    Rescatando todo lo comentado hasta ahora, creo que el manejo de archivos .txt con datos cargados previo a instalar la aplicación, y luego escribir en el mismo, etc., creo que esta un poco complicado en WP, y nada amigable...

    Saludos

    jueves, 3 de diciembre de 2015 21:31
  • Estimado:

    Tienes que diferenciar de los archivos que van con tu paquete de aplicación (que son parte de tu solución de Visual Studio) y los archivos del almacenamiento local de la aplicación (los datos de usuario). Para acceder a uno u otro existen distintos prefijos, que además son dependientes del framework que estés usando (Silverlight o Store Apps/XAML).

    En el link que puse en el posteo anterior aparece que para acceder a los archivos que son parte de tu paquete de aplicación tienes que usar appdata:/ (Silverlight) o ms-appx:/ (XAML/Windows Store).

    martes, 8 de diciembre de 2015 22:09
  • Hola Ivan,

    Tomando tu codigo de ejmplo tampoco funciona ya sea utilizando el appdata:/ o ms-appx:/. 

    Ninguna de las dos rutas encuentra el archivo que tengo por defecto incluido en mi solucion.

    Gracias de todos modos, saludos

    jueves, 10 de diciembre de 2015 2:33
  • Ojo que si en tu proyecto de VS tienes una carpeta Assets y adentro un archivo "usuarios.txt" tiene que tener Build Type: Content para que vaya incluído en tu paquete.

    Ese archivo lo referencias como appdata:/Assets/usuarios.txt o como ms-appdata:///local/Assets/usuarios.txt

    jueves, 10 de diciembre de 2015 13:40
  • Estimado Ivan

    Tampoco funciona de ninguna de las dos formas, tomando en cuenta el código que me pasaste.

    Ni siquiera encuentra el archivo, la funcional de "ExisteArchivo" siempre me devuelve False.

    Ya puse el archivo en la carpeta Assets, y el archivo tiene el Build Action en Content.

    Si tienes tiempo prueba el código y verás que no funciona.

    Gracias de todos modos, saludos

    lunes, 14 de diciembre de 2015 2:24
  • Fabian:

    Te sugiero lo siguiente: verifica que el archivo se esté adjuntando al paquete XAP. Esto lo puedes hacer abriendo el XAP con 7Zip, o inspeccionando la aplicación en tu teléfono con Windows Phone Power Tools: https://wptools.codeplex.com/

    Si el archivo está, significa que en el código se está referenciando mal. Si no está, es un problema al empaquetar.


    lunes, 14 de diciembre de 2015 16:44
  • Estimado Ivan,

    Este no es el caso ya que con el otro método que ya mencioné, el archivo lo lee perfectamente bien al instalarlo en el celular o ejecutándolo desde el simulador.

    Por lo tanto hay un error en el código que me estas pasando.

    Saludos

    viernes, 18 de diciembre de 2015 6:20