Problema en c# con lectura y escritura en un archivo de texto

Iniciado por Andesat, 3 Abril 2015, 20:54 PM

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

Andesat

Sucede que he estado aprendiendo c# y estoy dando apenas los primeros pasos. Buscando por ahí me encontre con un ejercicio que me parecía sencillo pero me he estancado :-[ y no estoy muy seguro de como resolverlo.

El ejercicio consistía en establecer un entero como contador, leer un documento de texto y copiar el contenido de este dentro de otro documento de texto, por cada quince caracteres copiados el contador disminuye en uno y al llegar a cero la copia se detiene durante cinco segundos.

Ahora viene en donde me da problemas. Una vez terminados los cinco segundos, el contador vuelve al valor original continua la copia de texto y si esta no se terminó, debe retomarla desde donde quedó la última vez y seguir copiado hasta que el contador llegue a cero nuevamente o hasta que termine de copiar, lo que suceda primero ypor ultimo avisar si la copia terminó.

No se como hacer para que empiece a copiar desde donde quedó y la verdad no quisiera dejar esto sin hacer despues de haberme interesado.

Estoy usando c# 5.0 en visual studio 2012.

Agradecería la ayuda ;D
Un hombre sabio puede aprender más de una pregunta absurda que un tonto puede aprender de una respuesta sabia

DarK_FirefoX

Creo que si pones el código de lo que tienes hecho te podríamos ayudar más. Porque así me vienen varias cosas a la mente, pero sabiendo lo que tienes hecho te podría ayudar de una manera más concisa

Salu2s

Andesat

#2
Claro!
Disculpa la demora es que hubo un apagón.

Código (csharp) [Seleccionar]
           Console.WriteLine("Ingrese ruta del archivo de origen: ");
           string rutaO = Console.ReadLine();
           
           Console.WriteLine("Ingrese ruta del archivo de destino: ");
           string rutaD = Console.ReadLine();

           Console.WriteLine("Ingrese el contador: ");
           int cont = int.Parse(Console.ReadLine());

           StreamReader sr = new StreamReader(rutaO);
           string contenido = sr.ReadToEnd();
           sr.Close();

           StreamWriter sw = new StreamWriter(rutaD, true);

           
           while (cont > 0)
           {
               for (int i = 0; i < 15; i++)
               {
                   char Caracter = contenido[i];
                   sw.Write(Caracter);
               }
               cont--;
           }

           Console.ReadKey();


Esto es lo que intenté hacer al final pero no me funcionó
Un hombre sabio puede aprender más de una pregunta absurda que un tonto puede aprender de una respuesta sabia

Eleкtro

#3
No vas del todo mal encaminado, aunque también podrías hacerlo con una pila de caracteres.

Te muestro una posible solución siguiendo el enfoque que le has dado, puedes trasladarlo a tu aplicación de consola.

VB.Net:
Código (vbnet) [Seleccionar]
Imports System.IO
Imports System.Text
Imports System.Threading.Interlocked
Imports System.Threading.Thread

Public Class Form1

   Private Sub Test() Handles MyBase.Shown

       Writer(sourceFilepath:="C:\Source.txt",
              targetFilepath:="C:\Target.txt",
              maxChars:=15,
              sleepCount:=3,
              sleepInterval:=5 * 1000)

   End Sub

   Public Sub Writer(ByVal sourceFilepath As String,
                     ByVal targetFilepath As String,
                     ByVal maxChars As Integer,
                     ByVal sleepCount As Integer,
                     ByVal sleepInterval As Integer)

       Dim cloneSleepCount As Integer = sleepCount

       Dim charCount As Integer = -1
       Dim sr As StringReader = New StringReader(File.ReadAllText(sourceFilepath, Encoding.Default))
       Dim sw As New StringWriter

       Do Until (sr.Peek = -1)

           sw.Write(Convert.ToChar(sr.Read))

           If (Increment(charCount) = maxChars) OrElse (sr.Peek = -1) Then

               If Decrement(cloneSleepCount) = 0 Then
                   Debug.WriteLine(String.Format("Deteniendo por {0} ms...", sleepInterval))
                   Sleep(sleepInterval)
                   cloneSleepCount = sleepCount - 1
               End If

               Debug.WriteLine(String.Format("Copiando {0} caracteres: '{1}'", charCount, sw.ToString))
               File.AppendAllText(targetFilepath, sw.ToString, Encoding.Default)

               charCount = -1
               sw.GetStringBuilder.Clear()

           End If

       Loop

       sr.Close()
       sw.Close()
       Debug.WriteLine("Copia terminada.")

   End Sub

End Class


Traducción online a C#:
Código (csharp) [Seleccionar]
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading.Interlocked;
using System.Threading.Thread;

public class Form1
{

private void Test()
{
Writer(sourceFilepath: "C:\\Source.txt", targetFilepath: "C:\\Target.txt", maxChars: 15, sleepCount: 3, sleepInterval: 5 * 1000);
}

public void Writer(string sourceFilepath, string targetFilepath, int maxChars, int sleepCount, int sleepInterval)
{
int cloneSleepCount = sleepCount;

int charCount = -1;
StringReader sr = new StringReader(File.ReadAllText(sourceFilepath, Encoding.Default));
StringWriter sw = new StringWriter();

while (!((sr.Peek == -1))) {

sw.Write(Convert.ToChar(sr.Read));

if ((Increment(charCount) == maxChars) || (sr.Peek == -1)) {

if (Decrement(cloneSleepCount) == 0) {
Debug.WriteLine(string.Format("Deteniendo por {0} ms...", sleepInterval));
Sleep(sleepInterval);
cloneSleepCount = sleepCount - 1;
}

Debug.WriteLine(string.Format("Copiando {0} caracteres: '{1}'", charCount, sw.ToString));
File.AppendAllText(targetFilepath, sw.ToString, Encoding.Default);

charCount = -1;
sw.GetStringBuilder.Clear();
}
}

sr.Close();
sw.Close();
Debug.WriteLine("Copia terminada.");
}
}

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


Saludos








DarK_FirefoX

#4
Bueno, siguiendo de acuerdo al código que ya escribiste, te voy a tratar de explicar lo que puedes hacer.

Lo que tenías está bastante bien. Verás en el siguiente código, una manera diferente de usar los StreamReadery StreamWriter, te explico.

Utilizando el using, garantizamos que el stream se cree y a la vez dentro del ámbito del using este abierto, luego que se salga de ese ámbito, el stream automáticamente se cierra. Gracias a esta funcionalidad podemos hacer uso del método Peek() que te devuelve el próximo caracter disponible (sin consumirlo), este método devuelve un int, entonces devuelve -1 si no hay chars para leer por lo tanto utilizamos eso para controlar el ciclo, ahora, este puntero es modificado por varios métodos de la clase StreamReader. Como por ejemplo el que utilicé: ReadBlock(). El cuál recibe varios parámetros, un array de char (char[]), el cuál va a servir como un buffer para ir almacenando en este caso los 15 chars leídos (debes declararlo e iniciarlo previamente como verás en el código. El otro parámetro es la posición en cual va a comenzar a copiar los chars en el buffer, en este caso 0, para que sea desde el principio. Y por último, la cantidad de chars a leer del fichero, 15 en este caso.

Luego la otra linea se ejecuta sobre el StreamWriter, es el método Write(), el cual tiene varias sobrecargas (varias definiciones del método donde cambian los tipos de parámetros y/o la cantidad). En particular tiene una que recibe un array de char (char[]), o sea un buffer. Por lo tanto le pasamos el buffer que teníamos anteriormente y el escribirá en el StreamWriter los chars en ese array.

Por ultimo, tienes que añadir a los usings de tu aplicación:

Código (csharp) [Seleccionar]
using System.Threading;

para poder hacer uso del método estático

Código (csharp) [Seleccionar]
Thread.Sleep(5000);

Donde 5000 significan los 5s, pues el método recibe como parámetro un int que son la cantidad de milisegundos que te va a suspender el hilo actual (esperar).

Aquí te dejo el código:

Código (csharp) [Seleccionar]
Console.WriteLine("Ingrese ruta del archivo de origen: ");
           string rutaO = Console.ReadLine();

           Console.WriteLine("Ingrese ruta del archivo de destino: ");
           string rutaD = Console.ReadLine();

           Console.WriteLine("Ingrese el contador: ");
           int cont = int.Parse(Console.ReadLine());

           using (StreamReader sr = new StreamReader(rutaO))
           {
               using(StreamWriter sw = new StreamWriter(rutaD))
           {
                   int i = cont;

                       while (sr.Peek() != -1)
                       {
                           if (i == 0)
                           {
                               Thread.Sleep(5000);
                               i = cont;
                           }
                           char[] buffer = new char[15]; //creamos e inicializamos el array de char para usarlo como buffer
                           sr.ReadBlock(buffer, 0, 15); //Lee y copia en el buffer desde el StreamReader
                           sw.Write(buffer); //Escribe en el StreamWriter desde el buffer
                           i--;
                       }
                   
           }
           }


Espero lo hayas entendido todo, trate de explicarte lo mejor posible.
Dinos como te funcionó.

Saludos

Andesat

#5
Gracias a todos por tomarse el tiempo para responder a mi pregunta!

DarK_FirefoX, todo esta muy bien explicado, y funciona perfecto para lo que estoy haciendo.

He aprendido algo nuevo hoy, muchas gracias.

Saludos.
Un hombre sabio puede aprender más de una pregunta absurda que un tonto puede aprender de una respuesta sabia

DarK_FirefoX

Cita de: Andesat en  4 Abril 2015, 04:50 AM
Gracias a todos por tomarse el tiempo para responder a mi pregunta!

DarK_FirefoX, todo esta muy bien explicado, y funciona perfecto para lo que estoy haciendo.

He aprendido algo nuevo hoy, muchas gracias.

Saludos.

Un placer!, que bueno que todo se haya entendido. Cualquier otra duda, ya sabes ;)
Salu2s