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:
- In Solution Explorer, click the file.
- 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.