Title: Rename JPEG files to JPG files in C#
Some applications seem to still be stuck in the 1990s so they produce JPEG files. If you use File Explorer to rename them so they have a .jpg extension, Windows warns you that changing the extension might make them not work with other applications. (Which is silly because .jpeg and .jpg files are the same.)
Anyway I wrote this program to rename them JPEG files so they have the .jpg extension.
The program has three main pieces of interest, and you can download it to see additional details. The pieces described here are:
Selecting and Storing Files
Use the File menu's open command to select files. If you select one or more files and click Open, the program adds the files to its CheckedListBox control.
The CheckedListBox displays the text associated with whatever objects it contains. To make it display the files' short names, the program stores each file's information in FileNameInfo objects. The following code shows that class.
internal class FileNameInfo
{
internal string Name;
internal string FullName;
internal FileNameInfo(string full_name)
{
FileInfo file_info = new FileInfo(full_name);
Name = file_info.Name;
FullName = full_name;
}
public override string ToString()
{
return Name;
}
}
The class's constructor takes a file's full name as a parameter. It uses it to create a FileInfo object and then uses that object's Name property to get the file's short name without its path. Later the class's ToString method returns that short name. When the CheckedListBox (or any other list or combo box) displays the object, it calls its ToString method to find the text that it should display.
Ranaming Files
You can check and uncheck files in the list. When you click Rename, the following code executes.
// Rename the files.
private void btnRename_Click(object sender, EventArgs e)
{
Cursor = Cursors.WaitCursor;
int num_renamed = 0;
foreach (FileNameInfo name_info in clbFiles.CheckedItems)
{
if (!RenameFile(name_info, ref num_renamed)) break;
}
// Remove the checked files from the list.
clbFiles.RemoveChecked();
Cursor = Cursors.Default;
MessageBox.Show(string.Format("Renamed {0} files.", num_renamed));
}
This code loops through the checked files and calls the RenameFile method (described shortly) to rename each file.
After it renames the files, this method calls the RemoveChecked extension method (also described shortly) to remove those files form the list. It then displays the number of files that were renamed.
The following code shows how the RenameFile method renames a file.
// Rename the file. Return true if we should continue.
private bool RenameFile(FileNameInfo name_info, ref int num_renamed)
{
// Ignore files that do not end with .jpeg.
string old_name = name_info.FullName;
if (!old_name.ToLower().EndsWith(".jpeg"))
return true;
// Compose the new file name.
string new_name =
old_name.Substring(0, old_name.Length - 4)
+ "jpg";
// Try to rename the file.
try
{
File.Move(old_name, new_name);
num_renamed++;
return true;
}
catch (IOException ex)
{
return MessageBox.Show("Cannot rename file "
+ name_info.Name + ".\n\n" + ex.Message
+ "\nDo you want to continue?",
"Rename Error",
MessageBoxButtons.YesNo) == DialogResult.Yes;
}
}
This method gets the NameInfo object's full name and checks whether it ends with the .jpeg extension. If the file does not end with that extension, the method simply returns.
Next the code creates the new file name by replacing the "jpeg" at the end with "jpg."
Then, inside a try block, the code uses File.Move to rename the file. If an error occurs, the program displays an error message and asks if you would like to continue. That lets you exit the file processing loop early if, for example, you selected 100 files that will all have errors.
The most likely reason why you would get an error is if the new file's name already exists. For example, if you try to rename image1.jpeg to image1.jpg but image1.jpg already exists.
Removing Checked Items
After it process all of the files, the program calls the following CheckedListBox extension method to remove the checked files from the CheckedListBox.
// Remove the checked files from the list.
public static void RemoveChecked(this CheckedListBox clb)
{
// Make a new list holding the checked items.
object[] checked_items = new object[clb.CheckedItems.Count];
clb.CheckedItems.CopyTo(checked_items, 0);
// Remove the items.
foreach (object obj in checked_items)
clb.Items.Remove(obj);
}
The idea is to loop through the checked objects and remove them from the controls items. However, when you remove an item, that modifies the list of checked items and you cannot iterate through a list while it is being modified.
To work around that issue, the program makes a new list holding the objects that are checked and then loops through that.
There are several ways that you can make such as list. This example makes an array big enough to hold all of the checked objects and then uses the CopyTo method to copy the checked item into it. Now the program can safely loop through the array and remove its object from the CheckedListBox.
Note that this removes all of the checked objects even if you bail out of the loop early. You can fix that if you like, but I'm leaving it as is for now because it's good enough for my current needs.
Download the example to experiment with it and to see additional details.
|