Leron
Leron

Reputation: 9886

C# - customizing image name converted to string

I have a method that copies selected image from an OpenFileDialog to a defined location, and I want to check if an image with the same name exists, and if so to change the name on the fly.

Here is my method:

 public void SaveImage(IList<AppConfig> AppConfigs, string ImageNameFilter)
        {
            string imgPath = AppConfigs[0].ConfigValue.ToString();
            Int32 i = 0;
            StringBuilder sb = new StringBuilder(selectedFileName);

            while (File.Exists(imgPath + "\\" + ImageNameFilter + selectedFileName))
            {
                sb.Insert(i, 0);
                i++;
                //ImageNameFilter += (i++).ToString();
            }
            File.Copy(selectedFile, imgPath + "\\" + ImageNameFilter + selectedFileName);
        }

ImageNameFilter is a custom filter that is added at the beginning of each image and the users need this prefix to be able to recognize what the image is used for, only by seeing the prefix. selectedFileName is the name of the image taken with SafeFileName, which means it looks like this - imageName.jpeg.

There are several problems that I have with this code. Firstly, I wanted to change the name like this - imageName1.jpeg, imageName2.jpeg, imageName3.jpeg...imageName14.jpeg.., but if I'm using selectedFileName with the += everything is added, even after the .jpeg, which is not what I want. The only solution that I can think of is to use regex, but I really want to find another way.

Also, incrementing i++ and adding it with += leads to unwanted result which is : imageName1.jpeg, imageName12.jpeg, imageName123.jpeg...imageName1234567.jpeg.

So, how can I get the result I want and the compromise I see here is to add underscore _ right after the ImageNameFilter and then add i at the beginning of selectedFileName rather in the end as it is by default. But adding something to the beginning of the string is also something I don't know how to do. As you may see I tried StringBuiledr + Insert, but I don't get the expected result.

Upvotes: 0

Views: 197

Answers (2)

Jon
Jon

Reputation: 437784

Basically you need to separate the base file name from the extension (use the helpful methods on Path to do this) before starting the loop, and then keep producing filenames. Each candidate will not be produced based on the last one (it's just based on fixed information and the current iteration count), so you don't need to involve a StringBuilder at all.

Here's one neat way to do it in two steps. First, set up the bookkeeping:

var canonicalFileName = ImageNameFilter + selectedFileName;
var baseFileName = Path.GetFileNameWithoutExtension(canonicalFileName);
var extension = Path.GetExtension(canonicalFileName);

Then do the loop -- here I 'm using LINQ instead of a loop statement because I can, but there's no essential difference from a stock while loop:

var targetFileName = Enumerable.Range(1, int.MaxValue - 1)
    .Select(i => Path.Combine(imgPath, baseFileName + i + extension))
    .First(file => !File.Exists(file));

File.Copy(selectedFile, targetFileName);

Upvotes: 3

Dustin Kingen
Dustin Kingen

Reputation: 21275

Use Path.GetFileNameWithoutExtension or String.TrimEnd('.') to get the FileName without extension. You can use FileInfo to get the extension as well.

Upvotes: 1

Related Questions