C# 如何从我的目录中搜索视觉上重复的图像并移动它们?

C# 如何从我的目录中搜索视觉上重复的图像并移动它们?,c#,image,loops,file-io,infinite-loop,C#,Image,Loops,File Io,Infinite Loop,我在这一行收到了一个NotSupportedException: private void button4_Click(object sender, EventArgs e) { FileStream outputFileStream = new FileStream("log.txt", FileMode.Create, FileAccess.Write); StreamWriter writer = new StreamWriter(outputFileStream);

我在这一行收到了一个
NotSupportedException

private void button4_Click(object sender, EventArgs e)
{
    FileStream outputFileStream = new FileStream("log.txt", FileMode.Create, FileAccess.Write);
    StreamWriter writer = new StreamWriter(outputFileStream);

    string originalPathFile = @"C:\Users\user\Downloads\CaptchaCollection\Small\";
    string duplicatePath = @"C:\Users\user\Downloads\CaptchaCollection\Small\Duplicates\";
    string movedOriginal = @"C:\Users\user\Downloads\CaptchaCollection\Small\Sorted\";

    foreach( String fileToCheck in Directory.GetFiles(originalPathFile,"*.png"))
    {
        foreach (String fileWithCheck in Directory.GetFiles(originalPathFile, "*.png"))
        {
            if (fileToCheck != fileWithCheck)
            {
                // Your code to compare...
                Bitmap im1 = new Bitmap(fileToCheck);
                Bitmap im2 = new Bitmap(fileWithCheck);   

                if (compare(im1, im2))
                {
                    // if it's equal
                    File.Move(originalPathFile + fileWithCheck + ".png", duplicatePath + fileWithCheck + ".png");
                    writer.WriteLine(fileWithCheck + ".png" + " is a duplicate of " + fileToCheck + ".png");
                }

            }
        }

        File.Move(originalPathFile + fileToCheck + ".png", movedOriginal + fileToCheck + ".png");
        writer.WriteLine(fileToCheck + ".png " + "has had its duplicates removed.");
    }

    writer.Close();
    outputFileStream.Close();
}

我不知道你的代码为什么会进入无限循环,尽管我注意到你正在将检查的文件数与目录中的文件数进行比较——而且因为你正在检查的文件只是那些具有数字名称和.png扩展名的文件,如果该目录中有其他文件,你的比较就会有缺陷

更新后的代码引发
NotSupportedException
的原因是源文件名或目标文件名的格式不正确。请注意,
Directory.GetFiles()
返回指定目录中的所有文件,包括它们的路径-因此当您使用
OriginalPathFile+fileToCheck+.png”
-换句话说,如果
originalPath
是“C:\Temp\ImageFiles\”,例如,然后您实际传入的文件名是
“C:\Temp\ImageFiles\C:\Temp\ImageFiles\”+fileToCheck+“.png”

此外,
foreach
中的集合是不可变的-您不能更改它(添加或删除项),因此即使
File.Move
方法有效,您也会在下一次迭代中遇到错误

下面的代码(未经测试,但至少应该给您一些开始的东西)显示了另一种方法,它试图保持您的原始意图不变

File.Move(originalPathFile + fileWithCheck + ".png", duplicatePath + fileWithCheck + ".png");
var files=Directory.GetFiles(originalPathFile)
.Select(nameWithExtension=>Path.GetFileNameWithoutExtension(nameWithExtension))
.Where(name=>{int number;返回int.TryParse(name,out number);})
.Select(name=>int.Parse(name))
.OrderBy(number=>number).ToArray();
while(files.Length>1)
{
对于(int j=1;jPath.GetFileNameWithoutExtension(nameWithExtension))
.Where(name=>{int number;返回int.TryParse(name,out number);})
.Select(name=>int.Parse(name))
.OrderBy(number=>number).ToArray();
}
在上面的代码中,首先检索文件列表并将其放入
var
文件中

只要目录中有多个文件,就会执行外部
while
循环。在
while
循环中,使用
for
循环遍历文件列表(从第二个元素开始-注意
j=1
)并进行比较。如果找到匹配项,则该文件将移动到“重复项”文件夹。与
foreach
循环不同,可以在
for
循环中修改集合的内容

for
循环完成后,原始文件将被移动,循环将继续,直到文件列表中只剩下一个文件与您要查找的文件相匹配。还有另一个获取文件列表的调用,因为它可能已被修改,您将获得不再存在的文件的异常

如果需要,您可以在
循环完成后移动该文件


毫无疑问,可以进行一些改进(我认为LINQ在这里可以工作),但这至少会给您一些尝试。

writer.WriteLine(files[I].ToString()+“.png”+”已经删除了它的重复项。“)我不存在。什么变量应该是
i
?哦,我猜你的意思是
0
或者什么?哦,它工作得很好,所以谢谢:)是的,对不起-它应该是0(我最初从2 for循环开始,但忘了编辑代码)。很高兴它为您工作-快乐编码:)
private void button4_Click(object sender, EventArgs e)
{
    FileStream outputFileStream = new FileStream("log.txt", FileMode.Create, FileAccess.Write);
    StreamWriter writer = new StreamWriter(outputFileStream);

    string originalPathFile = @"C:\Users\user\Downloads\CaptchaCollection\Small\";
    string duplicatePath = @"C:\Users\user\Downloads\CaptchaCollection\Small\Duplicates\";
    string movedOriginal = @"C:\Users\user\Downloads\CaptchaCollection\Small\Sorted\";

    foreach( String fileToCheck in Directory.GetFiles(originalPathFile,"*.png"))
    {
        foreach (String fileWithCheck in Directory.GetFiles(originalPathFile, "*.png"))
        {
            if (fileToCheck != fileWithCheck)
            {
                // Your code to compare...
                Bitmap im1 = new Bitmap(fileToCheck);
                Bitmap im2 = new Bitmap(fileWithCheck);   

                if (compare(im1, im2))
                {
                    // if it's equal
                    File.Move(originalPathFile + fileWithCheck + ".png", duplicatePath + fileWithCheck + ".png");
                    writer.WriteLine(fileWithCheck + ".png" + " is a duplicate of " + fileToCheck + ".png");
                }

            }
        }

        File.Move(originalPathFile + fileToCheck + ".png", movedOriginal + fileToCheck + ".png");
        writer.WriteLine(fileToCheck + ".png " + "has had its duplicates removed.");
    }

    writer.Close();
    outputFileStream.Close();
}
File.Move(originalPathFile + fileWithCheck + ".png", duplicatePath + fileWithCheck + ".png");
var files = Directory.GetFiles(originalPathFile)
                     .Select(nameWithExtension => Path.GetFileNameWithoutExtension(nameWithExtension))
                     .Where(name => { int number; return int.TryParse(name, out number); })
                     .Select(name => int.Parse(name))
                     .OrderBy(number => number).ToArray();

while (files.Length > 1)
{

    for (int j = 1; j < files.Length; j++)
    {
        Bitmap im1 = new Bitmap(originalPathFile + files[0].ToString() + ".png");
        Bitmap im2 = new Bitmap(originalPathFile + files[j].ToString() + ".png");

        if (compare(im1, im2))
        {
            File.Move(originalPathFile + files[j].ToString() + ".png", duplicatePath + files[j].ToString() + ".png");
            writer.WriteLine(files[j].ToString() + ".png" + " is a duplicate of " + files[0].ToString() + ".png");
        }
    }

    File.Move(originalPathFile + files[0].ToString() + ".png", movedOriginal + files[0].ToString() + ".png");
    writer.WriteLine(files[0].ToString() + ".png " + "has had its duplicates removed." );

    files = Directory.GetFiles(originalPathFile)
                     .Select(nameWithExtension => Path.GetFileNameWithoutExtension(nameWithExtension))
                     .Where(name => { int number; return int.TryParse(name, out number); })
                     .Select(name => int.Parse(name))
                     .OrderBy(number => number).ToArray();
}