如何读取包含多行记录的文件 - C#

时间:2016-01-19 19:37:16

标签: c# asp.net filestream

我有这个只有一行的文本文件。每个文件包含一个客户名称,但包含多个项目和描述 以00(公司名称)开头的记录的字符长度为10 01(项目编号) - 字符长度为10
02(描述) - 炭长50

我知道如何读取文件,但我不知道如何只循环一行,查找记录00,01,02并根据长度抓取文本,最后从位置开始最后记录并再次启动循环。有人可以告诉我如何阅读这样的文件吗?

输出:

companyName     16622        Description
companyName     15522        Description

输入文本文件示例

00Init    0115522   02Description                                     0116622   02Description                                    

5 个答案:

答案 0 :(得分:7)

此解决方案假定数据是固定宽度,并且该项目编号将在描述之前(01之前的01)。每次遇到描述记录时,此解决方案都会发出记录,并处理同一公司的多个产品。

首先,定义一个用于保存数据的类:

public class Record
{
    public string CompanyName { get; set; }
    public string ItemNumber { get; set; }
    public string Description { get; set; }
}

然后,迭代你的字符串,在你得到描述时返回一条记录:

public static IEnumerable<Record> ReadFile(string input)
{
    // Alter these as appropriate
    const int RECORDTYPELENGTH = 2;
    const int COMPANYNAMELENGTH = 41;
    const int ITEMNUMBERLENGTH = 8;
    const int DESCRIPTIONLENGTH = 48;

    int index = 0;
    string companyName = null;
    string itemNumber = null;

    while (index < input.Length)
    {
        string recordType = input.Substring(index, RECORDTYPELENGTH);
        index += RECORDTYPELENGTH;

        if (recordType == "00")
        {
            companyName = input.Substring(index, COMPANYNAMELENGTH).Trim();
            index += COMPANYNAMELENGTH;
        }
        else if (recordType == "01")
        {
            itemNumber = input.Substring(index, ITEMNUMBERLENGTH).Trim();
            index += ITEMNUMBERLENGTH;
        }
        else if (recordType == "02")
        {
            string description = input.Substring(index, DESCRIPTIONLENGTH).Trim();
            index += DESCRIPTIONLENGTH;

            yield return new Record
            {
                CompanyName = companyName,
                ItemNumber = itemNumber,
                Description = description
            };
        }
        else 
        {
            throw new FormatException("Unexpected record type " + recordType);
        }
    }
}

请注意,问题中的字段长度与示例数据不匹配,因此我对其进行了调整,以便解决方案能够处理您提供的数据。您可以通过调整常量来调整字段长度。

使用如下所示:

string input = "00CompanyName                              0115522   02Description                                     0116622   02Description                                     ";

foreach (var record in ReadFile(input))
{
    Console.WriteLine("{0}\t{1}\t{2}", record.CompanyName, record.ItemNumber, record.Description);
}

答案 1 :(得分:0)

如果您将整个文件读成字符串,则有几个选项。

一,使用string.split可能有用。

另一种选择是使用string.indexof。获得索引后,可以使用string.substring

答案 2 :(得分:0)

假设指定了固定宽度,让我们创建两个简单的类来将客户端及其相关数据保存为列表:

    // can hold as many items (data) as there are in the line
    public class Client
    {
        public string name;
        public List<ClientData> data;
    };

    // one single item in the client data
    public class ClientData
    {
        public string code;
        public string description;
    };

要解析单行(假设有一个单独的客户端和一个连续的项/描述列表),我们可以这样做(注意:为简化起见,我只是创建一个静态类,其中包含一个静态方法) ):

    // this parser will read as many itens as there are in the line
    // and return a Client instance with those inside.
    public static class Parser
    {
        public static Client ParseData(string line)
        {
            Client client = new Client ();
            client.data = new List<ClientData> ();
            client.name = line.Substring (2, 10);

            // remove the client name
            line = line.Substring (12);

            while (line.Length > 0)
            {
                // create new item
                ClientData data = new ClientData ();
                data.code = line.Substring (2, 10);
                data.description = line.Substring (14, 50);
                client.data.Add (data);

                // next item
                line = line.Substring (64);
            }

            return client;
        }
    }

因此,在主循环中,刚从文件中读取新行后,您可以调用上述方法来接收新客户端。像这样:

        // should be from a file but this is just an example
        string[] lines = {
            "00XXXXXXXXXX01YYYYYYYYYY02XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXXX",
            "00XXXXXXXXXX01YYYYYYYYYY02XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXXX01YYYYYYYYYY02XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXXX",
            "00XXXXXXXXXX01YYYYYYYYYY02XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXXX",
            "00XXXXXXXXXX01YYYYYYYYYY02XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXXX",
            "00XXXXXXXXXX01YYYYYYYYYY02XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXX.XXXXXXXXXX",
        };

        // loop through each line
        // (lines can have multiple items)
        foreach (string line in lines)
        {
            Client client = Parser.ParseData (line);
            Console.WriteLine ("Read: " + client.name);
        }

答案 3 :(得分:0)

Sample.txt的内容:

00Company1  0115522     02This is a description for company 1.              00Company2  0115523     02This is a description for company 2.              00Company3  0115524     02This is a description for company 3               

请注意,在下面的代码中,字段比原始问题中指定的字段长2个字符。这是因为我在每个字段的长度中包含标题,因此通过在标题中包含10,长度为12的字段实际上为00。如果这是不合需要的,请调整fieldLengths数组中条目的偏移量。

String directory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
String file = "Sample.txt";
String path = Path.Combine(directory, file);
Int32[] fieldLengths = new Int32[] { 12, 12, 52 };

List<RowData> rows = new List<RowData>();

Byte[] buffer = new Byte[fieldLengths.Sum()];
using (var stream = File.OpenRead(path))
{
    while (stream.Read(buffer, 0, buffer.Length) > 0)
    {
        List<String> fieldValues = new List<String>();

        Int32 offset = 0;
        for (int i = 0; i < fieldLengths.Length; i++)
        {
            var value = Encoding.UTF8.GetString(buffer, offset, fieldLengths[i]);
            fieldValues.Add(value);
            offset += fieldLengths[i];
        }

        String companyName = fieldValues[0];
        String itemNumber = fieldValues[1];
        String description = fieldValues[2];

        var row = new RowData(companyName, itemNumber, description);
        rows.Add(row);
    }
}

RowData的类定义:

public class RowData
{
    public String Company { get; set; }
    public String Number { get; set; }
    public String Description { get; set; }

    public RowData(String company, String number, String description)
    {
        Company = company;
        Number = number;
        Description = description;
    }
}

结果将在rows变量中。

答案 4 :(得分:-1)

您必须根据分隔符拆分行。在您的情况下,您似乎使用空格作为分隔符。

您正在寻找的方法是String.Split(),它应该满足您的需求:)文档位于https://msdn.microsoft.com/en-us/library/system.string.split(v=vs.110).aspx - 它还包括示例。

我会做这样的事情:

string myLineOfText = "MyCompany    12345    The description of my company";
string[] partsOfMyLine = myLineOfText.Split(new string[] { "    " }, StringSplitOptions.RemoveEmptyEntries);

祝你好运! :)