Страница Ивана Рощина > Статьи >

© Иван Рощин, Москва

ZXNet: 500:95/462.53
E-mail: bestview@mtu-net.ru
WWW: http://www.ivr.da.ru

Автоматическое проставление размеров файлов в HTML-документах

Радиомир. Ваш компьютер» 11/2004)
Дополненная версия.

Введение
Постановка задачи
Описание алгоритма
Текст программы
Руководство пользователя
Дополнение
Источники

Введение

При выкладывании на своей web-странице zip-архивов я указываю их длину в килобайтах (см. рис. 1, 2), так как эта информация может пригодиться посетителям (например, чтобы оценить время загрузки архива).

Рис. 1
Фрагмент изображения
web-страницы

Рис. 2
Фрагмент изображения
web-страницы

Но то, что удобно для посетителей страницы, не так удобно для её создателя. :–) Каждый раз при добавлении нового архива или при изменении уже существующего архива мне приходилось вычислять его размер в килобайтах и добавлять эти сведения в HTML-документ, содержащий ссылку на архив. И вот однажды, после изменения значительного количества архивов, я оценил объём предстоящей работы по проставлению их новых размеров и задумался об автоматизации этого процесса. В результате была написана программа, о которой я и хочу рассказать в этой статье.

Постановка задачи

На жёстком диске моего компьютера находится локальная копия web-страницы, с которой я и работаю. Эта копия включает в себя и все zip-архивы, размер которых требуется указывать. В HTML-документах я использую относительные адреса в ссылках на эти архивы, так что ссылки работают независимо от того, где расположена web-страница: у меня на жёстком диске или в Интернете.

В HTML-документах я указываю размер архива либо в тексте ссылки (рис. 1), либо в атрибуте «title» ссылки (тогда размер отображается при наведении курсора на ссылку — см. рис. 2).

Случаю, когда размер архива указан в тексте ссылки, соответствует примерно такой фрагмент HTML-документа (этот фрагмент взят как раз из документа, изображённого на рис. 1):

<p class="ms"><a href="all_zx.zip">Скачать все программы
для&nbsp;ZX (292&nbsp;КБ&nbsp;ZIP)</a></p>

Случаю, когда размер архива указан в атрибуте «title», соответствует примерно такой фрагмент (этот фрагмент взят как раз из документа, часть которого изображена на рис. 2):

<p><b>2.03.2004.</b> Выложена <a href="prog/bv_2_19.zip"
title="Скачать (75&nbsp;КБ&nbsp;ZIP)">очередная версия
BestView&nbsp;&#151; 2.19</a>.</p>

Случаю, когда я добавляю новую ссылку на zip-архив, размер которого требуется указывать, соответствует фрагмент, аналогичный первому или второму из рассмотренных выше, за исключением того, что размер архива в нём не указан, то есть вместо, например, строки «(75&nbsp;КБ&nbsp;ZIP)» в документе содержится просто «(&nbsp;КБ&nbsp;ZIP)».

В моих HTML-документах во всех трёх перечисленных выше случаях (и только в них) после адреса ссылки на zip-архив, размер которого требуется указывать, но до адреса следующей ссылки (если она есть) обязательно содержится строка вида «(*&nbsp;КБ&nbsp;ZIP)», где «*» — ни одной, одна или несколько десятичных цифр. Таким образом, по этому признаку при обработке HTML-документа можно отличать ссылки, для которых надо проставлять размер (назовём такие ссылки «нужными»), от других ссылок.

От программы требуется, чтобы она просматривала указанный HTML-документ и для каждой «нужной» ссылки определяла размер соответствующего архива в килобайтах и подставляла этот размер вместо «*» в находящуюся после этой ссылки строку вида «(*&nbsp;КБ&nbsp;ZIP)».

Описание алгоритма

Исходя из сказанного выше, можно предложить такой алгоритм: просматриваем обрабатываемый HTML-файл от начала к концу; если встретили строку «href="» (или «HREF="» — регистр букв не имеет значения) — значит, далее (до следующего символа «"») следует адрес ссылки (пока неизвестно, «нужная» это ссылка или нет), и этот адрес надо запомнить. Если встретили строку вида «(*&nbsp;КБ&nbsp;ZIP)», где «*» — ни одной, одна или несколько десятичных цифр, — значит, последняя встретившаяся ссылка (её адрес запомнен) — «нужная». Преобразуем адрес этой ссылки в полное имя соответствующего файла (zip-архива) на жёстком диске. Определяем размер этого файла в байтах, затем вычисляем размер в килобайтах, округляя до ближайшего целого числа (но если длина файла — от 1 до 511 байтов включительно, то устанавливаем длину в килобайтах равной 1, а не 0, так как надпись «0 КБ» будет выглядеть несколько странно: всё-таки длина файла не равна нулю). После этого подставляем размер в килобайтах вместо «*».

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

Ещё одна особенность реализации: при описании алгоритма упоминается о поиске в файле строки вида «(*&nbsp;КБ&nbsp;ZIP)», но так как эта строка содержит русские буквы, возникает сложность: в различных кодировках коды русских букв различны, а кодировка обрабатываемого HTML-файла заранее не известна. Можно было, конечно, ограничиться какой-то одной кодировкой (у меня, например, в локальной копии web-страницы все HTML-файлы хранятся в кодировке Windows-1251), но я предпочёл другой способ: при поиске в файле вышеуказанной строки русским буквам могут соответствовать любые символы. Таким образом, можно обрабатывать HTML-файлы в любой кодировке вида «один символ — один байт» (например, DOS, Windows-1251, KOI8-R, ISO 8859-5). Более того, даже если вы решите сделать версию web-страницы на английском языке, и вместо русского сокращения «КБ» в HTML-документах будет английское «KB», программа всё равно будет работать правильно! Хотя при разработке программы такая задача и не ставилась. :–)

Текст программы

/* =============================
     File: "add_kb.c"
     Compiler: Turbo C 2.0
 ============================= */

#include <io.h>
#include <stdio.h>
#include <dir.h>
#include <ctype.h>
#include <string.h>

/* ========================== Описание функций =========================== */

int cmp_str (FILE* f, char* s);
long def_len (char* href, char* cur_path);
void chdir_1 (char* path);
FILE* fopen_1 (char* name, char* mode);
int fgetc_1 (FILE* f);
void ungetc_1 (int c, FILE* f);
void fputc_1 (int c, FILE* f);
void fputs_1 (char* s, FILE* f);
void fclose_1 (FILE* f);

/* ======================== Пошла сама программа ========================= */

#define MAX_HREF_LEN 255    /* Максимальная длина адреса ссылки. */
#define MAX_PATH_LEN 128    /* Максимальная длина пути к файлу.  */

int code_k, code_b;         /* Коды русских букв "К" и "Б" в кодировке
                               обрабатываемого HTML-файла (определяются
                               автоматически). */

int main (int argc, char *argv[])
{
 FILE *f_src;               /* Исходный файл. */
 FILE *f_dst;               /* Формируемый файл. */
 int  href_found=0;         /* Признак "в исходном файле уже обнаружена
                               хотя бы одна ссылка". */
 char href[MAX_HREF_LEN+1]; /* Адрес (т.е. значение атрибута "href")
                               последней встреченной в исходном файле
                               ссылки. */
 int  href_overflow;        /* Признак "длина адреса последней встреченной
                               в исходном файле ссылки оказалась больше
                               максимальной" (т.е. больше MAX_HREF_LEN). */
 long l,l_kb;               /* Длина zip-архива, на который указывает ссылка
                               (l - длина в байтах, l_kb - в килобайтах). */
 char cur_path[MAX_PATH_LEN+1]; /* Путь к обрабатываемому HTML-файлу. */
 char *temp_name="$.tmp";   /* Имя формируемого временного файла. */
 int i,c;

        /* ============ Подготовительные действия ============ */

 printf ("\n+------------------------------------------------------------------------+\n");
 printf   ("| Add_KB - автоматическое проставление размеров файлов в HTML-документах.|\n");
 printf   ("| (c) Иван Рощин, Москва, 22.04.2004                                     |\n");
 printf   ("| E-mail: bestview@mtu-net.ru                  WWW: http://www.ivr.da.ru |\n");
 printf   ("+------------------------------------------------------------------------+\n\n");

 if (argc!=2) {printf ("Syntax: add_kb.exe filename.htm\n\n"); exit(1);}
 if (getcwd(cur_path,MAX_PATH_LEN)==NULL)
 {printf ("Ошибка при определении пути к HTML-файлу!\n\n"); exit (1);}
 f_src=fopen_1(argv[1],"rb");
 f_dst=fopen_1(temp_name,"wb");

        /* ================== Главный цикл =================== */

main_loop:

 /* Если в исходном файле с текущей позиции находится строка 'href="', то
    считаем, что обнаружена ссылка. Устанавливаем признак href_found.
    Считываем идущий за 'href="' адрес ссылки, пока не встретим символ '"',
    и помещаем этот адрес в переменной href. При этом копируем в выходной
    (временный) файл символы, считанные из исходного файла. Если окажется,
    что адрес ссылки длиннее MAX_HREF_LEN, то устанавливаем признак
    href_overflow (нельзя сразу же прерывать выполнение программы с выдачей
    сообщения о слишком длинном адресе ссылки, так как эта ссылка вполне
    может и не относиться к файлу, размер которого требуется указывать). */

 if (cmp_str(f_src,"href=\"")==1)
 {
  href_found=1;
  i=0;                         /* Текущая длина адреса ссылки. */
  href_overflow=0;
  fputs_1 ("href=\"",f_dst);
  while ((c=fgetc_1(f_src))!='"')
  {
   if (c==EOF) goto end_loop; /* Если конец файла - выходим из главного цикла. */
   if (i<MAX_HREF_LEN) {href[i]=c; href[i+1]=0; i++;} else href_overflow=1;
   fputc_1(c,f_dst);
  }
  fputc_1('"',f_dst);
  goto main_loop;    /* Возвращаемся к началу главного цикла. */
 }

 /* Если в исходном файле с текущей позиции находится строка вида
    "(*&nbsp;?&nbsp;ZIP)" (о том, что в этой строке обозначают символы "*"
    и "?", можно узнать из описания функции cmp_str), значит, надо определить
    длину файла (zip-архива), соответствующего последней встреченной ссылке,
    и подставить её в формируемый файл вместо "*". */

 if (cmp_str(f_src,"(*&nbsp;?&nbsp;ZIP)")==1)
 {
  if (href_found==0)
  {
   printf ("Ошибка: в исходном файле встречена строка вида \"(*&nbsp;КБ&nbsp;ZIP)\",\n");
   printf ("но нет ссылки, предшествующей этой строке!\n\n");
   exit (1);
  }

  printf ("%s\n",href); /* Печатаем на экране адрес ссылки. */

  if (href_overflow==1)
  {
   printf ("Ошибка: в исходном файле встречена строка вида \"(*&nbsp;КБ&nbsp;ZIP)\",\n");
   printf ("но адрес ссылки, предшествующей этой строке, оказался слишком длинным!\n\n");
   exit (1);
  }

  l=def_len(href,cur_path); /* Узнали длину файла, соответствующего ссылке. */

  /* Теперь преобразуем полученную длину файла в байтах в длину в килобайтах,
     округляя до ближайшего целого числа. Но если длина файла - от 1 до 511
     байтов включительно, то устанавливаем длину в килобайтах равной 1, а не
     0, так как "0 КБ" будет выглядеть несколько странно: всё-таки длина файла
     не равна 0. */

  if ((l>=1)&&(l<=511)) l_kb=1;
  else l_kb=(l+512)/1024;

  fputc_1 ('(',f_dst);
  if (fprintf(f_dst,"%ld",l_kb)==EOF) {printf ("\nОшибка записи!\n\n"); exit (1);}
  fputs_1 ("&nbsp;",f_dst);
  fputc_1 (code_k,f_dst);
  fputc_1 (code_b,f_dst);
  fputs_1 ("&nbsp;ZIP)",f_dst);
  goto main_loop;    /* Возвращаемся к началу главного цикла. */
 }

 /* Если в исходном файле с текущей позиции нет ни строки 'href="', ни строки
    вида "(*&nbsp;?&nbsp;ZIP)", то, если ещё не достигнут конец исходного
    файла, просто копируем символ из исходного файла в формируемый временный
    файл и переходим к началу главного цикла. */

 c=fgetc_1(f_src);
 if (c!=EOF) {fputc_1(c,f_dst); goto main_loop;}

        /* ======= Выполнение главного цикла закончено ======= */

end_loop:
 fclose_1 (f_src);
 fclose_1 (f_dst);

 /* Исходный файл успешно обработан. Теперь открываем сформированный
    временный файл для чтения, а исходный файл - для записи, и копируем
    содержимое временного файла в исходный. Затем удаляем временный файл. */

 chdir_1 (cur_path);
 f_src=fopen_1(temp_name,"rb");
 f_dst=fopen_1(argv[1],"wb");
 while((c=fgetc(f_src))!=EOF) fputc (c,f_dst);
 fclose_1 (f_src);
 fclose_1 (f_dst);
 unlink (temp_name);

 printf ("\nAll OK!\n\n");
 exit (0);
}

/* ==========================================================================
   Функция def_len - определение длины файла по адресу ссылки на этот файл.
   Вход:  href - адрес ссылки на файл,
          cur_path - путь к обрабатываемому HTML-файлу.
   Выход: длина (в байтах) файла, на который указывает ссылка.
 ========================================================================= */

long def_len (char* href, char* cur_path)
{
 char temp_path[MAX_PATH_LEN+1]; /* Здесь будем формировать путь к файлу,
                                    на который указывает ссылка. */
 int i;
 long l;
 FILE *f_tmp;

 strcpy (temp_path,cur_path); /* Первоначальное значение пути - это путь
                                 к обрабатываемому HTML-файлу. */

 /* Для более удобного выполнения последующих действий приводим путь к виду
    без '\' в конце. Если путь указывает не на корневой каталог (тогда его
    длина больше трёх символов), то это условие уже выполняется, иначе (путь
    вида "C:\", длина - три символа) отбрасываем последний символ пути. */

 if (strlen(temp_path)==3) temp_path[2]=0;

 while (strchr(href,'/')!=NULL)   /* Пока в адресе ссылки ещё есть "/". */
 {
  /* Если первые три символа href - "../", то переходим на уровень вверх:
     отрезаем эти три символа от href и отрезаем от temp_path все символы,
     начиная с последнего "\" и до конца. */

  if (memcmp(href,"../",3)==0)
  {
   href=href+3;
   if (strlen(temp_path)==2)  /* Если уже в корневом каталоге. */
   {
    printf ("Ошибка: в обрабатываемой ссылке слишком много переходов на уровень вверх!\n\n");
    exit (1);
   }
   *strrchr(temp_path,'\\')=0;
   continue;
  }

  /* Иначе начало href до первого "/" - это имя каталога, в который надо
     перейти. Отрезаем это имя от href и добавляем к temp_path. */

  i=strchr(href,'/')-href;                   /* Длина имени каталога. */
  if ((strlen(temp_path)+1+i)>MAX_PATH_LEN)
  {printf ("Ошибка: слишком длинный путь к файлу!\n\n"); exit (1);}
  strncat(temp_path,"\\",1);
  strncat(temp_path,href,i);
  href=href+1+i;
 }

 /* Теперь в href осталось только имя файла, а путь к файлу сформирован
    в temp_path. Если этот путь указывает на корневой каталог (тогда его
    длина - два символа), добавляем "\" в конце. */

 if (strlen(temp_path)==2) {temp_path[2]='\\'; temp_path[3]=0;}

 /* Осталось определить длину этого файла. */

 chdir_1 (temp_path);
 f_tmp=fopen_1(href,"rb");
 l=filelength(fileno(f_tmp));
 fclose_1(f_tmp);
 return (l);
}

/* ==========================================================================
   Функция cmp_str - проверка совпадения (без учёта регистра букв) строки s
   и того, что находится в файле f с текущей позиции. Символу "*" в строке
   соответствуют ни одной, одна или несколько десятичных цифр в файле.
   Символу "?" в строке соответствуют любые два символа в файле.
   При совпадении функция возвращает 1, а позиция в файле указывает на первый
   символ после строки; если в строке был символ "?", то коды соответствующих
   ему двух символов в файле сохраняются в глобальных переменных code_k и
   code_b.
   При несовпадении функция возвращает 0, позиция в файле не меняется.
 ========================================================================= */

int cmp_str (FILE* f, char* s)
{
 fpos_t pos;
 int c,i;
 int k,b;
 int result=1;

 fgetpos (f,&pos);         /* Запомнили текущую позицию в файле. */
 for (i=0;i<strlen(s);i++)
 {
  if (s[i]=='*')
  {
   while (isdigit(c=fgetc_1(f))); /* Пропускаем все цифры. */
   if (c!=EOF) ungetc_1(c,f);
   continue;
  }
  if (s[i]=='?')
  {
   k=fgetc_1(f); if (k==EOF) {result=0; break;}
   b=fgetc_1(f); if (b==EOF) {result=0; break;}
   continue;
  }
  if (tolower(fgetc_1(f))!=tolower(s[i])) {result=0; break;}
 }
 if (result==0) fsetpos (f,&pos);    /* Восстановили позицию в файле. */
 else {code_k=k; code_b=b;}
 return (result);
}

/* ==========================================================================
   Аналоги некоторых функций для работы с файлами (chdir, fgetc, ungetc,
   fputc, fputs, fopen, fclose). При ошибке прерывают выполнение программы,
   печатая соответствующее сообщение; таким образом, после вызова этих функций
   не надо проверять, была ли ошибка.
 ========================================================================= */

void chdir_1 (char* path)
{
 if (chdir(path)!=0)
 {printf ("Ошибка при переходе в каталог \"%s\"!\n\n",path); exit (1);}
}

int fgetc_1 (FILE* f)
{
 int c;
 c=fgetc(f); if ferror(f) {printf ("\nОшибка чтения!\n\n"); exit (1);}
 return (c);
}

void ungetc_1 (int c, FILE* f)
{
 if (ungetc(c,f)==EOF) {printf ("\nОшибка при вызове функции \"ungetc\"!\n\n"); exit (1);}
}

void fputc_1 (int c, FILE* f)
{
 if (fputc(c,f)==EOF) {printf ("\nОшибка записи!\n\n"); exit (1);}
}

void fputs_1 (char* s, FILE* f)
{
 if (fputs(s,f)==EOF) {printf ("\nОшибка записи!\n\n"); exit (1);}
}

FILE* fopen_1 (char* name, char* mode)
{
 FILE* f;
 char* s;
 char* s1="чтение";
 char* s2="запись";

 f=fopen(name,mode);
 if (f==NULL)
 {
  if (mode[0]=='r') s=s1; else s=s2;
  printf ("\nОшибка открытия файла \"%s\" на %s!\n\n",name,s);
  exit (1);
 }
 return (f);
}

void fclose_1 (FILE* f)
{
 if (fclose(f)==EOF) {printf ("\nОшибка закрытия файла!\n\n"); exit (1);}
}
Скачать исполняемый файл программы (для DOS) (8 КБ ZIP)
Скачать листинг программы в текстовом виде (4 КБ ZIP)

Руководство пользователя

Использовать программу, конечно, имеет смысл только в случае, если у вас такая же ситуация, как описано в разделе «Постановка задачи». Также обратите внимание на следующие ограничения программы:

При запуске программы необходимо указать в командной строке имя обрабатываемого HTML-файла (он должен находиться в текущем каталоге):

add_kb.exe filename.htm

В процессе работы программа выводит адреса встретившихся в этом файле «нужных» ссылок. После успешной обработки файла программа печатает сообщение «All OK!» и заканчивает работу.

Как уже упоминалось в разделе «Описание алгоритма», в процессе обработки HTML-файла программа не изменяет исходный файл сразу же, а записывает результат во временный файл. Таким образом, если на этапе создания временного файла выполнение программы будет прервано из-за какой-либо ошибки (скажем, если в одной из «нужных» ссылок был указан неправильный адрес и соответствующий файл, длину которого надо было определить, не был найден), то исходный HTML-файл останется неизменным.

После того, как исходный HTML-файл полностью обработан и временный файл успешно сформирован, программа копирует содержимое временного файла в исходный файл и после успешного завершения копирования удаляет временный файл. Таким образом, если при копировании выполнение программы будет прервано из-за какой-либо ошибки, то результат работы программы останется на диске во временном файле (его имя — «$.tmp»).

Программа возвращает операционной системе код завершения: 0 в случае удачного завершения и 1 при какой-либо ошибке. Сообщение об ошибке также выводится на экран. Если программа была вызвана из bat-файла или из другой программы, код завершения может быть в них проанализирован и в зависимости от его значения могут быть предприняты какие-либо действия.

Кстати, помимо выполнения основной задачи, ещё одна польза от программы в том, что она обнаруживает ситуацию, когда в «нужной» ссылке адрес zip-архива указан неправильно, так что ему не соответствует никакой файл. В этом случае выполнение программы будет прервано с выдачей сообщения о невозможности открытия соответствующего файла (при этом обрабатываемый HTML-документ останется неизменным). У меня самого так обнаружилась неправильность пары ссылок. :–)

Дополнение

На моей web-странице, в разделе «Статьи», есть такая ссылка на zip-архив (указанный размер архива в килобайтах, конечно, со временем изменяется):

Рис. 3
Изображение
ссылки

Раньше ей соответствовал следующий фрагмент HTML-кода:

<a href="txt_zip/all_txt.zip">Скачать <nobr>txt-версии</nobr>
всех статей (1370&nbsp;КБ&nbsp;ZIP)</a>

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

Пришлось изменить соответствующий фрагмент HTML-кода, указав в нём прямую ссылку на новое местоположение архива:

<a href="http://www.comail.ru/~ivr/all_txt.zip">Скачать
<nobr>txt-версии</nobr> всех статей (1370&nbsp;КБ&nbsp;ZIP)</a>

Таким образом, проблема с превышением 10-мегабайтного лимита была решена, но это привело к появлению новой проблемы: теперь я уже не мог использовать свою программу, автоматически простанавливающую размеры файлов, для обработки HTML-документа, содержащего вышеописанную ссылку. В самом деле, программа, встретив в вышеприведённом фрагменте этого документа строку «(1370&nbsp;КБ&nbsp;ZIP)», анализирует адрес последней встреченной ссылки (то есть «http://www.comail.ru/~ivr/all_txt.zip»), а этот адрес не указывает на локальную копию файла «all_txt.zip», поэтому программа аварийно завершает работу, не обработав документ.

Мне, тем не менее, хотелось всё-таки сделать так, чтобы в этом HTML-документе можно было бы автоматически проставлять размеры файлов (в том числе и файла «all_txt.zip»), причём не хотелось изменять программу, которая этим занимается. И после недолгих раздумий решение проблемы всё же нашлось, причём оно оказалось на удивление простым!

Смотрите: хотя в Интернете файл «all_txt.zip» и расположен теперь по другому адресу, но в моей локальной копии web-страницы он остался на прежнем месте, и ему продолжает соответствовать относительный адрес «txt_zip/all_txt.zip». Надо было, таким образом, «убедить» мою программу, что этот файл по-прежнему находится по относительному адресу «txt_zip/all_txt.zip», и в то же время добиться того, чтобы для посетителя web-страницы адрес этого файла был правильным — http://www.comail.ru/~ivr/all_txt.zip. И тут я вспомнил об одном свойстве программы: она «не умеет» игнорировать комментарии в обрабатываемом HTML-документе. Тогда я изменил вышеупомянутый фрагмент HTML-кода так:

<a href="http://www.comail.ru/~ivr/all_txt.zip"><!--
href="txt_zip/all_txt.zip"-->Скачать <nobr>txt-версии</nobr>
всех статей (1370&nbsp;КБ&nbsp;ZIP)</a>

Теперь программа при обработке этого фрагмента, встретив строку «(1370&nbsp;КБ&nbsp;ZIP)», будет считать адресом последней встреченной ссылки именно «txt_zip/all_txt.zip» (напомню, адресом последней ссылки программа считает то, что было после последнего встреченного «href="») — и, таким образом, сможет определить длину файла «all_txt.zip» и проставить её в обрабатываемом HTML-документе. В то же время, так как содержимое комментариев игнорируется браузером, для посетителя web-страницы данной ссылке будет соответствовать адрес http://www.comail.ru/~ivr/all_txt.zip, что и требуется.

Источники

  1. HTML 4.01 Specification.
    http://www.w3.org/TR/1999/REC-html401-19991224/
  2. T.Berners-Lee, R.Fielding, L.Masinter. “Uniform Resource Identifiers (URI): Generic Syntax” (RFC 2396).
    http://www.ietf.org/rfc/rfc2396.txt
  3. В.Э.Фигурнов. «IBM PC для пользователя». Изд. 5-е, испр. и доп. — Москва, «Финансы и статистика», 1994.

Другие мои статьи о создании и/или обработке HTML-документов:

1. 

«Преобразование псевдографических таблиц в формат HTML». «Радиомир. Ваш компьютер» 5—7/2003.

2. 

«Добавление в HTML-документы информации об их кодировке». «Радиомир. Ваш компьютер» 10/2003.

Страница Ивана Рощина > Статьи >