windows - Sådan læses en tekstfil og viser den på en tekstblok i Visual Studio (C #)

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg er nybegynder i Visual Studio (C #). Jeg vil gemme en tekst, der læses fra en tekstfil og vise den på en TextBlock-kontrol, men kun for en bestemt række. Hvordan kan jeg gøre det?
Jeg har forsøgt at søge på internettet, og de fleste af dem viser bare vejen til at læse og skrive.


Jeg har en TextBlock (kaldet 'FlashText'), og to knapper (den ene til 'Forrige' knappen, en anden er til 'Næste' knappen). Hvad jeg vil, er, når jeg rammer knappen 'Næste', så viser TextBlock en tekst, der læses fra en txt-fil på en bestemt række (for eksempel den første række). Og når jeg slår 'Næste' igen, så skal TextBlock vise den anden række tekst, der læses fra filen.


Formålet er at lave et simpelt flashkort. Koden er her:


`


private void btnRight\_Click(object sender, RoutedEventArgs e) { 
  string filePath = @"D:My WorkspacesWindows Phone 7 SolutionSimpleFlashCardEnglishFlashCard.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();


`


Hjælp venligst. Mange tak.





UPDATE:


For nylig er hovedkoden:


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 WorkspacesWindows Phone 7 SolutionFCardMyDocumentsEnglishFlashCard.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);
        }
    }
}


Og det gælder klassen ' 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 < \_lines.Count - 1)
        {
            \_currentLine++;
        }

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


Jeg har fejlmeddelelse, mens løsningen løber: Forsøg på at få adgang til metoden mislykkedes: System.IO.File.Exists (System.String) .


Jeg har forsøgt at bruge breakpoint og mens den får LoadCard () -metoden, sættes den direkte til undtagelsen på konstruktøren. Jeg har kontrolleret txt banen, men det er sandt.


Og jeg har også fået en fejlmeddelelse, mens jeg trykker på knappen 'Næste'/'Forrige' på ' return \_lines [[\_currentLine]]; ' linjen sagde: ArgumentOutOfRangeException var uhåndteret Det forekommer på GetPreviousLine () -metoden, hvis du trykker på knappen 'Forrige' og GetNextLine () for 'Next'.


Skulle du have brug for flere oplysninger, er jeg glad for at give det. :)





UPDATE 2


Her er den seneste kode:


public partial class MainPage : PhoneApplicationPage
{
    private string path = @"D:My WorkspacesWindows Phone 7 SolutionFCardEnglishFlashCard.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();
        }
    }
}


Jeg har fået fejlen på linjen markeret ovenfor: Felt 'FCard.MainPage.\_lines' er aldrig tildelt og vil altid have sin standardværdi null .

Bedste reference


Hvis du vil kunne læse linjer, der bevæger sig baglæns og fremad i filen, skal du enten gemme alle linjerne inde i en genstand (måske en List<string> eller streng-array), eller du skal Flyt markøren manuelt via en Seek metode (f.eks. FileStream.Seek). Det afhænger af, hvor stor flash-kortfilen er. Hvis den er meget stor (indeholder mange linjer), vil du måske ikke gemme alt i hukommelsen, og du foretrækker i stedet søgemuligheder. [24]


Her er en prøve, der indlæser hele indholdet af flashkortet:


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:PathToEnglishFlashCard.txt");
        }


Din belastningsfil kunne se sådan ud:


        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;
        }


Dit tidligere klik kunne se sådan ud:


        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];
        }


Din næste klik på klik kan se sådan ud:


        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];
        }
    }
}


Du vil gerne tilføje nogle fejlkontrol selvfølgelig (hvad hvis filen mangler osv.).


PS - Jeg har samlet denne kode ved hjælp af en fil med følgende linjer og bekræftet, at det virker:


Line one 
Line two 
Line three 
Line four


UPDATE:


Hvis du vil gå med noget mere beslægtet med en objektorienteret tilgang, overveje at oprette en FlashCard-klasse. Noget sådan:


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];
    }
}


Nu kan du i stedet gøre noget som dette i din hovedform:


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:	empEnglishFlashCard.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();
    }
}

Andre referencer 1


Du kan adskille parseringsfasen fra displayfasen.
Læs først hver række af din fil og lav en liste med streng af det:


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];


Derefter skal du holde et id for det aktuelle emne og vise det i din blok.


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];

Andre referencer 2


Jeg kan godt lide de eksisterende svar, men jeg tror at lave en klasse for at repræsentere en liste over objekter er overkill for dette problem. Jeg foretrækker at holde det enkelt - en liste med streng skal bare være repræsenteret af List<string>.


public partial class Form1 : Form
{
    private string path = @"D:	emp	est.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;
    }
}


Tre enkle metoder - en til at håndtere Back-klik, en til at håndtere fremadgående klik og en til at opdatere etiketten.


    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];
    }


Og når Egenskaben CurrentLineIndex er indstillet, udløs UpdateContentLabel()


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

Andre referencer 3


Brug denne funktion. Det virker for mig, håber det hjælper dig også


    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";
    }


Brug derefter split funktion til at dele den på . På den måde får du linjerne i filen. Gem dem i en matrix eller en liste. Ring derefter til det respektive indeks på næste eller forrige. Tjek for NULL, inden du fortsætter.