Хранение изображений в базе данных MySQL

Для хранения изображений в базе данных MySQL необходимо определить одно из полей таблицы как производное от типа BLOB. Сокращение BLOB означает большой двоичный объект. Тип хранения данных BLOB обладает несколькими вариантами:

  • TINYBLOB — может хранить до 255 байт
  • BLOB — может хранить до 64 килобайт информации
  • MEDIUMBLOB — до 16 мегабайт
  • LONGBLOB — до 4 гигабайт

Соответсвенно, для хранения изображений нам надо создать таблицу images с двумя полями:

  • id — уникальный ID изображения
  • content — поле для хранения изображения

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

<form action="putimage.php" enctype="multipart/form-data" method="post"> Изображение: <input name="image" type="file" />
<input type="submit" value="Загрузить" />
</form>Обработчик формы - файл putimage.php:
// Проверяем пришел ли файл
if( !empty( $_FILES['image']['name'] ) ) {
// Проверяем, что при загрузке не произошло ошибок
if ( $_FILES['image']['error'] == 0 ) {
// Если файл загружен успешно, то проверяем - графический ли он
if( substr($_FILES['image']['type'], 0, 5)=='image' ) {
// Читаем содержимое файла
$image = file_get_contents( $_FILES['image']['tmp_name'] );
// Экранируем специальные символы в содержимом файла
$image = mysql_escape_string( $image );
// Формируем запрос на добавление файла в базу данных
$query="INSERT INTO `images` VALUES(NULL, '".$image."')";
// После чего остается только выполнить данный запрос к базе данных
mysql_query( $query );
}
}
}
?>

Извлечь сохраненный файл изображения можно следующим образом (файл image.php):

if ( isset( $_GET['id'] ) ) {
// Здесь $id номер изображения
$id = (int)$_GET['id'];
if ( $id > 0 ) {
$query = "SELECT `content` FROM `images` WHERE `id`=".$id;
// Выполняем запрос и получаем файл
$res = mysql_query($query);
if ( mysql_num_rows( $res ) == 1 ) {
$image = mysql_fetch_array($res);
// Отсылаем браузеру заголовок, сообщающий о том, что сейчас будет передаваться файл изображения
header("Content-type: image/*");
// И  передаем сам файл
echo $image['content'];
}
}
}
?>

Чтобы вывести изображение в HTML-документе, делаем так:

<img src="image.php?id=17" alt="" />

И последнее: графические файлы иногда имеют довольно большой размер, убедитесь, что настройки сервера позволяют работать с таким объемом данных. В файле php.ini это директивы post_max_size — определяет максимальный объем данных передаваемых методом POST, и upload_max_filesize — определяет максимальный размер загружаемого файла. Так же проверьте, позволяют ли настройки MySQL обрабатывать запросы с большим объемом данных (директива max_allowed_packet файла my.ini).

Коды ответов (ошибок) HTTP сервера

При любом HTTP запросе сервер сначала возвращает код ответа на HTML запрос. Проанализировав этот ответ можно сделать вывод о том, был ли запрос выполнен успешно, или в процессе обработки запроса произошла ошибка.

Коды ответа HTTP сервера могут принадлежать следующим группам:
1xx — Информационный ответ
2xx — Успешная обработка запроса
3xx — Переадресация (редирект)
4xx — Неполный запрос к серверу
5xx — При обработке запроса произошла ошибка

Естественно, что кодов ответа в каждой группе не по 100. Браузер (клиент IE, Opera, Mozilla и т.д.), получая от сервера тот или иной код, сам решает как его интерпретировать. Если код клиенту неизвестен, то как минимум он может определить диапазон кода и повести себя соответствующим образом.

Информационные ответы

100 Continue
Часть запроса принята. Как правило это занчит, что можно отправлять следующую часть запроса.

101 Switching Protocols
Сервер производит переключение протоколов в соответствии с заголовком Upgrade.

Успешная обработка запроса

200 OK
Запрос обработан успешно.

201 Created
Данный код используется когда происходит создание нового URI. Вместе с кодом сервер посылает заголовок Location с адресом нового URI.

202 Accepted
Запрос принят и обрабатывается. В теле ответа как правило содержится дополнительная информация.

203 Non-Authoritative Information
Ответ означает, что информация получена из ненадежного источника (например, с другого сервера).

204 No Content
Запрос обработан, но в ответ ничего не возвращается. Как правило используется если в ответ на запрос не нужно обновлять содержимое документа.

205 Reset Content
Означает, что содержимое документа должно быть сброшено в начальное состояние. Обычно используется при очистке форм ввода данных..

206 Partial Content
При данном ответе возвращается лишь часть данных. Обычно используется если клиент запросил часть данных с использованием заголовка Range.

Переадресация

300 Multiple Choices
Означает, что существует несколько вариантов запрашиваемой страницы. Например, сайт, переведенный на несколько языков.

301 Moved Permanently
Данный ответ означает, что данный документ был перемещен и клиенту следует изменить все ссылки на данный документ его новым местоположением.

302 Moved Temporarily
Документ временно перемещен в другое место.

303 See Other
Данный документ можно найте по другим ссылкам. Список ссылок передан в теле ответа.

304 Not Modified
Данный код ответа возвращается если был запрос lf-Modified-Since, и документ не изменялся с указанной даты.

305 Use Proxy
Доступ к документу должен осуществляться через proxy-сервер, адрес которого указан в Location.

Неполные запросы клиента

400 Bad Request
Ошибка в строке запроса.

401 Unauthorized
Ответ означает, что пользователь не имеет достаточных прав для просмотра документа.

402 Payment Required
Данный код зарезервирован на будущее. Видимо будет означать, что запрошенный документ является платным ресурсом.

403 Forbidden
Запрос не будет выполнен по какой-либо причине.

404 Not Found
Запрашиваемого документа нет на сервере.

405 Method Not Allowed
Означает, что метод, используемый клиентом, не поддерживается.

406 Not Acceptable
Ресурс существует, но не в той форме, что клиент запросил. Например, может различаться язык документа.

407 Proxy Authentication Required
Для Proxy-сервера необходима авторизация.

408 Request Time-out
Сервер разорвал соединение из-за превышенного таймаута.

409 Conflict
Запрос конфликтует с другим запросом.

410 Gone
Данный код означает, что документ был удален с сервера.

411 Length Required
Пропущено необходимое поле в заголовке запроса Content-Length.

412 Precondition Failed
Условие указанное в заголовке не выполняется.

413 Request Entity Too Large
Слишком большое тело запроса.

414 Request-URI Too Long
Слишком длинный URI в запросе.

415 Unsupported Media Type
Сервер не поддерживает указанный формат данных.

Ошибки сервера

500 Internal Server Error
Внутренняя ошибка сервера. Например, ошибка при выполнении скрипта.

501 Not Implemented
Недопустимое действие.

502 Bad Gateway
Недопустимый ответ с другого ресурса.

503 Service Unavailable
Данный код означает, что указанный сервис временно недоступен.

504 Gateway Time-out
Превышен таймаут ожидания от другого ресурса

505 HTTP Version not supported
Данная версия протокола HTTP не поддерживается сервером.

Настройка сетевого интерфейса в OpenBSD

Настройка сети в OpenBSD выполняется с помощью текстовых файлов в /etc, для каждого интерфейса создается файл с именем – hostname + псевдоним сетевого интерфейса. Интерфейсы называются по типу карты, а не по типу соединения. Название сетевого интерфейса узнаем выполнив команду:

$ ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33200
        index 3 priority 0 llprio 3
        groups: lo
        inet 127.0.0.1 netmask 0xff000000
fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        lladdr 00:02:b3:5b:12:f8
        index 1 priority 0 llprio 3
        media: Ethernet autoselect (100baseTX full-duplex)
        status: active
        inet 10.0.0.5 netmask 0xffffff00 broadcast 10.0.0.255
enc0: flags=0<>
        index 2 priority 0 llprio 3
        groups: enc
        status: active
pflog0: flags=141<UP,RUNNING,PROMISC> mtu 33200
        index 4 priority 0 llprio 3
        groups: pflog

В файле /etc/hostname.fxp0 прописываются настройки интерфейса fxp0:

$ cat /etc/etc/hostname.fxp0
inet 10.0.0.5 255.255.255.0 NONE media 100baseTX mediaopt full-duplex

где inet — семейство протоколов (IPv4), 10.0.0.5 — IP-адрес, 255.255.255.0 — маска подсети, NONE — широковещательный адрес (будет выбран автоматически), media 100baseTX mediaopt full-duplex — опции сетевого адаптера, если не задать будет сконфигурено автоматически, но возможно не так как требуется . Для конфигурирования интерфейса с помощью DHCP, необходимо поместить в файл строку dhcp.

Добавить второй ip на интерфейс:

$ cat /etc/etc/hostname.fxp0
inet 10.0.0.5 255.255.255.0 NONE media 100baseTX mediaopt full-duplex
inet alias 10.0.0.77 255.255.255.255

Шлюз по умолчанию указывается в файле /etc/mygate

$ cat /etc/mygate
10.0.0.1

Название хоста указывается в файле /etc/myname

$ cat /etc/myname
test.example.com

Указать DNS сервера в системе

$ cat /etc/resolv.conf
search example.com
nameserver 10.0.1.194
nameserver 10.0.1.195
lookup file bind

Перезагрузить настройки сети

$ sh /etc/netstart

Получение нового IP от DHCP сервера в Windows

В этой статье описан лучший способ сбросить IP адрес и получить его заново, если ваш компьютер настроен на использование DHCP сервера.

1. Перейдите в меню Start и нажмите Run

2. Появится окно вызова. Введите cmd и нажмите OK

3. Откроется командная строка. Введите ipconfig. Вы увидите IP адрес и другую информацию о сетевых интерфейсах вашего компьютера.

4. Введите ipconfig /release для освобождения IP адреса.

5. Наконец введите ipconfig /renew для получения нового адреса.

Использование комманд diff и patch

Комманды diff и patch представляют собой мощную комбинацию. Они часто используются для получения разницы между оригинальными файлами и обновленными, что бы другие люди, у которых есть только только оригинальные файлы могли обновить их используя файлы, которые содержат только разницу. В этой статье показаны базовые принципы использования этих команд.

В этой статье используются без объяснения некоторые базовые команды Linux, такие как смена смена директории, копирование файлов и редактирование текстовых файлов.

Использование diff для создания простого патча

Наиболее простой пример использования команды diff — получение различий между двумя файлами, оригинальным и обновленным. Можете, например, написать насколько слов обычного текста, сделать какие-нибудь изменения, и сохранить измененния во второй файл. Теперь вы можете сравнить эти эти два файла, используя команду diff:

[rechosen@localhost ~]$ diff originalfile updatedfile

Конечно, надо заменить originalfile и updatedfile соответствующими именами файлов. В результате должно получиться что-то вроде этого:

1c1
 
< These are a few words.
 
\ No newline at end of file
 
---
 
> These still are just a few words.
 
\ No newline at end of file

Обратите внимание: Что бы продемонстрировать создание простого патча, я использовал оригинальный файл, содержащий строку «These are a few words.», и измененный файл, содержащий строку «These still are just a few words.» Вы можете создать эти файлы сами, если хотите запустить команду из статьи и получить тот же результат.

1c1 показывает номер строки и то, что с ней надо сделать. Обратите внимание, что может быть сразу несколько строк(например, 12,15, что означает со строки 12 до строки 15). Символ «c» означает, что патч заменит эту строку. Есть еще два других символа: «a» и «d». Они означают «добавить»(add) и «удалить»(delete) соответственно. Таким образом, синтаксис следующий: (номер строки или диапазон строк)(c,a или d)(номер строки или диапазон строк), хотя когда используются «a» или «d», одна из частей (номер строки или диапазон строк) может содержать только номер одной строки.

  • Когда используется «c», номера строк слева — это строки в оригинальном файле, которые надо заменить строками, находящимися в патче, а номера строк справа — это строки, которые должны быть в пропатченном файле.
  • Когда используется «a», номер слева может быть только номером одной строки, который показывает, где надо добавить строку в пропатченном файле, а номера строк справа — это строки, которые должны быть в пропатченном файле.
  • Когда используется «d», номера строк слева — это строки, которые надо удалить, чтобы получить пропатченную версию файла, а номер строки справа может быть только номером одной строки, который показывает где будут строки в пропатченном файле, если они не будут удалены. Вы можете подумать, что последний номер не нужен, но не забывайте, что патч можно применить для восстаноления исходного файла. Это будет объяснено позже.

Знак «<» означает, что патч должен удалить символы после этого знака, а знак «>» означает, что символы после этого знака надо добавить. Когда надо заменить строки («c» между номерами строк), вы увидите оба знака: и «<«, и «>». Когда надо добавить строку («a» между номерами строк), вы увидите только знак «>», а когда надо удалить строку («d» между номерами строк), вы увидите только знак «<«.

Строка «\ No newline at end of file» появилась из-за того, что я не не нажал enter после того как набрал слова. Считается хорошим тоном заканчивать текстовый файл пустой строкой. Некоторым программам она необходима для работы. Поэтому эта строка появилась после работы команды diff. Добавим пустые строки в конец файлов, и получим более короткий вывод команды diff:

1c1
 
< These are a few words.
 
---
 
> These still are just a few words.

Как вы возможно заметили, я не объяснил что означают 3 знака «-«. Они означают конец строк, которые надо заменить и начало строк на которые надо заменить. Разделение старых и новых строк. Вы увидите это знак только при замене («c» между номерами строк).

Если мы хотим создать патч, мы должны поместить вывод команды diff в файл. Конечно это можно сделать, скопировав его из консоли и вставив в вашем любимом текстовом редакторе, а затем сохранив этот файл, но есть способ проще. Мы можем с помощью bash направить вывод команды diff в текстовый файл:

[rechosen@localhost ~]$ diff originalfile updatedfile > patchfile.patch

Опять же не забудьте заменить originalfile и updatedfile на соответствующие имена файлов. Вы наверное знаете, что опция bash «>» работает со всеми командами. Это очень полезное свойство.

Применение простого патча, который мы создали

Мы можем использовать патч, который только что создали, чтобы получить из оригинального файла обновленный. Для этого надо скопировать оригинальный файл и патч в одно и тоже место. И затем применить патч:

[rechosen@localhost ~]$ patch originalfile -i patchfile.patch -o updatedfile

Естественно, и здесь надо изменить имена файлов на необходимые. Если все прошло хорошо, должен получиться файл, идентичный обновленному. Вы можете убедиться в этом, используя команду diff с опцией «-s»:

[rechosen@localhost ~]$ diff -s updatedfile [/path/to/the/original/updatedfile]/updatefile

Замените текст между [ и ] на путь к оригинальному файлу. Например, если обновленный файл, который вы использовали при создании патча находится в родительской директории вышай текущей, то «[/path/to/the/original/updatedfile]» надо заменить на «..» (bash понимает это как родительскую директорию от текущей). И конечно надо изменить имена файлов на верные.

Поздравляю! Если diff сообщила, что файлы идентичные, вы только что успешно создали и применили патч! Однако формат патча, который мы только что использовали не единственный. В следующей главе мы рассмотрим другой формат патча.

Контекстный патч

В первой главе мы создали патч, используя нормальный формат команды diff. Однако этот формат не обеспечивает контекстной зависимости, а использует строки целиком. Создадим патч для того же файла, но используя контектсный формат:

[rechosen@localhost ~]$ diff -c originalfile updatedfile

Результат получится следующий:

*** originalfile        2007-02-03 22:15:48.000000000 0100
 
--- updatedfile 2007-02-03 22:15:56.000000000 0100
 
***************
 
*** 1 ****
 
! These are a few words.
 
--- 1 ----
 
! These still are just a few words.

Как вы видите, здесь включено имя файла. Это значит, что нам не придется набирать его во время применения патча. Далее идет дата и время последнего изменения файла. строка с 15 «*» показывает начало изменений. Они показывают, что надо сделать со следующим блоком текста. Два номера 1 — это номера строк (здесь тоже может быть сразу несколько строк), а «!» означает, что строки надо заменить. Строка с «!» перед тремя «-» должна быть заменена второй строкой с «!», которая идет после трех «-«(конечно сам ! не будет включен; это синтаксис контекстного формата). Как вы можете видеть, здесь нет знаков «c», «a» и «d».Действие, которое нужно сделать, определяется символом в начале строки. «!» означает замену. Другие символы — «+», «-» и » » (пробел). «+» означает добавление, «-» означает удаление, а » » означает ничего не делать: патч использует его чтобы убедиться, что он изменяет правильную часть файла.

Применять этот патч легче: при тех же условиях, что и для предыдущего патча (записываем вывод команды diff в файл, затем копируем патч и оригинал в одно и то же место), надо выполнить следующую команду:

[rechosen@localhost ~]$ patch -i patchfile.patch -o updatedfile

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

Получение различий между несколькими файлами

Наиболее простой способ получить различия между несколькими файлами — это положить их в одну директорию и выполнить команду diff для этой директории целиком. Вы можете просто передать команде diff в качестве параметров имена директорий вместо имен файлов:

[rechosen@localhost ~]$ diff originaldirectory/ updateddirectory/

Обратите внимание: Если в директория есть поддиректории, то надо использовать опцию «-r».

В результате должно получится что-то вроде этого:

diff originaldirectory/file1 updateddirectory/file1
 
1c1
 
< This is the first original file.
 
---
 
> This is the first updated file.
 
diff originaldirectory/file2 updateddirectory/file2
 
1c1
 
< This is the second original file.
 
---
 
> This is the second updated file.
 
14d13
 
< We're going to add something in this file and to delete this line.
 
26a26
 
> This is line has been added to this updated file.

Обратите внимание: Я создал несколько несколько файлов для примера. Вы можете скачать архив, содержащий эти файлы: http://www.linuxtutorialblog.com/resource/uploads/diffpatchexamplefiles.tar.gz.

Как вы видите, нормальный формат содержит только имена файлов и изменяемые строки.

Теперь используем контекстный формат:

diff -c originaldirectory/file1 updateddirectory/file1
 
*** originaldirectory/file1     2007-02-04 16:17:57.000000000 +0100
 
--- updateddirectory/file1      2007-02-04 16:18:33.000000000 +0100
 
***************
 
*** 1 ****
 
! This is the first original file.
 
--- 1 ----
 
! This is the first updated file.
 
diff -c originaldirectory/file2 updateddirectory/file2
 
*** originaldirectory/file2     2007-02-04 16:19:37.000000000 +0100
 
--- updateddirectory/file2      2007-02-04 16:20:08.000000000 +0100
 
***************
 
*** 1,4 ****
 
! This is the second original file.
 
  S
 
  O
 
--- 1,4 ----
 
! This is the second updated file.
 
  S
 
  O
 
***************
 
*** 11,17 ****
 
  C
 
  E
 
- We're going to add something in this file and to delete this line.
 
  S
 
  O
 
--- 11,16 ----
 
***************
 
*** 24,28 ****
 
--- 23,28 ----
 
  C
 
  E
 
+ This is line has been added to this updated file.
 
  Something will be added above this line.

Первая вещь, которую вы должны были заметить — это увеличение размера; контекстный формат содержит больше информации, чем нормальный. Этого не было заметно в первом премере, так как не было контекста. Однако теперь контекст есть, и за счет него размер патча увеличился. Кроме того, вы наверное заметили, что имя файла повторяется дважды. Это возможно сделано для того, чтобы легче было понять когда начался патч следующего файла или для обеспечения лучшего восстановления.

Другой способ получить разницу между между несколькими файлами — это написать скрипт, который выполняет команду diff несколько раз и добавляет результат выполнения в один файл. Мы не будем рассматривать этот способ, так как положить все файлы в одну директорию горазда проще.

Создать патч было легко, но использование директорий ставит следующую проблему: бедут ли патч изменять только соответствующие файлы в текущей директории, или будет использовать соответствующий путь, указанный в файле? Чтобы узнать это, смотрите следующую главу!

Применение патча к нескольким файлам

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

[rechosen@localhost ~]$ diff -c originaldirectory/ updateddirectory/ > patchfile.patch

Обратите внимание: мы используем контекстный формат патча, так как это является хорошим тоном.

Теперь надо использовать полученный патч. Скопируйте оригинальную директорию и патч куда-нибудь и примените следующую команду:

[rechosen@localhost ~]$ patch -i patchfile.patch

Однако возникает ошибка, что невозможно найти файлы для патча. Команда пытается найти файл file1 в текущей директории (по умолчанию патч убирает все пути перед именем файла). И конено файла нет, так как мы пытаемся обновить файлы в директории originaldirectory. Поэтому мы должны заставить патч использовать полный путь. Это делается следующим образом:

[rechosen@localhost ~]$ patch -p0 -i patchfile.patch

Обратите внимание: Вы может подумать, что можно просто переместиться в originaldirectory и запустить патч. Но это не так! Так делать не стоит: если в в патче содержатся поддиректории, то он будет искать их в рабочей директории, и не найдет, или найдет не те. Используйте опцию «-p», чтобы заставить патч искать файлы в поддиректориях.

Опция «-p» говорит патчу сколько слэшей (включая то, что перед ними, обычно директории) нужно вырезать перед именем файла (обратите внимание, что при использовании опции «-p0», патч будет будет искать файлы и в originaldirectory и в updateddirectory).Когда мы устанавливаем 0, это означает что не надо удалять пути, но можно поставить 1, чтобы удалить первый слэш, или 2, чтобы удалить два слэша, и т.д. Это может быть полезно, если если в патче используется структура каталогов, отличная от вашей. Например, если в патче используется следующая структура каталогов:

(...)
 
*** /home/username/sources/program/originaldirectory/file1     2007-02-04 16:17:57.000000000 +0100
 
--- /home/username/sources/program/updateddirectory/file1      2007-02-04 16:18:33.000000000 +0100
 
(...)

Вам надо просто посчитать количество слэшей (/ (1) home/ (2) username/ (3) sources/ (4) program/ (5)) и передать это число в опцие «-p». Если вы используете «-p5», то патч будет искать и в originaldirectory/file1 и в updateddirectory/file1. Не забудьте, что патч рассматривает два слэша друг за другом (как в /home/username//sources) как один. Это вызвано тем, что иногда патч скрипты добавляют дополнительный слэш между директориями.

Восстановление оригинального файла из пропатченного

Иногда возникает необходимость восстановить оригинальный файл из пропатченного. Например, если в нем содержится ошибка. Для этого надо использовать опцию «-R»:

[rechosen@localhost ~]$ patch -p0 -R -i patchfile.patch

Обычно эта операция проходит без ошибок, и вы получаете исходный файл. Однако лучше на всякий случай сделать резервную копию перед восстанолением файлов.

Унифицированный формат

Есть еще один формат вывода различий командой diff: унифицированный формат. Он более компактен, так как содержит уменьшенные контекстные строки. Однако он поддерживается только GNU diff и patch. Если вы его используете, вы должны быть уверены, что у пользователей, для которых патч предназначен, GNU patch. Linux допускает использование этого формата.

Унифицированный формат похож на контекстный, но это не одно и тоже. Патч в унифицированном формате можно создать так:

[rechosen@localhost ~]$ diff -u originaldirectory/ updateddirectory/

Результат будет седующий:

diff -u originaldirectory/file1 updateddirectory/file1
 
--- originaldirectory/file1     2007-02-04 16:17:57.000000000 +0100
 
+++ updateddirectory/file1      2007-02-04 16:18:33.000000000 +0100
 
@@ -1 +1 @@
 
-This is the first original file.
 
+This is the first updated file.
 
diff -u originaldirectory/file2 updateddirectory/file2
 
--- originaldirectory/file2     2007-02-04 16:19:37.000000000 +0100
 
+++ updateddirectory/file2      2007-02-04 16:20:08.000000000 +0100
 
@@ -1,4 +1,4 @@
 
-This is the second original file.
 
+This is the second updated file.
 
 S
 
 O
 
@@ -11,7 +11,6 @@
 
 C
 
 E
 
-We're going to add something in this file and to delete this line.
 
 S
 
 O
 
@@ -24,5 +23,6 @@
 
 C
 
 E
 
+This is line has been added to this updated file.
 
 Something will be added above this line.

Как вы видите, номера строк заключены между «@». Кроме того, есть дополнительный пробел после «+» или «-«. Это экономит несколько байт. Другое различие: в унифицированном формате нет специального знака для замены. Он просто удаляет старые строки («-«) и добавляет новые («+»). Разница между этими действиями заключается в том, что при замене используется один и тот же номер строки, а при удалении и добавлении разные.

Сравнение форматов

Читая про три разных формата, вы вероятно задумались: а какой же выбрать? Вот небольшое сравнение:

  • Нормальный формат наиболее совместимый. Любые команды похожие на diff/patch должны понять его. Его недостаток — это отсутствие контекста.
  • Контекстный формат широко распространен, но не все команды его понимают. Его преимущество в наличии контекста.
  • Унифицированный формат тоже включает контекст, и при этом более компактем. Но его поддерживает только GNU diff and patch.

Если вы уверены, что патч буду использовать только пользователи с GNU diff/patch, то лучше всего выбрать унифицированный формат, так как он более компактный. В большинстве других случаев лучший выбор — это контекстный формат. Нормальный формат следует использовать если вы уверены, что пользователь будет применять патч командами, не поддерживающими контекстный формат.

Изменение количества контекстных строк

Можно заставить команду diff включать в патч сеньшее количество строк контекста, чем должно быть. В больших патчах это может сильон уменьшить его размер. Однако если уменьшить количество контекстных строк, это может привести в неработоспособности патча. Цитати из справки GNU diff: «Для большинства операций в патче должно быть хотя бы две строки контекста.»

Указать количество контестных строк можно несколькими способами:

  • Если вы хотит использовать контекстный формат, вы можете вы можете совместить эти указания, добавив в опцию «-C». Пример:
    [rechosen@localhost ~]$ diff -C 2 originaldirectory/ updateddirectory/

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

  • Если вы хотит использовать контекстный формат, вы можете вы можете совместить эти указания, добавив в опцию «-U». Пример:

    [rechosen@localhost ~]$ diff -U 2 originaldirectory/ updateddirectory/

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

  • Если не указывать какой формат вы хотите использовать, то команда будет выглядеть примерно так:
    [rechosen@localhost ~]$ diff -2 originaldirectory/ updateddirectory/

    Однако это будет работать только если вы определите формат. Вам необходимо использовать эту опцию или с «-c» или с «u».

Заключительные слова

Несмотря на то, что эта статья описывает множество особенностей работы команд diff и patch, она не может описать все их возможности. Если вы хотите узнать больше об этих командах, вы можете прочитать страницу помощи по этим командам и документацию GNU.