You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
csharp-basics/12. Files and Streams.md

7.8 KiB

marp paginate math theme title
true true mathjax buutti 12. Files and Streams

Files and Streams

Overview

  • Files and Streams
  • Reading from a File
  • Writing to a File
  • JSON Serialization
  • JSON Deserialization

Files and streams

  • The .NET library contains classes for manipulating files and directories
  • The FileStream class contains methods for read and write operations for files
  • The goal is usually to turn the data in your code into an outside resource, such as a .txt file, and vice versa

Using the File Class

  • To get started, add the following namespace to your project:
    using System.IO;
    
  • System.IO provides basic directory and folder support, and allows reading and writing to files and data streams
  • Check if a file exists with the .Exists() method:
    string path = @"C:\\Users\\Public\\TestFolder\\TestFile.txt";
    if (!File.Exists(path))
    {
      Console.WriteLine($"The file {path} does not exist.");
    }
    

Reading from a file

  • Get the entire document as a string with File.ReadAllText
  • Get all lines of a document as a string array with File.ReadAllLines
    string path = @"C:\\Users\\Public\\TestFolder\\TestFile.txt";
    if (!File.Exists(path))
    {
      Console.WriteLine($"The file {path} does not exist.");
    }
    else
    {
      var allLines = File.ReadAllLines(path);
      foreach (string line in allLines)
        Console.WriteLine(line);
    }
    

Writing to a file

  • Writing to a file is done with File.WriteAllText and File.WriteAllLines methods:
string path = @"C:\Users\Public\TestFolder\TestFile.txt";
string[] lyrics = new string[]
  {
    "Hello",
    "Is it me you're looking for",
    "I can see it in your eyes",
    "I can see it in your smile"
  };

if (File.Exists(path))
  File.Delete(path);                 // If file exists, deletes the old file

File.WriteAllLines(path, lyrics);    // Creates a new file with lyrics

Exercise 1: A simple parser

  1. Create a console application which keeps asking the user for a string. Each string is added into a list of strings.
  2. If the user returns an empty string, the program asks for a path to a .txt file.
  3. If the file exists, its contents are replaced with each string written to a separate line. If not, a new file with the contents is created.

JSON

  • JSON (JavaScript Object Notation) is a way to represent code objects in text form, a "data-interchange format"
  • Enables reading and writing series of objects into a text file
  • Consists of two types of structures
    • Objects, or unordered name-value pairs
    • Ordered lists of values
  • Language-independent, although the JSON notation resembles the C-family of languages (C#, Java, JavaScript etc.)

JSON Serialization: set-up

  • .NET projects do not directly support JSON serialization
  • A NuGet package for that exists, called Newtonsoft.Json
  • Install the package from Tools > NuGet Package Manager > Manage NuGet Packages for Solution…
    • Select Browse
    • The Newtonsoft.Json should be the topmost package. If not, search for it from the search bar
    • Select the package, check the checkbox next to Project and click Install

JSON Serialization: an example

You can serialize an object (e.g. a list) into a JSON string with the JsonConvert.SerializeObject() method:

class Product
{
  public int Id { get; set; }
  public string Name { get; set; }
}
static void Main(string[] args)
{
  List<Product> products = new List<Product>
  {
    new Product{Id=1, Name="Awesome Product"},
    new Product{Id=2, Name="Terrible Product"}
  };
  string jsonString = JsonConvert.SerializeObject(products);
  File.WriteAllText(@"C:\Users\OMISTAJA\source\repos\Example\Products.json", jsonString);
}

The contents of the output file Products.json are as follows:

JSON Deserialization

Deserializing the contents of a JSON file into an object in your program can be done with the JsonConvert.DeserializeObject() method:

string json = File.ReadAllText(
  @"C:\Users\OMISTAJA\source\repos\Luentoesimerkit\Luentoesimerkit\db.json");

List<Product> deserializedProducts = new List<Product>();
deserializedProducts = JsonConvert.DeserializeObject<List<Product>>(json);

foreach(Product product in deserializedProducts)
{
  Console.WriteLine(product.Name);
}

Exercise 2: Serializing Your Classes

  1. Create a class Note with the properties int Id, DateTime TimeStamp and string Text.
  2. Create a main loop that keeps asking the user for a new note.
  3. After the user has entered each note, a new Note object is created with a running Id (1, 2, 3…), TimeStamp set to current time and Text as the inputted note. Each new note is added to a list of notes allNotes.
  4. Every time a new note is submitted, the allNotes list is serialized into a json file notes.json. Set the path to the current project path (you can get the path by right-clicking the project in solution explorer and selecting Copy Full Path. Remember to change the file name!)

Extra: FileStream

  • The files have to be opened before reading or writing and closed after
  • Behind the scenes, the ReadAll... and WriteAll... methods automatically do the opening and closing, as described in the Microsoft documentation:
  • Writing to or reading only a part of the file requires opening and closing the file manually
  • This creates a FileStream object that can be used for accessing parts of the file

FileStream (continued)

  • When inserting string data into a file, it needs to be converted into bytes
string path = @"C:\Users\Public\TestFolder\TestWriteFile.txt";
int nOfLines = 4;
FileStream fs = null;
if (!File.Exists(path))                                       // If file does not exist
  fs = File.Create(path);                                     // create a new file and open it
else                                                          // If file exists
  fs = File.OpenWrite(path);                                  // open an existing file for writing
for (int i = 0; i < nOfLines; ++i)
{
  string input = Console.ReadLine() + "\\n";                  // Read user input, add newline
  byte[] byteInput = new UTF8Encoding(true).GetBytes(input);  // Get the string as a sequence of bytes
  fs.Write(byteInput, 0, byteInput.Length);                   // Write the bytes at the end of the file
}
fs.Close();                                                   // Close the file

Extra: The using statement

  • From the Microsoft Documentation about the FileStream class:
  • This means that wrapping the file handling in an using block handles the opening and closing of the stream for you

The following reads the first 20 characters of a file and prints them to the console

string path = @"C:\Users\Public\TestFolder\TestFile.txt";
int nOfBytesToPrint = 20;
byte[] byteArray = new byte[nOfBytesToPrint];

if (!File.Exists(path))
  Console.WriteLine($"The file {path} does not exist.");
else
  using (FileStream fs = File.OpenRead(path))
  {
    fs.Read(byteArray, 0, nOfBytesToPrint);
  };
// No need to close the file since it was handled inside of a using block

Console.WriteLine(Encoding.UTF8.GetString(byteArray, 0, byteArray.Length));