user152356 user152356 - 3 months ago 27
C# Question

C#: Reading the next file in a folder?

I have a folder containing

.txt
files which are numbered like so:

0.txt
1.txt
...
867.txt
...


What I am trying to do is each time
readNextFile();
is called, I want it to return the contents of the next file in that folder, and
return string.Empty;
if there is no file after the last one it read. I want to have a button that, when pressed, will make the program read the next file and do stuff with it's contents. The files might change between button presses. The way I did this before was this:

int lastFileNumber = 0;

string readNextFile()
{
string result = string.Empty;
//I know it is recommended to use as few of these as possible, this is just an example.
try
{
string file = Path.Combine("C:\Somewhere", lastFileNumber.ToString() + ".txt");
if (File.Exists(file))
{
result = File.ReadAllText(file);
lastFileNumber++;
}
}
catch
{

}
return result;
}


Problem is there might sometimes be this kind of situation:

0.txt
1.txt
5.txt
6.txt
...


It would obviously get stuck at
1.txt
because
2.txt
doesn't exist. I need it to skip to the next existing file and read that one. And clearly it is not possible to just sort the file names alphabetically in a string array since the file names are not Padded, so doing that will result in
1000000000.txt
being read right after
1.txt
.

Any idea how I can achieve this?

Answer

You can use linq to check the next file based on the stored number. That is done after ordering the file by converting its name into integer representation:

int lastFileNumber = -1;
bool isFirst = true;
private void buttonNext_Click(object sender, EventArgs e)
{
    int lastFileNumberLocal = isFirst ? -1 : lastFileNumber;
    isFirst = false;
    int dummy;
    var currentFile = Directory.GetFiles(@"D:\", "*.txt", SearchOption.TopDirectoryOnly)
                            .Select(x => new { Path = x, NameOnly = Path.GetFileNameWithoutExtension(x) })
                            .Where(x => Int32.TryParse(x.NameOnly, out dummy))
                            .OrderBy(x => Int32.Parse(x.NameOnly))
                            .Where(x => Int32.Parse(x.NameOnly) > lastFileNumberLocal)
                            .FirstOrDefault();

    if (currentFile != null)
    {
        lastFileNumber = Int32.Parse(currentFile.NameOnly);

        string currentFileContent = File.ReadAllText(currentFile.Path);
    }
    else
    {
       // reached the end, do something or show message
    }
}