开发者

How Read a Text File and Display it onto a TextBlock in Visual Studio (C#)

开发者 https://www.devze.com 2023-03-29 02:14 出处:网络
I am a newbie in Visual Studio (C#). I want to store a text read from a text file and display it on a TextBlock control, but just for a specified row. How can I do that?

I am a newbie in Visual Studio (C#). I want to store a text read from a text file and display it on a TextBlock control, but just for a specified row. How can I do that? I've try to search on the internet, and most of them just show the way to read and write.

I have one TextBlock (named 'FlashText'), and two Button (one for the 'Previous' button, another one is for the 'Next' button). What I want is, when I hit the 'Next' button, then the TextBlock showing a text read from a txt file on a specified row (for instance, the first row). And when I hit the 'Next' again, then the TextBlock should be show the second row text read from the file.

The purpose is to make a simple flash card. The code is here:

`

private void btnRight_Click(object sender, RoutedEventArgs e) { 
  string filePath = @"D:\My Workspaces\Windows Phone 7 Solution\SimpleFlashCard\EnglishFlashCard.txt"; 
  int counter = 0;
  string line; 
  System.IO.StreamReader file = new System.IO.StreamReader(filePath); 
  while((line = file.ReadLine()) != null) { 
    Console.WriteLine(line); 
    counter++; 
  } 
} 

file.Close(); 
FlashText.Text = Console.ReadLine();

`

Please help. Thanks a bunch.


UPDATE:

Recently the main code is:

public partial class MainPage : PhoneApplicationPage
{
    private FlashCard _flashCard;

    // Constructor
    public MainPage()
    {
        InitializeComponent();

        // This could go under somewhere like a load new flash card button or
        // menu option etc.
        try
        {
            _flashCard = new FlashCard(@"D:\My Workspaces\Windows Phone 7 Solution\FCard\MyDocuments\EnglishFlashCard.txt");
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void btnLeft_Click(object sender, RoutedEventArgs e)
    {
        DisplayPrevious();
    }

    private void btnRight_Click(object sender, RoutedEventArgs e)
    {
        DisplayNext();
    }

    private void DisplayNext()
    {
        try
        {
            FlashText.Text = _flashCard.GetNextLine();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    private void DisplayPrevious()
    {
        try
        {
            FlashText.Text = _flashCard.GetPreviousLine();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

And this is for the class 'FlashCard':

public class FlashCard
{
    private readonly string _file;
    private readonly List<string> _lines;

    private int _currentLine;

    public FlashCard(string file)
    {
        _file = file;
        _currentLine = -1;

        // Ensure the list is initialized
        _lines = new List<string>();

        try
        {
            LoadCard();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message); // This line got a message while running the solution
        }
    }

    private void LoadCard()
    {
        if (!File.Exists(_file))
        {
            // Throw a file not found exception
        }

        using (var reader = File.OpenText(_file))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                _lines.Add(line);
            }
        }
    }

    public string GetPreviousLine()
    {
        // Make sure we're not at the first line already
        if (_currentLine > 0)
        {
            _currentLine--;
        }

        return _lines[_currentLine]; //-- This line got an error
    }

    public string GetNextLine()
    {
        // Make sure we're not at the last line already
        if (_currentLine &开发者_运维问答lt; _lines.Count - 1)
        {
            _currentLine++;
        }

        return _lines[_currentLine]; //-- This line got an error
    }
}

I've got at error message while running the solution: Attempt to access the method failed: System.IO.File.Exists(System.String).

I've tried using breakpoint and while it's getting the LoadCard() method, it's directly thrown to the exception on the constructor. I've rechecked the txt path but it's true.

And I've also got an error message while hitting the 'Next' / 'Previous' button on 'return _lines[_currentLine];' line said: ArgumentOutOfRangeException was unhandled (It's occured on the GetPreviousLine() method if hitting the 'Previous' button and GetNextLine() method for the 'Next'.

Should you need more information I'm glad to provide it. :)


UPDATE 2

Here is the recent code:

public partial class MainPage : PhoneApplicationPage
{
    private string path = @"D:\My Workspaces\Windows Phone 7 Solution\FCard\EnglishFlashCard.txt";
    private List<string> _lines; //-- The error goes here
    private int _currentLineIndex;

    //private FlashCard _flashCard;

    // Constructor
    public MainPage()
    {
        InitializeComponent();
        //_lines = System.IO.File.ReadLines(path).ToList();

        if (File.Exists(path))
        {
            using (StreamReader sr = new StreamReader(path))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                    _lines.Add(line);
            }
        }

        CurrentLineIndex = 0;
    }

    private void btnLeft_Click(object sender, RoutedEventArgs e)
    {
        this.CurrentLineIndex--;
    }

    private void btnRight_Click(object sender, RoutedEventArgs e)
    {
        this.CurrentLineIndex++;
    }

    private void UpdateContentLabel()
    {
        this.FlashText.Text = _lines[CurrentLineIndex];
    }

    private int CurrentLineIndex
    {
        get {  return _currentLineIndex; }
        set
        {
            if (value < 0 || value >= _lines.Count) return;
            _currentLineIndex = value;
            UpdateContentLabel();
        }
    }
}

I've got the error on the line marked above said: Field 'FCard.MainPage._lines' is never assigned to, and will always have its default value null.


If you want to be able to read lines moving backward and forward within the file you'll either need to store all of the lines inside of an object (perhaps a List<string> or string array), or you'll have to manually reposition your cursor via a Seek method (such as FileStream.Seek). It will depend on how big the flash card file is. If it's very large (contains many lines), you may not want to store it all in memory, preferring instead the seek option.

Here is a sample loading the entire contents of the flash card:

namespace FlashReader
{
    public partial class Form1 : Form
    {
        // Hold your flash card lines in here
        private List<string> _lines;

        // Track your current line
        private int _currentLine;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Load up your file
            LoadFile(@"D:\Path\To\EnglishFlashCard.txt");
        }

Your load file could look something like this:

        private void LoadFile(string file)
        {
            using (var reader = File.OpenText(file))
            {
                _lines = new List<string>();

                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    _lines.Add(line);
                }
            }

            // Set this to -1 so your first push of next sets the current
            // line to 0 (first element in the array)
            _currentLine = -1;
        }

Your previous click could look like this:

        private void btnPrevious_Click(object sender, EventArgs e)
        {
            DisplayPrevious();
        }

        private void DisplayPrevious()
        {
            // Already at first line
            if (_currentLine == 0) return;

            _currentLine--;

            FlashText.Text = _lines[_currentLine];
        }

Your next button click could look like this:

        private void btnNext_Click(object sender, EventArgs e)
        {
            DisplayNext();
        }

        private void DisplayNext()
        {
            // Already at last line
            if (_currentLine == _lines.Count - 1) return;

            _currentLine++;

            FlashText.Text = _lines[_currentLine];
        }
    }
}

You would want to add some error checking of course (what if the file is missing etc.).

PS - I've compiled this code using a file with the following lines and confirmed that it works:

Line one 
Line two 
Line three 
Line four

UPDATE:

If you want to go with something more akin to an object-oriented approach, consider creating a FlashCard class. Something like this:

public class FlashCard
{
    private readonly string _file;
    private readonly List<string> _lines;

    private int _currentLine;

    public FlashCard(string file)
    {
        _file = file;
        _currentLine = -1;

        // Ensure the list is initialized
        _lines = new List<string>();

        try
        {
            LoadCard();
        }
        catch (Exception ex)
        {
            // either handle or throw some meaningful message that the card
            // could not be loaded.
        }
    }

    private void LoadCard()
    {
        if (!File.Exists(_file))
        {
            // Throw a file not found exception
        }

        using (var reader = File.OpenText(_file))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                _lines.Add(line);
            }
        }
    }

    public string GetPreviousLine()
    {
        // Make sure we're not at the first line already
        if (_currentLine > 0)
        {
            _currentLine--;
        }

        return _lines[_currentLine];
    }

    public string GetNextLine()
    {
        // Make sure we're not at the last line already
        if (_currentLine < _lines.Count - 1)
        {
            _currentLine++;
        }

        return _lines[_currentLine];
    }
}

Now you can instead do something like this in your main form:

public partial class Form1 : Form
{
    private FlashCard _flashCard;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // This could go under somewhere like a load new flash card button or
        // menu option etc.
        try
        {
            _flashCard = new FlashCard(@"c:\temp\EnglishFlashCard.txt");
        }
        catch (Exception)
        {
           // do something
        }
    }

    private void btnPrevious_Click(object sender, EventArgs e)
    {
        DisplayPrevious();
    }

    private void DisplayPrevious()
    {
        FlashText.Text = _flashCard.GetPreviousLine();
    }


    private void btnNext_Click(object sender, EventArgs e)
    {
        DisplayNext();
    }

    private void DisplayNext()
    {
        FlashText.Text = _flashCard.GetNextLine();
    }
}


You might separate the parsing phase from the displaying phase. First, read each row of your file and make a list of string of it:

List<string> list = new List<string>();
System.IO.StreamReader file = new System.IO.StreamReader(filePath); 
while(!file.EndOfStream)
{ 
  string line = file.ReadLine();
  list.Add(line);
} 
Console.WriteLine("{0} lines read", list.Count);
FlashText.Text = list[0];

Then, keep an id of the current item and display it in your block.

private int curId = 0;

// on next button click
if (curId < list.Count - 1)
  FlashText.Text = list[++curId];

// on prev button click
if (curId > 0)
  FlashText.Text = list[--curId];


I like the existing answers, but I think creating a class to represent a list of objects is overkill for this problem. I'd prefer to keep it simple - a list of string should just be represented by List<string>.

public partial class Form1 : Form
{
    private string path = @"D:\temp\test.txt";
    private List<string> _lines;
    private int _currentLineIndex;

    public Form1()
    {
        InitializeComponent();
        // if you're adding these using a reader then 
        // you need to initialize the List first...
        _lines = new List<string>();

        _lines = System.IO.File.ReadAllLines(path).ToList();
        CurrentLineIndex = 0;
    }
}

Three simple methods - one to handle the Back click, one to handle the Forward click, and one to update the label.

    private void BackButton_Click(object sender, EventArgs e)
    {
        this.CurrentLineIndex--;
    }

    private void ForwardButton_Click(object sender, EventArgs e)
    {
        this.CurrentLineIndex++;
    }

    private void UpdateContentLabel()
    {
        this.ContentLabel.Text = _lines[CurrentLineIndex];
    }

And when the CurrentLineIndex property is set, trigger the UpdateContentLabel()

    private int CurrentLineIndex
    {
        get {  return _currentLineIndex; }
        set
        {
            if (value < 0 || value >= _lines.Count) return;
            _currentLineIndex = value;
            UpdateContentLabel();
        }
    }


Use this function. It works for me, hope it helps you too

    private string ReadFile(string filePath)
    {
        //this verse is loaded for the first time so fill it from the text file
        var ResrouceStream = Application.GetResourceStream(new Uri(filePath, UriKind.Relative));
        if (ResrouceStream != null)
        {
            Stream myFileStream = ResrouceStream.Stream;
            if (myFileStream.CanRead)
            {
                StreamReader myStreamReader = new StreamReader(myFileStream);

                //read the content here
                return myStreamReader.ReadToEnd();
            }
        }
        return "NULL";
    }

Then use split function to split it on \n\r. In that way you will get the lines of the file. Store them in an array or list. Then call for the respective index on next or previous. Check for NULL before proceeding.

0

精彩评论

暂无评论...
验证码 换一张
取 消