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.
me salta este error:
En esta línea:
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:
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:
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í:
<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:
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#:
[Serializable()]
public sealed class Contact
{
public string Name { get; set; }
public string Surname { get; set; }
}
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(' ');
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)
' ***********************************************************************
' 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:
<Serializable>
Public NotInheritable Class Contact
Public Property Name As String
Public Property Surname As String
End Class
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#:
// ***********************************************************************
// 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:
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) {
((BinaryFormatter)serializer).Serialize(fs, obj);
break;
((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) {
return (T)((BinaryFormatter)serializer).Deserialize(fs);
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)
//=======================================================
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;
}
}
[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:
<?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.