johnfish92
johnfish92

Reputation: 157

Creating unique files in another directory

Currently i am taking in multiple .txt files from a directory i have specified (sourceDirectory). I am generating new .csv files with the same name as the .txt files - one .csv file for each .txt file.

However i want to generate these new files in another directory which i have specified (directoryPath). If i run my program once it creates these files in the initial directory, however if i run my program again it now generates the files in the destination directory.

The following is my code where i complete the above:

static void Main(string[] args)
    {
        string sourceDirectory = @"C:directoryWhereTXTFilesAre";

        var txtFiles = Directory.EnumerateFiles(sourceDirectory, "*.txt", SearchOption.AllDirectories);

        foreach (string currentFile in txtFiles)
        {
            readFile(currentFile);
        }

        string directoryPath = @"C:\destinationForCSVFiles"; 
    }

I then create the new .csv files name based on the original .txt file like this:

static FileStream CreateFileWithUniqueName(string folder, string fileName, int maxAttempts = 1024)
        {
            var fileBase = Path.GetFileNameWithoutExtension(fileName);
            var ext = Path.GetExtension(fileName);

            // build hash set of filenames for performance
            var files = new HashSet<string> (Directory.GetFiles(folder));

            for (var index = 0; index < maxAttempts; index++)
            {
                // first try with the original filename, else try incrementally adding an index
                var name = (index == 0)
                    ? fileName
                    : String.Format("{0} ({1}){2}", fileBase, index, ext);

                // check if exists
                var fullPath = Path.Combine(folder, name);
                string CSVfileName = Path.ChangeExtension(fullPath, ".csv");
                if (files.Contains(CSVfileName))
                    continue;

                // try to create the file
                try
                {
                    return new FileStream(CSVfileName, FileMode.CreateNew, FileAccess.Write);
                }
                catch (DirectoryNotFoundException) { throw; }
                catch (DriveNotFoundException) { throw; }
                catch (IOException)
                {

                }
           }      

I don't see why it's creating the .csv files initially in the same directory that the .txt files are in and then second time i run my code it creates them in the directoryPath.

Desired output: sourceDirectory left as it is with only .txt files and directoryPath to hold the .csv files.

The only other place i call CreateFileWithUniqueName is within my readFile method, the code is below:

     using (var stream = CreateFileWithUniqueName(@"C:destinationFilePath", currentFile))
                    {
                        Console.WriteLine("Created \"" + stream.Name + "\"");
                newFileName = stream.Name;
                Globals.CleanedFileName = newFileName;
    }

Upvotes: 3

Views: 82

Answers (1)

Steve
Steve

Reputation: 216293

It seems that you are passing the full filename of the source file. This confuses the Path.Combine inside the CreateFileWithUniqueFilename because you are falling in this subtle remarks found on the documentation of Path.Combine

paths should be an array of the parts of the path to combine. If the one of the subsequent paths is an absolute path, then the combine operation resets starting with that absolute path, discarding all previous combined paths.

You can fix it easily with

 using (var stream = CreateFileWithUniqueName(@"C:\destinationFilePath",  
                                        Path.GetFileName(currentFile)))
 {
      Console.WriteLine("Created \"" + stream.Name + "\"");
      newFileName = stream.Name;
      Globals.CleanedFileName = newFileName;
}

Or better extract the filename without path inside the CreateFileWithUniqueName

static FileStream CreateFileWithUniqueName(string folder, string fileName, int maxAttempts = 1024)
{
    var fileBase = Path.GetFileName(fileName);
    fileBase = Path.GetFileNameWithoutExtension(fileBase);
    var ext = Path.GetExtension(fileBase);

also, you should build your CSVfileName using the cleaned filename

    var name = (index == 0)
        ? String.Format("{0}{1}", fileBase, ext);
        : String.Format("{0} ({1}){2}", fileBase, index, ext);
    var fullPath = Path.Combine(folder, name);
    string CSVfileName = Path.ChangeExtension(fullPath, ".csv");
    if (files.Contains(CSVfileName))
        continue;

Upvotes: 1

Related Questions