Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有动态列数的平面文件规范化_C#_Parsing_Text_Formatting_Flat File - Fatal编程技术网

C# 具有动态列数的平面文件规范化

C# 具有动态列数的平面文件规范化,c#,parsing,text,formatting,flat-file,C#,Parsing,Text,Formatting,Flat File,我有一个带有动态列结构的平面文件。在值的层次结构中有一个值,层次结构中的每一层都有自己的列。例如,我的平面文件可能类似于: StatisticID|FileId|Tier0ObjectId|Tier1ObjectId|Tier2ObjectId|Tier3ObjectId|Status 1234|7890|abcd|efgh|ijkl|mnop|Pending ... StatisticID|FileId|Tier0ObjectId|Tier1ObjectId|Tier2ObjectId|St

我有一个带有动态列结构的平面文件。在值的层次结构中有一个值,层次结构中的每一层都有自己的列。例如,我的平面文件可能类似于:

StatisticID|FileId|Tier0ObjectId|Tier1ObjectId|Tier2ObjectId|Tier3ObjectId|Status
1234|7890|abcd|efgh|ijkl|mnop|Pending
...
StatisticID|FileId|Tier0ObjectId|Tier1ObjectId|Tier2ObjectId|Status
1234|7890|abcd|efgh|ijkl|Complete
...
第二天的相同饲料可能类似于:

StatisticID|FileId|Tier0ObjectId|Tier1ObjectId|Tier2ObjectId|Tier3ObjectId|Status
1234|7890|abcd|efgh|ijkl|mnop|Pending
...
StatisticID|FileId|Tier0ObjectId|Tier1ObjectId|Tier2ObjectId|Status
1234|7890|abcd|efgh|ijkl|Complete
...
问题是,我不太在乎所有的层次;我只关心最后一个底层的id,以及不属于层列的所有其他行数据。我需要将提要规范化为类似的内容,以便注入关系数据库:

StatisticID|FileId|ObjectId|Status
1234|7890|ijkl|Complete
...
对于确定最后一层对象id和按所述组织数据,什么是一种高效、易于阅读的机制?我所做的每一次尝试对我来说都是困难的

我做过一些事情:

我试图检查正则表达式模式的列名,确定分层的列,按名称降序排列,并选择第一条记录。。。但是这样我就丢失了顺序列的编号,所以看起来不太好。 我已经将我想要的列放置到IDictionary对象中以供引用,但再次强调,可靠地收集动态列的序号是一个问题,而且这似乎是相当没有性能的。
就我个人而言,我不会尝试重新格式化你的文件。我认为最简单的方法是从前面和后面解析每一行。例如:

itemArray = getMyItems();
statisticId = itemArray[0];
fileId = itemArray[1];
//and so on for the rest of your pre-tier columns

//Then get the second to last column which will be the last tier
lastTierId = itemArray[itemArray.length -1];
因为你知道最后一层永远是距离终点的第二层,所以你可以从终点开始,继续前进。这似乎比尝试重新格式化数据文件要容易得多


如果你真的想创建一个新文件,你可以使用这种方法来获取你想要写出的数据。

我不知道C语法,但大致如下:

使用|作为分隔符将线拆分为多个部分 获取部分[0]、[1]、[length-2]和[length-1] 将部件传递给数据库处理代码
几年前我遇到了一个类似的问题。我用了一本字典来映射这些列,虽然不好看,但很管用

首先做一本字典:

private Dictionary<int, int> GetColumnDictionary(string headerLine)
    {
        Dictionary<int, int> columnDictionary = new Dictionary<int, int>();
        List<string> columnNames = headerLine.Split('|').ToList();

        string maxTierObjectColumnName = GetMaxTierObjectColumnName(columnNames);
        for (int index = 0; index < columnNames.Count; index++)
        {
            if (columnNames[index] == "StatisticID")
            {
                columnDictionary.Add(0, index);
            }

            if (columnNames[index] == "FileId")
            {
                columnDictionary.Add(1, index);
            }

            if (columnNames[index] == maxTierObjectColumnName)
            {
                columnDictionary.Add(2, index);
            }

            if (columnNames[index] == "Status")
            {
                columnDictionary.Add(3, index);
            }
        }

        return columnDictionary;
    }

    private string GetMaxTierObjectColumnName(List<string> columnNames)
    {
        // Edit this function if Tier ObjectId is greater then 9
        var maxTierObjectColumnName = columnNames.Where(c => c.Contains("Tier") && c.Contains("Object")).OrderBy(c => c).Last();

        return maxTierObjectColumnName;
    }
之后,它只需在文件中运行:

private List<DataObject> ParseFile(string fileName)
    {
        StreamReader streamReader = new StreamReader(fileName);

        string headerLine = streamReader.ReadLine();
        Dictionary<int, int> columnDictionary = this.GetColumnDictionary(headerLine);

        string line;
        List<DataObject> dataObjects = new List<DataObject>();
        while ((line = streamReader.ReadLine()) != null)
        {
            var lineValues = line.Split('|');

            string statId = lineValues[columnDictionary[0]];
            dataObjects.Add(
                new DataObject()
                {
                    StatisticId = lineValues[columnDictionary[0]],
                    FileId = lineValues[columnDictionary[1]],
                    ObjectId = lineValues[columnDictionary[2]],
                    Status = lineValues[columnDictionary[3]]
                }
            );
        }

        return dataObjects;
    }

我希望这能帮上一点忙。

举一些其他尝试的例子,这样其他尝试回答的人就不会重复这些努力了。对我来说,这看起来不像是平版文件。“是的。”阿贝米斯勒嗯,看起来也是这样。我习惯于固定列长的平面文件。我们使用平面文件来区分固定列格式和其他格式,包括csv。不知道它也用于csv。所以我的评论可能是错误的…CSV或任何分隔的文本文件都是平面的。Non-flat类似于XML或JSON,具有结构,可以准确表示层次结构。我简化了示例,实际上提要中存在多个可变长度层列,因此我认为这对我来说没有帮助,但这是一种我没有考虑过的方法。所以最后一层列并不总是最后一层列的第二个?嗯,从位置上来说,是的,但是提要中有多个基于层的结构,每个结构都有一个潜在的动态列计数,并且它们不是相邻的,因此,我认为这种方法不适用于在整个提要中收集列信息。听起来你必须对标题列进行疯狂的解析,然后才能确定你想要的数据驻留在哪里。看看是否可以让他们向您发送XML或JSON。如果这和我从别人那里获取数据文件的经历有什么相似的话,这可能是一个失败的原因,但值得一试。这与我最终所做的非常相似。我有点沮丧,因为没有一个更优雅、更高效的解决方案,但它确实奏效了。