[C#] Editar líneas de archivos de texto

Iniciado por DeMoNcRaZy, 2 Septiembre 2015, 23:10 PM

0 Miembros y 1 Visitante están viendo este tema.

DeMoNcRaZy

Buenas,

Tengo un problema a la hora de modificar las líneas (textos) que hay dentro de un archivo .txt

Código (csharp) [Seleccionar]

using (StreamWriter fileWrite = new StreamWriter(@"C:\Users\Usuario\Desktop\Textos\carpetaArchivos\" + nombreArchivo + ".txt"))
                {
                    using (StreamReader fileRead = new StreamReader(@"C:\Users\Usuario\Desktop\Textos\carpetaArchivos\" + nombreArchivo + ".txt"))
                    {
                        string line;
                        string txtUsuario;

                        while ((line = fileRead.ReadLine()) != null)
                        {
                            string[] datos = line.Split(new char[] { ' ' });
                            if (datos[0] != txtUsuario.Text)
                            {
                                fileWrite.WriteLine(line);
                            }

                        }
                    }
                }


Lo cual intento leer 2 líneas que tengo introducidas del archivo así:

Nombre: Bruce
Apellidos: Lee


Pero en txtUsuario.Txt me da el siguiente error:

Use of unassigned local variable "txtUsuario"

Por lo que no me deja editar los dos campos que tengo introducidos en el archivo.

Agradezco cualquier información adicional.
Me quedé un poco trabado en esta parte.

Gracias.

Saludos.
Esta página web no está disponible - Google Chrome

someRandomCode

Yuse lo que te dice es que estas usando la variable txtUsuario sin haberle asignado valor antes

DeMoNcRaZy

Si le asigno un valor no me muestra nada o me salta este error:



En esta línea:

Código (csharp) [Seleccionar]
using (StreamReader fileRead = new StreamReader(@"C:\Users\Usuario\Desktop\Textos\carpetaArchivos\" + nombreArchivo + ".txt"))

Que creo que puede ser por que estoy llamando dos veces al mismo proceso dentro del mismo.

Lo que quiero saber si esta es la manera correcta de editar dichas líneas dentro de un archivo de texto.

Saludos.
Esta página web no está disponible - Google Chrome

someRandomCode


DeMoNcRaZy

Gracias por las molestias/ayuda.

Al final he encontrado la manera de hacerlo de una manera más eficaz.

Código (csharp) [Seleccionar]

string path = @"C:\\Users\\Usuario\\Desktop\\Textos\\carpetaArchivos\\" + nombreArchivo + ".txt";

            string nombre = "Nombre: ";
            string apellidos = "Apellidos: ";

            Console.WriteLine("Introduzca el nombre:");
            string nuevoNombre = Console.ReadLine();
            Console.WriteLine("Introduzca el/los apellidos:");
            string nuevoApellido = Console.ReadLine();

            var lines = File.ReadAllLines(path);

            var replaced = lines.Select(x =>
            {
                if (x.StartsWith(nombre))
                    return nombre + nuevoNombre;
                if (x.StartsWith(apellidos))
                    return apellidos + nuevoApellido;
                return x;
            });

            File.WriteAllLines(path, replaced);

            Console.WriteLine("El archivo se ha modificado correctamente.");


Saludos.
Esta página web no está disponible - Google Chrome

DarK_FirefoX

Cita de: someRandomCode en  2 Septiembre 2015, 23:16 PM
Yuse lo que te dice es que estas usando la variable txtUsuario sin haberle asignado valor antes

Exacto estás declarando la variable txtUsuario y no le estás asignando ningun valor y luego estas comparando esa variable con otra.

Pero no solo eso!

Código (csharp) [Seleccionar]
if (datos[0] != txtUsuario.Text)

la clase string no contiene ninguna definición de propiedad o método de extensión que sea Text, así que en principio esto te daría error de compilación (De hecho, el intelissense (si estás en VS) te lo debe mostrar como error)

Salu2s

Eleкtro

#6
El problema lo has solucionado de la manera más incorrecta, ya que no has aprendido a cómo solucionar los errores que tenías, simplemente has preferido optar por utilizar otra metodología distinta para evitar encontrarte con esos errores. ¿te compensa?, piensalo.

Lee el comentario de @Dark_Firefox y si no entiendes algo pregunta hasta que lo entiendas, por que de lo contrario el mismo conflicto te va a volver a suceder una y otra vez y no sabrás por qué, ya que un objeto sin inicializar (accidentálmente) es un despiste humano muy típico, y algo muy sencillo de comprender y solucionar.




Cita de: YuseTist en  2 Septiembre 2015, 23:29 PMme salta este error:



En esta línea:
Código (csharp) [Seleccionar]
using (StreamReader fileRead = new StreamReader(@"C:\Users\Usuario\Desktop\Textos\carpetaArchivos\" + nombreArchivo + ".txt"))

El mensaje de error se explica por si mismo, justo antes de esa instrucción ya tienes el archivo abierto con esto:
Citar
Código (csharp) [Seleccionar]
Using fileWrite As New StreamWriter("C:\Users\Usuario\Desktop\Textos\carpetaArchivos\" + nombreArchivo + ".txt")

Cuando "abres" un archivo se crea un handle especial en el sistema, el cual no puedes compartir con otro proceso (ni con tu propio proceso) a menos que así lo indiques, entonces no puedes esperar mantener abierto el archivo para su lectura mientras al mismo tiempo intentas abrirlo de nuevo para su escritura, sin embargo, si que puedes mantenerlo abierto con ambos permisos al mismo tiempo.

Lo que puedes hacer es utilizar el overload que toma cómo parámetro un stream, de la siguiente manera:

Código (csharp) [Seleccionar]
using (FileStream fs = File.Open("C:\\file.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.None)) {

using (StreamReader sr = new StreamReader(stream: fs, encoding: Encoding.Default)) {

using (StreamWriter sw = new StreamWriter(stream: fs, encoding: Encoding.Default)) {

while (!(sr.EndOfStream)) {

                               string line = sr.ReadLine;
                               // Leer o escribir en el stream...

}

} // sw

} // sr

} // fs


De todas formas yo optaría por evitar el uso de StreamReader, StreamWriter y demás, ya que tu intención no es mantener el archivo abierto mientras le haces cambios durante el tiempo de vida del proceso (ej. un sistema de logging), es un cambio pequeño y sencillo así que no requiere más que la solución que encontraste usando LINQ, aunque es imprecisa, pues yo, siguiendo la linea del último ejemplo, y siendo consciente de "donde está todo escrito" y cómo lo está, sin posibilidad a errores, lo haría más bien así:

Código (vbnet) [Seleccionar]
   <Serializable>
   Public NotInheritable Class Contact

       Public Property Name As String
       Public Property Surname As String

   End Class

   Private Function GetContact(ByVal filePath As String) As Contact

       Const FieldName As String = "Nombre:"
       Const FieldSurname As String = "Apellidos:"

       Dim lines As IEnumerable(Of String) = File.ReadAllLines(filePath, Encoding.Default)

       If (lines.Count <> 2) Then
           Throw New Exception(message:="Número incorrecto de lineas.")
       End If

       Dim currentName As String =
           lines(0).Substring(lines(0).IndexOf(FieldName, StringComparison.OrdinalIgnoreCase) + FieldName.Length).
                Trim(" "c)

       Dim currentSurname As String =
           lines(1).Substring(lines(1).IndexOf(FieldSurname, StringComparison.OrdinalIgnoreCase) + FieldSurname.Length).
                Trim(" "c)

       Return New Contact With
              {
                  .Name = currentName,
                  .Surname = currentSurname
              }

   End Function

   Private Sub SetContact(ByVal filepath As String, ByVal contact As Contact)

       Const FieldName As String = "Nombre"
       Const FieldSurname As String = "Apellidos"

       Dim sb As New StringBuilder
       sb.AppendLine(String.Format("{0}: {1}", FieldName, contact.Name))
       sb.AppendLine(String.Format("{0}: {1}", FieldSurname, contact.Surname))

       File.WriteAllText(filepath, sb.ToString, Encoding.Default)

   End Sub


Para darle el siguiente uso:

Código (vbnet) [Seleccionar]
Dim filePath As String = "C:\file.txt"

Dim currentContact As Contact = GetContact(filePath)

Console.WriteLine(String.Format("Name...: {0}", currentcontact.Name))
Console.WriteLine(String.Format("Surname: {0}", currentcontact.Surname))

currentContact.Name = "Pepito"
currentContact.Surname = "Palotes"

Me.SetContact("C:\file.txt", currentContact)


Código traducido a C#:

Código (csharp) [Seleccionar]
[Serializable()]
public sealed class Contact
{

public string Name { get; set; }
public string Surname { get; set; }

}


Código (csharp) [Seleccionar]

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Text;

public sealed class Form1 : Form
{

private void Test()
{
string filePath = "C:\\file.txt";

Contact currentContact = GetContact(filePath);

Console.WriteLine(string.Format("Name...: {0}", currentContact.Name));
Console.WriteLine(string.Format("Surname: {0}", currentContact.Surname));

currentContact.Name = "Pepito";
currentContact.Surname = "Palotes";

this.SetContact("C:\\file.txt", currentContact);

}

private Contact GetContact(string filePath)
{

const string FieldName = "Nombre:";
const string FieldSurname = "Apellidos:";

IEnumerable<string> lines = File.ReadAllLines(filePath, Encoding.Default);

if ((lines.Count != 2)) {
throw new Exception(message: "Número incorrecto de lineas.");
}

string currentName = lines(0).Substring(lines(0).IndexOf(FieldName, StringComparison.OrdinalIgnoreCase) + FieldName.Length).Trim(' ');

string currentSurname = lines(1).Substring(lines(1).IndexOf(FieldSurname, StringComparison.OrdinalIgnoreCase) + FieldSurname.Length).Trim(' ');

return new Contact {
Name = currentName,
Surname = currentSurname
};

}


private void SetContact(string filepath, Contact contact)
{
const string FieldName = "Nombre";
const string FieldSurname = "Apellidos";

StringBuilder sb = new StringBuilder();
sb.AppendLine(string.Format("{0}: {1}", FieldName, contact.Name));
sb.AppendLine(string.Format("{0}: {1}", FieldSurname, contact.Surname));

File.WriteAllText(filepath, sb.ToString, Encoding.Default);

}

}

//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================





PEEEEEEEEERO... en mi humilde opinión debo mencionar que la metodología que empleas en el primer y el segundo ejemplo que has mostrado (y también la que yo he empleado en el último ejemplo de arriba) en realidad es bastante primitiva, ya que aprendiendo a cómo manipular un archivo de texto tipo "contacto" de esa manera en realidad no aprendes nada útil. Si fuese para otra cosa, tal vez, pero para contactos lo que deberías usar, repito, en mi opinión, sería la serialización de datos, no por la ofuscación de datos, sino simplemente por que aporta mucho más control y seguridad sobre las acciones que haces en el archivo, en lugar de tener que estar "partiendo" y evaluando string a string ya que hay muchos posibles fallos que necesitarían ser controlados manualmente. Al menos deberías probar la serialización de datos para familiarizarte con esto.

Un ejemplo:

(si quieres que los datos sean legibles, puedes utilizar la serialización XML)

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 05-September-2015
' ***********************************************************************
' <copyright file="SerializationUtil.vb" company="Elektro Studios">
'     Copyright (c) Elektro Studios. All rights reserved.
' </copyright>
' ***********************************************************************



' ESTA CLASE ESTÁ PARCIALMENTE DEFINIDA (O PARCIALMENTE CAPADA) SOLO PARA SATISFACER LAS NECESIDADES DE ESTA PREGUNTA.



#Region " Imports "

Imports System
Imports System.Data
Imports System.IO
Imports System.Linq
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Xml.Serialization

#End Region

''' <summary>
''' Contains related serialization utilities.
''' </summary>
Public NotInheritable Class SerializationUtil

#Region " Constructors "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Prevents a default instance of the <see cref="SerializationUtil"/> class from being created.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private Sub New()
   End Sub

#End Region

#Region " Private Methods "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="System.ArgumentException">
   ''' Wrong Serialization Format.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   <DebuggerHidden>
   Private Shared Function GetSerializer(Of T)(ByVal format As SerializationFormat) As Object

       Select Case format

           Case SerializationFormat.Binary
               Return New BinaryFormatter

           Case SerializationFormat.Xml
               Return New XmlSerializer(type:=GetType(T))

           Case Else
               Throw New ArgumentException(message:="Wrong Serialization Format.", paramName:="serializationFormat")

       End Select

   End Function

#End Region

#Region " Public Methods "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Serializes the data of an Object to the specified file, using the specified serialization format.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <typeparam name="T">
   ''' </typeparam>
   '''
   ''' <param name="obj">
   ''' The object to be serialized.
   ''' </param>
   '''
   ''' <param name="filepath">
   ''' The filepath where to save the serialized data.
   ''' </param>
   '''
   ''' <param name="format">
   ''' The serialization format.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   <DebuggerHidden>
   Public Shared Sub Serialize(Of T)(ByVal obj As T,
                                     ByVal filepath As String,
                                     ByVal format As SerializationFormat)

       Dim serializer As Object = SerializationUtil.GetSerializer(Of T)(format)

       Using fs As New FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.Read)

           Select Case serializer.GetType

               Case GetType(BinaryFormatter)
                   DirectCast(serializer, BinaryFormatter).Serialize(fs, obj)

               Case GetType(XmlSerializer)
                   DirectCast(serializer, XmlSerializer).Serialize(fs, obj)

           End Select

       End Using

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Deserializes the data of an Object from the specified file, using the specified deserialization format.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <typeparam name="T">
   ''' </typeparam>
   '''
   ''' <param name="filepath">
   ''' The filepath where from deserialize the serialized data.
   ''' </param>
   '''
   ''' <param name="format">
   ''' The serialization format.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   <DebuggerHidden>
   Public Shared Function Deserialize(Of T)(ByVal filepath As String,
                                            ByVal format As SerializationFormat) As T

       Dim serializer As Object = SerializationUtil.GetSerializer(Of T)(format)

       Using fs As New FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)

           Select Case serializer.GetType

               Case GetType(BinaryFormatter)
                   Return DirectCast(DirectCast(serializer, BinaryFormatter).Deserialize(fs), T)

               Case GetType(XmlSerializer)
                   Return DirectCast(DirectCast(serializer, XmlSerializer).Deserialize(fs), T)

           End Select

       End Using

   End Function

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Deserializes the data of an Object from the specified file, using the specified deserialization format.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <typeparam name="T">
   ''' </typeparam>
   '''
   ''' <param name="filepath">
   ''' The filepath where from deserialize the serialized data.
   ''' </param>
   '''
   ''' <param name="format">
   ''' The serialization format.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   <DebuggerHidden>
   Public Shared Sub Deserialize(Of T)(ByRef refObj As T,
                                       ByVal filepath As String,
                                       ByVal format As SerializationFormat)

       refObj = SerializationUtil.Deserialize(Of T)(filepath, format)

   End Sub

#End Region

End Class


Modo de empleo:

Código (vbnet) [Seleccionar]
<Serializable>
Public NotInheritable Class Contact

   Public Property Name As String
   Public Property Surname As String

End Class


Código (vbnet) [Seleccionar]
Public NotInheritable Class Form1 : Inherits Form

   Private Sub Form1_Load() Handles MyBase.Shown
       Test()
   End Sub

   Private Sub Test()

       Dim filePath As String = "C:\file.dat"

       Dim currentContact As Contact = GetContact(filePath)

       Console.WriteLine(String.Format("Name...: {0}", currentContact.Name))
       Console.WriteLine(String.Format("Surname: {0}", currentContact.Surname))

       currentContact.Name = "Pepito"
       currentContact.Surname = "Palotes"

       Me.SetContact("C:\file.dat", currentContact)

   End Sub

   Private Function GetContact(ByVal filePath As String) As Contact

       Return SerializationUtil.Deserialize(Of Contact)(filePath, SerializationFormat.Binary)

   End Function

   Private Sub SetContact(ByVal filepath As String, ByVal contact As Contact)

       SerializationUtil.Serialize(contact, filepath, SerializationFormat.Binary)

   End Sub

End Class


Todo traducido a C#:
Código (csharp) [Seleccionar]
// ***********************************************************************
// Author   : Elektro
// Modified : 05-September-2015
// ***********************************************************************
// <copyright file="SerializationUtil.vb" company="Elektro Studios">
//     Copyright (c) Elektro Studios. All rights reserved.
// </copyright>
// ***********************************************************************



// ESTA CLASE ESTÁ PARCIALMENTE DEFINIDA (O PARCIALMENTE CAPADA) SOLO PARA SATISFACER LAS NECESIDADES DE ESTA PREGUNTA.



#region " Usings "

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml.Serialization;

#endregion

/// <summary>
/// Contains related serialization utilities.
/// </summary>
public sealed class SerializationUtil
{

#region " Constructors "

/// ----------------------------------------------------------------------------------------------------
/// <summary>
/// Prevents a default instance of the <see cref="SerializationUtil"/> class from being created.
/// </summary>
/// ----------------------------------------------------------------------------------------------------
private SerializationUtil()
{
}

#endregion

#region " Private Methods "

/// ----------------------------------------------------------------------------------------------------
/// <exception cref="System.ArgumentException">
/// Wrong Serialization Format.
/// </exception>
/// ----------------------------------------------------------------------------------------------------
[DebuggerStepThrough()]
[DebuggerHidden()]
private static object GetSerializer<T>(SerializationFormat format)
{

switch (format) {

case SerializationFormat.Binary:

return new BinaryFormatter();
case SerializationFormat.Xml:

return new XmlSerializer(type: typeof(T));
default:

throw new ArgumentException(message: "Wrong Serialization Format.", paramName: "serializationFormat");
}

}

#endregion

#region " Public Methods "

/// ----------------------------------------------------------------------------------------------------
/// <summary>
/// Serializes the data of an Object to the specified file, using the specified serialization format.
/// </summary>
/// ----------------------------------------------------------------------------------------------------
/// <typeparam name="T">
/// </typeparam>
///
/// <param name="obj">
/// The object to be serialized.
/// </param>
///
/// <param name="filepath">
/// The filepath where to save the serialized data.
/// </param>
///
/// <param name="format">
/// The serialization format.
/// </param>
/// ----------------------------------------------------------------------------------------------------
[DebuggerStepThrough()]
[DebuggerHidden()]
public static void Serialize<T>(T obj, string filepath, SerializationFormat format)
{
object serializer = SerializationUtil.GetSerializer<T>(format);

using (FileStream fs = new FileStream(filepath, FileMode.Create, FileAccess.Write, FileShare.Read)) {

switch (serializer.GetType) {

case typeof(BinaryFormatter):
((BinaryFormatter)serializer).Serialize(fs, obj);

break;
case typeof(XmlSerializer):
((XmlSerializer)serializer).Serialize(fs, obj);

break;
}

}

}

/// ----------------------------------------------------------------------------------------------------
/// <summary>
/// Deserializes the data of an Object from the specified file, using the specified deserialization format.
/// </summary>
/// ----------------------------------------------------------------------------------------------------
/// <typeparam name="T">
/// </typeparam>
///
/// <param name="filepath">
/// The filepath where from deserialize the serialized data.
/// </param>
///
/// <param name="format">
/// The serialization format.
/// </param>
/// ----------------------------------------------------------------------------------------------------
[DebuggerStepThrough()]
[DebuggerHidden()]
public static T Deserialize<T>(string filepath, SerializationFormat format)
{

object serializer = SerializationUtil.GetSerializer<T>(format);

using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)) {

switch (serializer.GetType) {

case typeof(BinaryFormatter):

return (T)((BinaryFormatter)serializer).Deserialize(fs);
case typeof(XmlSerializer):

return (T)((XmlSerializer)serializer).Deserialize(fs);
}

}

}

/// ----------------------------------------------------------------------------------------------------
/// <summary>
/// Deserializes the data of an Object from the specified file, using the specified deserialization format.
/// </summary>
/// ----------------------------------------------------------------------------------------------------
/// <typeparam name="T">
/// </typeparam>
///
/// <param name="filepath">
/// The filepath where from deserialize the serialized data.
/// </param>
///
/// <param name="format">
/// The serialization format.
/// </param>
/// ----------------------------------------------------------------------------------------------------
[DebuggerStepThrough()]
[DebuggerHidden()]
public static void Deserialize<T>(ref T refObj, string filepath, SerializationFormat format)
{
refObj = SerializationUtil.Deserialize<T>(filepath, format);

}

#endregion

}

//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================


Código (csharp) [Seleccionar]
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;

public sealed class Form1 : Form
{

private void Form1_Load()
{
Test();
}


private void Test()
{
string filePath = "C:\\file.dat";

Contact currentContact = GetContact(filePath);

Console.WriteLine(string.Format("Name...: {0}", currentContact.Name));
Console.WriteLine(string.Format("Surname: {0}", currentContact.Surname));

currentContact.Name = "Pepito";
currentContact.Surname = "Palotes";

this.SetContact("C:\\file.dat", currentContact);

}

private Contact GetContact(string filePath)
{

return SerializationUtil.Deserialize<Contact>(filePath, SerializationFormat.Binary);

}


private void SetContact(string filepath, Contact contact)
{
SerializationUtil.Serialize(contact, filepath, SerializationFormat.Binary);

}
public Form1()
{
Shown += Form1_Load;
}

}


Código (csharp) [Seleccionar]
[Serializable()]
public sealed class Contact
{

public string Name { get; set; }
public string Surname { get; set; }

}

//=======================================================
//Service provided by Telerik (www.telerik.com)
//=======================================================


EDITO:
Ejemplo al utilizar la serialización XML:
Código (xml) [Seleccionar]
<?xml version="1.0"?>
<Contact xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Name>Pepito</Name>
  <Surname>Palotes</Surname>
</Contact>


Saludos.