Windows Forms C# - Working with directories and files

2018/02/07 04:42
Reading from a text file
Text files provide the ideal solution for reading and writing data that should be used frequently, but too voluminous to manually enter each time the program is started. Here you will be examined how to read and write text files with the .NET Framework and C# language.
The StreamReader class for reading a text file
The System.IO.StreamReader class provides the easiest way to read a text file. StreamReader is not a stream for reading files, but it can work with streams. It provides the easiest and most readable class for reading from a text file.
Writing in a text file
Writing in text files is a very convenient way to store different kinds of information. For example, the results of running a program can be saved. Text files can be used, for example, making a log of the program - a convenient way to track when it was started, making various mistakes in execution, and so on.


Writing will use the StreamWriter class.
The StreamWriter class
The StreamWriter class is part of the System.IO namespace and is used exclusively for text data handling. It closely resembles the StreamReader class, but instead of reading methods, it offers writing to file methods. Unlike other streams, before it writes the data to the desired location, it turns them into bytes. StreamWriter enables us to define the encoding desired by the developer.
Capture exceptions when working with files
Perhaps the most common file handling error is FileNotFoundException (this exception appears to indicate that the requested file was not found). It may occur when creating a StreamReader.
When specifying a particular encoding when creating StreamReader or StreamWriter, an ArgumentException exception may occur. This means that the selected encoding is not supported.
Another common mistake is IOException. This is a base class for all I/O errors when working with streams.
The standard approach to processing file exception exceptions is as follows: Class StreamReader or StreamWriter variables are declared in the try-catch block. The blocks are initialized with the required values and the potential errors are appropriately captured and processed. For closure of the flows the using construct is used.
The OpenFileDialog class
This class allows the user to select an existing file from the file system and open it. The class opens a standard dialog box to select a file.
The FolderBrowseDialog class
This class allows the user to search for a directory, create a directory, and choose a directory. The directory choice is made using a tree structure. Only files from the file system can be selected.


Sample tasks
1) Create application with the following functionalities:
1.1) To list names of images from specified directory into ListBox control. When selecting a picture from the list, the same to be loaded into PictureBox control.
1.2) To directly choose and display image to PictureBox.
1.3) To read from text file “To Do” tasks and to load them into ComboBox control.
1.4) To read from file people names and their birthday dates, load the names into ComboBox. When selecting person name to show in label how old that person will be in the present year.
1.5) Create module for creating To-Do list. To be created using menu containing the following buttons: Exit, Add, Delete, Save:
- Exit – to close the application.
- Add – to add elements into ComboBox control.
- Delete – to delete element form the ComboBox control.
- Save – to save all elements from the ComboBox to text file.

Solution: 

Create new Windows Form Application project and design the form as shown on the picture:


Drag OpenFileDialog, FolderBrowserDialog and DirectoryEntry to the form they will appear at the bottom of Visual Studio.
Name the controls as follows:
  • ListBox – lbBrowse 
  • Button “Browse To Select Folder” – bBrowse 
  • PictureBox – pbShowPic 
  • Button “Choose Image File” – bOpen 
  • ComboBox в Exmaple 3 – cbToDo 
  • Button “Load Tasks” – bToDo 
  • Label “Names” – lNames 
  • ComboBox в Exmaple 4 – cbNames 
  • Button “Load List” – bLoadList 
  • Button “Example 5: Create To Do Tasks” – bCreateToDo 
(1) To list names of images from specified directory into ListBox control. When
In the click event of the button “Browse to select folder” the folder browser dialog will be opened. When a directory is chosen and “OK” button is clicked, the list box control will be populated with the names of image files (with extensionst .bmp, .gif, .jpg, .png). On SelectedIndexChanged event occurrence the path to selected file will be found and the image will be displayed into the picture box.
private void bBrowse_Click(object sender, EventArgs e)
{
    if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
        DirectoryInfo selectedDir = new DirectoryInfo(folderBrowserDialog1.SelectedPath);

        lbBrowse.Items.Clear();

        foreach (FileInfo file in selectedDir.GetFiles())
        {
            bool bPic = false;
            string sFileName = file.ToString();

            sFileName = sFileName.ToLower();

            if (sFileName.EndsWith(".bmp"))
                bPic = true;

            if (sFileName.EndsWith(".gif"))
                bPic = true;

            if (sFileName.EndsWith(".jpg"))
                bPic = true;

            if (bPic)
                lbBrowse.Items.Add(sFileName);

            if (sFileName.EndsWith(".png"))
                bPic = true;

            if (lbBrowse.Items.Count > 0)
            {
                lbBrowse.SelectedIndex = 0;
                lbBrowse.Visible = true;
            }
            else
                lbBrowse.Visible = false;
        }
    }
}
private void lbBrowse_SelectedIndexChanged(object sender, EventArgs e)
{
    string sPathAndFileName = folderBrowserDialog1.SelectedPath + "\\" + lbBrowse.Text;
    this.Text = sPathAndFileName;
    pbShowPic.Load(sPathAndFileName);
}
(2) To directly choose and display image to PictureBox.
In the click event of the button “open image file” the open file dialog will be opened. For this dialog the following settings are applied: initial directory, filter for file types, which extension from the filter will be selected by default and what to the file name. When “Open” button is clicked from the dialog a check is done if a file is selected or not. If there is selected file it is then loaded to the PictureBox control.
private void bOpen_Click(object sender, EventArgs e)
{
    openFileDialog1.InitialDirectory = @"c:\";
    openFileDialog1.Filter = "Bitmaps |*.bmp|JPGs|*.jpg|GIFs|*.gif|All files|*.*";
    openFileDialog1.FilterIndex = 2;
    openFileDialog1.FileName = "";

    openFileDialog1.ShowDialog();

    if (openFileDialog1.FileName != string.Empty)
        pbShowPic.Load(openFileDialog1.FileName);
    else
        return;
}
(3) To read from text file “To Do” tasks and to load them into ComboBox control.
In the click event of the button “Load Tasks” the ToDo.txt file is read row by row. A check is done if the read row is empty or not, and if not it is added to the combobox, otherwise skipped.
private void bToDo_Click(object sender, EventArgs e)
{
    string sPath = Directory.GetCurrentDirectory() + @"\ToDo.txt";

    using (StreamReader sr = new StreamReader(sPath))
    {
        while (!sr.EndOfStream)
        {
            for (int i = 0; i < 4; i++)
            {
                string sListItem = sr.ReadLine();

                if (!String.IsNullOrEmpty(sListItem))
                    cbToDo.Items.Add(sListItem);
            }
        }
    }
}
(4) To read from file people names and their birthday dates, load the names into ComboBox. When selecting person name to show in label how old that person will be in the present year.
A global variable iListYear of type List<int> will be used to store the birthday dates of the people in the list. The iListYear variable will be populated during the reading of the file. In the click event of the “Load List” button the text file Names will be opened and read row by row. The names will be separated from the birth dates and will be added into the ComboBox control. The first item from the combo box will be selected. The name and ages of the selected person will be displayed in the label control.
List<int> iListYear = new List<int>();
private void bLoadList_Click(object sender, EventArgs e)
{
    string sPath = Directory.GetCurrentDirectory() + @"\Names.txt";
            
    using (StreamReader sr = new StreamReader(sPath))
    {
        while (!sr.EndOfStream)
        {
            string sListName = sr.ReadLine();
                    
            string[] sArrayName = sListName.Split(',');
                    
            cbNames.Items.Add(sArrayName[0]);

            int iSArrayNameLenght = sArrayName.Length;
                    
            iListYear.Add(Convert.ToInt16(sArrayName[1]));
        }
    }

    if(cbNames.Items.Count > 0)
        cbNames.SelectedIndex = 0;
}
private void cbNames_SelectedIndexChanged(object sender, EventArgs e)
{
    int iIndex = cbNames.SelectedIndex;
    int iThisYear = DateTime.Today.Year;
    int iAge = iThisYear - iListYear[iIndex];

    lNames.Text = cbNames.SelectedItem + " will be " + iAge + " in " + iThisYear;
}
(5) Create module for creating To-Do list
Add new Windows Form to the project and name it CreateToDosForm. Design it as show on the picture:


To add buttons to the MenuStrip control, the name of each button must be entered in the “Type Here” field.
In the click event of the “Example 5: Create To Do Tasks” button add the following code to open the form.
private void bCreateToDo_Click(object sender, EventArgs e)
{
   CreateToDosForm frmCreateToDoTasks = new CreateToDosForm();

   frmCreateToDoTasks.ShowDialog();
}
The following global variables are declared:
bool bChanged = false;
bool bCancel = false;
The function for writing to the text file:
private void SaveList()
{
    SaveFileDialog sfDialog = new SaveFileDialog();

    sfDialog.Filter = "Text File | *.txt";

    if (sfDialog.ShowDialog() == DialogResult.OK)
    {
        StreamWriter writer = new StreamWriter(sfDialog.OpenFile());

        for (int i = 0; i < cbToDo2.Items.Count; i++)
            writer.WriteLine(cbToDo2.Items[i].ToString());

        writer.Dispose();
        writer.Close();
    }

    MessageBox.Show("Items saved: " + cbToDo2.Items.Count);
}
Function for save prompt:
private void AskToSave()
{
    DialogResult drAnswer = new DialogResult();

    if (bChanged)
    {
        drAnswer = MessageBox.Show("Do you want to save?", "Save", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);

        if (drAnswer == DialogResult.Yes)
        {
            SaveList();
            this.Close();
        }

        if (drAnswer == DialogResult.No)
            this.Close();

        if (drAnswer == DialogResult.Cancel)
            bCancel = true;
    }
}
Function for deleting task:
private void DeleteItem()
{
    if (cbToDo2.Items.Count > 0)
        cbToDo2.Items.RemoveAt(cbToDo2.SelectedIndex);
    else
        cbToDo2.Text = "";

    if (cbToDo2.Items.Count > 0)
        cbToDo2.SelectedIndex = 0;
}
Add new Windows Form to the project, name it AddNewTaskForm, and design it as shown:


Button “Add” – click event: 
private void miAdd_Click(object sender, EventArgs e)
{
    int iPositionOfNewTask = 0;

    string sTBNewTask = "";

    AddNewTaskForm frmAddTask = new AddNewTaskForm();

    if (frmAddTask.ShowDialog() == DialogResult.OK)
    {
        sTBNewTask = frmAddTask.tbNewTask.Text;

        if (sTBNewTask != "")
        {
            iPositionOfNewTask = cbToDo2.FindString(sTBNewTask);

            if (iPositionOfNewTask == -1)
            {
                cbToDo2.Items.Add(sTBNewTask);

                iPositionOfNewTask = cbToDo2.FindString(sTBNewTask);
            }
            else
                MessageBox.Show("Task already exists!");

            cbToDo2.SelectedIndex = iPositionOfNewTask;
        }

        bChanged = true;
    }
}
Button “Save” – click event:
private void miSave_Click(object sender, EventArgs e)
{
    SaveList();
}
Button “Delete” –click event:
private void miDelete_Click(object sender, EventArgs e)
{
    DeleteItem();
}
Button “Exit” – click event:
private void miExit_Click(object sender, EventArgs e)
{
    AskToSave();
}
Form “CreateToDosForm – FormClosing event:
private void CreateToDosForm_FormClosing(object sender, FormClosingEventArgs e)
{
    AskToSave();
}


Self-assignments
1) Create an application that reads all subdirectories and files of chosen by the user folder. The content of the folder to be written in .csv file with 3 columns: FileName, FileExtension, FileLastAccessed.
2) Create an application that list information about person from text file. The form to have five text fields: ID, First Name, Last Name, Phone, Address. Two buttons for switching between records – next and previous. One button to save changes made to add new record to the file. Record format:

ID:01,
FName:Dragan,
LName:Petkanov,
Address:USA,
Phone:0888123321;
ID:02,
FName:Petkan,
LName:Draganov,
Address:Russia,
Phone:0888123321;

...