2016-05-02 2 views
1

У меня возникают трудности с работой сегмента кода. Вот рассказ: у меня есть несколько текстовых файлов, которые имеют определенное форматирование (поскольку они генерируются кодом), что мне нужно извлечь определенные блоки текста и отобразить только те блоки текста в текстовом поле. Например, одним из таких блоков будет «STN COMMENT» «END COMMENT». Этот файл может иметь два, три или даже 10 таких блоков и будет иметь разные типы блоков, где COMMENT будет заменен ВОПРОСОМ, ОБЪЯВЛЕНИЕМ или ТРАФИКОМ. Все заканчивается соответствующим «END». Вот первый сегмент кода я попытался:StreamReader throws System.NullReferenceException

'block to parse only this user's announcements 
'dl is variable alias for: Environment.NewLine + Environment.NewLine 
txtNetLog.Text = "" 'clears the textbox 
TmpFileName = logPath + ByCall + "-" + Format(Now, "dd-MMM-yyyy") + ".tmp" 'sets filename with path defined in module 
Try 
    Using sr As StreamReader = New StreamReader(TmpFileName) 
    Dim line As String = sr.ReadLine() 
     While Not (line Is Nothing) 
      line = sr.ReadLine() 
      If line.Contains("STN ANNOUNCEMENT") Then '***This is line 238 from exception 
       Do 
        txtNetLog.Text = txtNetLog.Text & line + dl 
        line = sr.ReadLine() 
       Loop Until line.Contains("END ANNOUNCEMENT") 
      End If 
     End While 
    End Using 
Catch ex As Exception 
    Dim msg As String = "Error: Failure Parsing Temp File For Announcements. Contact Developer" + dl + ex.ToString 
    Dim title = "Error in StreamReader" 
    Dim errorFile As System.IO.StreamWriter 
    Dim errorFileName As String = logPath + "Errors.txt" 
    errorFile = My.Computer.FileSystem.OpenTextFileWriter(errorFileName, True) 
    errorFile.Write(msg) 
    errorFile.Close() 
    MsgBox(msg, MsgBoxStyle.ApplicationModal, title) 
End Try 

Это вызвало следующее исключение:

System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта. в GSPASEC_Net_Control.ReviewNetLogFrm.ParseLog (Int32 ТипДанных, Int32 SortType) в C: \ Users \ KE4NHW \ Documents \ Visual Studio 2010 \ Projects \ GSPASEC Net Control \ GSPASEC Net Control \ ReviewNetLogFrm.vb: линия 238

У меня есть строка 238, помеченная в коде выше. Однако, здесь есть выход этого блока:

STN АНОНС: 18:50:54 KE4NHW

ASDFASDFASDFASDF

STN АНОНС: 18:50:57 KE4NHW

DFADFADFASWERASDF

STN ОБЪЯВЛЕНИЕ: 18:51:01 KE4NHW

GHSDETGJNHSDFAW34ASDFG

В этом выпуске отсутствует строка «END ANNOUNCEMENT», которая должна быть помещена в текстовое поле, но в противном случае она получит все объявления. Он пропускает одну строку на текстовый блок (конечную строку) и выдает исключение nullreference; кроме этого, если я могу получить конечный оператор для отображения, то по крайней мере у нас будет весь текст, который нужно потянуть.

Я также попытался следующие изменения без успеха, все производят ту же ошибку:

Изменено While Not (линия Is Nothing) ... End While делать ... Loop Пока линия не Ничто

Изменено что делать до линии нечего ... Loop

Моя последняя версия испытания заключается в следующем:

txtNetLog.Text = "" 
    'block to parse only this user's Comments 
    TmpFileName = logPath + ByCall + "-" + Format(Now, "dd-MMM-yyyy") + ".tmp" 
    Try 
     Using sr As StreamReader = New StreamReader(TmpFileName) 
      Dim line As String = sr.ReadLine() 
      Do Until line Is Nothing 
       line = sr.ReadLine() 
       If line.Contains("STN COMMENT") Then 
        Do Until line.Contains("END COMMENT") 
         txtNetLog.Text = txtNetLog.Text + line + nl + nl 
         line = sr.ReadLine() 
        Loop 
       End If 
      Loop 
     End Using 
    Catch ex As Exception 
     Dim msg As String = "Error: Failure Parsing Temp File For Comments. Contact Developer" + nl + nl + ex.ToString 
     Dim title = "Error in StreamReader" 
     MsgBox(msg, MsgBoxStyle.ApplicationModal, title) 
     ErrorLogWriter("ErrorLog.txt", msg) 
    End Try 

То же самое. Не помещает «КОНЕЦ КОММЕНТАРИИ» в текстовое поле и выдает одно и то же исключение. Мне не хватает идей, чтобы заставить блок try просто отключить исключение, но это, безусловно, вызовет проблемы. Любая идея по этому поводу?

+1

Вы не проверяете, является ли строка «строка» ничем после чтения в предыдущей строке. – Plutonix

+0

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

+0

Вы также не проверяете содержимое первой строки ('Dim line ....'), поэтому в этой строке сигнализируется начало одного из этих блоков, код пропустит его. Если чтение файлов невелико, вы можете прочитать весь файл и обработать его по строкам; если они большие, вы, вероятно, должны использовать StringBuilder для результата ... и то же самое на отладчике – Plutonix

ответ

0

Смотрите, если это будет работать:

Dim sb As New StringBuilder 
Dim startToken = "STN ANNOUNCEMENT" 
Dim endToken = "END ANNOUNCEMENT" 
Dim line As String 

Using sr As StreamReader = New StreamReader("C:\Temp\LogData.Txt") 

    Do Until sr.EndOfStream 
     line = sr.ReadLine 
     If line.StartsWith(startToken) Then 
      sb.AppendLine(line) 
      Do Until sr.EndOfStream OrElse line.StartsWith(endToken) 
       line = sr.ReadLine 
       sb.AppendLine(line) 
      Loop 
     End If 
    Loop 

End Using 

tbLog.Text = sb.ToString 

Sample data used

Я не знаю, что вероятность некорректных блоков, но я мог бы просто посмотреть на «END», как endToken так, что конец любой тип блока остановит захват. Это дает возможность пересинхронизации.

Или сигнал конца блока может включать начало любой блок. В этом случае вы можете вручную добавить «END ANNOUNCEMENT» для однородности или что-то еще, чтобы заметить, что обнаружен поврежденный блок. Содержание этих данных может включать данные, не связанные с ANNOUCEMENT.

Кроме того, он использует StringBuilder вместо того, чтобы бесконечно возиться с пользовательским интерфейсом. Строки неизменяемы, поэтому добавление к свойству Text означает повторное его перестроение. Это должно ускорить его, когда захваченные линии выходят за определенную точку.

+0

Решение, которое вы дали здесь, отлично работает! Мне пришлось немного подстроить его, например добавить среду Environment.NewLine в построителе строк, но не такую ​​безупречную! Моя репутация не настолько высока, так как я еще недостаточно квалифицирован, чтобы отвечать на вопросы других людей, но если бы это было, я бы наверняка поддержал это. Если кто-то еще может поддержать это, пожалуйста, сделайте это, как отличное решение. Большое спасибо Плутоникс и всем, кто помог мне с этим! Разбор текста Grr - это боль. Я думал, что на минуту я собирался должен вспыхнуть или импорт Regex ... –

+0

Это также работает: 'Использование стер Как StreamReader = New StreamReader (TmpFileName) Dim линия As String = sr.ReadLine() ли Если line.Contains ("STN COMMENT") Тогда ли txtNetLog.Text = txtNetLog.Text + NL + линия линия = sr.ReadLine() Loop До line.Contains ("END COMMENT") txtNetLog.Text = txtNetLog .Text + nl End If line = sr.ReadLine Loop Until line Is Nothing End Использование' –

+0

Извините, я предполагаю, что вы знаете, куда положить линия ломается, если нет, я могу использовать; чтобы указать, куда они идут. Это почти работает, но это немного на новых линиях, которые можно настроить. Кажется, вся проблема была в readline() прямо над Do ... Loop До тех пор пока линия не будет. Это вызвало разрыв строки. Конец (токен), потому что он пытался разобрать Ничего. Вау, это все о размещении. Мне нужно освежить программную логику ... спасибо всем за то, что помогли мне, теперь она работает! –