【问题标题】:Read text file from specific position and store in two arrays从特定位置读取文本文件并存储在两个数组中
【发布时间】:2015-06-09 11:10:45
【问题描述】:

我有一个包含如下行的文本文件:

@relation SMILEfeatures
@attribute pcm_LOGenergy_sma_range numeric
@attribute pcm_LOGenergy_sma_maxPos numeric
@attribute pcm_LOGenergy_sma_minPos numeric...

这些属性的大约 6000 行在哪里,在属性之后是这样的行:

@data
1.283827e+01,3.800000e+01,2.000000e+00,5.331364e+00
1.850000e+02,4.054457e+01,4.500000e+01,3.200000e+01...

我需要将这些字符串分隔在两个不同的数组中。到目前为止,我只设法将所有内容存储在一个数组中。

这是我在数组中存储的代码:

 using (var stream = new FileStream(filePath, FileMode.OpenOrCreate))
                {
                using (var sr = new StreamReader(stream))
                {
                    String line;

                   while ((line = sr.ReadLine()) != null)
                    {
                            sb.AppendLine(line);
                    }
                 }
               string allines = sb.ToString();
               Console.WriteLine(sb);
                 }

【问题讨论】:

  • 问题是什么?哪些字符串应该在第二个数组中?
  • 所有以@relation SMILEfeatures 开头并包含@attribute 的字符串都应存储在第一个数组中。以@data 开头的数字应存储在第二个数组中。
  • 表示一串=一行?还是@data 仅在每个段落之前?
  • 我的意思是线条。在另一个带有数字的段落之后有一个带有属性的大段落。
  • 目前您正在阅读文件中的所有文本,不是吗?实现此目的的更简单方法是: string text = System.IO.File.ReadAllText(filePath);为了获得文本的指定方,如果您有分隔部分,我建议使用 String.Split() 方法;如果您的文本中有固定方案,则建议使用 String.Substring() 方法。 System.String 类有很多方法可以使用,查看 MSDN 以找到合适的方法。

标签: c# arrays file text


【解决方案1】:

@relation SMILEfeatures 之后并包含@attribute 的所有字符串都存储在第一个数组中。 @data 之后的所有字符串都应该存储在第二个数组中。希望这是你想要的。

        var relationLineNumbers = new List<int>();
        var dataLineNumbers = new List<int>();
        var relation = new StringBuilder();
        var data = new List<string>();

        using (var stream = new FileStream(filepath, FileMode.OpenOrCreate))
        {
            using (var sr = new StreamReader(stream))
            {
                string line;
                bool isRelation = false;
                bool isData = false;

                int lineNumber = 0;
                while ((line = sr.ReadLine()) != null)
                {
                    lineNumber++;

                    if (line.StartsWith("@relation SMILEfeatures"))
                    {
                        isRelation = true;
                        isData = false;
                        continue;
                    }

                    if (line.StartsWith("@data"))
                    {
                        isData = true;
                        isRelation = false;
                        continue;
                    }

                    if (isRelation)
                    {
                        if (line.StartsWith("@attribute"))
                        {
                            relation.Append(line);
                            relationLineNumbers.Add(lineNumber);
                        }
                    }

                    if (isData)
                    {
                        data.AddRange(line.Split(','));
                        dataLineNumbers.Add(lineNumber);
                    }
                }
            }

            Console.WriteLine("Relation");
            Console.WriteLine(relation.ToString());
            Console.WriteLine("Data");
            data.ForEach(Console.WriteLine);

【讨论】:

  • 如何分割字符串?我写了sbData.append(line.split(',')),但它不起作用。我遗漏了什么或做错了什么?
  • 我已经编辑了代码 sn-p。由于您想拆分数据,因此我使用了列表而不是字符串生成器。
  • 还有一个问题。我需要知道具体属性在哪一行,并将行号存储在数组中。怎么做?例如,我需要知道该属性在哪一行,并将行号存储在数组中:@attribute pcm_LOGenergy_sma_range
  • 你需要使用一个整数来存储行数,并在while循环中增加行数。为行号创建两个数组,并在追加到 stringbuilder/list 时添加行号
【解决方案2】:

所有以@relation SMILEfeatures 开头并包含@attribute 的字符串都应存储在第一个数组中。以@data 开头的数字应该存储在第二个数组中。

使用string.Contains()string.StatsWith() 进行检查。

阅读每一行并决定你想把这一行放在哪个数组/列表中

void ReadAndSortInArrays(string fileLocation)
{
    List<string> noData = new List<string>();
    List<string> Data = new List<string>();

    using(StreamReader sr = new StreamReader(fileLocation))
    {
        string line;

        while(!sr.EndOfStream)
        {
            line = sr.ReadLine();

            if(line.StartsWith("@relation") && line.Contains("@attribute"))
            {
                noData.Add(line);
            }
            else if(line.StartsWith("@data")
            {
                Data.Add(line);
            }
            else
            {
                // This is stange
            }
        }
    }

    var noDataArray = noData.ToArray();
    var DataArray = Data.ToArray();
}

但我认为并非每一行都以“@data”开头

所以你可能想阅读所有行并做一些这样的想法:

string allLines;
using(StreamReader sr = new StreamReader(yourfile))
{
    allLines = = sr.ReadToEnd();
}


var arrays = allLines.Split("@data");

// arrays[0] is the part before @data
// arrays[1] is the part after @data (the numbers)
// But array[1] does not contain @data

【讨论】:

  • 你也可以使用File.ReadAllLines
【解决方案3】:

这个问题不是很清楚。但我的看法是,在一个桶中收集所有以@relation 或@attribute 开头的行,然后在另一个桶中收集所有数字行。我选择忽略 @data 行,因为它们似乎不包含任何额外信息。

可以通过确保数据行(即数字行)包含逗号分隔的可解析数值列表来执行错误检查。

var dataLines = new List<string>();
var relAttLines = new List<string>();

foreach (var line in File.ReadAllLines())
{
    if (line.StartsWith("@relation") || line.StartsWith("@attribute"))
        relAttLines.Add(line);
    else if (line.StartsWith("@data"))
        //ignore these
        continue;
    else
        dataLines.Add(line);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 2013-11-19
    相关资源
    最近更新 更多