读取要组合的多个文本文件的相应行

时间:2015-04-15 14:16:30

标签: c#

首先,我是C#的新手,我很难弄清楚我是如何做到这一点的。

基本上,我有多个文本文件都有自己的数据类型。我的目的是读取每个文件的第一行并将它们组合成一个字符串,以便我可以在各自的日期对它们进行排序。

例如,在每个文件的第一行中可能有值...

  • 文件1:16/02/15
  • 文件2:星期一
  • 档案3:75.730
  • 文件4:0.470
  • 文件5:75.260
  • 档案6:68182943

所以我想把它们组合成一个像这样的字符串" 16/02/15 Monday 75.730 0.470 75.260 68182943"

我也想为第二,第三,第四行等做这个。总共有144个条目或行。

这是我到目前为止的代码。我不确定自己是否走在正确的轨道上。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace BankAlgorithms
{
    class Algorithms
    {
        static void Main(string[] args)
        {
            //Saves each individual text file into their own string arrays.
            string[] Day = File.ReadAllLines(@"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files\Day.txt");
            string[] Date = File.ReadAllLines(@"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files\Date.txt");
            string[] Close = File.ReadAllLines(@"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files\SH1_Close.txt");
            string[] Diff = File.ReadAllLines(@"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files\SH1_Diff.txt");
            string[] Open = File.ReadAllLines(@"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files\SH1_Open.txt");
            string[] Volume = File.ReadAllLines(@"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files\SH1_Volume.txt");

            //Lists all files currently stored within the directory
            string[] bankFiles = Directory.GetFiles(@"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files");

            Console.WriteLine("Bank Files currently saved within directory:\n");
            foreach (string name in bankFiles)
            {
                Console.WriteLine(name);
            }

            Console.WriteLine("\nSelect the day you wish to view the data of (Monday-Friday). To view a grouped \nlist of all days, enter \"Day\"\n");
            string selectedArray = Console.ReadLine();

            if (selectedArray == "Day")
            {
                Console.WriteLine("Opening Day File...");
                Console.WriteLine("\nDays grouped up in alphabetical order\n");

                var sort = from s in Day
                           orderby s
                           select s;
                foreach (string c in sort)
                {
                    Console.WriteLine(c);
                }
            }
            Console.ReadLine();
        }
    }
}

3 个答案:

答案 0 :(得分:0)

从集合中访问文件字符串,使用此代码从每个文件中读取并使用StringBuilder构建字符串。

Read only the first few lines of text from a file

var builder = new StringBuilder();
foreach(var file in fileList)
{
    using (StreamReader reader = new StreamReader(file))
    {
        builder.Append(reader.ReadLine());
    }
}

return builder.ToString();

答案 1 :(得分:0)

您可以使用以下方法:首先将所有内容放入string[][],然后更容易:

string[][] all = { Day, Date, Close, Diff, Open, Volume };

获得所有的最小长度:

int commonRange = all.Min(arr => arr.Length);

现在这就是你所需要的:

string[] merged = Enumerable.Range(0, commonRange)
    .Select(i => string.Join(" ", all.Select(arr => arr[i])))
    .ToArray();

这类似于for - 从0到commonRange的循环,您可以访问具有相同索引的所有数组,并使用String.Join从所有数组中获取string文件行。


由于您已注释您只想合并特定日期的行:

var lineIndexes = Day.Take(commonRange)
    .Select((line, index) => new { line, index })
    .Where(x => x.line.TrimStart().StartsWith("Monday", StringComparison.InvariantCultureIgnoreCase))
    .Select(x => x.index);

string[] merged = lineIndexes
    .Select(i => string.Join(" ", all.Select(arr => arr[i])))
    .ToArray();

答案 2 :(得分:0)

所以这可能比你严格需要的多一点,但我认为它会健壮,非常灵活,并且如果需要的话能够处理大量文件。

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

namespace ConsoleApplication2
{
class Program
{
    private static void Main(string[] args)
    {
      //  const string folder = @"C:\Users\computing\Desktop\algorithms\CMP1124M_Assigment_Files";
        const string folder = @"C:\Temp\SO";
        var filenames = new[] { @"Date.txt", @"Day.txt", @"SH1_Close.txt", @"SH1_Diff.txt", @"SH1_Open.txt", @"SH1_Volume.txt" };

        var dataCombiner = new DataCombiner(folder, filenames);
        var stockParser = new StockParser();
        foreach (var stock in dataCombiner.GetCombinedData(stockParser.Parse)) //can also use where clause here
        { 
            if (ShowRow(stock))
            {
                var outputText = stock.ToString();
                Console.WriteLine(outputText);
            }
        }

        Console.ReadLine();
    }

    private static bool ShowRow(Stock stock)
    {
        //use input from user etc...
        return     (stock.DayOfWeek == "Tuesday" || stock.DayOfWeek == "Monday")
                && stock.Volume > 1000 
                && stock.Diff < 10; // etc
    }
}

internal class DataCombiner
{
    private readonly string _folder;
    private readonly string[] _filenames;

    public DataCombiner(string folder, string[] filenames)
    {
        _folder = folder;
        _filenames = filenames;
    }

    private static IEnumerable<string> GetFilePaths(string folder, params string[] filenames)
    {
        return filenames.Select(filename => Path.Combine(folder, filename));
    }

    public IEnumerable<T> GetCombinedData<T>(Func<string[], T> parserMethod) where T : class
    {
        var filePaths = GetFilePaths(_folder, _filenames).ToArray();
        var files = filePaths.Select(filePath => new StreamReader(filePath)).ToList();

        var lineCounterFile = new StreamReader(filePaths.First());
        while (lineCounterFile.ReadLine() != null)// This can be replaced with a simple for loop if the files will always have a fixed number of rows
        {
            var rawData = files.Select(file => file.ReadLine()).ToArray();
            yield return parserMethod(rawData);
        }
    }
}

internal class Stock
{
    public DateTime Date { get; set; }
    public string DayOfWeek { get; set; }
    public double Open { get; set; }
    public double Close { get; set; }
    public double Diff { get; set; }
    public int Volume { get; set; }

    public override string ToString()
    {
        //Whatever format you want
        return string.Format("{0:d} {1} {2} {3} {4} {5}", Date, DayOfWeek, Close, Diff, Open, Volume);
    }
}

internal class StockParser
{
    public Stock Parse(string[] rawData)
    {
        //TODO: Error handling required here
        var stock = new Stock();
        stock.Date = DateTime.Parse(rawData[0]);
        stock.DayOfWeek = rawData[1];
        stock.Close = double.Parse(rawData[2]);
        stock.Diff = double.Parse(rawData[3]);
        stock.Open = double.Parse(rawData[4]);
        stock.Volume = int.Parse(rawData[5]); 
        return stock;
    }

    public string ParseToRawText(string[] rawData)
    {
        return string.Join(" ", rawData);
    }
}
}

PS:
我不是从文件中读取它,而是从Date开始计算DayOfWeek。 从不同的语言环境解析日期时也要小心(例如,USA vs UK)。 如果您有选项我只使用ISO 8601日期时间格式。