Что такое бинарный редактор?

Бинарный редактор — это инструмент, который позволяет редактировать файлы непосредственно в шестнадцатеричном или ASCII-представлении. В то время как обычные текстовые редакторы работают со «строками», бинарный редактор получает доступ к «сырым последовательностям байтов» файла и может изменять любой бит или байт напрямую.

В анализе ПО, восстановлении данных и исследовании протоколов без него не обойтись. Среди настольных GUI-приложений популярны HxD и Binary Ninja. Но моя цель заключалась в том, чтобы создать «один-единственный файл бинарного редактора, который работает исключительно в браузере».


Подход к реализации

  • Полностью на стороне клиента (никаких внешних передач данных)
  • Чтение локальных файлов через FileReader API
  • Слева отображается шестнадцатеричное представление (Hex), справа — ASCII
  • Клик переводит ячейку в режим редактирования и позволяет менять значение напрямую
  • Изменённые ячейки подсвечиваются красным цветом
  • Можно переключаться между режимами редактирования HEX и ASCII
  • Результат редактирования снова сохраняется в файл для загрузки

Проблемы и их решение

1. Смещённая рамка редактирования

В первой версии, когда вокруг целевой ячейки появлялась жёлтая рамка, она немного смещалась от центра и выглядела странно. Причиной стали эффекты CSS-свойств line-height и компоновки flex: базовые точки символа и рамки не совпадали. Хотя я рассчитывал на моноширинный шрифт, браузеры могут по-разному выстраивать базовую линию, и итогом становится визуальный сдвиг вверх или вниз.

Проблема решилась, когда я принудительно задал vertical-align: middle и сделал элемент display: inline-block, чтобы выровнять высоту.

.hex-cell.editing {
  outline: 2px solid yellow;
  vertical-align: middle;
}

2. Нажатие ESC приводило к вводу символов

В ранней реализации, если при активной рамке нажать ESC, в ячейке появлялись строки вроде «EE».

Происходило это потому, что обработчик keydown не перехватывал событие, и браузер передавал код клавиши прямо в логику ввода ячейки. Обычный ввод рассчитан только на 0–9 и A–F, но у Escape тоже есть код (раньше keyCode=27, сейчас стандарт говорит key="Escape"), поэтому он попадал в обработчик и трактовался как "E".

Решение простое: перехватить Escape в keydown и заменить ввод на отмену редактирования.

document.addEventListener("keydown", e => {
  if (e.key === "Escape") {
    cancelEdit();
    e.preventDefault(); // блокируем исходный путь ввода
  }
});

Теперь ESC служит только для отмены редактирования и не оставляет символов в ячейке.

3. Красная подсветка сохранялась при повторной загрузке

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

Причина в том, что массив или состояние, отслеживающее изменённые ячейки, не обнулялось при чтении нового файла. Даже если область вывода очищалась, внутренний «флаг изменений» оставался, и новый файл унаследовал красную подсветку.

Я добавил вызов clearModifiedState() сразу после чтения файла, чтобы полностью сбрасывать флаги.

4. Переключение между режимами HEX и ASCII

Изначально редактирование HEX и ASCII было доступно одновременно, и понять, какое значение «правильное», было сложно. Один и тот же байт обрабатывался двумя формами ввода, из-за чего возникала конкуренция за запись в ячейку по разным путям. ASCII мгновенно переписывал HEX, но в процессе ввода на экране возникала кратковременная несогласованность.

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


Фрагмент кода

Основная логика редактирования выглядит так.

function applyEdit(offset, newValue) {
  if (mode === "hex") {
    buffer[offset] = parseInt(newValue, 16);
  } else {
    buffer[offset] = newValue.charCodeAt(0);
  }
  markModified(offset);
  render();
}

markModified(offset) отвечает за красную подсветку: если значение отличается от исходного, добавляется соответствующий класс. Реализация предельно простая.


Итоги

Браузерный бинарный редактор работает офлайн и, будучи «полностью клиентским инструментом», удовлетворяет требованиям безопасности.

  • Когда нужно быстро поправить небольшие участки бинарных данных
  • Для исследований в среде, где нельзя установить специальное приложение
  • В учебных целях, чтобы наглядно объяснить «последовательность байтов»

Во всех этих сценариях инструмент оказывается полезен.