上一篇记录了下重命名的一般操作步骤,这篇以一个具体的小例子做记录。
文件重命名要求:
将Pic目录下的照片进行重命名,命名规则:(1) 道路照片编号01-09;(2) 建筑物照片编号11-19;(3) 其他类别照片文件名顺序41以后。
原始文件名形如:“道路名称_0101_0_2322.jpg” ,释义为“被拍摄对象的名称”+“下划线”+“被拍摄对象的类别编码”+“下划线”+“被拍摄对象的多媒体类别”+“下划线”+“四位随机数”.jpg。
其中多媒体类别即道路照片对应0, 建筑物照片对应1, 其他类别照片对应4。
重命名后文件名形如:“道路名称_0101_01.jpg"。
说明:每个被拍摄对象可能会有多张照片(最多9张),此时要将末尾的四位随机数换成编号递增进行处理。被拍摄名称会不同,其类别会不同,其多媒体类别会不同,故每次出现不同,在对应其多媒体类别的同时编号都要从1开始递增。
最初思路:
1、从原文件名fileName中分别解析出:被拍摄对象名称(stdName)、类别(type)、多媒体类别(mediaType);
2、对于同一对象相同类别的多张照片进行计数操作,将第1步解析出来的部分结合该计数进行组合即可。
起初感觉这样可以,但实现时依次对每个文件处理时却发现由于stdName,type,mediaType都有可能不同,无法确定计数起点和终点。但分部分重新组合是可行的,故问题转换为如何确定最后一位的递增数目。大牛 鹏哥指点了下,”先对所有文件排序,出现stdName、type、mediaType不同就截断进行处理...“,按照鹏哥的思路我想了一个”盒子算法“。
”盒子算法“的主要思路是:
定义一个盒子Box(即List<string> box),对fileNameList中各项先排序(Sort排序即可),排序后两两比较(称为前项first和后项second),满足条件M(【条件M:前项后项的stdName、type、mediaType三项都相同,说明两项是同一物体同类别且同多媒体类型的不同照片】)则将后项入盒,盒子状态置为打开,first = second,second = second.next,继续循环比较;若不满足条件M,说明两项已不是同一组的照片(不论是名称不同、类别不同或多媒体类型不同,总之该项的末尾命名编号是*1),盒子状态置为关闭(盒子状态对最开始初始化时的first有效,因为最初要先将first入盒,确保只有一个文件,或第一个文件跟第二个文件不同类时前者能被正确处理),对盒子内的项重命名,清空盒子,first = second, second = second.next,循环继续。直到最后一个文件时,单独处理。
简单地讲,就是循环进行两两比较,条件M都匹配的则入盒直到遇到不匹配的,这样当前盒子里都是同一种类的照片,再集中对其按次序命名;每次不匹配就可以立即对盒子里的项进行重命名。
其关键代码如下:
private void preRename() { string first = fileNameList[0]; string second = fileNameList[1]; bool keepOpen = false; int index = 2; do { if (!keepOpen) // box为关闭状态 { box.Add(first); } if (match(first, second)) { keepOpen = true; box.Add(second); first = second; second = fileNameList[index]; } else { keepOpen = false; renameFile(ref box); // 对盒子中现存项重命名 output(0,box); box.Clear(); first = second; second = fileNameList[index]; } index++; if (index == picNameList.Count) // 说明是最后一个文件,单独处理,处理完跳出循环即可 { if (!keepOpen) { box.Add(first); } if (match(first, second)) { box.Add(second); renameFile(ref box); output(0,box); box.Clear(); } else { renameFile(ref box); output(0,box); box.Clear(); renameFile(ref second); // 单独对second(即最后一个文件)重命名 fileNameListNew.Add(second); // 既要输出box中的值,也要对second输出 } } } while (index < fileNameList.Count); }
<pre name="code" class="csharp"><pre name="code" class="csharp">private bool match(string first, string second) { if (firStdName.Equals(secStdName) && firType.Equals(secType) && firMediaType.Equals(secMediaType)) // 若名称、类别和多媒体类型均相同返回 true { return true; } else { return false; } }
虽然只是个简单的重命名功能,但实际的需求往往并不一定那么顺畅,需要自己再做一些思考,这本身就是很好的学习。在纸上写下伪代码,再代码实现,再一步步完善。