Introduction
Basic manipulation and navigating files & directories within the Windows Operating System which uses the “File Explorer” is really quite easy for most users. However; in some instances, file management could be an important part of an enterprise application. As a result, the Microsoft .NET framework provides a significant class-libraries inside System.IO namespace for file handling. Which returns the favor to developers, to do certain basic and advanced manipulation of files and directories.
If you are a newbie and need to somehow learn: how to handle and manage some file/directory manipulation within his/her application, this article is made just for you. However; those who are more advanced developers and/or readers are also welcome.
Let’s get started then.
In this article, we are going to explore the following classes: System.IO.Path, System.IO.Directory & System.IO.DirectoryInfo, System.IO.File to see the features it has to offer. See our objectives below.
Objectives
- Using the Path class to deal with filenames, directories, and paths to manage file-extensions, temporary files, temporary path, directory-name, and file-name, etc.
- Using the Directory and DirectoryInfo classes to manipulate directories (create and delete) and add a directory to a certain access-rule.
- Using the File class to deal with read and write to file.
Project Structure
The following classes, Explore_File_IO_Path.cs, Explore_File_IO_Directory.cs, Explore_File_IO_File.cs are unit test classes. The objective of these unit tests is basically to test the methods that we are going to tackle and study. Moreover; there’s one common thing about these classes, they have an Initialize method which literally initializes the projectPathLocation to get the directory of the running project. See the source code below.
- string projectPathLocation = string.Empty;
-
- [TestInitialize]
- public void Initialize()
- {
- projectPathLocation = AppConfig.ProjectPathLocation;
- }
The AppConfig.cs file acts as a configuration-class to get those project paths and directory structure in mind. See the source code below.
- public static class AppConfig
- {
- public const string ProjectFiles = "project-files";
-
- public static string[] ProjectDirectories = new string[]
- {
- "App-Data-1",
- "App-Data-2",
- "App-Data-3"
- };
-
- public static Dictionary<string, string[]> projectDirectoriesWithChild = new Dictionary<string, string[]>
- {
- { "Directory-1",
- new string[] { "A", "B", "C", "D", "E" }},
- { "Directory-2",
- new string[] { "A", "B", "C", "D", "E", }},
- { "Directory-3",
- new string[] { "A", "B", "C", "D", "E", }},
- { "Directory-4",
- new string[] { "A", "B", "C", "D", "E", }}
- };
-
- public static string ProjectPathLocation
- {
- get { return Assembly.GetExecutingAssembly().Location; }
- }
- }
Lastly, to further visualize, see figure 1 for the project structure. The entire project can also be downloaded
here.
Figure 1
Explore and Play with System.IO.Path
Path class, it is a static class which provides common operations on dealing with filenames, directories, and paths. It is commonly known on String instances that contain files and/or directory path information. See figure 2 below to visualize the System.IO.Path static class and the methods it provides.
Figure 2
Let us see the examples below.
In the example below, we have tried to explore the methods HasExtension and GetExtension which is straightforward.
- [TestMethod]
- [Priority(1)]
- public void Test_PathLocation_If_Has_FileExtension_And_CheckExtension()
- {
-
- Assert.IsTrue(Path.HasExtension(projectPathLocation));
-
-
- string projectFileExtension =
- Path.GetExtension(projectPathLocation);
-
-
- Assert.IsTrue(projectFileExtension == ".dll");
- }
In the example below, we have tried to explore the method GetFilenameWithOutExtension. This method is really helpful when you only care about the filename only.
- [TestMethod]
- [Priority(2)]
- public void Test_Path_Method_GetFileName_Wihout_Extension()
- {
-
- string fileName =
- Path.GetFileNameWithoutExtension(projectPathLocation);
-
- //true
- Assert.AreEqual(fileName, "Playing_With_File_IO_Csharp");
- }
In the example below, we have tried to explore the method Combine and ChangeExtension. As you can see we can combine different paths which will give us the full-string-path. And if you are interested to change the file extension of a file, you could use ChangeExtension.
- [TestMethod]
- [Priority(3)]
-
- public void Test_Path_Method_GetFile_Then_Change_FileExtension()
- {
- //pattern to verify file extension
- string pattern = @"([^\\]+)\.{0}$";
-
- //file-type extension
- string[] fileExtensions = new string[] { "txt", "docx" };
-
- string fullPath =
- Path.Combine(projectPathLocation,
- "Playing_With_File_IO_Csharp.txt");
-
- //true
- Assert.IsTrue(Regex.IsMatch(fullPath,
- string.Format(pattern, fileExtensions[0])));
- string changedPath = Path.ChangeExtension(fullPath, ".docx");
-
- //true
- Assert.IsTrue(Regex.IsMatch(changedPath,
- string.Format(pattern, fileExtensions[1])));
- }
In the last example below, we have tried to explore the methods GetTempPath, GetTempFileName which is really helpful for developers when dealing with temporary files. If we have an application that deals with temporary files and dump those files to temp-path, these two methods are very handy.
- [TestMethod]
- [Priority(4)]
- public void Test_Path_Method_GetTempFilePath_And_CreateTemporaryFile()
- {
-
- string temporaryPath = System.IO.Path.GetTempPath();
-
-
- Assert.IsTrue(Directory.Exists(temporaryPath));
-
-
- string tempFileName = System.IO.Path.GetTempFileName();
-
-
- Assert.IsTrue(File.Exists(tempFileName));
- }
Explore and Play with System.IO.Directory
Directory class is a static class which provides a lot of methods for dealing with directories. It exposes a lot of methods for creating, enumerating directories and subdirectories. However; I can’t discuss everything but will try to explore some. See figure 3 to visualize the System.IO.Directory static class and the methods it provides.
Figure 3
Let us see the examples below.
In the example below, we have shown how to create a new directory using the CreateDirectorymethod. Upon successfully creating a directory the method CreateDirectory returns a DirectoryInfoclass which you can use to get information about the directory, sub-directories, and files.
- [TestMethod]
- [Priority(1)]
- public void Test_ProjectPath_Create_Directory()
- {
-
- string directoryName = Path.GetDirectoryName(projectPathLocation);
-
-
- string directoryToCreate = AppConfig.ProjectDirectories[0];
-
-
- string fullPath = Path.Combine(directoryName,
- directoryToCreate);
-
-
- bool exists = Directory.Exists(fullPath);
-
- if (!exists)
- {
-
- var result = Directory.CreateDirectory(fullPath);
-
-
- Assert.IsNotNull(result);
-
-
- Assert.IsInstanceOfType(result, typeof(DirectoryInfo));
- }
- }
The example below, shows how to delete a directory using the
Delete method. Straight-forward in my opinion and after successfully deleting the directory, it checks whether the directory still exists using the
Exists method.
- [TestMethod]
- [Priority(2)]
- public void Test_ProjectPath_Delete_Directory()
- {
- string directoryName =
- Path.GetDirectoryName(projectPathLocation);
-
- string directoryToCreate =
- AppConfig.ProjectDirectories[0];
-
- string fullPath =
- Path.Combine(directoryName, directoryToCreate);
-
- bool exists = Directory.Exists(fullPath);
-
- if (exists)
- {
- Directory.Delete(fullPath);
-
- Assert.IsFalse(Directory.Exists(fullPath));
- }
- }
Let us show more examples on how to create/delete a directory with sub-directories. See the examples below.
- [TestMethod]
- [Priority(3)]
- public void Test_ProjectPath_Create_Multiple_Directories_With_SubDirectories()
- {
- string directoryName =
- Path.GetDirectoryName(projectPathLocation);
-
- foreach (var item in AppConfig.projectDirectoriesWithChild)
- {
- foreach (var child in item.Value)
- {
- string fullPath =
- Path.Combine(directoryName, item.Key, child);
-
- var result = Directory.CreateDirectory(fullPath);
-
- Assert.IsNotNull(result);
- Assert.IsInstanceOfType(result, typeof(DirectoryInfo));
- }
- }
- }
-
- [TestMethod]
- [Priority(4)]
- public void Test_Project_Delete_Directory_Including_SubDirectories()
- {
- string directoryName =
- Path.GetDirectoryName(projectPathLocation);
-
- foreach (var item in AppConfig.projectDirectoriesWithChild)
- {
- string fullPath = Path.Combine(directoryName, item.Key);
-
- var childDirectories = Directory.GetDirectories(fullPath);
-
- Assert.IsTrue(childDirectories.Length > 0);
-
- if (childDirectories.Length > 0)
- {
- Directory.Delete(fullPath, true);
- }
-
- Assert.IsFalse(Directory.Exists(fullPath));
- }
- }
Now we have seen examples on creating and deleting directories and subdirectories. Let us try to create a directory with a DirectorySecurity class/object as passed argument to DirectoryInfo using the method SetAccessControl.
- [TestMethod]
- [Priority(5)]
- public void Test_Create_Directory_With_Directory_Security()
- {
- string directoryName = Path.GetDirectoryName(projectPathLocation);
-
- foreach (var item in AppConfig.projectDirectoriesWithChild)
- {
- foreach (var child in item.Value)
- {
- string fullPath = Path.Combine(directoryName, item.Key, child);
-
- if (!Directory.Exists(fullPath))
- {
- DirectoryInfo directoryInfo =
- Directory.CreateDirectory(fullPath);
-
- Assert.IsNotNull(directoryInfo);
- Assert.IsInstanceOfType(directoryInfo,
- typeof(DirectoryInfo));
-
- DirectorySecurity directorySecurity =
- new DirectorySecurity();
-
- directorySecurity.AddAccessRule(
- new FileSystemAccessRule("Power Users",
- FileSystemRights.FullControl, AccessControlType.Allow));
-
- directorySecurity.AddAccessRule(
- new FileSystemAccessRule("Guests",
- FileSystemRights.Delete, AccessControlType.Deny));
-
- directoryInfo.SetAccessControl(directorySecurity);
- }
- }
- }
- }
Explore and Play with System.IO.File
File class is a static class which provides a lot of methods for dealing with files. It exposes methods for creating, copying, deleting, moving, etc. for a single file. See figure 4 to visualize the System.IO.File static class and the methods it provides.
Figure 4
In this last section, we are going to focus on the read and write to file, focusing on 3 methods WriteAllText, WriteAllLines, and ReadAllLines. To further prove the sample code, I decided to compare the content that was set on the file and verify if we have the same content after calling the method ReadAllLines. Let us see the examples below.
- string projectPathLocation = string.Empty;
-
- string projectFile_FullPath = string.Empty;
-
- [TestInitialize]
- public void Initialize()
- {
- projectPathLocation = AppConfig.ProjectPathLocation;
-
- projectFile_FullPath = Path.Combine(Path.GetDirectoryName(projectPathLocation), "project-files");
- }
-
- [TestMethod]
- public void Test_File_WriteAllText_And_ReadContent_Then_Compare_If_Equal()
- {
-
-
- StringBuilder content = new StringBuilder();
-
- content.AppendLine("Hello System.IO.File");
-
- content.AppendLine("File class");
-
-
- string fullContent = content.ToString();
-
-
- string fullPathToFile =
- Path.Combine(projectFile_FullPath, "Playing_With_File_IO_Csharp_1.txt");
-
-
- File.WriteAllText(fullPathToFile, string.Empty, Encoding.UTF8);
-
-
- File.WriteAllText(fullPathToFile, fullContent, Encoding.UTF8);
-
-
- string[] fileContent = File.ReadAllLines(fullPathToFile, Encoding.UTF8);
-
-
- Assert.AreEqual(string.Compare(fullContent,
- string.Format("{0}{1}",
- string.Join(Environment.NewLine, fileContent),
- Environment.NewLine)), 0);
-
- }
-
- [TestMethod]
- public void Test_File_WriteAllLines_And_ReadContent_Then_Compare_If_Equal_Using_Array()
- {
- string[] fileContents = new string[]
- { "Hello", "World", "File", "Class",
- "Welcome", "To", "The", "World",
- "Of", "System.IO" };
-
- string fullPathToFile =
- Path.Combine(projectFile_FullPath, "Playing_With_File_IO_Csharp_2.txt");
-
- File.WriteAllText(fullPathToFile, string.Empty, Encoding.UTF8);
-
- File.WriteAllLines(fullPathToFile, fileContents, Encoding.UTF8);
-
-
- string[] readFileContents =
- File.ReadAllLines(fullPathToFile, Encoding.UTF8);
-
-
- var result = Enumerable.SequenceEqual(fileContents, readFileContents);
-
-
- Assert.IsTrue(result);
- }
Summary
In this article, I’ve discussed the Path, Directory and File static classes inside the System.IO namespace. We have seen and explored some exposed methods by creating and deleting directories and subdirectories; by manipulating strings via Path class; and lastly, by writing and reading to a file using the File static class. I’m hoping you have enjoyed it and until next time, happy programming!