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.

7.3 KiB

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

Application Code

Stream writer / reader

String, int, ...

FileStream object

.txt, .csv, .png, ...


https://learn.microsoft.com/en-us/dotnet/api/system.io?view=net-7.0

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.");

}


https://learn.microsoft.com/en-us/dotnet/api/system.io?view=net-7.0

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

Create a console application which keeps asking the user for a string. Each string is added into a list of strings.

If the user returns an empty string, the program asks for a path to a .txt file.

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 Serialization

  • 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.)

https://www.json.org/json-en.html

JSON Serialization (continued)

  • .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 -> M anage 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

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 products = new List

{

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\Johannes\source\repos\Luentoesimerkit\Luentoesimerkit\db.json");

List deserializedProducts = new List();

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

foreach(Product product in deserializedProducts)

{

Console.WriteLine(product.Name);

}

Exercise 2: Serializing Your Classes

Create a class Note with the properties int Id, DateTime TimeStamp and string Text.

Create a main loop that keeps asking the user for a new note.

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 is the inputted note. Each new note is added to a list of notes, allNotes.

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!)

FileStream

The files have to be opened before read/write 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

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