www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Подписка
Архив номеров
Где купить
Авторам
Рекламодателям
Контакты
   

  Опросы
  Статьи

Мониторинг  

Какая задача мониторинга отнимает больше всего времени?

Многие системные администраторы тратят до 30% рабочего времени на рутину мониторинга. Но

 Читать далее...

Рынок труда  

Какие навыки вы хотите развивать в 2026 году?

Рынок труда меняется быстро. Еще вчера его называли рынком соискателей, а сегодня

 Читать далее...

Книжная полка  

От сисадмина до архитектора: книги, которые прокачают ваш стек в этом году

Новинки от издательства «БХВ» отличаются тем, что в них часто делается упор

 Читать далее...

Автоматизация  

Автоматизируем рутину: что реально работает?

Многие сисадмины автоматизировали что-то за последний год. Но далеко не все остались

 Читать далее...

Защита ИТ-системы  

Практическая защита: что вы внедрили и что мешает?

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

 Читать далее...

Вопрос-ответ  

Обеспечиваем безопасную эксплуатацию базы данных

Что для вас чаще всего является причиной инцидентов с БД? Как вы

 Читать далее...

Книжная полка  

От «безопасного» Linux до Контролируемого взлома

Издательство «БХВ» продолжает радовать читателей интересными новинками и в наступившем году. Вы можете

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 13502
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 13614
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

12.03.2018г.
Просмотров: 11074
Комментарии: 0
Глубокое обучение с точки зрения практика

 Читать далее...

12.03.2018г.
Просмотров: 5935
Комментарии: 0
Изучаем pandas

 Читать далее...

12.03.2018г.
Просмотров: 6784
Комментарии: 0
Программирование на языке Rust (Цветное издание)

 Читать далее...

19.12.2017г.
Просмотров: 6661
Комментарии: 0
Глубокое обучение

 Читать далее...

19.12.2017г.
Просмотров: 9498
Комментарии: 0
Анализ социальных медиа на Python

 Читать далее...

19.12.2017г.
Просмотров: 6105
Комментарии: 0
Основы блокчейна

 Читать далее...

19.12.2017г.
Просмотров: 6322
Комментарии: 0
Java 9. Полный обзор нововведений

 Читать далее...

16.02.2017г.
Просмотров: 10483
Комментарии: 0
Опоздавших не бывает, или книга о стеке

 Читать далее...

17.05.2016г.
Просмотров: 13956
Комментарии: 0
Теория вычислений для программистов

 Читать далее...

30.03.2015г.
Просмотров: 15406
Комментарии: 0
От математики к обобщенному программированию

 Читать далее...

18.02.2014г.
Просмотров: 17729
Комментарии: 0
Рецензия на книгу «Читаем Тьюринга»

 Читать далее...

13.02.2014г.
Просмотров: 12579
Комментарии: 0
Читайте, размышляйте, действуйте

 Читать далее...

12.02.2014г.
Просмотров: 10586
Комментарии: 0
Рисуем наши мысли

 Читать далее...

10.02.2014г.
Просмотров: 8792
Комментарии: 4
Страна в цифрах

 Читать далее...

18.12.2013г.
Просмотров: 7392
Комментарии: 0
Большие данные меняют нашу жизнь

 Читать далее...

18.12.2013г.
Просмотров: 6200
Комментарии: 0
Компьютерные технологии – корень зла для точки роста

 Читать далее...

04.12.2013г.
Просмотров: 5824
Комментарии: 0
Паутина в облаках

 Читать далее...

03.12.2013г.
Просмотров: 6144
Комментарии: 1
Рецензия на книгу «MongoDB в действии»

 Читать далее...

Друзья сайта  

 Реинкарнация данных II: memo-поля

Архив номеров / 2005 / Выпуск №5 (30) / Реинкарнация данных II: memo-поля

Рубрика: Базы данных /  Оптимизация

СЕРГЕЙ СУПРУНОВ

Реинкарнация данных II: memo-поля

В прошлом номере журнала (см. №4 за 2005 г.) мы рассмотрели несколько способов переноса данных из таблиц формата DBF в PostgreSQL. Однако чтобы не перегружать статью, вопрос работы с полями типа memo, достаточно широко используемыми в FoxPro, был оставлен без внимания. Теперь пришло время восполнить данный пробел.

Формат memo-полей

Если нужно сохранить в одном поле данные большого или неопределенного объема, в FoxPro (как и в некоторых других СУБД) используются поля специального типа – так называемые memo-поля. Данные такого поля физически сохраняются в отдельном файле (в случае с FoxPro он имеет то же имя, что и dbf-файл, но с расширением fpt). Логически мемо-поля связываются с таблицей таким образом, что доступны, как и любое другое поле текущей записи.

Файл fpt для упрощения работы с данными хранит их поблочно. Размер блока по умолчанию в FPD 2.6 составляет 64 байта. Заголовок fpt-файла имеет размер 512 байт, структура его следующая:

Таблица. Структура заголовка fpt-файла

Смещение

Длина поля

Назначение

0

4

Номер следующего свободного блока

4

2

Не используется

6

2

Размер блока

8

504

Не используется

Начиная с 513-го байта от начала файла, располагаются блоки данных. Значение поля может занимать один или несколько блоков. Каждый блок, являющийся первым для записи, содержит 8-байтный заголовок (4 байта сигнатура 0х00000001 и 4 байта – длина поля), после которого следуют собственно данные.

Для обеспечения связи таблицы с данными в fpt-файле в каждой записи dbf-файла memo-полю отводится 10 байт, в которые заносится номер первого блока данных. Причем номер хранится в символьном виде с ведущими пробелами. Например, для указания на блок 8 данное поле будет содержать значение «         8» (в шестнадцатеричном виде «20 20 20 20 20 20 20 20 20 38», где 38 – ASCII-код символа «8»). Нумерация блоков идет от начала файла, то есть включает и заголовок.

Например, при стандартной длине блока 64 байта записи данных будут начинаться с блока 8 (длина заголовка 512, деленная на размер блока 64).

С чем предстоит бороться

Теоретически формат DBF позволяет хранить в поле типа memo до 4 Гб данных. Однако на практике из-за внутренних ограничений FoxPro на длину строки оперировать с полями свыше 65504 символов становится проблематично. На практике длина этого поля редко превышает несколько тысяч символов. Поэтому вполне допустимо полагать, что данные из поля типа memo могут быть размещены в поле типа text таблицы PostgreSQL (максимальное значение поля – 1 Гб). Так что размеры полей проблемой считать не будем.

Сложнее то, что memo-поля могут содержать разнообразные символы, включая символ перевода строки. Поскольку при обработке текстового файла PostgreSQL воспринимает этот символ как разделитель записей, то необходимо позаботиться об его экранировании. Причем в случае формата конца строки в стиле DOS (CR+LF) экранировать нужно как символ перевода строки (0x0D), так и символ возврата каретки (0x0A).

Можно использовать формат CSV для загрузки в PostgreSQL – в этом случае значением поля будут считаться все символы, заключенные в «кавычки». «Кавычками» в данном случае может выступать любой символ, он задается как параметр команды COPY. Теперь внутри поля нужно экранировать «кавычки» (путем удвоения), однако в данном случае больше шансов найти подходящий символ, мало используемый внутри поля данных. К тому же исключаются проблемы с различными стилями перевода строки.

Реализация на FoxPro

FoxPro работает с memo-полями прозрачно, так что никаких усилий со стороны программиста не требуется. Не забудьте поставить символ «» перед символами-разделителями:

Листинг 1. Файл memo2pg.prg (FoxPro)

close databases

* Это – комментарий с начала строки

&& А так выделяются комментарии в произвольном месте строки

use wmem    && Открываем таблицу с memo-полями

m.delimiter = chr(9)    && символ Tab

m.txf = fcreate('memo2pg.txt')

scan

* Текстовое поле – экранируем разделители и символ «\»

    m.descr = strtran(Descr, '\', '\\')

    m.descr = strtran(m.descr, m.delimiter, ;

                                 '\' + m.delimiter)

* В memo-поле дополнительно экранируем символы конца строки (ASCII-коды 10 и 13)

    m.memfld = strtran(Memfld, '\', '\\')

    m.memfld = strtran(m.memfld, m.delimiter, ;

                                 '\' + m.delimiter)

    m.memfld = strtran(m.memfld, chr(13), ;

                                 '\' + chr(13))

    m.memfld = strtran(m.memfld, chr(10), ;

                                 '\' + chr(10))

* Записываем результат в файл, разделяя поля символом, хранящимся в переменной m.delimiter

    =fputs(m.txf, m.descr + ;

                   m.delimiter + ;

                   m.memfld)

endscan

=fclose(m.txf)

wait window 'Finished.'

Рисунок. Рабочее окно FoxPro

Рисунок. Рабочее окно FoxPro

Если вы решите работать с CSV-форматом, то вместо табуляции в качестве разделителя будет использоваться запятая, а каждое поле данных, независимо от типа, нужно будет окружить символом-«кавычкой», например «”», который используется по умолчанию. Ну и внутри полей все «кавычки» должны быть удвоены, чтобы исключить их специальную интерпретацию.

Реализация на Python

А вот здесь нам придется применить все накопленные выше знания по формату файлов DBF и FPT. Поскольку полностью сценарий разбора DBF-файла приводился в прошлой статье, здесь ограничимся только той частью, которая отвечает за получение данных из мемо-поля. За основу взят сценарий dbf2pg.py, рассмотренный в предыдущей статье (см. листинг 2). В него добавлена обработка полей типа «M» в цикл, обрабатывающий каждую запись (соответствующие строки выделены красным шрифтом):

Листинг 2. Фрагмент сценария dbf2pg.py, добавленные строки

.. .. ..

                 for i in range(num):

                        fld = dbf.read(fields[i].len)

           # Добавлено: vvvvvvv

                        if fields[i].type == 'M':

                               fld = memo2pg(fld)

           # ----------^^^^^^^

                        if fields[i].type == 'D':

                               fld = fld[:4] + '-' +  fld[4:6] + '-' + fld[6:]

.. .. ..

Здесь при обнаружении поля типа memo считанное значение трактуется как содержащее номер первого блока данных, и вызывается функция разбора fpt-файла:

Листинг 3. Фрагмент сценария dbf2pg.py, функция memo2pg

def memo2pg(startblock):

# Номер блока преобразуем в число

    startblock = int(startblock)

    fpt = open(basetabname + '.fpt', 'rb')

    fpt.read(6)

# Считываем размер блока

    blocksize = int(ord(fpt.read(1)) * 256 + ord(fpt.read(1)))

# Смещаемся к началу блока данных

    fpt.seek(blocksize * startblock)

    fpt.read(4)

# Считываем размер поля данных

    fieldsize = ord(fpt.read(1)) * 16777216 + ord(fpt.read(1)) * 65536 + ord(fpt.read(1)) * 256 + ord(fpt.read(1))

# Читаем данные

    data = fpt.read(fieldsize)

    fpt.close()

# Перекодировка, экранирование и проч.

    data = unicode(data, 'cp866').encode('koi8-r')

    data = data.replace('\\', '\\\\')

    data = data.replace('\x0A', '\\' + '\x0A')

    data = data.replace('\x0D', '\\' + '\x0D')

    data = data.replace(delimiter, '\\' + delimiter)

    return data

Наконец, нужно позаботиться, чтобы Python не обрабатывал символы перевода строки самостоятельно, для чего вместо вывода каждой сформированной строки с помощью оператора print мы будем осуществлять запись в файл, открытый в двоичном режиме, и формировать конец строки вручную так, как нам нужно:

Листинг 4. Фрагмент сценария dbf2pg.py, запись строки в файл

.. .. ..

           #      print line[:-1]

                 outfile.write(line[:-1] + '\r\n')

.. .. ..

В результате dbf2pg.py теперь может обрабатывать и memo-поля.

Заключение

Язык FoxPro предоставляет развитые средства для работы со своими файлами (выглядело бы странно, если бы это было не так), и осуществить конвертирование файла DBF в другой формат c его помощью – дело нескольких строк кода. Однако не беда, если вы не очень дружны с ним или не можете им воспользоваться по каким-то причинам. Двоичный формат DBF, как вы могли убедиться, достаточно прост и удобен. Так что при необходимости реализовать его обработку имеющимися подручными средствами труда не составит.


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-45
E-mail: sa@samag.ru