可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have files in directory like that
0-0.jpeg 0-1.jpeg 0-5.jpeg 0-9.jpeg 0-10.jpeg 0-12.jpeg
....
when i loading files:
FileInfo[] files = di.GetFiles();
They getting in wrong order (they should go like above):
0-0.jpeg 0-1.jpeg 0-10.jpeg 0-12.jpeg 0-5.jpeg 0-9.jpeg
How to fix that?
I was trying to sort them but no way:
1) Array.Sort(files, (f1, f2) => f1.Name.CompareTo(f2.Name)); 2) Array.Sort(files, (x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.Name, y.Name));
回答1:
Alphabetically, the "wrong" order is in fact correct. If you want it sorted numerically then you'll need to either:
- convert the filenames to a list of numeric numbers and sort them
- name the files in such a way that alphabetic and numeric sorting are the same (0-001.jpeg and 0-030.jpg)
- rely on the file creation time to sort (presuming the files were created in order).
See the answer to Sorting Directory.GetFiles() for an example of #3.
回答2:
See the "CustomSort" function here here.
List list = new List() { "0-5.jpeg", "0-9.jpeg", "0-0.jpeg", "0-1.jpeg", "0-10.jpeg", "0-12.jpeg"}; list.CustomSort().ToList().ForEach(x => Console.WriteLine(x));
Its output:
0-0.jpeg 0-1.jpeg 0-5.jpeg 0-9.jpeg 0-10.jpeg 0-12.jpeg
回答3:
For solving this problem you can use StrCmpLogicalW windows API.
For more details see This Artice.
回答4:
I know this might be late, but here is another solution which works perfectly
FileInfo[] files = di.GetFiles().OrderBy(n => Regex.Replace(n.Name, @"\d+", n => n.Value.PadLeft(4, '0')));
Using Regex replace in the OrderBy Clause
:
Regex.Replace(n.Name, @"\d+", n => n.Value.PadLeft(4, '0'))
So what this does, it pads
the numeric values in the file name with a length of 4 chars in each number:
0-0.jpeg -> 0000-0000.jpeg 0-1.jpeg -> 0000-0001.jpeg 0-5.jpeg -> 0000-0005.jpeg 0-9.jpeg -> 0000-0009.jpeg 0-10.jpeg -> 0000-0010.jpeg 0-12.jpeg -> 0000-0012.jpeg
But this only happens in the OrderBy
clause, it does not touch the original file name in any way. The order you will end up with in the array is the "human natural" order.
回答5:
You filenames appear to be structured. If you just sort them, they sort as ordinary strings. You need to:
- Parse the file name into its constituent component parts.
- Convert the numeric segments to a numeric value.
- Compare that structure in the desired order to get the intended collation sequence.
Personally, I'd create a class that represented the structure implicit in the filename. Perhaps it should wrap the FileInfo
. The constructor for that class should parse the filename into its constituent parts and instantiate the properties of the class appropriately.
The class should implement IComparable
/IComparable
(or you could create an implementation of Comparer).
Sort your objects and they should then come out in the collating sequence you desire.
If looks like your file names are composed of 3 parts:
- a high-order numeric value (let's call it 'hi'),
- a low-order numeric value (let's call it 'lo'),
- and an extension (let's call it 'ext')
So your class might look something like
public class MyFileInfoWrapper : IComparable,IComparable { public MyFileInfoWrapper( FileInfo fi ) { // your implementation here throw new NotImplementedException() ; } public int Hi { get ; private set ; } public int Lo { get ; private set ; } public string Extension { get ; private set ; } public FileInfo FileInfo { get ; private set ; } public int CompareTo( MyFileInfoWrapper other ) { int cc ; if ( other == null ) cc = -1 ; else if ( this.Hi other.Hi ) cc = +1 ; else if ( this.Lo other.Lo ) cc = +1 ; else cc = string.Compare( this.Extension , other.Extension , StringComparison.InvariantCultureIgnoreCase ) ; return cc ; } public int CompareTo( object obj ) { int cc ; if ( obj == null ) cc = -1 ; else if ( obj is MyFileInfoWrapper ) cc = CompareTo( (MyFileInfoWrapper) obj ) ; else throw new ArgumentException("'obj' is not a 'MyFileInfoWrapper' type.", "obj") ; return cc ; } }