-2

im building an WPF application in which i have a textbox, but the problem is that this textbox needs to get the contents of a file as text, only the txt file keeps getting written too.

i have made a class to handle this:

public class ChatHandler
{
    public FileStream stream;
    StreamWriter writer;
    StreamReader reader;

    public ChatHandler()
    {
        stream = new FileStream(@"chat/" + DateTime.Today.ToString("d") + ".txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
        writer = new StreamWriter(stream);
        reader = new StreamReader(stream);
    }

    public void Write(string line)
    {
        writer.WriteLineAsync(line);
        writer.Flush();
    }

    public string Read()
    {
        string tmp = "";
        string line;
        while((line = reader.ReadLine()) != null){
            tmp += line + '\n';
        }
        return tmp;
    }
}

and i have a user control which has the textbox:

public partial class ChatScreen : UserControl
{
    MainWindow parent;
    ChatHandler chatHandler;
    BackgroundWorker worker;
    public ChatScreen()
    {
        InitializeComponent();
        chatHandler = new ChatHandler();

        worker = new BackgroundWorker();
        worker.WorkerSupportsCancellation = true;
        worker.DoWork += new DoWorkEventHandler(run);
    }

    private void load()
    {

    }

    private void write(string text)
    {
        if (chat.Text != text && text != "")
        {
            chat.Text = text;
        }
    }

    private void run(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bg = sender as BackgroundWorker;
        while (!bg.CancellationPending)
        {
            chat.Dispatcher.BeginInvoke((Action)(()=>{
                write(parent.Handler.Read());                    
            }));
            Thread.Sleep(100);
        }
    }

    private void chat_Loaded(object sender, RoutedEventArgs e)
    {
        parent = (MainWindow)Window.GetWindow(this);
        if (!worker.CancellationPending)
        {
            worker.RunWorkerAsync();
        }

    }

    private void chat_Unloaded(object sender, RoutedEventArgs e)
    {
        worker.CancelAsync();
    }
}

but now the problem occurs: the text is never changed, it gets set once and is never changed at all anymore :( eventhough in the text file the lines are getting added.

the content of the xaml file are:

<UserControl x:Class="tantiBotv2.ChatScreen"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="381" d:DesignWidth="641" Loaded="chat_Loaded" Unloaded="chat_Unloaded">
    <Grid Style="{StaticResource ContentRoot}">
        <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Visible">
            <TextBox IsReadOnly="true" Margin="0,0,0,0" TextWrapping="Wrap" Name="chat" IsReadOnlyCaretVisible="false"/>
        </ScrollViewer>
    </Grid>
</UserControl>

can anyone please help me with this problem?

  • You haven't either provided the complete code or you have forgotten to set Read and Set Text value to the TextBox. Where do you read and set Text? – CharithJ Aug 16 '15 at 22:10
  • the read is inside the handler class AND is called inside the backgroundworker as visible in the code – Giovanni Le Grand Aug 16 '15 at 22:12

1 Answers1

1

I cannot reproduce your exact problem, the problem I get is that only new text in the text file appears. This is because the StreamReader is a member variable and it is a forward only reader. You can fix this by doing:

public string Read()
{
    using (var stream = new FileStream(@"chat.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
    {
        using (var reader = new StreamReader(stream))
        {
            string tmp = "";
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                tmp += line + '\n';
            }
            return tmp;
        }
    }
}

EDIT: After the problem was clarified a bit more:

XAML:

<Grid>

    <Grid.ColumnDefinitions>
        <ColumnDefinition></ColumnDefinition>
        <ColumnDefinition></ColumnDefinition>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>

    <DockPanel Grid.Column="0" LastChildFill="True">
        <Label DockPanel.Dock="Top">IRC channel simulator</Label>
        <Button DockPanel.Dock="Top" Click="Button_Click">Send Chat</Button>
        <ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Visible">
            <TextBox Background="AliceBlue" AcceptsReturn="True" Margin="0,0,0,0" TextWrapping="Wrap" Name="chatWriter" IsReadOnlyCaretVisible="false" />
        </ScrollViewer>
    </DockPanel>

    <ScrollViewer Grid.Column="1" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Visible">
        <TextBox IsReadOnly="true" Margin="0,0,0,0" TextWrapping="Wrap" Name="chat" IsReadOnlyCaretVisible="false"/>
    </ScrollViewer>
</Grid>

Code Behind Xaml:

public partial class MainWindow : Window
{
    ChatHandler chatHandler;
    BackgroundWorker worker;

    public MainWindow()
    {
        InitializeComponent();

        chatHandler = new ChatHandler();

        worker = new BackgroundWorker();
        worker.WorkerSupportsCancellation = true;
        worker.DoWork += new DoWorkEventHandler(run);
    }

    private void write(string text)
    {
        if (chat.Text != text && text != "")
        {
            chat.Text = text;
        }
    }

    private void run(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker bg = sender as BackgroundWorker;
        while (!bg.CancellationPending)
        {
            chat.Dispatcher.BeginInvoke((Action)(() => {
                write(chatHandler.Read());
            }));
            Thread.Sleep(100);
        }
    }

    private void chat_Loaded(object sender, RoutedEventArgs e)
    {
        if (!worker.CancellationPending)
        {
            worker.RunWorkerAsync();
        }
    }

    private void chat_Unloaded(object sender, RoutedEventArgs e)
    {
        worker.CancelAsync();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        chatHandler.Write(chatWriter.Text);
    }
}

ChatHandler.cs

public class ChatHandler
{
    public FileStream stream;
    //StreamWriter writer;
    //StreamReader reader;

    public ChatHandler()
    {
        stream = new FileStream(@"chat.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
        //writer = new StreamWriter(stream);
        //reader = new StreamReader(stream);
    }

    public void Write(string line)
    {
        using (var fileStream = new FileStream(@"chat.txt", FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
        {
            using (var writer = new StreamWriter(fileStream))
            {
                writer.WriteLineAsync(line);
                writer.Flush();
            }
        }
    }

    public string Read()
    {
        using (var fileStream = new FileStream(@"chat/" + DateTime.Today.ToString("d") + ".txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            using (var reader = new StreamReader(fileStream))
            {
                string tmp = "";
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    tmp += line + '\n';
                }
                return tmp;
            }
        }
    }
}
Ruskin
  • 1,504
  • 13
  • 25
  • is it really needed to make a new instance of streamreader and filestream everytime i want to read from the file, the way that i use the writer works perfectly so why wont the reader? they are both setup the same and use the same filestream to make the reader and writer from – Giovanni Le Grand Aug 16 '15 at 22:14
  • Your writer works because it always appends to the file. You can do complicated stuff like moving the StreamReader around, your call. You need to brush up on your Stream understanding...This might help. http://cc.davelozinski.com/c-sharp/the-fastest-way-to-read-and-process-text-files – Ruskin Aug 16 '15 at 22:16
  • so basicly the reader only holds the file as of the load instead of also reads the added files? – Giovanni Le Grand Aug 16 '15 at 22:17
  • No, like I said, I couldn't reproduce your exact problem. Although I can see an issue with the fact that when you read the first time (on load) your stream reader has a pointer which then moves to the next index/pointer. No matter what you do to text above/before that index/pointer, that text won't be read because your pointer has moved on. – Ruskin Aug 16 '15 at 22:20
  • i tried your exact code and its still the same as before, only shows the actual content on load – Giovanni Le Grand Aug 16 '15 at 22:22
  • Interesting. How/who writes to chat.txt document? – Ruskin Aug 16 '15 at 22:24
  • the chatHandler writes to the chat/(date).txt and also reads from the file – Giovanni Le Grand Aug 16 '15 at 22:26
  • Unrelated note: That could all be replaced by a call to `System.IO.File.ReadAllText`... or at the very least it should use a `StringBuilder`. – Chris Aug 16 '15 at 22:27
  • i have actually tried to use the file.readalltext but this is impossible since the writer writes to the file almost every 10 milliseconds – Giovanni Le Grand Aug 16 '15 at 22:29
  • So your textbox writes in itself the contents of the file which it reads and when it writes it writes back to the file? Am I the only one who is lost...can you please clarify your problem statement because judging from all the comments, no one can really understand the problem! – Ruskin Aug 16 '15 at 22:35
  • no the textbox should only display the contents of a file, the file is being filled by reading a line from an irc channel – Giovanni Le Grand Aug 16 '15 at 22:37
  • Okay, according to that the edited solution works as expected. Your solution to the problem is very flaky IMO but you can clean that up as you go. – Ruskin Aug 16 '15 at 23:03
  • this does work except that he only reads the last line now :S – Giovanni Le Grand Aug 16 '15 at 23:19
  • Brings us back to the original problem about the pointer/index for stream reader. Your understanding of Streams and Files is a bit weak, please read up on that and then see if you can fit that into your solution! – Ruskin Aug 16 '15 at 23:23