调整循环结束时正在读取的文件的名称而不中断循环

时间:2012-12-04 09:48:47

标签: c# date increment

每天结束时有2份报告。我希望能够在每个月末对它们进行分析。

每个文件里面都有一千行左右的长ASCII字符串。这已经成功编码,但只能一次提取和执行一个文件的分析。

我会试着把下面代码的相关结构放进去。我希望这足以让我知道需要做些什么。如果没有,我很乐意发布整个事情。

using (StreamReader reader = new StreamReader("YYYYMMDD----1234D.dat"))
{
while loop //this goes through all the lines in the file. 
{if //if meets certain criteria then store into a list, otherwise ignore

}
foreach // this part does the analysis of all the values in the list, totals, etc

第一个报告采用上述格式,另一个采用不同的编号代替1234D(为了论证,5678D,所以:yyyymmdd ---- 5678D)。这两个数字始终保持不变。

我希望能够将所有数据从每个文件存储到我的列表中,然后在整个月内执行分析,而不是每天都有细分,因此它会循环遍历每个文件,当它到达文件的末尾,将名称增加一天,循环等等(或查找具有一个月X的所有文件 - 以较好者为准)。这将填充列表,然后foreach将执行其分析和输出。我希望将所有必需的文件放在与程序当前使用的文件夹相同的文件夹中。

当前代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq;

class Program 
{
    public class EntryLine
    {
        public int I { get; set; }
        public string LineStart { get; set; }
        public string Letters { get; set; }
        public int TVolume { get; set; }
        public long TPrice { get; set; }
        public double MVolume { get; set; }
        public string Currency { get; set; }
        public string DateTime {get; set; }

    }

    static void Main(string[] args)
    {
        List<EntryLine> myList = new List<EntryLine>();
        int i = 1;
        using (StreamReader reader = new StreamReader("20121203----1234D.dat"))
        {
            string line;
            var locations = new Dictionary<string, int[]>() {
            {"210", new [] {405, 4, 128, 12, 141, 12, 247, 15, 121, 3}}, 
            {"310", new [] {321, 4, 112, 12, 125, 12, 230, 15, 105, 3}}, 
            {"410", new [] {477, 4, 112, 12, 125, 12, 360, 15, 105, 3}} 
        };

            while ((line = reader.ReadLine()) != null)
            {
                var lineStart = line.Substring(0, 3);

                if (lineStart == "210" || lineStart == "310" || lineStart == "410")
                {
                    var currentLocations = locations[lineStart];
                    var letters = line.Substring(currentLocations[0], currentLocations[1]);

                    var tvolume =
                        int.Parse(line.Substring(currentLocations[2], currentLocations[3])) +
                        int.Parse(line.Substring(currentLocations[4], currentLocations[5]));

                    var tprice = long.Parse(line.Substring(currentLocations[6], currentLocations[7]));
                    var mvolume = tprice * tvolume * 0.01 * 0.0000001;
                    var currency = line.Substring(currentLocations[8], currentLocations[9]);

                    myList.Add(new EntryLine()
                    {
                        I = i,
                        LineStart = lineStart,
                        Letters = letters,
                        TVolume = tvolume,
                        TPrice = tprice,
                        MVolume = mvolume,
                        Currency = currency
                    });
                    i = i + 1;
                }
            }

            var x = myList.GroupBy(g => new { g.Letters, g.Currency })
                .Select(a => new { a.Key.Letters, a.Key.Currency, TSum = a.Sum(s => s.TVolume), MSum = a.Sum(s => s.MVolume) });

            foreach (var item in x)
            {
                Console.WriteLine("{0} currency: {1} tvolume: {2} mVolume: {3}", item.Letters, item.Currency, item.TSum, item.MSum);
            }
        } Console.ReadLine();
    }

}

3 个答案:

答案 0 :(得分:1)

有很多方法可以做到这一点。这里有一个选项:首先,将程序分解为几个函数,以便于代码维护。然后使用一个函数循环遍历所有文件并构建一个信息列表,另一个函数用于分析该信息。

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ReportAnalysis {
static class Program {
    static void Main() {
        //lets run the analysis for Nov, 2012

        //First, read in all report files, and store relevant lines
        var reportInfo = ReportAnalyzer.ReadFiles(2012, 11);

        //Now analyze all files at once
        ReportAnalyzer.RunAnalysis(reportInfo);
    }
}
class ReportAnalyzer {
    struct ReportFile {
        public string Path;
        public DateTime Date;
        public List<string> Lines;
    }

    public static IList<ReportFile> ReadFiles(int year, int month) {
        //Put names of files here.
        string[] fileNames = new string[] { "{0:YYYYMMDD}----1234D.dat", "{0:YYYYMMDD}----5678D.dat" };

        DateTime dateStart = new DateTime(year, month, 1); //start of month
        DateTime dateEnd = dateStart.AddMonths(1); //start of NEXT month (i.e. 1 day past end of this month)

        var reportList = new List<ReportFile>();

        DateTime date = dateStart;
        while (date < dateEnd) {  //we don't actually get to dateEnd, just the day before it.
            foreach (var fileTemplate in fileNames) {
                //insert the date in YYYYMMDD format
                var file = string.Format(fileTemplate, date);
                if (File.Exists(file)) {
                    var report = new ReportFile() {
                        Date = date,
                        Path = file,
                        Lines = GetReportLines(file)
                    };
                    reportList.Add(report);
                }
            }
            //now jump to next day
            date = date.AddDays(1);
        }
        return reportList;
    }

    private static List<string> GetReportLines(string file) {
        var lines = new List<string>();
        try {
            using (StreamReader reader = new StreamReader(file)) {
                while (!reader.EndOfStream) {
                    var line = reader.ReadLine();
                    if (true /* insert criteria */)
                        lines.Add(line);
                }
            }
        } catch (Exception ex) {
            //log the error however you see fit
            lines.Add(string.Format("ERROR Could not open report file {0}: {1}", file, ex.Message));
        }
        return lines;
    }

    public static void RunAnalysis(IList<ReportFile> reports) {
        foreach (var r in reports) {
            //Do whatever analysis you need
            Console.WriteLine(r.Date);
            Console.WriteLine(r.Path);
            foreach (var line in r.Lines)
                Console.WriteLine(line);
        }
    }
}
}

这是一个“简短的甜蜜”版本,只涉及重要的部分:

void ProcessReports {
    string[] fileNames = new string[] { "{0:YYYYMMDD}----1234D.dat", "{0:YYYYMMDD}----5678D.dat" };
    DateTime dateStart = new DateTime(year, month, 1); //start of month
    DateTime dateEnd = dateStart.AddMonths(1); //start of NEXT month (i.e. 1 day past end of this month)
    List<string> lines = new List<string>();
    DateTime date = dateStart;
    while (date < dateEnd) {  //we don't actually get to dateEnd, just the day before it.
        foreach (var fileTemplate in fileNames) {
            //insert the date in YYYYMMDD format
            var file = string.Format(fileTemplate, date);
            if (File.Exists(file)) {
                using (StreamReader reader = new StreamReader(file)) {
                    while (!reader.EndOfStream) {
                        var line = reader.ReadLine();
                        if (true /* insert criteria */)
                            lines.Add(line);
                    }
                }
            }
        }
        //now jump to next day
        date = date.AddDays(1);
    }   
    //Now we have all the lines. Let's process them;
    foreach (var line in lines) {
        //do something with the report lines
    }
}

答案 1 :(得分:0)

如果您只是将foreach移出using块,那么就没有什么可以阻止您使用第二个文件名复制using块,或者放置using块在你自己的循环中,你将文件名传递给:

string[] filenames = new string[] {
    "20121203 ----1234D.dat",
    "20121204 ----1234D.dat",
    "20121205 ----1234D.dat" };
List<Whatever> yourListOfMatchingItems = new List<Whatever>();

foreach (string filename in filenames)
{
    using (StreamReader reader = new StreamReader(filename))
    {
        while (/* whatever you had before */)
        {
            if (/* whatever you had before */)
            {
            }
        }
    }
}
foreach (/* item in your list */)
{
}

答案 2 :(得分:0)

您需要动态创建文件的名称,而不是对其进行硬编码。然后,您可以遍历所有文件以生成值列表,然后处理它们。

为什么不把它分成几个方法?类似的东西:

public void Process()
{
    // logic to get string[] of filenames here. You could loop through each
    // day you need a list for and generate a filename for the given day
    var values = new List<T>();
    foreach (var filename in filenames)
    {
        var valuesFromFile = GetValuesFrom(filename);
        values.AddRange(valuesFromFile);
    }
    ProcessValues(values);
}

private List<T> GetValuesFrom(string filename)
{
    var values = new List<T>();
    while loop //this goes through all the lines in the file. 
    {if //if meets certain criteria then store into a list, otherwise ignore
    }
    return values;
}

private void ProcessValues(List<T> values)
{
    foreach // this part does the analysis of all the values in the list, totals, etc
}

T当然是您的价值类型