ПОНЯТНО О Visual Basic NET (том 3)

       

Сейсмодатчик»


Здесь мы рассмотрим пример работы с нетипизированными файлами.

Задание. Высоко в Гималаях расположена автоматическая сейсмостанция. Находящийся на ней сейсмодатчик измеряет колебания земной коры. Каждое измерение представляет собой целое число в диапазоне от 0 до 100, характеризующее амплитуду колебаний. Данные измерений передаются на компьютер, находящийся где-нибудь в Дели, и пишутся в файл. Время от времени (нерегулярно) в тот же файл записывается и точное время (в формате строки). Иногда до сейсмодатчика добирается Йети и бьет по нему лапой, тогда показания датчика превышают число 100. За лето 2005 года в файл было записано несколько миллионов чисел – результатов измерений и несколько тысяч моментов времени.

В конце лета ученых заинтересовали странные колебания, якобы зарегистрированные рядом сейсмостанций 28 августа. Причем многие утверждают, что никаких колебаний вообще не было. В связи с этим сейсмолог Бхагараджа решил срочно написать программу для работы с файлом данных от нашей гималайской станции, чтобы определить, были ли на ней 28 августа зарегистрированы какие-нибудь колебания, а если были, то распечатать все результаты измерений за эти сутки, включая и моменты времени.

Данные в файл писались последовательно. Это значит после нескольких сотен или тысяч чисел – результатов измерений попадается строка времени, затем опять идет цепочка чисел, затем снова время и так далее. Чтобы при считывании можно было отличить время от чисел, перед записью каждого момента времени записывался байт с числом 255 (пусть это и ненадежная «метка» (вспомним хотя бы Йети!), но для учебного примера сойдет). Поскольку время писалось нерегулярно, представить этот файл типизированным никак нельзя. Значит нужно работать с ним, как с нетипизированным.

Задача программиста: Считывать все байты из файла по порядку. Наткнувшись на байт с числом 255, проверять записанное время. Если это 28 августа, распечатывать байты и строки времени до тех пор, пока не наткнешься на 29 августа или более позднюю дату. Если число превышает 100, печатать сообщение «Это Йети!».  Если момента времени 28 августа в файле не было вообще и достигнут конец файла, выдать сообщение «Колебаний не было».


Пишем в файл. Чтобы отлаживать нашу будущую программу, нужен исходный файл. Пусть данные в нем записаны в таком порядке:
23
17
86
255
28.08.2005 8:59:27
90


47
35
205
19
255
29.08.2005 1:19:11
46
90
164
18
Как видите, станцию два раза посетил Йети.
В учебных целях напишем программу, которая не считывает, а записывает эту информацию в файл:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim FS As New FileStream("E:\Папка\Сейсмостанция.Ind", FileMode.OpenOrCreate)
        Dim BW As New BinaryWriter(FS)
        Dim B1() As Byte = {23, 17, 86}
        Dim B2() As Byte = {90, 47, 35, 205, 19}
        Dim B3() As Byte = {46, 90, 164, 18}
        Dim Метка As Byte = 255
        BW.Write(B1)
        BW.Write(Метка)
        BW.Write(CStr(#8/28/2005 8:59:27 AM#))
        BW.Write(B2)
        BW.Write(Метка)
        BW.Write(CStr(#8/29/2005 1:19:11 AM#))
        BW.Write(B3)
        BW.Close()
        FS.Close()
End Sub
Пояснения: Метод Write умеет записывать не только байты, но и многие другие простые типы данных, например, дробные числа или строки. К сожалению, класс BinaryReader не умеет читать даты, поэтому я вынужден был записывать их в файл преобразованными к типу String.
Читаем из файла. Вот готовая программа:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim FS As New FileStream("E:\Папка\Сейсмостанция.Ind", FileMode.Open)
        Dim BR As New BinaryReader(FS)
        Dim By As Byte
        Dim Время As DateTime
        Dim Были_колебания As Boolean = False
        Do Until BR.PeekChar() = -1
              By = BR.ReadByte
              If By = 255 Then
                      Время = CDate(BR.ReadString)
                      If Время.Date
> #8/28/2005# Then Exit Do
                      Debug.WriteLine(Время)
              ElseIf Время.Date = #8/28/2005# Then


                      Были_колебания = True
                      Debug.WriteLine(By)
                      If By > 100 Then Debug.WriteLine("Это Йети!")
              End If
        Loop
        BR.Close()
        FS.Close()
        If Not Были_колебания Then MsgBox("Колебаний не было")
End Sub
При работе с нашим примером файла программа распечатывает такую информацию:
28.08.2005 8:59:27
90
47
35
205
Это Йети!
19
Пояснения: Вначале переменной Были_колебания, естественно, присваивается значение False, но если 28 августа было хоть одно показание датчика, то программа меняет его на True. Последняя строка программы в зависимости от значения этой переменной выдает или не выдает сообщение «Колебаний не было».
Данные из файла считываются в цикле Do-Loop. Чтобы остановить чтение при достижении конца файла, используется функция PeekChar (попробуй символ) класса BinaryReader. Она работает аналогично функции Peek класса StreamReader (19.2.5). При достижении конца файла чтение становится невозможным и функция принимает значение -1.
Вы видите, что если считано число 255, то компьютер его не распечатывает, а методом ReadString класса BinaryReader считывает строку, в которой записано время. У класса BinaryReader есть несколько методов для считывания из файла данных разных простых типов, например, ReadBoolean или ReadDouble. Но нет метода для считывания дат, поэтому даты и были записаны в файл в строковом виде. А сейчас они функцией CDate преобразовываются опять к типу DateTime.
Если эта дата Время.Date является более поздней (>), чем 28 августа, то компьютер выходит из цикла, иначе время распечатывается.
Если считанный байт не является числом 255, то проверяется, не 28 ли августа нынче в файле, и если да, то делается вывод о том, что колебания, точно, были, и распечатывается численное значение считанного байта, а если оно еще и превосходит 100, то в этом обвиняется Йети.

Содержание раздела