Тест: Мастерство ввода‑вывода NodeJS
Проверьте свои знания о файлах, потоках и буферах
Готовы погрузиться в мир NodeJS I/O? 🌊
Этот тест проверит, насколько вы понимаете операции ввода‑вывода Node, от базовых действий с файловой системой до продвинутых концепций потоков. Мы разберём буферы, кодировки и лучшие практики эффективной обработки данных.
Посмотрим, насколько вы знакомы со своими потоками и буферами! 🚀
Что делает этот код?
const buf = Buffer.alloc(5);console.log(buf);Buffer.alloc(size) создаёт новый Buffer указанного размера, заполненный нулями.
Вывод будет: <Buffer 00 00 00 00 00>
Buffer.allocUnsafe(5) пропускает заполнение нулями: байты могут содержать прежнее содержимое памяти. Это не генератор случайных чисел. Инициализируйте каждый байт перед чтением или передачей наружу; для случайных байтов используйте crypto.randomBytes(5).
Что будет выведено?
const buf = Buffer.from([65]);console.log(buf.toString());Числа в массиве представляют ASCII‑коды:
- 65: ‘A’
toString() преобразует эти байты в их строковое представление, используя кодировку UTF-8 по умолчанию.
Какой порядок вывода?
import fs from 'fs';fs.readFile('test.txt', 'utf8', (err, data) => { console.log(data);});console.log('Done');Поскольку readFile асинхронен, код продолжает выполняться, пока файл читается.
Поэтому “Done” будет выведено до содержимого файла.
Чтобы дождаться чтения файла, можно использовать версию на основе Promise:
import { promises as fs } from 'fs';
async function read() { const data = await fs.readFile('test.txt', 'utf8'); console.log(data); console.log('Done');}Что возвращает fs.readFileSync() по умолчанию?
import fs from 'fs';const content = fs.readFileSync('test.txt');fs.readFileSync() возвращает Buffer по умолчанию, если не указана кодировка. Если нужна строка, нужно либо:
- Указать кодировку:
fs.readFileSync('test.txt', 'utf8') - Преобразовать Buffer:
content.toString()
Какой набор событий обычно используется с Readable‑потоками?
Readable потоки генерируют несколько важных событий:
- ‘data’: Когда данные доступны для чтения
- ‘end’: Когда больше нет данных для чтения
- ‘error’: Когда происходит ошибка
- ‘close’: Когда поток и подлежащий ресурс закрыты
const readable = fs.createReadStream('file.txt');readable.on('data', chunk => console.log(chunk));readable.on('end', () => console.log('Done!'));Что делает опция recursive?
import fs from 'fs';fs.mkdirSync('./a/b/c', { recursive: true });recursive: true опция создаёт родительские каталоги, если их нет.
Без этой опции попытка создать ’./a/b/c’ вызовет ошибку, если ’./a’ или ’./a/b’ не существуют.
Это аналогично shell‑команде mkdir -p.
Что будет выведено?
import { Transform } from 'stream';const upperCase = new Transform({ transform(chunk, encoding, callback) { callback(null, chunk.toString().toUpperCase()); }});process.stdin .pipe(upperCase) .pipe(process.stdout);// Input: "hello world"Трансформирующие потоки изменяют данные по мере их прохождения. Здесь каждый кусок данных:
- Преобразуется в строку
- Переводится в верхний регистр
- Передаётся в stdout
Это создаёт конвейер, который переводит весь ввод в верхний регистр.
Сколько раз fs.watch() гарантировано сработает при изменении файла?
import fs from 'fs';fs.watch('test.txt', (eventType, filename) => { console.log(`${filename} was changed`);});// Then modify test.txt oncefs.watch() не гарантирует срабатывание ровно один раз за логическое изменение файла. Часто он срабатывает несколько раз, потому что многие текстовые редакторы:
- Сохраняют в временный файл
- Переименовывают его в целевой файл
Для более надёжного отслеживания рассмотрите:
- Пакет
chokidar - Дебаунсинг колбэка
- Использование
fs.watchFile()(хотя он менее эффективен)
Какова основная цель обратного давления в потоках?
Обратное давление — это механизм, который предотвращает переполнение памяти, приостанавливая чтение, когда запись не успевает.
Пример ручного обратного давления:
readable.on('data', (chunk) => { const canContinue = writable.write(chunk); if (!canContinue) { readable.pause(); writable.once('drain', () => readable.resume()); }});pipe() обрабатывает это автоматически!
Что делает этот код?
import fs from 'fs';fs.symlinkSync('target.txt', 'link.txt');symlinkSync создаёт символическую ссылку (как ярлык) на целевой файл.
Ключевые отличия от жёстких ссылок:
- Может ссылаться на каталоги
- Может пересекать файловые системы
- Прерывается, если цель удалена
Чтобы вместо этого создать жёсткую ссылку:
fs.linkSync('target.txt', 'hardlink.txt');В каких режимах могут работать потоки Node.js?
Потоки могут работать в:
- Двоичный режим (по умолчанию): для буферов и строк
- Объектный режим: для любого значения JavaScript, кроме
null, которое обозначает конец читаемого потока
Пример объектного режима:
import { Transform } from 'stream';const objectStream = new Transform({ objectMode: true, transform(chunk, encoding, callback) { callback(null, { value: chunk }); }});Надеюсь, вам понравилось проверять свои знания по NodeJS IO! Хотите продолжить? Загляните в мою Коллекцию викторин для новых задач!
