Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 11.10.2016
Сообщений: 15

Распарсить текст файла

11.10.2016, 09:26. Показов 896. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, помогите пожалуйста с правильным решением для выделения подстрок в текстовом файле следующей структуры:
Кликните здесь для просмотра всего текста

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
~VERSION INFORMATION
VERS           .                                 2.0 : CWLS LOG ASCII STANDART - VERSION 2.0
WRAP           .                                  NO : ONE LINE PER DEPTH STEP
#END VERSION INFORMATION
~WELL INFORMATION SECTION
#MNEM          .UNIT                      VALUE/NAME : DESCRIPTION
#----          .----                      ---------- : -----------
STRT           .M                            12.0000: START DEPTH
STOP           .M                         1800.1000 : STOP DEPTH
STEP           .M                            0.1000 : STEP VALUE
NULL           .                           -999.2500 : NULL VALUE
#END WELL INFORMATION
#
#
~CURVE INFORMATION
DEPT           .M                                   : DEPTH
CURVE 1      .M                                   : 
CURVE 2      .ATM                                   : 
CURVE 3      .SEC                                   : 
#END CURVE INFORMATION
#
#
~PARAMETER INFORMATION
# END PARAMETER INFORMATION
#
#
~OTHER INFORMATION
#END OTHER INFORMATION

Файл состоит из нескольких секций, каждая из которых начинается символом "~". Порядок и длинна каждой секции заранее не известны. Строки начинающиеся с "#" - коментарии и их присутствие не обязательно, могут быть, а могут отсутствовать.
Мне интересен блок ~CURVE INFORMATION, точнее его содержимое до следующей "~" без учета комментариев. Другими словами, нужно получить названия всех кривых (всегда расположено до точки), единицы кривой (между точкой и двоеточием, может отсутствовать) и описание (всегда после двоеточия, также может отсутствовать).
Самостоятельно получилось сделать следующее:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    'Структура для хранения считанных данных
    Private Structure CurveInformation
        Public Mnemonic As String
        Public Unit As String
        Public Description As String
    End Structure
    Dim Curves() As CurveInformation
 
        'Весь файл считывается в AllText
        Dim AllText() As String = IO.File.ReadAllLines(Path)
        Dim j As Integer
        'Перебор элеметов AllText
        For i = LBound(AllText) To UBound(AllText) - 1
            'Если встретилось начало требуемого блока
            If AllText(i).StartsWith("~CURVE INFORMATION") Then
                'Структура заполняется данными кривых до начала следующего блока, символа "~" 
                Do Until AllText(i).StartsWith("~PARAMETER INFORMATION") = True
                    i += 1
                    'Коментарии игнорируются и не заносятся в структуру
                    If AllText(i).StartsWith("#") = False Then
                        Curves(j).Mnemonic = Trim(AllText(i).Substring(0, AllText(i).IndexOf(".")))
                        Curves(j).Unit = Trim(AllText(i).Substring(AllText(i).IndexOf(".") + 1, AllText(i).IndexOf(":") - AllText(i).IndexOf(".") - 1))
                        Curves(j).Description = Trim(AllText(i).Substring(AllText(i).IndexOf(":") + 1, AllText(i).Length - AllText(i).IndexOf(":") - 1))
                        j += 1
                        ReDim Preserve Curves(j)
                    End If
                Loop
            End If
        Next
В приведенном выше решении я ищу начало требуемой секции и ее конец по признаку "~PARAMETER INFORMATION" (началу следующей), как можно использовать "~" как начало следующей секции ? Т.е решить в общем виде, вне зависимости от взаимного расположения секций в файле.
Цикл Do Until так же берет строку ~PARAMETER INFORMATION и прекращается только после того, как она встретится. Можно как то изменить код, чтобы не бралась ?
Можно (и нужно ли) заменить обилие SubString и IndexOf на что-то другое для выделения подстрок или это нормальное решение ?

Заранее спасибо.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
11.10.2016, 09:26
Ответы с готовыми решениями:

Распарсить текст
Подскажите как исправить ошибку? Имеется код: Public Class Form1 Dim a As String = """" Dim...

Распарсить текст из Richtextbox'a
Доброе время суток) .. Помогите .. с запроса получаю данные в Richtextbox.. после чего нужно из него вытащить несколько данных .. ...

Распарсить из текстового файла текст для получения координат
Необходимо прочитать текст файла и отформатировать данные. Данные в файле: 23.8976,12.3218 25.7639,11.9463 24.8293,12.2134 Нужно...

10
 Аватар для ViterAlex
8951 / 4863 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
11.10.2016, 10:32
Цитата Сообщение от VSerg Посмотреть сообщение
Можно (и нужно ли) заменить обилие SubString и IndexOf на что-то другое для выделения подстрок
Можно и нужно
VB.NET
1
2
3
4
Dim ar() as String = AllText(i).Split(Char() = {"."c, ":"c}))
Curves(j).Mnemonic = Trim(ar(0))
Curves(j).Unit = Trim(ar(1))
Curves(j).Description = Trim(ar(2))
1
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18287 / 14210 / 5368
Регистрация: 17.03.2014
Сообщений: 28,889
Записей в блоге: 1
11.10.2016, 11:25
VSerg, как вариант.
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Imports System.IO
Imports System.Linq
Imports System.Text.RegularExpressions
...
Dim curves = File.ReadAllLines("c:\users\ieuser\desktop\test.txt"). _
    SkipWhile(Function(l) l <> "~CURVE INFORMATION"). _
    Skip(1). _
    TakeWhile(Function(l) Not l.StartsWith("~")). _
    Where(Function(l) Not l.StartsWith("#")). _
    Select(Function(l)
        Dim m As Match = Regex.Match(l, "^([^.]+)*\.([^:]+):(.*)$")
        Return New CurveInformation() With { _
            .Mnemonic = m.Groups(1).Value.Trim(),
            .Unit = m.Groups(2).Value.Trim(), _
            .Description = m.Groups(3).Value.Trim() _
        }
    End Function). _
    ToArray()
 
...
 
Private Class CurveInformation
        Public Mnemonic As String
        Public Unit As String
        Public Description As String
End Class
3
0 / 0 / 0
Регистрация: 11.10.2016
Сообщений: 15
11.10.2016, 16:03  [ТС]
ViterAlex, OwenGlendower спасибо за участие !

OwenGlendower, я извиняюсь, можно вопрос по использованию ? Мне не совсем понятно куда записываются результаты и как я могу их получить ?
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18287 / 14210 / 5368
Регистрация: 17.03.2014
Сообщений: 28,889
Записей в блоге: 1
11.10.2016, 16:36
VSerg, результат записывается в массив curves с элементами типа CurveInformation.
0
1548 / 1521 / 325
Регистрация: 03.10.2012
Сообщений: 1,551
11.10.2016, 16:53
Цитата Сообщение от VSerg Посмотреть сообщение
и как я могу их получить ?
Например,так
VB.NET
1
2
3
4
5
6
For Each el As CurveInformation In curves
            ListBox1.Items.Add(el.Description)
            ListBox1.Items.Add(el.Mnemonic)
            ListBox1.Items.Add(el.Unit)
            ListBox1.Items.Add("=============")
        Next
1
0 / 0 / 0
Регистрация: 11.10.2016
Сообщений: 15
11.10.2016, 17:51  [ТС]
Огромное спасибо, все работает прекрасно.
Помогите пожалуйста с еще одним регулярным выражением для разбора нижеприведенной части:
Кликните здесь для просмотра всего текста

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
~WELL INFORMATION SECTION
#MNEM          .UNIT                      VALUE/NAME : DESCRIPTION
#----          .----                      ---------- : -----------
STRT           .FT                           12.6000 : START DEPTH
STOP           .FT                         9136.1000 : STOP DEPTH
STEP           .FT                            0.1000 : STEP VALUE
NULL           .                           -999.2500 : NULL VALUE
COMP           .                                     : COMPANY
WELL           .                            WELL-167 : WELL
FLD            .                                     : FIELD
PROV           .                                     : PROVINCE
CTRY           .                                     : COUNTRY
SRVC           .                                     : SERVICE COMPANY
DATE           .                                     : LOG DATE
UWI            .                                     : UNIQUE WELL ID
#END WELL INFORMATION
#
#
~CURVE INFORMATION

Т.е. я сделал по образу и подобию выше приведенного решения, но пытаюсь выделить четыре параметра вместо трех:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    Private Class WellInformation
        Public PropertyName As String
        Public PropertyUnit As String
        Public PropertyValue As String
        Public PropertyDescription As String
    End Class
...
        Dim Properties = File.ReadAllLines(Path).
            SkipWhile(Function(l) l <> "~WELL INFORMATION SECTION").
            Skip(1).
            TakeWhile(Function(l) Not l.StartsWith("~")).
            Where(Function(l) Not l.StartsWith("#")).
            Select(Function(l)
                       Dim m As Match = Regex.Match(l, "^([^.]+)*\.([^:]+):(.*)$")
                       Return New WellInformation() With {
                       .PropertyName = m.Groups(1).Value.Trim(),
                       .PropertyUnit = m.Groups(2).Value.Trim(),
                       .PropertyValue = m.Groups(3).Value.Trim(),
                       .PropertyDescription = m.Groups(4).Value.Trim()
                       }
                   End Function).
        ToArray()
...
Видимо, нужно все-таки изменить
VB.NET
1
Regex.Match(l, "^([^.]+)*\.([^:]+):(.*)$")
потому, что если в строке между "." и ":" находятся два параметра (напр. STRT .FT 12.6000 : START DEPTH), а не один, они сливаются в FT 12.6000.
0
 Аватар для ViterAlex
8951 / 4863 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
11.10.2016, 19:18
VSerg, вот так это будет выглядеть:
VB.NET
1
"^([^.]+)*\.([^: ]+)*([^:]+):(.*)$"
1
0 / 0 / 0
Регистрация: 11.10.2016
Сообщений: 15
12.10.2016, 17:10  [ТС]
Еще раз хочу поблагодарить всех откликнувшихся. Все сделанное работает превосходно, но прошу помощи добить еще один блок. Блок содержит численные значения для обработки и представлен в виде колонок с цифрами, вида:
Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
~ASCII LOG DATA
     24.2000  -999.2500     0.0000  -999.2500  -999.2500  -999.2500  -999.2500
     24.3000  -999.2500     0.0000  -999.2500  -999.2500  -999.2500  -999.2500
     24.4000  -999.2500     0.0000  -999.2500  -999.2500  -999.2500  -999.2500
     24.5000     0.4650     0.0000     0.4720     0.5003     0.4437     0.4722
     24.6000     0.4653     0.0000     0.4720     0.5003     0.4437     0.4722
     24.7000     0.4653     0.0000     0.4720     0.5003     0.4437     0.4722
     24.8000     0.4653     0.0000     0.4720     0.5003     0.4437     0.4722
     24.9000     0.4653     0.0000     0.4720     0.5003     0.4437     0.4722
     25.0000     0.4653     0.0000     0.4720     0.5003     0.4437     0.4722
     25.1000     0.4653     0.0000     0.4720     0.5003     0.4437     0.4722

Используя советы из постов выше, я кое чему научился и получаю данные из этого блока следующим образом:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    Private Sub DataReading(Path)
        'Двумерный массив для хранения данных
        Dim CurvesData(0, 0) As String
        'Переменные счетчики элементов в массиве
        Dim i As Integer
        Dim j As Integer
 
        'Считывание данных из файла. Данные начинаются со строки следующей за "~ASCII LOG DATA" и представляют собой колонки цифр.
        'Количество строк одинково во всех колонках, но не известно заранее.
        'Значения могут быть целыми, дробными, положительными и отрицательными.
        'Колонки отделены друг от друга как минимум одним пробелом.
        'Количество колонок может быть определено заранее, оно соответсвует количеству незакоментированных строк в секции "~CURVE INFORMATION"
        Dim AsciiData() = File.ReadAllLines(Path).
        SkipWhile(Function(l) Not l.Contains("~ASCII LOG DATA")).
             Skip(1).
        Where(Function(l) Not l.StartsWith("#")).ToArray
 
        'Для хранения и полследующей обработки предполагалось использование двумерного массива
        'Заполнение по строкам
        For i = LBound(AsciiData) To UBound(AsciiData) - 1
            'Каждая строка делится на элементы которые записываются в буфер (выделяются численные значения)
            Dim buff As String() = (From M As Match In Regex.Matches(AsciiData(i), "[0-9]+(\.[0-9]+)?") Select M.Groups(0).Value).ToArray()
            'И заносится в массив
            For j = LBound(buff) To UBound(buff) - 1
                CurvesData(i, j) = buff(j)
                ReDim Preserve CurvesData(i, j + 1)
            Next
            ReDim Preserve CurvesData(i + 1, j)
        Next
 
    End Sub
Проблема возникает при записи в массив. Для хранения данных я предполагал использование двумерного динамического массива, но оказывается VB не позволяет менять обе его размерности. Гугл подсказывает структуры как альтернативу, но с ними я тоже никогда не сталкивался.
Не могли бы вы посоветовать, что должно использоваться для хранения и последующей обработки такого рода данных ?
0
 Аватар для Step_UA
1591 / 664 / 225
Регистрация: 09.06.2011
Сообщений: 1,334
12.10.2016, 17:45
Задайте размерность массива до начала обработки AsciiData - Вам ведь известно количество его элементов ... последнюю размерность неправильно менять в теле цикла по j, т.к. например для второй записи AsciiData вторая размерность будет изменяться 1,2 ... теряя соответствующие значения первой записи
1
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18287 / 14210 / 5368
Регистрация: 17.03.2014
Сообщений: 28,889
Записей в блоге: 1
12.10.2016, 18:28
VSerg, я бы сделал так:
VB.NET
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Dim asciiLines() = File.ReadAllLines(Path).
    SkipWhile(Function(l) Not l.Contains("~ASCII LOG DATA")).
    Skip(1).
    Where(Function(l) Not l.StartsWith("#")).
    ToArray()
 
Dim asciiData(,) As Double
Dim reNumbers = new Regex("-?\d+(\.\d+)?")
ReDim asciiData(asciiLines.Length-1, reNumbers.Matches(asciiLines(0)).Count-1)
For I = 0 To asciiLines.Length-1
    Dim matches = reNumbers.Matches(asciiLines(I))
    For J = 0 To matches.Count-1
        asciiData(I,J) = double.Parse(matches(J).Value, CultureInfo.InvariantCulture)
    Next
Next
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
12.10.2016, 18:28
Помогаю со студенческими работами здесь

Распарсить текст
Добрый день, уважаемые форумчане, прошу вашей помощи в решении задачки Нужно получить строки из файла с условиями: 1) если условие 1...

Распарсить текст
Имеется текст Type *hap, void* (*_Type)(size_t), void (*_free)(void*), void* (*_realloc)(void*, size_t) Как мне из него...

Распарсить текст
Приветствую здешних обитателей. Нужна помощь людей дружащих с perl Есть такая бяка: Отсюда нужно выбирать некоторые параметры, а...

Распарсить текст HTML
&lt;TD bgColor=#666666 width=15&gt;&lt;/TD&gt; &lt;TD class=header4&gt;Имя&lt;/TD&gt; &lt;TD class=header2&gt;Ардак&lt;/TD&gt;&lt;/TR&gt; как можно выбрать текст...

Распарсить текст в массив
входные данные вида &quot;текст1:текст2&quot; содержатся в переменной var1. строк там будет несколько. как мне спарсить все значения в массив? и ещё...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru