【问题标题】:Combine multiple lines into 1 string with stream reader使用流阅读器将多行合并为 1 个字符串
【发布时间】:2018-01-29 05:34:02
【问题描述】:

我有一个需要解析的大小合适的文件(95K 行)。对于以下示例数据...

<FIPS>10440<STATE>AL<WFO>BMX
8                 32.319   32.316  -86.484  -86.487   32.316  -86.484
32.316  -86.484
102               32.501   31.965  -85.919  -86.497   32.496  -86.248
32.448  -86.181   32.432  -86.189   32.433  -86.125   32.417  -86.116
32.406  -86.049   32.419  -86.023   32.337  -85.991   32.333  -85.969
32.276  -85.919   32.271  -85.986   32.250  -85.999   31.968  -85.995
31.965  -86.302   32.052  -86.307   32.051  -86.406   32.245  -86.410
32.276  -86.484   32.302  -86.491   32.332  -86.475   32.344  -86.497
32.364  -86.492   32.378  -86.463   32.405  -86.460   32.414  -86.396
32.427  -86.398   32.433  -86.350   32.412  -86.310   32.441  -86.325
32.487  -86.314   32.473  -86.288   32.488  -86.260   32.501  -86.263
32.496  -86.248

我需要做的是从一个 FIPS 读取到下一个 FIPS,并将每组中的行组合成一条巨大的行,如下所示...

<FIPS>10440<STATE>AL<WFO>BMX 8 32.319   32.316  -86.484  -86.487   32.316  -86.484 32.316  -86.484...
<FIPS>10440<STATE>AL<WFO>BMX 102 32.501   31.965  -85.919  -86.497   32.496  -86.248 32.448  -86.181...

我目前有以下代码(关于我当天的第 6 个变体)。我错过了什么?

using (var reader = new StreamReader(winterBoundsPath))
        {
            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine().Trim();


                if (!Char.IsLetter(line[0]))
                {
                    if (line.Contains("<FIPS>"))
                    {
                        var lineReplace = line.Replace('<', ' ').Replace('>', ' ');
                        string[] rawData = lineReplace.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        temp = new WinterJsonModel
                        {
                            FIPS = rawData[1],
                            State = rawData[3],
                            Center = rawData[5],
                            polyCoords = new List<polyCoordsJsonData>()
                        };
                    }
                    else
                    {
                        string[] rawData2 = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        if (rawData2.Count() > 1)
                        {
                            allValues.Add(listPointValue);
                            listPointValue = new List<string>();
                        }

                        // Add values to line
                        foreach (string value in rawData2)
                        {
                            listPointValue.Add(value);
                        }
                    }
                }
            }
            reader.Close();
        }

【问题讨论】:

  • 我刚刚意识到这不是最新版本。我很抱歉。向我展示如何执行此操作的示例可能更容易,而无需修复我当前的代码。

标签: c# parsing


【解决方案1】:

从您提供的示例来看,换行符是 CRLF 字符。这意味着你真的只需要知道两件事。 1. 如果该行包含“FIPS”作为 string 文字包含为标签 2. 如果你已经到达有回车的行尾。

我现在将忽略 JSON 位,因为它不是您问题的一部分。我假设这意味着您已经妥善处理了 JSON,如果我们以您想要的方式获得这些 strings,那么您就可以从那里得到它。

var x = new List<string>();
while (!reader.EndOfStream)
{
    var line = reader.ReadLine().Trim();
    if (line.Contains("<FIPS>"))
    { 
        x.Add(line.Replace(Environment.NewLine, " "));  
    }
    else
    { 
        var s = String.Concat(x.Last(), line.Replace(Environment.NewLine, string.Empty), " "); 
        x[x.Count - 1] = s;
    }
}             

这里的重点是将数据的组织与实际放入对象中分开。从这里,您可以遍历foreach 中的列表,根据string.Split()string 中每个string 的结果创建新对象

【讨论】:

  • 男人!我讨厌这些简单的解决方案。我总是让它变得更难。除了我必须处理的一些格式之外,这正是我正在寻找的。谢谢!
  • 存在组号时不能合并行。请参阅其他答案中的 OPs cmets。
【解决方案2】:

我解析文本文件已有 40 多年了。下面的代码是我所做的示例

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

namespace Oppgave3Lesson1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.txt";
        static void Main(string[] args)
        {
            WinterJsonModel data = new WinterJsonModel();
            data.ParseFile(FILENAME);
        }
    }
    public class WinterJsonModel
    {
        public static List<WinterJsonModel> samplData = new List<WinterJsonModel>();

        public string fips { get; set; }
        public string state { get; set; }
        public string wfo { get; set; }
        public List<Group> groups = new List<Group>();


        public void ParseFile(string winterBoundsPath)
        {
            WinterJsonModel winterJsonModel = null;

            Group group = null;
            List<KeyValuePair<decimal, decimal>> values = null;

            using (var reader = new StreamReader(winterBoundsPath))
            {
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine().Trim();
                    if (line.Length > 0)
                    {
                        if (line.StartsWith("<FIPS>"))
                        {
                            winterJsonModel = new WinterJsonModel();
                            WinterJsonModel.samplData.Add(winterJsonModel);
                            string[] rawData = line.Split(new char[] { '<', '>' }, StringSplitOptions.RemoveEmptyEntries);
                            winterJsonModel.fips = rawData[1];
                            winterJsonModel.state = rawData[3];
                            winterJsonModel.wfo = rawData[5];
                            group = null; // very inportant line
                        }
                        else
                        {
                            decimal[] rawData = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries).Select(x => decimal.Parse(x)).ToArray();
                            //if odd number of numbers in a line
                            if (rawData.Count() % 2 == 1)
                            {
                                group = new Group();
                                winterJsonModel.groups.Add(group);
                                group.id = (int)rawData[0];
                                //remove group number from raw data
                                rawData = rawData.Skip(1).ToArray();
                            }
                            for (int i = 0; i < rawData.Count(); i += 2)
                            {
                                group.values.Add(new KeyValuePair<decimal, decimal>(rawData[i], rawData[i + 1]));
                            }
                        }
                    }
                }

            }
        }

    }
    public class Group
    {
        public int id { get; set; }
        public List<KeyValuePair<decimal, decimal>> values = new List<KeyValuePair<decimal, decimal>>();
    }

}

【讨论】:

  • 这是一个比我的更重量级的解决方案,并且对于这个问题可能有点矫枉过正,但如果正则表达式比空格字符和回车更复杂,那么它绝对是要走的路。 +1
  • 正则表达式仅适用于标题行,不适用于数字。本来想跟的你怎么看? string[] header = input.Split(new char[] {''}, StringSpitOptions.Remove EmptyEntries).ToArray(); fips = header[1];state = header[3];wfo = header[5];
  • 我也要试试jdweng的版本。谢谢你们。
  • @jdweng - 所以我今晚正在使用你的代码,我这辈子都不知道为什么它不起作用。在我运行它之前我没有收到错误。在更仔细地查看数据后,我意识到数据在这个 95k 行文件中一直不一样。我看到的是这个 90000FLTBW 10 29.141 29.139 -83.035 -83.038 29.139 -83.035 29.139 -83.035 8 29.141 29.141 -83.036 -83.036 306 29.1411 -83.0。
  • “TBW”之后的“10”和 -83.035 之后的“8”是子集,因为没有更好的术语。所以我需要的是以下 90000FLTBW 10 29.141 29.139 -83.035 -83.038 29.139 -83.035 29.139 -83.035 和 90000FLTBW 8 29.141 29.141 - 83.036 -83.036 29.141 -83.036 29.141 -83.036。跟着我?你能帮我解决这个问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-20
  • 2016-01-21
  • 1970-01-01
  • 2013-09-15
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多