Create a console app that saves to a file

Disclaimer: Before my inbox is flooded with people saying what I'm doing is wrong - These blogs are me documenting my learning. Constructive criticism is appreciated and welcomed but please don't just tell me I'm wrong, provide valuable feedback so that I can learn from the mistakes.

I've decided to start writing more code related blogs. This is for a couple of reasons. One, I like blogging, two, I want to share my knowledge and three, it's a small attempt to help me get over some real Imposter Syndrome issues I'm having with regards to my abilities as a developer.

I hope that by sharing these blogs with you that you find them useful but also that it maybe allows someone else to have confidence to share their code.

The first blog I'm going to share with you is how to create a Console App that reads in data and saves it to an external file. I'm going to be coding in C# and I'm going to be using .Net Core.

The reason I've chosen .Net Core is because Umbraco 9, which is due for release later this year, will be released on Core and so I get to learn Core while also blogging. Win! Win!

Create new dotnet core console app.

> dotnet new console

I made a new folder called OwainCodes\_Blogs\ConsoleApp and then from within that folder I ran the above command. This created 2 new files and one new folder.

The command created a new C# project file named the same as the folder it was created in. In this example ConsoleApp.csproj. If you plan to write your console app in F# or VB, you can. You just need to set the language when you run the dotnet new console command. For info on how to do this, check out the dotnet-new documentation.

The command also created a Program.cs file and an obj folder which has files in it. The obj folder is used to store temporary object files and other files used to create the final binary. We don't need to worry about it.

To create a Solution File, I opened the ConsoleApp.csproj file in Visual Studio and then saved the Solution.

From within Visual Studio you can now run the Program.cs file without making any changes to the code and you will see a console window open with the message Hello World!.

Requirements

I now have a C# console app working so it's time to plan what I'm going to build.

  • A .Net Core Console app.
  • Save data to an external file

This is pretty high level requirements so I'll make smaller tasks.

  • Initially, the data will come from a hardcoded string
  • The program will run once
  • Each time the program runs, it will either create a new file or overwrite the file if it already exists
  • Once the file has been created, we will read back the contents of the file and display it in the console
  • The filename and path are hardcoded

The code

I have the default Program.cs and I've created a new file named OutputFile.cs.

Here is the code from the Program.cs file:

namespace ConsoleApp
{
    class Program
    {
        public static string text = "The last time you had a cheeseburger was too long ago. Try not to drool when you think about the slightly charred, ";


        public static void Main()
        {
            string path = @"D:\Development\OwainCodes_Blogs\testFile.txt";
            var output = new OutputFile(path, text);

        }

    }
}

The Program.cs only does one thing, the OutputFile does all the logic.

using System;
using System.IO;
using System.Text;

namespace ConsoleApp
{
    public class OutputFile
    {
        public OutputFile(string path, string text)
        {
            var fileDeleted = DeleteFile(path);
            bool fileCreated = false;

            if (fileDeleted)
                fileCreated = CreateFile(path, text);

            if (fileCreated)
                ReadFile(path);

        }

        public bool DeleteFile(string path)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
            }

            return true;
        }

        public bool CreateFile(string path, string text)
        {
            using (FileStream fs = File.Create(path))
            {
                // Take input from the text string
                AddText(fs, text);

                // add the next two lines after the input text
                AddText(fs, "\r\nThis is some more text,");
                AddText(fs, "\r\nand this is on a new line");

                return true;
            }

            return false;

        }

        public void ReadFile(string path)
        {
            //Open the stream and read it back.
            using (FileStream fs = File.OpenRead(path))
            {
                byte[] b = new byte[1024];
                UTF8Encoding temp = new UTF8Encoding(true);
                while (fs.Read(b, 0, b.Length) > 0)
                {
                    Console.WriteLine(temp.GetString(b));
                }
            }
        }
        private static void AddText(FileStream fs, string value)
        {
            byte[] info = new UTF8Encoding(true).GetBytes(value);
            fs.Write(info, 0, info.Length);
        }
    }

}

There we have it. Our first console app which creates a text file with the contents from a text string. It also adds two hardcoded lines to the file too, the reason? Why not 😂

What does it all do though?

Rather than just publish this and say Tada 🎉 it just works. I'll now try and explain my thinking behind what I've coded.

Let's start with the Program.cs file. I've tried to keep this as small and as clean as possible. It is literally just the starting point for the console app. It's where the program will always start from, or to be more precise, the Main method is the entry point, but after that, we move in to the OutputFile.cs file.

Once we are within the OutputFile method, which we have passed in the output path and also the text for the file from the Main method, we first delete any file that might already be created.

Once the file is deleted, we create a new File using FileStream.

Use the FileStream class to read from, write to, open, and close files on a file system, and to manipulate other file-related operating system handles, including pipes, standard input, and standard output. - Microsoft Documentation

What does AddText do? Why not just save the text string as is? Well, you'll notice that in the hard coded lines that they have \r\n within the string, this is a return character so I can take a new line, but I don't want the \r\n to be displayed in my text file. I want to do what I asked, go to the next line after the end of the string. I use the AddText to encode the entire string and this then allows me to use new the return characters. It also allows me to use emojis in my string and the Emoji will be saved in my text file.

The final part is to read the file back to the console. Unfortunately, I couldn't get the Emoji to display in the console. That might be something to do with the font I use in my console or something that I've missed.

Improvements

I could also swap out the hardcoded string and take an input from the Console with a small tweak to the Program.cs file.

using System;

namespace ConsoleApp
{
    class Program
    {
        public static void Main()
        {
            Console.Write("Enter a sentence to save to the file: ");
            string text = Console.ReadLine();
            string path = @"D:\Development\OwainCodes_Blogs\testFile.txt";
            var output = new OutputFile(path, text);

        }

    }
}

The next blog I plan to release is titled : Creating a console app that retrieves data from an unathenticated API.

Thanks to Joe Golmblek for pointing me in the direction of the Thunder Forest API. I'll be using that for my next blog.

I would like to thank Nik Rimington for the blog subject ideas. If anyone has any other suggestions for code blogs, please get in touch.