Статьи

Текстовый файл, как база данных.

Довольно часто случается, что в программе необходима маленькая база данных (записей на 50-200, не более). Так что же? Брать mdb-шный файл (что само по себе "кусаемо" по объемам) плюс привязывать к нему для работы библиотеки ADO (или DAO). Не слишком ли "жирно" для 50 записей?

В данной статье я хочу показать вариант сохранения базы данных в текстовом файле. Попутно будет рассмотрено еще несколько вопросов. Итак:

·        сохранение  БД в файле формата txt, используя объектно-ориентированный подход к программированию;

·        работа с диалоговыми окнами открытия и сохранения файлов через API-функции и построение собственного класса для этого;

·        работа с VB 6 Class Builder Utility;

·        считывание и запись информации в файлы последовательного доступа, используя библиотеку FSO (FileSystemObject).

Я проведу Вас пошагово от начала до конца. В результате получим упрощенный вариант телефонного справочника.

 

Шаг 1. Откройте новый проект и создайте форму, аналогичную, нарисованной ниже.

 

Текстовые поля называются txtLastName, txtFirstName, txtNumber. Первая колонка кнопок носит названия cmdDB, с индексами соответственно от 0 до 2; вторая колонка – cmdEdit (Index = 0 to 2); и наконец кнопки внизу, заведующие перемещением по записям – cmdMove (Index =  0 to 3). Лейбл-индикатор номера записи носит имя lblID.

 

Шаг 2. Для поиска файла можно использовать стандартный элемент управления CommonDialog. При желании, можно построить диалоговую форму самому (с помощью стандартных встроенных ЭУ: Dir, Drive, File). И, наконец, можно использовать API-функции, напрямую обращаясь к библиотекам Windows. Рассмотрим последнюю возможность, но сделаем специальный класс для работы с диалоговым окном. Впоследствии Вы сможете многократно использовать этот класс в различных своих программах.

Здесь нам поможет утилита для создания классов. Выберите меню Add-Ins/Add-In Manager… и в диалоговом окне отметьте опцию VB 6 Class Builder Utility. Нажмите ОК. А теперь выберите непосредственно это меню Add-Ins/Class Builder Utility… Создадим новый класс и назовем его clsCommonDialog. Для этого выберите меню File/New/Class… Замените предлагаемое по-умолчанию имя Class1 на выбранное нами и подтвердите нажатием на кнопку "ОК". Теперь создадим свойства для этого класса (меню File/New/Property…). Все они перечислены ниже в таблице:

Name Type

Action

Integer

APIReturn

Long

CancelError

Boolean

DefaultExt

String

DialogTitle

String

ExtendedError

Long

FileName

String

FileTitle

String

Filter

String

FilterIndex

Integer

Flags

Long

hdc

Long

InitDir

String

MaxFileSize

Long

И два метода (меню File/New/Method…): ShowOpen и ShowSave. Оба метода без аргументов.

Закроем утилиту, подтвердив произведенные изменения. И перейдем в только что созданный класс.

Для работы нам понадобится три API-функции и один Type:

Private m_cancelled As Boolean

'****************************************************
'API function
'****************************************************

'API функция для ShowOpen method

Private Declare Function GetOpenFileName Lib "comdlg32.dll" _
   
Alias "GetOpenFileNameA" (pOpenfilename As OpenFilename) As Long

'API функция для ShowSave method

Private Declare Function GetSaveFileName Lib "comdlg32.dll" _
   
Alias "GetSaveFileNameA" (pOpenfilename As OpenFilename) As Long

'API функция для возвращения расширенной информации об ошибке

Private Declare Function CommDlgExtendedError Lib "comdlg32.dll" () As Long

'****************************************************
'Type
'****************************************************

Private Type OpenFilename
    lStructSize As Long
    hwndOwner As Long
    hInstance As Long
    lpstrFilter As String
    lpstrCustomFilter As String
    nMaxCustFilter As Long
    iFilterIndex As Long
    lpstrFile As String
    nMaxFile As Long
    lpstrFileTitle As String
    nMaxFileTitle As Long
    lpstrInitialDir As String
    lpstrTitle As String
    Flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As String
    lCustData As Long
    lpfnHook As Long
    lpTemplateName As String
End Type

 

Для свойств Action, APIReturn и ExtendedError удалим блоки с Property Let – эти свойства только для чтения.

Теперь займемся методами. И тот и другой метод у нас опираются на одну и ту же процедуру ShowFileDialog, только с разными индексами:

Public Sub ShowOpen()

    'вывод на экран диалога "Открыть файл"

    ShowFileDialog (1) 

End Sub

 

Public Sub ShowSave()

    ' вывод на экран диалога "Сохранить файл"

    ShowFileDialog (2)

End Sub

 

Вся суть этого класса как раз и заключается в процедуре ShowFileDialog. В ней происходит передача значений из свойств в объект tOpenFile, для последующего использования в API-функциях.

Private Sub ShowFileDialog(ByVal iAction As Integer)

    Dim tOpenFile As OpenFilename

    Dim lMaxSize As Long

    Dim sFileNameBuff As String

    Dim sFileTitleBuff As String

    

    On Error GoTo ShowFileDialogError

    'инициализация буфера

    iAction = iAction  'Action property

    lApiReturn = 0  'APIReturn property

    lExtendedError = 0  'ExtendedError property

    tOpenFile.lStructSize = Len(tOpenFile)

    tOpenFile.hwndOwner = lhdc

    'Замена "|" на Chr(0)

    tOpenFile.lpstrFilter = sAPIFilter(sFilter)

    tOpenFile.iFilterIndex = iFilterIndex

    'определение размера буфера от свойства MaxFileSize

        If lMaxFileSize > 0 Then

            lMaxSize = lMaxFileSize

        Else

            lMaxSize = 255

        End If

         sFileNameBuff = sFileName

        'заполнение пробелами до 255

        While Len(sFileNameBuff) < lMaxSize - 1

            sFileNameBuff = sFileNameBuff & " "

        Wend

        'обрежем до длины lMaxFileSize - 1

        If lMaxFileSize = 0 Then

            sFileNameBuff = Mid$(sFileNameBuff, 1, lMaxSize - 1)

        Else

            sFileNameBuff = Mid$(sFileNameBuff, 1, lMaxFileSize - 1)

        End If

        'установим в конце нулевой знак

        sFileNameBuff = sFileNameBuff & Chr$(0)

    tOpenFile.lpstrFile = sFileNameBuff

    If lMaxFileSize <> 255 Then  

        tOpenFile.nMaxFile = 255

    End If

     'операции, аналогичные вышеисполненным

    sFileTitleBuff = sFileTitle

        While Len(sFileTitleBuff) < lMaxSize - 1

            sFileTitleBuff = sFileTitleBuff & " "

        Wend

        If lMaxFileSize = 0 Then

            sFileTitleBuff = Mid$(sFileTitleBuff, 1, lMaxSize - 1)

        Else

            sFileTitleBuff = Mid$(sFileTitleBuff, 1, lMaxFileSize - 1)

        End If

    sFileTitleBuff = sFileTitleBuff & Chr$(0)

    tOpenFile.lpstrFileTitle = sFileTitleBuff

    tOpenFile.lpstrInitialDir = sInitDir

    tOpenFile.lpstrTitle = sDialogTitle

    tOpenFile.Flags = lFlags

    tOpenFile.lpstrDefExt = sDefaultExt

    'выполним GetOpenFileName API-функцию

    Select Case iAction

        Case 1  'ShowOpen

            lApiReturn = GetOpenFileName(tOpenFile)

        Case 2  'ShowSave

            lApiReturn = GetSaveFileName(tOpenFile)

        Case Else

            Exit Sub

    End Select

    m_cancelled = False

    'Возвращение дескриптора от API-функции GetOpenFileName

    Select Case lApiReturn

        Case 0  'нажата кнопка Cancel

            'генерация ошибки

            m_cancelled = True

            Exit Sub

        Case 1  'пользователь выбрал или ввел файл

            'Используем внутреннюю процедуру sLeftOfNull 

'для получения пути и имени файла

            sFileName = sLeftOfNull(tOpenFile.lpstrFile)

            sFileTitle = sLeftOfNull(tOpenFile.lpstrFileTitle)

        Case Else   'если произошла ошибка вызываем CommDlgExtendedError

            lExtendedError = CommDlgExtendedError

    End Select

Exit Sub

ShowFileDialogError:

    Exit Sub

End Sub

 

И теперь еще две вспомогательные функции. Функция "разбирающая" значение фильтра и заменяющая знак"|" на Chr(0)

Private Function sAPIFilter(sIn)

    Dim lChrNdx As Long

    Dim sOneChr As String

    Dim sOutStr As String

    

    For lChrNdx = 1 To Len(sIn)

        sOneChr = Mid$(sIn, lChrNdx, 1)

        If sOneChr = "|" Then

            sOutStr = sOutStr & Chr$(0)

        Else

            sOutStr = sOutStr & sOneChr

        End If

    Next

    sOutStr = sOutStr & Chr$(0)

    sAPIFilter = sOutStr

End Function

И функция "обрезающая" пробелы в названии пути и имени файла:

Private Function sLeftOfNull(ByVal sIn As String)

    Dim lNullPos As Long

    sLeftOfNull = sIn

    lNullPos = InStr(sIn, Chr$(0))

    If lNullPos > 0 Then

        sLeftOfNull = Mid$(sIn, 1, lNullPos - 1)

    End If

End Function

 

Класс для работы с диалоговым окном "Открытие-Сохранение файла" – готов.

Шаг 3. Создадим код для кнопки создания файла. В разделе деклараций объявим класс для работы с диалоговым окном:

Private dlgDb As New clsCommonDialog

А теперь сам код:

With dlgDb

        .DialogTitle = "Создать текстовую БД"

        .Filter = "Текстовые БД (*.tdb)|*.tdb"

        .FilterIndex = 1

        .ShowOpen

End With

 

Шаг 4. Итак, мы ввели название для файла, нажали "OK" – теперь необходимо физически создать файл с этими параметрами. С первой версии VB существуют встроенные функции открытия и сохранения файлов:

Open pathname For [Input| Output| Append] As filenumber [Len = buffersize]

Open pathname For [Random] As filenumber Len = buffersize

Open pathname For Binary As filenumber

В VB 6.0 появилась новая возможность для этого, а именно модель объекта файловой системы – File System Object (FSO), о которой мало кто знает. Для того, чтобы использовать эту библиотеку выберите меню Project/References… В открывшемся диалоговом окне выберите "Microsoft Scripting Runtime"

Лирическое отступление 1. На данный момент библиотека может работать (редактировать) только с файлами последовательного доступа. Будем надеяться, что в VB 7 появится возможность работать так же и с бинарными файлами и с файлами произвольного доступа.

В разделе деклараций объявим переменные для работы с этой библиотекой:

Private fso As New FileSystemObject ' "верхний" объект библиотеки FSO

Private tsOpen As TextStream '

Private tsSave As TextStream 'текстовые потоки библиотеки FSO

Private tsNew As TextStream '

Лирическое отступление 2. Кроме раннего связвывания FSO можно также создать и поздним связыванием, например:

Set fso = CreateObject("Scripting.FileSystemObject")

Преимуществом позднего связывания является то, что данный синтаксис будет работать не только в Visual Basic, но и в VBScript.

Лирическое отступление 3. Кроме выбранных нами FileSystemObject (главного объекта группы, управляющего дисками, папками и файлами) и TextStream (текстовый поток – позволяющий создавать, читать и записывать текстовые файлы последовательного доступа), модель FSO содержит еще три основных объекта. Это Drive (собирает информацию о дисках, присоединенных к системе), Folder (создает, удаляет и перемещает папки) и Files (создает, удаляет и перемещает файлы)

Добавляем в код строки создания файла, а затем его закрываем, изменяем заголовок формы и приравниваем переменные-счетчики (их объявление так же необходимо вынести в раздел деклараций) к нулю.

Private CountEntries As Integer' общее количество записей

Private CurrentEntries As Integer' номер текущей записи

With dlgDb

        .DialogTitle = "Создать текстовую БД"

        .Filter = "Текстовые БД (*.tdb)|*.tdb"

        .FilterIndex = 1

        .ShowOpen

        'создание текстового файла последовательного доступа

        Set tsNew = fso.CreateTextFile(.FileName, True)

        'закрытие файла

        tsNew.Close

        'изменение заголовка

        Caption = "Demo FSO as DB (" & .FileTitle & ")"

End With

'установка счетчиков

CountEntries = 0

CurrentEntries = 0

 

Продолжение статьи

Hosted by uCoz