How to Save a list of strings to a file in C#
By FoxLearn 2/5/2025 9:30:18 AM 4
For example:
var scores = new List<int>() { 92, 85, 78 }; System.IO.File.WriteAllLines(@"C:\temp\scores.txt", scores.Select(s => s.ToString()));
This creates (or overwrites) the file and writes each integer as a string on a new line. The resulting file looks like this:
92\r\n 85\r\n 78\r\n
The newline characters \r\n
are shown here for clarity.
Specifying the separator character
What if you want to separate each integer with a semicolon (or another separator character), rather than placing each integer on a new line?
To do that, you can join the integers with a separator character and then use File.WriteAllText()
.
var scores = new List<int>() { 92, 85, 78 }; var semicolonSeparatedScores = string.Join(';', scores); System.IO.File.WriteAllText(@"C:\temp\scores.txt", semicolonSeparatedScores);
This creates (or overwrites) the specified file, outputting the integers separated by a semicolon:
92;85;78
Reading the integers from a file into a list
When each integer is on a new line
To read the integers from a file into a list, you can either read the file line by line with File.ReadLines()
or read the entire file at once with File.ReadAllLines()
.
// As an array int[] scoresArray = System.IO.File.ReadAllLines(@"C:\temp\scores.txt").Select(int.Parse).ToArray(); // As a list using System.Linq; List<int> scores = System.IO.File.ReadAllLines(@"C:\temp\scores.txt").Select(int.Parse).ToList(); // As an enumerable if you don't need to keep the integers around IEnumerable<int> scores = System.IO.File.ReadLines(@"C:\temp\scores.txt").Select(int.Parse);
When the integers are separated with a different character
To get the integers back into a list when they are separated by a different character, you'll need to read the file and split the string by that separator.
// As an array int[] scores = System.IO.File.ReadAllText(@"C:\temp\scores.txt").Split(';').Select(int.Parse).ToArray(); // As a list using System.Linq; var scores = System.IO.File.ReadAllText(@"C:\temp\scores.txt").Split(';').Select(int.Parse).ToList();
This reads the entire file, which might not be ideal for large files. If you don't want to load the whole file into memory at once, see the memory-efficient approach below.
Get an IEnumerable<int> when using a different separator character
If you want to avoid loading the entire file into memory and are dealing with non-newline separators, you can use the following memory-efficient generator method. This reads blocks of characters from the file stream and yields strings once a separator is encountered.
using System.IO; public static IEnumerable<int> ReadIntegers(string path, char separator) { var sb = new StringBuilder(); using (var sr = new StreamReader(path)) { char[] buffer = new char[1024]; int charsRead = 0; int charBlockIndex = 0; int charBlockCount = 0; while (!sr.EndOfStream) { charBlockIndex = 0; charBlockCount = 0; charsRead = sr.Read(buffer, 0, buffer.Length); for (int i = 0; i < charsRead; i++) { if (buffer[i] == separator) { sb.Append(buffer, charBlockIndex, charBlockCount); yield return int.Parse(sb.ToString()); sb.Clear(); charBlockIndex = i + 1; charBlockCount = 0; } else { charBlockCount++; } } if (charBlockCount > 0) sb.Append(buffer, charBlockIndex, charBlockCount); } if (sb.Length > 0) yield return int.Parse(sb.ToString()); } }
This approach reads the file in chunks and yields the integers one by one, which can significantly reduce memory usage.
Performance Comparison
Here’s a performance comparison between this generator method and the ReadAllText().Split()
approach:
Method | NumIntegers | Mean | Allocated |
---|---|---|---|
ReadAllText_Split | 10,000 | 3.5 ms | 2,600 KB |
Generator | 10,000 | 2.7 ms | 1,000 KB |
ReadAllText_Split | 100,000 | 45.5 ms | 26,000 KB |
Generator | 100,000 | 25.3 ms | 9,400 KB |
ReadAllText_Split | 1,000,000 | 420 ms | 250,000 KB |
Generator | 1,000,000 | 240 ms | 95,000 KB |
As seen in the table, the generator method is faster and uses much less memory, particularly with larger files. In the 1 million integer test, the generator used only 8 MB of memory compared to the 200 MB used by ReadAllText().Split()
.
- String to Byte Array Conversion in C#
- How to Trim a UTF-8 string to the specified number of bytes in C#
- How to Convert string list to int list in C#
- How to Convert string list to float list in C#
- How to Remove a list of characters from a string in C#
- How to Check if a string contains any substring from a list in C#
- Find a character in a string in C#
- Remove non-alphanumeric characters from a string in C#