воспользоваться многочисленными конвертерами, имеющимися в составе текстовых редакторов (например в WinWord), однако здесь есть несколько "но":

  1. эти редакторы нужно иметь (купить), да и компьютер должен быть соответствующим;
  2. пользоваться такими громоздкими редакторами бывает просто неудобно для решения подобных простых задач;
  3. не исключено появление нетривиальных случаев, не предусмотренных стандартными конвертерами.

Впрочем, если вы хотя бы в минимальной степени владеете программированием на Бейсике, решение проблем преобразования текстовых файлов может быть весьма простым. Я приведу примеры нескольких небольших утилит, которыми сам часто пользуюсь при работе с текстовыми файлами. Они представлены в виде варианта QB/PDS для DOS, но могут быть легко преобразованы как в вариант QBasic, так и в вариант Visual Basic for Windows. В первом случае нужно просто объединить все процедуры в один модуль, во втором - перенести текст заглавного модуля программы в процедуру MAIN.

1. Преобразование кириллических текстов из кодировки DOS в кодировку Windows и наоборот выполняется утилитой FILE_DW.BAS (листинг 1). В основе утилиты FILE_DW лежит обращение к функции RusDosWin$ (листинг 2, модуль STR_CHDW.BAS), которая, в свою очередь, использует универсальную процедуру StrChange$ (листинг 3, модуль STR_CHAN.BAS) для замены символов исходного набора на символы выходного набора. Обратите внимание, что изображение всех символов в RusDosWin$ приведено в кодировке DOS. Набор русских букв в кодировке Windows (константа W$) получить очень просто: они имеют коды от 192 до 255.

Хочу обратить ваше особое внимание на многофункциональность процедуры StrChange$ - с ее помощью можно производить замену любого набора символов на любой другой (например преобразование заглавных букв в строчные и наоборот).

2. Вторую утилиту (FILE_LEX. BAS, листинг 4) я использую для преобразования текстов из формата "Лексикона" в формат Word для DOS и наоборот. Конечно же, здесь имеются в виду чистые ASCII-файлы без специальных знаков форматирования.

Как известно, в упомянутых текстовых процессорах используются разные принципы представления абзацев. Собственно говоря, в "Лексиконе" понятия абзаца вообще нет - там работа ведется с отдельными строками, которые мы и видим на экране. В файле Word весь абзац представляет собой одну длинную строку. На экране мы видим его как несколько строчек, длина которых зависит от установленного режима форматирования. Все это создает определенные проблемы при переносе текста из одного редактора в другой. Если текст, подготовленный в "Лексиконе", просто загрузить в Word, то каждая строка файла станет там отдельным абзацем. От работников издательств часто приходится слышать: "Только не давайте нам текст в "Лексиконе" с выравниванием по правому краю, а то нам придется вручную убирать лишние пробелы и сливать строки в абзацы". С помощью утилиты FILE_ LEX.BAS эта проблема легко решается.

В режиме Code=0 производится преобразование в рамках лексиконовского формата: убираются двойные пробелы и пробелы в начале строки (абзацные отступы заменяются пустыми строками). Результат преобразования показан на рисунке.

В режиме Code=1 помимо операций предыдущего режима осуществляется слияние (с учетом переносов) всех строк абзаца в одну длинную строку. В результате этой операции вы получите нормальный файл Word - сливать отдельные строки не потребуется.

Режим Code>1 используется для обратной операции - разбиения абзаца, представленного в виде длинной строки, на несколько строк ограниченной длины (значение Code равно максимальной длине строки). Это бывает нужно, чтобы прочитать в "Лексиконе" или просто распечатать командой COPY текст, подготовленный в Word.

Если исходный файл отформатирован в "Лексиконе" с использованием переносов, а вы хотите убрать их, но сохранить "короткие" строки, это можно сделать, преобразовав файл утилитой FILE_LEX последовательно с Code=1 и с Code>1 (скажем, Code=70).

В утилите FILE_LEX используется функция DoubleSpaceDelete$ (модуль STR_FLTR.BAS, листинг 5). В этом модуле находится и другая полезная функция - StrFilter$. Она удаляет из строковой переменной недопустимые символы, набор которых задается пользователем.

3. Еще одна проблема связана с тем, что иногда приходится встречаться с текстами, в которых в качестве разделителя строк используется символ LF (его ASCII-код - 10), в то время как стандарт ASCII для DOS/Windows предусматривает разделитель из двух символов - CR+LF (13+10). Эти символы легко увидеть, если посмотреть текстовый файл в шестнадцатеричном режиме (например, нажав в Norton Commander F3, а затем F4).

Решить данную проблему можно с помощью небольшой утилиты FILE1013.BAS (листинг 6) - она вообще не использует никаких вспомогательных процедур.


Андрей Александрович Колесов - канд. техн. наук, зав. сектором НИИ по инженерным изысканиям, координатор Ассоциации пользователей Microsoft Basic. Контактный телефон: (095) 369-76-97. E-mail: akolesov@glas.apc.org.

Листинг 1. Преобразование кодировок (DOS и Windows)

"*******************************
" Модуль FILE_DW.BAS
"********************************
" Дополнительные внешние ссылки:
" загрузить модули STR_CHDW.BAS и STR_CHAN.BAS
""""""""""""""""""""""""""""""""""""""""""""""""
DECLARE FUNCTION RusDosWin$ (Text$, Code%)
"
" Преобразование ASCII-файла:
" кодировка DOS <-> Windows
""""""""""""""""""""""""""""""
PRINT "Преобразование ASCII-файла: кодировка DOS <-> Windows"
PRINT "Введите код операции:"
INPUT "DOS -> Windows (0) или Windows -> DOS (1) : "; Code%
INPUT "Введите имя входного файла - ", InputFile$
INPUT "Введите имя выходного файла - ", OutputFile$
OPEN "i", #1, InputFile$
OPEN "o", #2, OutputFile$
WHILE NOT EOF(1)
LINE INPUT #1, OldLine$ " ввод строки
PRINT OldLine$
NewLine$ = RusDosWin$(OldLine$, Code%) " перекодировка символов
PRINT #2, NewLine$ " ввод строки
WEND
CLOSE " закрыть файлы
END

Листинг 2. Функция RusDosWin$

DECLARE FUNCTION RusDosWin$ (Text$, Code%)
DECLARE FUNCTION SymChange$ (Text$, A$, B$)
"************************************************************
"************* K o l e s o v Q B T o o l s ************
"* БИБЛИОТЕКА подпрограмм QB_STR_CONV *
"************************************************************
"* Модуль STR_CHDW.BAS *
"* подпрограммы преобразования символьных переменных *
"*-----------------------------*
"* Состав процедур: *
"* RusDosWin$ - преобразование русских символов кодировки *
"* DOS <-> Windows *
"************************************************************
" Внешние ссылки: Модуль STR_CHAN.BAS (SymChange$)
FUNCTION RusDosWin$ (Text$, Code%)
"
" Преобразование КИРИЛЛИЦЫ:
" Code% = 0 - DOS - > WINDOWS
" = 1 - обратно
"--------------------------
CONST D$ = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя"
CONST W$ = 
" "
IF Code% = 0 THEN
RusDosWin$ = SymChange(Text$, W$, D$)
ELSE
RusDosWin$ = SymChange(Text$, D$, W$)
END IF
END FUNCTION

Листинг 3. Функция SymChange$

DECLARE FUNCTION SymChange$ (Text$, A$, B$)
"************************************************************
"************* K o l e s o v Q B T o o l s ************
"* БИБЛИОТЕКА подпрограмм QB_STR_CONV *
"************************************************************
"* Модуль STR_CHAN.BAS *
"* подпрограммы преобразования символьных переменных *
"*-----------------------------*
"* Состав процедур: *
"* SymChange$ - перекодирование символьных переменных *
"************************************************************
END
FUNCTION SymChange$ (Text$, NewCode$, OldCode$)
"
" Перекодирование символов:
" в переменной Text$ все символы из набора OldCode$
" заменяются на соответствующие символы набора NewCode$:
" OldCode$ -> NewCode$
" ВНИМАНИЕ! должно выполняться - LEN(NewCode$)=LEN(OldCode$)
"---------------------------
Sym$ = Text$: Ltext% = LEN(Text$)
IF Ltext% > 0 THEN
FOR i% = 1 TO Ltext%
k% = INSTR(OldCode$, MID$(Text$, i%, 1))
IF k% > 0 THEN MID$(Sym$, i%, 1) = MID$(NewCode$, k%, 1)
NEXT i%
END IF
SymChange$ = Sym$
END FUNCTION2

Листинг 4. Утилита преобразования Word <-> "Лексикон"

"*******************************
" Модуль FILE_LEX.BAS
"*******************************
" Дополнительные внешние ссылки:
" загрузить модуль STR_FLTR.BAS
"""""""""""""""""""""""""""""""""
DECLARE FUNCTION DoubleSpaceDelete$ (Text$)
"
PRINT " Преобразование ASCII-файла:"
PRINT " = 0 - a) убрать двойные пробелы"
PRINT " б) убрать пробелы слева"
PRINT " в) если абзац начинается с пробела, -"
PRINT " вставить пустую строку перед абзацем"
PRINT " = 1 - LEXICON -> Word"
PRINT " Признак конца абзаца - пустая строка или строки,"
PRINT " начинающиеся с пробела "
PRINT " Дополнительно:"
PRINT " убрать двойные пробелы и пробелы слева +"
PRINT " + слияние переноса"
PRINT " N > 1 - Word -> LEXICON"
PRINT " a) разбиваем длинную строку на"
PRINT " несколько (N - макс. длина строки абзаца)"
PRINT " б) разделитель абзацев - пустая строка."
INPUT "Введите код преобразования: 0, 1, N>1 - "; Code%
"
INPUT "Введите имя входного файла - ", InputFile$
INPUT "Введите имя выходного файла - ", OutputFile$
OPEN "i", #1, InputFile$
OPEN "o", #2, OutputFile$
WordLine$ = ""
WHILE NOT EOF(1)
LINE INPUT #1, OldLine$ " ввод строки
OldLine$ = LTRIM$(OldLine$)
PRINT OldLine$
NewLine$ = DoubleSpaceDelete$(OldLine$)
IF Code% <= 1 THEN
OL1$ = LEFT$(OldLine$, 1)
IF Code% = 0 THEN
IF OL1$ = " " THEN PRINT #2, ""
PRINT #2, NewLine$ " ввод строки
ELSE "преобразование LEXICON -> Word
IF OL1$ = " " OR OL1$ = "" THEN
PRINT #2, WordLine$ " вывод предыдущей строки
PRINT WordLine$
WordLine$ = NewLine$
ELSE " слияние строк абзаца
IF RIGHT$(WordLine$, 1) = "-" THEN
" проверка: это перенос или дефис?
D$ = RIGHT$(WordLine$, 2)
IF D$ <> " -" AND D$ <> "-" THEN
WordLine$ = LEFT$(WordLine$, LEN(WordLine$) - 1): 
s$ = ""
ELSE s$ = " "
END IF
ELSE IF WordLine$ <> "" THEN s$ = " " ELSE s$ = ""
END IF
WordLine$ = WordLine$ + s$ + NewLine$
END IF
END IF
ELSE " преобразование Word -> Lexicon
in1% = 0 " разбиваем строку на несколько
DO
in2% = INSTR(in1% + 1, NewLine$, " ")
IF in2% <= 0 THEN
IF LEN(NewLine$) > Code% THEN GOSUB SelectLine
EXIT DO
ELSE
IF in2% >= Code% THEN " превышен предел длины строки
GOSUB SelectLine: in1% = 0
ELSE in1% = in2%
END IF
END IF
LOOP
PRINT #2, NewLine$: PRINT #2, ""
END IF
WEND
IF WordLine$ <> "" THEN PRINT #2, WordLine$ " ввод строки Word
CLOSE " закрыть файлы
END
"
SelectLine:
" выделение короткого фрагмента из длинной строки
PRINT #2, LEFT$(NewLine$, in1% - 1)
NewLine$ = MID$(NewLine$, in1% + 1)
RETURN

Листинг 5. Вспомогательные функции к утилите преобразования форматов

DECLARE FUNCTION StrFilter$ (Text$, Filter$)
DECLARE FUNCTION DoubleSpaceDelete$ (Text$)
DEFINT I-N
"************************************************************
"************* K o l e s o v Q B T o o l s ************
"* БИБЛИОТЕКА подпрограмм QB_STR_CONV *
"************************************************************
"* Модуль STR_FLRT.BAS *
"* подпрограммы преобразования символьных переменных *
"*-----------------------------*
"* Состав процедур: *
"* StrFilter$ - удаление всех символов, кроме указанных в *
"* списке допустимых *
"* DoubleSpaceDelete$ - убрать двойные пробелы *
"************************************************************
FUNCTION DoubleSpaceDelete$ (Text$)
"
" убрать двойные пробелы
""""""""""""""""""""""""""""""""""
Temp$ = RTRIM$(Text$)
DO
in = INSTR(Temp$, " ") " поиск двойного пробела
IF in <= 0 THEN EXIT DO
Temp$ = LEFT$(Temp$, in) + MID$(Temp$, in + 2)
LOOP
DoubleSpaceDelete$ = Temp$
END FUNCTION
DEFSNG I-N
FUNCTION StrFilter$ (Text$, Filter$)
"====================================================
"* Фильтрация содержимого Text$%
"--------------------
" Filter$=CHR$(KodFilter%)+FilterString$
"* KodFilter%=ASC(Filter$)
"* 1) =0 - удаление всех символов из Text$, кроме указанных в
"* списке допустимых - FilterString$
"* 2) =1 - удаление всех символов из Text$, указанных в
"* списке НЕдопустимых - FilterString$
"====================================================
StringLength% = LEN(Text$)
Temp$ = Text$: k% = 0
FOR I% = 1 TO StringLength%
C$ = MID$(Text$, I%, 1)
IF (SGN(INSTR(2, Filter$, C$)) XOR KodFilter%) <> 0 THEN
k% = k% + 1: MID$(Temp$, k%, 1) = C$
END IF
NEXT I%
StrFilter$ = LEFT$(Temp$, k%)
END FUNCTION

Листинг 6. Преобразование разделителей строк к стандарту CR+LF

"******************************
" Модуль FILE1013.BAS
"******************************
" Пребразование текстового файла:
" ВНИМАНИЕ! Это вариант программы для преобразования исходного файла
" длиной не более 32 Кбайт!
" ----------------
" Разделитель строк:
" в исходном файле - код CHR$(10)
" в результирующем - коды CHR$(13)+CHR$(10)
"""""""""""""""""""""""""""""""""""""""""""""""""
INPUT "Имя исходного файла -", InputFile$
INPUT "Имя результирующего файла -", OutputFile$
OPEN "b", #1, InputFile$
OPEN "o", #2, OutputFile$
"
"
a$ = SPACE$(EOF(1)) " длина исходного файла (не более 32 Кбайт)
GET #1, 1, a$ " чтение всего файла в строковую переменную
in1% = 1 " указатель текущей записи
DO
" выделение содержимого текущей записи
in2% = INSTR(in1%, a$, CHR$(10))
b$ = MID$(a$, in1%, in2% - 1)
PRINT #2, b$ " вывод (коды 13+10 формируются автоматически)
in1% = in2% + 1
LOOP WHILE in2 < LEN(a$)
END
1966