C# 根据大小计算文件组数

C# 根据大小计算文件组数,c#,.net,linq,C#,.net,Linq,我如何简化这一点?我试图根据目录和子目录的大小获取Excel文件的数量。我至少有10个不同的分组 var queryList2Only = from i in di.GetFiles("*.xls", SearchOption.TopDirectoryOnly) .Where(f => f.Length <= 5120) select i.Length; if (queryLi

我如何简化这一点?我试图根据目录和子目录的大小获取Excel文件的数量。我至少有10个不同的分组

var queryList2Only = from i in di.GetFiles("*.xls", SearchOption.TopDirectoryOnly)
                                 .Where(f => f.Length <= 5120)
                     select i.Length;
if (queryList2Only.Any())
{
    dest.WriteLine("Excel File <= 5 KB");
    dest.WriteLine(queryList2Only.Count());
    dest.WriteLine("");
}

var queryList3Only = from i in di.GetFiles("*.xls", SearchOption.TopDirectoryOnly)
                                 .Where(f => f.Length > 5120 && f.Length <= 10240)
                     select i.Length;
if (queryList3Only.Any())
{
    dest.WriteLine("Excel File > 5 KB and <= 10 KB");
    dest.WriteLine(queryList3Only.Count());
    dest.WriteLine("");

您需要将范围放入集合中,并对其进行枚举。 下面是一个应该让您开始的示例-sizes数组包含步骤,当然您应该选择对应用程序有意义的步骤:

int[] sizes = Enumerable.Range(0,10).Select(n => (int)Math.Pow(2,n + 8)).ToArray();
int lower = 0;
foreach(var size in sizes)
{
    var files = di.GetFiles("*.*").Where(f => f.Length >= lower && f.Length < size);
    Console.WriteLine("Between {0} and {1} bytes:", lower,size);
    foreach(var file in files)
        Console.WriteLine("\t{0}",file);
    lower = size;
}
int[]size=Enumerable.Range(0,10)。选择(n=>(int)Math.Pow(2,n+8)).ToArray();
整数下限=0;
foreach(变量大小,以大小为单位)
{
var files=di.GetFiles(“*”)。其中(f=>f.Length>=lower&&f.Length
您需要将范围放入集合中,并对其进行枚举。 下面是一个应该让您开始的示例-sizes数组包含步骤,当然您应该选择对应用程序有意义的步骤:

int[] sizes = Enumerable.Range(0,10).Select(n => (int)Math.Pow(2,n + 8)).ToArray();
int lower = 0;
foreach(var size in sizes)
{
    var files = di.GetFiles("*.*").Where(f => f.Length >= lower && f.Length < size);
    Console.WriteLine("Between {0} and {1} bytes:", lower,size);
    foreach(var file in files)
        Console.WriteLine("\t{0}",file);
    lower = size;
}
int[]size=Enumerable.Range(0,10)。选择(n=>(int)Math.Pow(2,n+8)).ToArray();
整数下限=0;
foreach(变量大小,以大小为单位)
{
var files=di.GetFiles(“*”)。其中(f=>f.Length>=lower&&f.Length
您不一定需要LINQ。对你来说,通过它循环会更有效率。虽然Rup的解决方案在这里是LINQ的一个很好的使用

这里有一个更完整的版本,完全适合您想要做的事情

// count it
CountFiles(dest, di, @"*.xls");

public void CountFiles(TextWriter writer, DirectoryInfo directory, string searchPattern)
{
    var counter = new FileGroupCounter
    {
        { 5,    Multiplier.K },
        { 10,   Multiplier.K },
        { 20,   Multiplier.K },
        { 100,  Multiplier.K },
        { 1000, Multiplier.K },
        { 5,    Multiplier.M },
        { 10,   Multiplier.M },
        { 20,   Multiplier.M },
        { 50,   Multiplier.M },
        { 100,  Multiplier.M },
    };

    foreach (var file in directory.EnumerateFiles(searchPattern, SearchOption.AllDirectories))
                         // or use GetFiles() if you're not targeting .NET 4.0
    {
        counter.CountFile(file);
    }

    foreach (var result in counter)
    {
        writer.WriteLine("Excel File " + result);
        writer.WriteLine(result.Count);
        writer.WriteLine();
    }
}

// and the supporting classes
public enum Multiplier : long
{
    K = 1 << 10,
    M = 1 << 20,
    G = 1 << 30,
    T = 1 << 40,
}

public class FileGroupCounter : IEnumerable<FileGroupCounter.Result>
{
    public ReadOnlyCollection<long> Limits { get { return roLimits; } }
    public ReadOnlyCollection<int> Counts { get { return roCounts; } }
    public ReadOnlyCollection<Multiplier> Multipliers { get { return roMultipliers; } }

    public FileGroupCounter()
    {
        limits = new List<long>();
        counts = new List<int>();
        multipliers = new List<Multiplier>();
        roLimits= limits.AsReadOnly();
        roCounts= counts.AsReadOnly();
        roMultipliers= multipliers.AsReadOnly();
    }

    private List<long> limits;
    private List<int> counts;
    private List<Multiplier> multipliers;
    private ReadOnlyCollection<long> roLimits;
    private ReadOnlyCollection<int> roCounts;
    private ReadOnlyCollection<Multiplier> roMultipliers;

    private long CalculateLength(int index)
    {
        return limits[index] * (long)multipliers[index];
    }

    public void Add(long limit, Multiplier multiplier)
    {
        int lastIndex = limits.Count - 1;
        if (lastIndex >= 0 && limit * (long)multiplier <= CalculateLength(lastIndex))
            throw new ArgumentOutOfRangeException("limit, multiplier", "must be added in increasing order");

        limits.Add(limit);
        counts.Add(0);
        multipliers.Add(multiplier);
    }

    public bool CountFile(FileInfo file)
    {
        if (file == null)
            throw new ArgumentNullException("file");

        for (int i = 0; i < limits.Count; i++)
        {
            if (file.Length <= CalculateLength(i))
            {
                counts[i]++;
                return true;
            }
        }
        return false;
    }

    public IEnumerator<Result> GetEnumerator()
    {
        for (int i = 0; i < limits.Count; i++)
        {
            if (counts[i] > 0)
                yield return new Result(this, i);
        }
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }

    public class Result
    {
        public long Limit { get { return counter.limits[index]; } }
        public int Count { get { return counter.counts[index]; } }
        public Multiplier Multiplier { get { return counter.multipliers[index]; } }

        internal Result(FileGroupCounter counter, int index)
        {
            this.counter = counter;
            this.index = index;
        }
        private FileGroupCounter counter;
        private int index;

        public override string ToString()
        {
            if (index > 0)
                return String.Format("> {0} {1}B and <= {2} {3}B",
                    counter.limits[index - 1], counter.multipliers[index - 1],
                    counter.limits[index], counter.multipliers[index]);
            else
                return String.Format("<= {0} {1}B",
                    counter.limits[index], counter.multipliers[index]);
        }
    }
}
//数一数
countfile(dest,di,@“*.xls”);
公共void CountFiles(TextWriter编写器、DirectoryInfo目录、字符串搜索模式)
{
var counter=newfilegroupcounter
{
{5,乘数.K},
{10,乘数.K},
{20,乘数.K},
{100,乘数.K},
{1000,乘数.K},
{5,乘数.M},
{10,乘数M},
{20,乘数M},
{50,乘数.M},
{100,乘数.M},
};
foreach(directory.EnumerateFiles(searchPattern、SearchOption.AllDirectories)中的var文件)
//如果不是针对.NET 4.0,请使用GetFiles()
{
counter.CountFile(文件);
}
foreach(计数器中的var结果)
{
writer.WriteLine(“Excel文件”+结果);
writer.WriteLine(result.Count);
writer.WriteLine();
}
}
//以及支援阶层
公共枚举乘数:长
{

K=1你不一定需要LINQ来完成这个任务。你只需循环它就会更有效。尽管Rup的解决方案在这里是LINQ的一个很好的使用

这里有一个更完整的版本,完全适合您想要做的事情

// count it
CountFiles(dest, di, @"*.xls");

public void CountFiles(TextWriter writer, DirectoryInfo directory, string searchPattern)
{
    var counter = new FileGroupCounter
    {
        { 5,    Multiplier.K },
        { 10,   Multiplier.K },
        { 20,   Multiplier.K },
        { 100,  Multiplier.K },
        { 1000, Multiplier.K },
        { 5,    Multiplier.M },
        { 10,   Multiplier.M },
        { 20,   Multiplier.M },
        { 50,   Multiplier.M },
        { 100,  Multiplier.M },
    };

    foreach (var file in directory.EnumerateFiles(searchPattern, SearchOption.AllDirectories))
                         // or use GetFiles() if you're not targeting .NET 4.0
    {
        counter.CountFile(file);
    }

    foreach (var result in counter)
    {
        writer.WriteLine("Excel File " + result);
        writer.WriteLine(result.Count);
        writer.WriteLine();
    }
}

// and the supporting classes
public enum Multiplier : long
{
    K = 1 << 10,
    M = 1 << 20,
    G = 1 << 30,
    T = 1 << 40,
}

public class FileGroupCounter : IEnumerable<FileGroupCounter.Result>
{
    public ReadOnlyCollection<long> Limits { get { return roLimits; } }
    public ReadOnlyCollection<int> Counts { get { return roCounts; } }
    public ReadOnlyCollection<Multiplier> Multipliers { get { return roMultipliers; } }

    public FileGroupCounter()
    {
        limits = new List<long>();
        counts = new List<int>();
        multipliers = new List<Multiplier>();
        roLimits= limits.AsReadOnly();
        roCounts= counts.AsReadOnly();
        roMultipliers= multipliers.AsReadOnly();
    }

    private List<long> limits;
    private List<int> counts;
    private List<Multiplier> multipliers;
    private ReadOnlyCollection<long> roLimits;
    private ReadOnlyCollection<int> roCounts;
    private ReadOnlyCollection<Multiplier> roMultipliers;

    private long CalculateLength(int index)
    {
        return limits[index] * (long)multipliers[index];
    }

    public void Add(long limit, Multiplier multiplier)
    {
        int lastIndex = limits.Count - 1;
        if (lastIndex >= 0 && limit * (long)multiplier <= CalculateLength(lastIndex))
            throw new ArgumentOutOfRangeException("limit, multiplier", "must be added in increasing order");

        limits.Add(limit);
        counts.Add(0);
        multipliers.Add(multiplier);
    }

    public bool CountFile(FileInfo file)
    {
        if (file == null)
            throw new ArgumentNullException("file");

        for (int i = 0; i < limits.Count; i++)
        {
            if (file.Length <= CalculateLength(i))
            {
                counts[i]++;
                return true;
            }
        }
        return false;
    }

    public IEnumerator<Result> GetEnumerator()
    {
        for (int i = 0; i < limits.Count; i++)
        {
            if (counts[i] > 0)
                yield return new Result(this, i);
        }
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }

    public class Result
    {
        public long Limit { get { return counter.limits[index]; } }
        public int Count { get { return counter.counts[index]; } }
        public Multiplier Multiplier { get { return counter.multipliers[index]; } }

        internal Result(FileGroupCounter counter, int index)
        {
            this.counter = counter;
            this.index = index;
        }
        private FileGroupCounter counter;
        private int index;

        public override string ToString()
        {
            if (index > 0)
                return String.Format("> {0} {1}B and <= {2} {3}B",
                    counter.limits[index - 1], counter.multipliers[index - 1],
                    counter.limits[index], counter.multipliers[index]);
            else
                return String.Format("<= {0} {1}B",
                    counter.limits[index], counter.multipliers[index]);
        }
    }
}
//数一数
countfile(dest,di,@“*.xls”);
公共void CountFiles(TextWriter编写器、DirectoryInfo目录、字符串搜索模式)
{
var counter=newfilegroupcounter
{
{5,乘数.K},
{10,乘数.K},
{20,乘数.K},
{100,乘数.K},
{1000,乘数.K},
{5,乘数.M},
{10,乘数M},
{20,乘数M},
{50,乘数.M},
{100,乘数.M},
};
foreach(directory.EnumerateFiles(searchPattern、SearchOption.AllDirectories)中的var文件)
//如果不是针对.NET 4.0,请使用GetFiles()
{
counter.CountFile(文件);
}
foreach(计数器中的var结果)
{
writer.WriteLine(“Excel文件”+结果);
writer.WriteLine(result.Count);
writer.WriteLine();
}
}
//以及支援阶层
公共枚举乘数:长
{

K=1我认为这里唯一真正的优化是确保只调用
di.GetFiles(“*.xls”,SearchOption.TopDirectoryOnly)
一次-因为这实际上会命中文件系统,而不是像大多数LINQ一样被延迟执行。当然,文件系统会缓存这一操作的结果,但不能再慢了,以便留在内存中并重用列表

一旦你进入记忆,Jeff可能是对的-数一数你自己-觉得这似乎不是很优雅:-)除非你处理的是巨大的数字,否则这可能不会有太大的区别。你只想尽量减少分配/再分配的数量。尽可能多的LINQ我可以塞进

var files = di.GetFiles("*.xls", SearchOption.TopDirectoryOnly);
// map to a list of numbers, 0 = up to 5K, 1 = 5-10, etc.
var sizes = files.Select(f => (f.Length / 5120));
var countsBySize = sizes.GroupBy(s => s)
                        .Select(g => new { Size = g.Key, Count = g.Count() })
                        .OrderBy(s => s.Size);
var results = countBySize.ToList();

它返回5K个存储桶的列表和每个存储桶中的文件数。如果您只是想查看此列表,则不要执行最终的ToList。如果您想要每个存储桶中的单个文件,则应按(f.Length/5120)分组没有先选择它。

我认为这里唯一真正的优化是确保只调用
di.GetFiles(“*.xls”,SearchOption.TopDirectoryOnly)
一次-因为这实际上会命中文件系统,而不是像大多数LINQ一样被延迟执行。当然,文件系统会缓存这一操作的结果,但不能再慢了,以便留在内存中并重用列表

一旦你进入记忆,Jeff可能是对的-数一数你自己-觉得这似乎不是很优雅:-)除非你处理的是巨大的数字,否则这可能不会有太大的区别。你只想尽量减少分配/再分配的数量。尽可能多的LINQ我可以塞进

var files = di.GetFiles("*.xls", SearchOption.TopDirectoryOnly);
// map to a list of numbers, 0 = up to 5K, 1 = 5-10, etc.
var sizes = files.Select(f => (f.Length / 5120));
var countsBySize = sizes.GroupBy(s => s)
                        .Select(g => new { Size = g.Key, Count = g.Count() })
                        .OrderBy(s => s.Size);
var results = countBySize.ToList();

它返回5K个存储桶的列表和每个存储桶中的文件数。如果您只是想查看此列表,则不要执行最终的ToList。如果您想要每个存储桶中的单个文件,则应按(f.Length/5120)分组不首先选择它。

定义数组中的范围,然后在其上循环?这与存储库模式有什么关系?定义数组中的范围,然后在其上循环?这与存储库模式有什么关系?@bala:是的。但你可以始终回到u