С# - Извлечение спутниковых двухстрочных элементов из текстового файла

Я очень новичок в С# и программировании в целом, поэтому прошу прощения, если это не имеет смысла... Мне нужно иметь возможность искать текстовое поле или поле со списком, чтобы прочитать файл блокнота, содержащий много спутниковых двухстрочных кодов элементов. Текстовый файл устроен так:

0 VANGUARD 1
1 00005U 58002B   14242.42781498  .00000028  00000-0  24556-4 0  2568
2 00005 034.2497 271.4959 1848458 183.2227 175.4750 10.84383299975339
0 TRANSIT 2A
1 00045U 60007A   14245.43855606  .00000265  00000-0  95096-4 0  2208
2 00045 066.6958 193.0879 0251338 053.7315 060.2264 14.33038972819563
0 EXPLORER 11
1 00107U 61013A   14245.36883128  .00001088  00000-0  12832-3 0  1217
2 00107 028.7916 229.2883 0562255 219.9933 302.0575 14.05099145667434

И т.п.

Мне нужно найти в поле имя единственного спутника (имя после 0 в «первой» строке), извлечь это имя в другое текстовое поле и использовать в моем коде. Кроме того, мне нужно отдельно извлечь 2 строки кода непосредственно под именем, выбранным в поле (также для использования в коде).

Я написал код для использования этих двух строковых элементов, но я не могу автоматически поместить их в свой код.

Спасибо


person Gareth Moore    schedule 12.09.2014    source источник
comment
почему вы не можете просто использовать метод разделения ... тогда оттуда вы можете проверить, меньше ли длина разделенных строк data.lenth, чем длина самых длинных строк, которые кажутся каждой третьей строкой, с которой она начинается), затем имя. .это очень просто по своей природе на самом деле .. вы можете прочитать весь текст сразу и разделить эту информацию. Я только что сделал то же самое для файла, который мы получаем из показаний масла. Вы также хотите, чтобы кто-то закодировал это для вас ..?   -  person MethodMan    schedule 13.09.2014
comment
Я не совсем уверен, что такое метод разделения... Я хотел бы попробовать написать его сам, но я не знаю, с чего начать. Я также забыл сказать, что мне нужно игнорировать 0 при поиске имен   -  person Gareth Moore    schedule 13.09.2014
comment
Вам нужно наклоняться, если вы хотите писать программы. Вот методы и другие элементы, которые вам нужно использовать (и прочитать): Using System.IO; File.ReadAllLines(); Split(); Arrays.. And, if you are feeling strong Regular Expressions ie RegEx   -  person TaW    schedule 13.09.2014
comment
Я оставил вам почти полностью закодированный пример, который вы можете использовать в качестве основы, использовать отладчик и выполнить код, чтобы увидеть, нужно ли проверять какие-либо другие условия. Спасибо.   -  person MethodMan    schedule 13.09.2014


Ответы (3)


Для этой задачи вы можете использовать регулярные выражения.

(Я предполагаю, что блок букв/цифр после имени также является частью имени)

Этот код будет делать следующее:

  • захватите имя спутника и две линии в объект Satellite
  • заполнить ComboBox именами спутников
  • всякий раз, когда вы выбираете спутник, вы можете знать, какой это был
  • окно поиска, которое ищет первый спутник, начиная с введенного текста

Код:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        private readonly BindingList<Satellite> _satellites = new BindingList<Satellite>();
        private string _input = @"
0 VANGUARD 1
1 00005U 58002B   14242.42781498  .00000028  00000-0  24556-4 0  2568
2 00005 034.2497 271.4959 1848458 183.2227 175.4750 10.84383299975339
0 TRANSIT 2A
1 00045U 60007A   14245.43855606  .00000265  00000-0  95096-4 0  2208
2 00045 066.6958 193.0879 0251338 053.7315 060.2264 14.33038972819563
0 EXPLORER 11
1 00107U 61013A   14245.36883128  .00001088  00000-0  12832-3 0  1217
2 00107 028.7916 229.2883 0562255 219.9933 302.0575 14.05099145667434
";

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            var regexObj =
                new Regex(@"(?<=^\d+\s(?<name>[\w|\d|\s]+))\r\n(?<line1>(?<=^).*)\r\n(?<line2>(?<=^).*(?=\r))",
                    RegexOptions.Multiline);
            Match matchResult = regexObj.Match(_input);

            while (matchResult.Success)
            {
                string name = matchResult.Groups["name"].Value;
                string line1 = matchResult.Groups["line1"].Value;
                string line2 = matchResult.Groups["line2"].Value;


                var regexObj1 = new Regex(@"(?<=^[1|2].*)([\d\w.-]+)");
                Match matchResult1 = regexObj1.Match(line1);
                var numbers1 = new List<string>();
                while (matchResult1.Success)
                {
                    string s = matchResult1.Value;
                    numbers1.Add(s);
                    matchResult1 = matchResult1.NextMatch();
                }

                var regexObj2 = new Regex(@"(?<=^[1|2].*)([\d\w.-]+)");
                Match matchResult2 = regexObj2.Match(line2);
                var numbers2 = new List<string>();
                while (matchResult2.Success)
                {
                    string s = matchResult2.Value;
                    numbers2.Add(s);
                    matchResult2 = matchResult2.NextMatch();
                }

                _satellites.Add(new Satellite
                {
                    Name = name,
                    Line1 = line1,
                    Line2 = line2,
                    Numbers1 = numbers1,
                    Numbers2 = numbers2
                });


                matchResult = matchResult.NextMatch();
            }

            comboBox1.DataSource = _satellites;
            comboBox1.DisplayMember = "Name";
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            var comboBox = (ComboBox) sender;
            var satellites = comboBox.DataSource as List<Satellite>;
            if (satellites != null && comboBox.SelectedIndex > -1)
            {
                Satellite selectedSatellite = satellites[comboBox.SelectedIndex];
                Console.WriteLine("Selected satellite: " + selectedSatellite.Name);
            }
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            var textBox = (TextBox) sender;
            string text = textBox.Text;
            if (!string.IsNullOrWhiteSpace(text))
            {
                Satellite satellite =
                    _satellites.FirstOrDefault((s => s.Name.ToLower().StartsWith(text.ToLower())));
                if (satellite != null)
                {
                    Console.WriteLine("Found satellite: " + satellite);
                }
            }
        }

        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            var textBox = (TextBox) sender;
            string text = textBox.Text;
            if (!string.IsNullOrWhiteSpace(text))
            {
                Satellite satellite =
                    _satellites.FirstOrDefault(
                        s => s.Numbers1.Any(t => t.StartsWith(text)) || s.Numbers2.Any(t => t.StartsWith(text)));
                if (satellite != null)
                {
                    Console.WriteLine("Found satellite: " + satellite);
                }
            }
        }
    }

    internal class Satellite
    {
        public string Name { get; set; }
        public string Line1 { get; set; }
        public string Line2 { get; set; }
        public List<string> Numbers1 { get; set; }
        public List<string> Numbers2 { get; set; }

        public override string ToString()
        {
            return string.Format("Name: {0}", Name);
        }
    }
}

Результат:

введите здесь описание изображения

person aybe    schedule 12.09.2014
comment
Это гениально, спасибо. Но как мне включить это в поле со списком? Я могу связать поле со списком с текстовым файлом, но в качестве вывода мне понадобятся только 3 отдельные строки спутника. - person Gareth Moore; 13.09.2014
comment
Я обновил код, чтобы зафиксировать имя и две строки. Что касается вашего комментария, не могли бы вы объяснить немного больше, что вам нужно? - person aybe; 13.09.2014
comment
Надеюсь, это имеет смысл... Но это для программы определения местоположения спутников. Я использую два кода линейных элементов под спутником, чтобы найти координаты спутника и его положение по отношению к базовому местоположению (мои GPS-координаты). У меня есть приложение формы окна, выводящее координаты отдельного спутника, азимут и углы возвышения и т. д. Я хотел бы иметь текстовое поле, которое может выполнять поиск в базе данных спутниковых имен и элементов. Как только имя спутника выбрано, две строки чисел под этим именем будут отображаться в отдельном текстовом поле, которое я затем могу поместить в свой код. - person Gareth Moore; 13.09.2014
comment
Смотрите мой новый код! Я позволю тебе сделать все остальное, наверное, должно быть просто :D - person aybe; 13.09.2014
comment
Привет, у меня есть 3 примера спутников, связанных с выпадающим списком, и он выводит правильные элементы, когда конкретный спутник выбран из списка имен. Но я не могу добавить больше спутников в этот список (например, 0 ISS (Zarya), 1 25544U 98067a 14245.51991314 .00013026 00000-0 23431-3 0 101, 2 25544 051.6451 076.2836 0003709 072.7397020.634134343434343434343434134343413434343434183434183434183434183418341834341834183418343434183434183434183434183434183434343413434343434341тели. чтобы получить код для поиска этих элементов в текстовом файле. - person Gareth Moore; 13.09.2014
comment
Я обновил код, теперь вы можете добавить спутник, и он появится, второе текстовое поле позволяет вам искать один из этих номеров; также я разделил все эти числа на отдельные элементы, как вы увидите. - person aybe; 13.09.2014
comment
Я только что понял, что не могу добавить и найти МКС (ЗАРЯ), потому что он не содержит номера после спутника. Мне не нужно второе текстовое поле для поиска номеров спутников, так как выпадающего списка достаточно для выбора. Есть ли способ поиска в списках спутников, некоторые названия которых не содержат номеров. Текстовый файл, который я хотел бы найти, содержит несколько тысяч спутников, и его необходимо будет обновить, когда будут выпущены новые элементы спутников. Можно ли заменить этот список ссылкой на текстовый файл? - person Gareth Moore; 14.09.2014
comment
Совет: задайте другой вопрос, потому что он становится слишком широким, иначе он может быть закрыт. Я думаю, что ответил на главный вопрос вашего вопроса (извлечение спутников из текста), поэтому, если вы удовлетворены моим ответом, примите его, и вы всегда можете уведомить меня о своем новом вопросе, и я постараюсь ответить на него. См. справку о том, что можно/нужно спрашивать: stackoverflow.com/help/on-topic: D - person aybe; 14.09.2014
comment
Я сожалею, что я только что поймал, поскольку это совершенно новое для меня. Проще говоря, как мне искать в этом списке спутник, который не содержит номера после имени? Например. Я могу найти и выбрать спутник TRANSIT 2A, но спутник с названием ISS (ZARYA) не появляется в выпадающем списке, хотя я добавил его в список спутников. Спасибо - person Gareth Moore; 14.09.2014
comment
1\ Вы должны вставить весь код, добавление спутника позже работает для меня. 2\ Я использовал StartsWith(...) в качестве предиката для поиска по имени, не стесняйтесь использовать что-то еще, например Contains. - person aybe; 14.09.2014
comment
Я понял свою проблему. Код не распознавал имена спутников, содержащие скобки. Я изменил новый раздел имени строки Regex на это ‹name›[\w|\d|\s|()] и теперь он собирает такие имена, как ISS (ZAYRA). Я надеюсь, что это правильно и не меняет остальную часть кода. спасибо за помощь - person Gareth Moore; 14.09.2014
comment
Там должен быть \ перед скобками, но копирование и вставка не подняли его. - person Gareth Moore; 14.09.2014
comment
Отлично, не забудьте принять ответ, если он вас устраивает! :D - person aybe; 14.09.2014

вот что вы можете попробовать быстро и грязно, что я придумал.

1-й поместите файл в папку на локальном жестком диске.

2-й, где я определил путь к файлу, замените его вашим фактическим путем к файлу и узнайте, как использовать символ @ и что он означает в С#

3-е замечание, как я использовал строку .Replace Method.. вам придется ее настроить. Я только что дал вам идею. Я не собираюсь писать весь код за вас.. удачи.

static void Main(string[] args)
{
    var fileName = string.Empty;
    var filePath = @"C:\Users\myfolder\Documents\RGReports\"; //for testing purposes only 
    List<string> listNames = new List<string>();
    string[] filePaths = Directory.GetFiles(@filePath);
    foreach (string file in filePaths)
    {
        if (file.Contains(".txt"))
        {
            fileName = file;
            using (StreamReader sr = File.OpenText(fileName))
            {
                //string s = String.Empty;
                var tempFile = sr.ReadToEnd();
                var splitFile = tempFile.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);
                foreach (string str in splitFile)
                {
                    if (str.Length == 12)
                    {
                        listNames.Add(str.Substring(0, str.Length).Replace("0", "").Replace("1", "").Replace("2A",""));
                    }
                    Console.WriteLine(str);
                }
            }
        }
    }
}

Результаты дадут следующее для имен, например, протестированных в консольном приложении.

АВАНГАРД

ТРАНЗИТ

ИССЛЕДОВАТЕЛЬ

person MethodMan    schedule 12.09.2014

Если вы не хотите использовать регулярное выражение, вы можете сделать что-то вроде этого:

public List<string> GetSatelliteNames(string input)
{
    string[] split = input.split(new string[2] { "\n", "\r\n" });
    List<string> result = new List<string>();    
    foreach (var s in split)
    {
        string splitagain = s.split(new char[1] { ' ' });
        if (s[0] == "0") result.add(s[1]);
    }
    return result;
}
person B. Verhoeff    schedule 12.09.2014