Working with Files in C#: an overview

A program finds a file by its path. An absolute path starts at the drive; a relative path starts at the program's current folder, which in Visual Studio is the build folder, so data files are copied there.

Apprentice · C# · Updated

After this lesson you can

  • Tell an absolute path from a relative one, and say which folder a relative path starts from

Key takeaways

  • An absolute path starts at the drive and names every folder; a relative path starts at the program's current directory.
  • Run from Visual Studio, a program's current directory is the build folder, bin\Debug\net10.0, not the project folder.
  • Set a data file's Copy to Output Directory to Copy if newer, so it's copied next to the program and a relative path finds it.
  • A path is only a string: writing one doesn't open a file, create one or check that it exists.
  • In a C# string, double each backslash or put @ before the string, so a backslash is just a backslash.

A database is great for data your app shares and searches. But plenty of data lives in plain files: a list of students exported from a spreadsheet, a settings file, a log of everything that went wrong today. C# reads and writes files with the classes in System.IO (IO is short for input/output). A console app already has using System.IO; built in, so you can use them straight away.

Before a program can open a file, it has to say where the file is. That's the file's path.

Absolute paths

An absolute path starts at the top, the drive, and names every folder on the way down:

C:\Users\ada\Documents\bootcamp\student_grades.csv

It works from anywhere, but only on a computer where that exact folder exists. Ada's path is no use on Grace's laptop.

Relative paths

A relative path starts from the folder the program is running in, called its current directory (or working directory):

student_grades.csv
data\student_grades.csv

The first means "student_grades.csv, in the current directory." The second means "the data folder in the current directory, and student_grades.csv inside it." A relative path keeps working when the whole project moves to another computer, so it's what you'll use most.

You can ask a program for its current directory, and turn a relative path into the absolute one it stands for:

Console.WriteLine(Directory.GetCurrentDirectory());
Console.WriteLine(Path.GetFullPath("student_grades.csv"));

On Ada's computer, run from Visual Studio, that prints something like:

C:\Users\ada\Documents\bootcamp\GradeBook\bin\Debug\net10.0
C:\Users\ada\Documents\bootcamp\GradeBook\bin\Debug\net10.0\student_grades.csv

Where does a Visual Studio program run?

Look closely at that output. When Visual Studio runs a console app, the current directory isn't the project folder, it's the build folder: bin\Debug\net10.0. That's where the compiled program lives.

So if you add student_grades.csv to your project, the program won't find it until the file is copied into the build folder too. Tell Visual Studio to do that:

  1. In Solution Explorer, click the file.
  2. In the Properties window, set Copy to Output Directory to Copy if newer.

That adds a few lines to your .csproj file:

<ItemGroup>
  <None Update="student_grades.csv">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  </None>
</ItemGroup>

Now every build copies the file next to the program, and a relative path finds it. (When you start a program with dotnet run in a terminal, the current directory is wherever the terminal is, usually the project folder. The file is there too, so the same path works.)

A path is only a name

A path is just a string. Writing one doesn't open a file, create one, or even check that it exists. "homework.txt" names a file that may or may not be there. The next lessons show how to ask, and what happens when you try to open a file that isn't there.

Backslashes in C# strings

Windows separates folders with a backslash, but in a C# string a backslash starts an escape such as \n. Either double them, or put @ before the string to make it a verbatim string, where a backslash is just a backslash:

string path1 = "C:\\Users\\ada\\student_grades.csv";
string path2 = @"C:\Users\ada\student_grades.csv";

Console.WriteLine(path1 == path2);
True

Better still, don't type separators at all: the next lesson's Path.Combine puts them in for you.

Check yourself

1 question to try on the lesson page.

So what

Every file a program touches is found by its path. Prefer relative paths, remember they start at the current directory, and make sure your data files are copied to where the program runs.

Key terms

Cheat sheets