Node.js расширенное расширенное изучение файлового модуля fs

Node.js JavaScript
Node.js расширенное расширенное изучение файлового модуля fs

Людям не хватает не таланта, а амбиций, не способности добиться успеха, а желания много работать. —— Белвей

предисловие

Работа с файлами является неотъемлемой частью процесса разработки. Модуль fs в Node.js — это инкапсуляция файловых операций, обеспечивающая операции с файловой системой POSIX, такие как чтение, запись, переименование, удаление, перемещение по каталогам и ссылки. В отличие от других модулей, все операции в модуле fs имеют две версии: асинхронную и синхронную.Методы с суффиксом sync являются синхронными методами, а методы без суффикса sync — асинхронными методами.

Об авторе: koala, сосредоточив внимание на совместном использовании полного стека технологий Node.js, от JavaScript до Node.js, до серверной базы данных, я желаю вам стать отличным старшим инженером Node.js. [Руководство по развитию программиста] Автор, блог Github с открытым исходным кодомGitHub.com/koala-co Nth…

Обзор статьи

  • Немного здравого смысла о системах и файлах на компьютерах

    -- битовый режим разрешения

    -- бит флага

    -- файловый дескриптор fs

  • Подробное объяснение API модуля fs в Node.js и соответствующее Демо

    -- обычные файловые операции

    -- Расширенные манипуляции с файлами

    -- манипулирование каталогом файлов

  • API модуля fs в Node.js соответствует демо

  • Сценарии применения и практическое обучение модуля fs (копии больших и малых файлов)

интервью будет спрашивать

сказать несколькоfsОбщие функции модулей? когда использоватьfs.openспособ прочитать файл? использоватьfsПример модуля, записывающего копию большого файла (остерегайтесь больших файлов)?

Файл Здравый смысл

Некоторые знания о файлах на компьютере, битовый режим разрешения файла, бит флага, файловый дескриптор fd и т. д., которые вам необходимо понять. Это содержимое будет очень полезно для вас, чтобы изучить fs api, память и использование.

битовый режим разрешения

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

Таблица прав доступа к файлам:

В таблице выше мы видим, что система выделяет разрешения для трех типов, а именно владельца файла (я), группы, к которой принадлежит файл (семья), и других пользователей (чужих). права доступа Чтение, запись и выполнение, числа выражаются как восьмеричные числа, а восьмеричные числа с разрешениями соответственно4 ,2,1, не имеет разрешения 0.

Чтобы было легче понять, мы можем открыть его в любом каталогеGit,использоватьLinuxЗаказls -alпроверить биты разрешений файлов и папок в каталоге

drwxr-xr-x 1 koala 197121 0 Jun 28 14:41 core
-rw-r--r-- 1 koala 197121 293 Jun 23 17:44 index.md

В приведенной выше информации о каталоге легко увидеть такую ​​информацию, как имя пользователя, время создания и имя файла, но самое главное — это первый элемент (десять символов).

Первый представляет, является ли это файлом или папкой,dНачало представляет собой папку,-Начало представляет файл, а следующие девять представляют биты разрешений текущего пользователя, группы, к которой принадлежит пользователь, и других пользователей, разделенные на три, представляющие чтение (r), запись (w) и выполнение (x ), соответственно.-Указывает, что нет разрешения, соответствующего текущему биту.

Режим параметра разрешения предназначен в основном для операционных систем Linux и Unix.Разрешения Windows доступны для чтения, записи и неисполняемого по умолчанию, поэтому номер бита разрешения представлен как 0o666, а десятичное представление — 438.

флаг

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

символ значение
r Прочитайте файл и создайте исключение, если файл не существует.
r+ Прочитайте и запишите файл, создав исключение, если файл не существует.
rs Чтение и запись файлов, указание операционной системе обходить кэш локальной файловой системы.
w Запись в файл. Если файл не существует, он будет создан. Если он существует, он будет очищен и записан.
wx Записать в файл, открыть монопольно.
w+ Прочитайте и запишите файл, создайте файл, если он не существует, и запишите его после его очистки, если он существует.
wx+ Как и w+, открывается монопольно.
a Добавить запись, если файл не существует, создать файл.
ax Как , открыть исключительно.
a+ Прочитайте и добавьте запись, создайте, если она не существует.
ax+ Подобно a+ , он открывается монопольно.
В приведенной выше таблице показаны конкретные символы и значения этих флагов, но этот флаг используется нечасто и его нелегко запомнить, поэтому ниже приводится краткое описание метода ускорения памяти.
  • р: читать
  • ж: пиши
  • с: синхронизировать
  • +: увеличить противоположную операцию
  • x: эксклюзивный способ

Разница между r+ и w+, когда файл не существует, r+ не создаст файл, а выдаст исключение, а w+ создаст файл; если файл существует, r+ не будет автоматически очищать файл, а w+ автоматически удалить существующий файл. Содержимое пусто.

файловый дескриптор fs

Операционная система присваивает каждому открытому файлу числовой идентификатор, называемый файловым дескриптором. Файловые операции используют эти файловые дескрипторы для идентификации и отслеживания каждого конкретного файла. Система Windows использует другой, но концептуально похожий механизм для отслеживания. Ресурсы. Для удобства пользователей NodeJS абстрагируется от различий между разными операционными системами и присваивает числовые файловые дескрипторы всем открытым файлам.

В Node.js каждый раз при работе с файлом дескриптор файла увеличивается, и дескриптор файла обычно начинается с 3, потому что перед ними есть три специальных дескриптора 0, 1 и 2, представляющие соответственноprocess.stdin(стандартный ввод),process.stdout(стандартный вывод) иprocess.stderr(вывод ошибки).

файловые операции

Целостность операций чтения и записи файлов

чтение файла - fs.readFile

fs.readFile(filename,[encoding],[callback(error,data)]

функция чтения файлов

  1. Он получает первый обязательный параметр filename, который указывает имя файла для чтения.
  2. Второй параметр encoding является необязательным и представляет собой кодировку символов файла.
  3. третий параметрcallbackИспользуется ли функция обратного вызова для получения содержимого файла.

Описание: Если кодировка не указана, тоcallbackявляется вторым параметром. Функция обратного вызова предоставляет два параметра err и data, err указывает, есть ли ошибка, а data — это содержимое файла. Если указана кодировка, данные представляют собой проанализированную строку, в противном случае двоичные данные будут представлены в виде буфера.

demo:

const fs = require('fs');
const path = require('path');
const filePath = path.join(__dirname,'koalaFile.txt')
const filePath1 = path.join(__dirname,'koalaFile1.txt')
// -- 异步读取文件
fs.readFile(filePath,'utf8',function(err,data){
    console.log(data);// 程序员成长指北
});

// -- 同步读取文件
const fileResult=fs.readFileSync(filePath,'utf8');
console.log(fileResult);// 程序员成长指北

Файл записывается в fs.writeFile

fs.writeFile(filename,data,[options],callback)

операция записи файла

  1. Первый обязательный параметр, имя_файла, указывает имя файла для чтения.
  2. Данные, которые будут записаны во второй параметр
  3. Третий вариант параметра - это объект, как показано ниже.
encoding {String | null} default='utf-8'
mode {Number} default=438(aka 0666 in Octal)
flag {String} default='w'

В это время будут использоваться компьютерные знания, упомянутые в первой главе.Значение флага, которое по умолчанию равно w, очистит файл, а затем запишет его снова. Значение флага, r означает чтение файла, w означает запись файла, а означает добавление.

демо:

// 写入文件内容(如果文件不存在会创建一个文件)
// 写入时会先清空文件
fs.writeFile(filePath, '写入成功:程序员成长指北', function(err) {
    if (err) {
        throw err;
    }
    // 写入成功后读取测试
    var data=fs.readFileSync(filePath, 'utf-8');
    console.log('new data -->'+data);
});

// 通过文件写入并且利用flag也可以实现文件追加
fs.writeFile(filePath, '程序员成长指北追加的数据', {'flag':'a'},function(err) {
	    if (err) {
	        throw err;
	    }
	    console.log('success');
	    var data=fs.readFileSync(filePath, 'utf-8')
	    // 写入成功后读取测试
	    console.log('追加后的数据 -->'+data);
	});

добавить файл - appendFile

fs.appendFile(filename, data, [options], callback)
  1. Первый обязательный параметр, имя_файла, указывает имя файла для чтения.
  2. Второй параметр data, data может быть любой строкой или кешем
  3. Третий вариант параметра — это объект, и отличие от записи в том, что значение по умолчанию флага [параметров] равно «a», поэтому он записывает данные в режиме добавления.

Описание: Этот метод асинхронно вставляет данные в файл.Если файл не существует, он будет создан автоматически.

демо:

// -- 异步另一种文件追加操作(非覆盖方式)
// 写入文件内容(如果文件不存在会创建一个文件)
fs.appendFile(filePath, '新数据程序员成长指北456', function(err) {
    if (err) {
        throw err;
    }
    // 写入成功后读取测试
    var data=fs.readFileSync(filePath, 'utf-8');
    console.log(data);
});
// -- 同步另一种文件追加操作(非覆盖方式)

fs.appendFileSync(filePath, '同步追加一条新数据程序员成长指北789');

копировать файл - копировать файл

fs.copyFile(filenameA, filenameB,callback)
  1. Первый параметр - исходное имя файла
  2. Второй параметр - это имя файла для копирования.

демо:

// 将filePath文件内容拷贝到filePath1文件内容
fs.copyFileSync(filePath, filePath1);
let data = fs.readFileSync(filePath1, 'utf8');

console.log(data); // 程序员成长指北

удалить файл -отвязать

fs.unlink(filename, callback)
  1. Путь к первому файлу параметров должен знать каждый, и я не буду его повторять дальше.
  2. Второй обратный вызов функции обратного вызова

demo:

// -- 异步文件删除
fs.unlink(filePath,function(err){
	if(err) return;
});
// -- 同步删除文件
fs.unlinkSync(filePath,function(err){
    if(err) return;
});

Чтение и запись операций с файлами в указанном месте (расширенные операции с файлами)

Следующие расширенные операции с файлами будут немного отличаться от описанных выше, и процесс будет немного сложнее.fs.openчтобы открыть файл, а затем вы можете использоватьfs.readчитать или использоватьfs.writeдля записи файла, и, наконец, вам нужно использоватьfs.closeчтобы закрыть файл.

Особое примечание: метод чтения отличается от метода readFile.Как правило, файл слишком велик для чтения всего содержимого в кэш за один раз или размер файла неизвестен, и он считывается в буфер несколько раз. Если вы хотите понять Buffer, вы можете прочитать NodeJS — Buffer Interpretation. (обратите внимание, что это заменено моей статьей)

открыть файл - fs.open

fs.open(path,flags,[mode],callback)

Первый параметр: путь к файлу Второй параметр: такой же, как флаг идентификатора, упомянутый в начале. Третий параметр: [mode] — разрешение файла (необязательный параметр, значение по умолчанию — 0666) Четвертый параметр: функция обратного вызова обратного вызова

demo:

fs.open(filePath,'r','0666',function(err,fd){
   console.log('哈哈哈',fd); //返回的第二个参数为一个整数,表示打开文件返回的文件描述符,window中又称文件句柄
})

демонстрационное описание: Второй возвращаемый параметр — это целое число, представляющее файловый дескриптор, возвращаемый при открытии файла, который также называется дескриптором файла в окне.文件描述符инструкция.

чтение файла - fs.read

fs.read(fd, buffer, offset, length, position, callback);

шесть параметров

  1. fd: файловый дескриптор, сначала нужно открыть с помощью open, используйтеfs.openДескриптор файла возвращается после успешного открытия;
  2. буфер: объект буфера,v8Раздел памяти, выделенный движком, Буфер, в который должно быть прочитано содержимое;
  3. смещение: целое число, начальная позиция для записи в буфер буфера, в байтах;
  4. length: целое число, длина прочитанного файла;
  5. position: целое число, начальная позиция читаемого файла, размер файла в байтах
  6. callback: функция обратного вызова, имеет три параметра err (ошибка), bytesRead (число фактически прочитанных байтов), buffer (объект буфера, который нужно записать) и выполняется после завершения выполнения чтения.

демо:

const fs = require('fs');
let buf = Buffer.alloc(6);// 创建6字节长度的buf缓存对象

// 打开文件
fs.open('6.txt', 'r', (err, fd) => {
  // 读取文件
  fs.read(fd, buf, 0, 3, 0, (err, bytesRead, buffer) => {
    console.log(bytesRead);
    console.log(buffer);

    // 继续读取
    fs.read(fd, buf, 3, 3, 3, (err, bytesRead, buffer) => {
      console.log(bytesRead);
      console.log(buffer);
      console.log(buffer.toString());
    });
  });
});

// 3
// <Buffer e4 bd a0 00 00 00>

// 3
// <Buffer e4 bd a0 e5 a5 bd>
// 你好

запись в файл -fs.write

fs.write(fd, buffer, offset, length, position, callback);

шесть параметров

  1. fd: файловый дескриптор, использоватьfs.openВозврат после успешного открытия;
  2. буфер: объект буфера,v8Раздел памяти, выделенный движком для хранения Буфера для записи в файл данных;
  3. offset: целое число, начальная позиция чтения данных из буфера Buffer, в байтах;
  4. длина: целое число, количество байтов для чтения данных буфера;
  5. position: целое число, начальная позиция файла записи;
  6. обратный вызов: функция обратного вызова после завершения операции записи, есть три параметра err (ошибка), bytesWritten (количество фактически записанных байтов), буфер (объект буфера для чтения) и выполняется после завершения записи.

демо:

закрыть файл -fs.close

fs.close(fd,callback)
  1. Первый параметр: файл fdopenпередается, когда文件描述符
  2. Второй параметр обратного вызова — это функция обратного вызова, функция обратного вызова имеет параметр err (ошибка), который выполняется после закрытия файла.

demo:

// 注意文件描述符fd
fs.open(filePath, 'r', (err, fd) => {
  fs.close(fd, err => {
    console.log('关闭成功');// 关闭成功
  });
});

Операции с каталогами (папками)

1. fs.mkdir создает каталог

fs.mkdir(path, [options], callback)
  1. Первый параметр: путь к каталогу
  2. Второй параметр [options], рекурсивный. Значение по умолчанию: false.

режим Не поддерживается в Windows. По умолчанию: 0o777. Необязательный параметр options может быть целым числом, указывающим режим (разрешения и фиксированные биты), или объектом со свойством режима и рекурсивным свойством (указывающим, следует ли создавать родительскую папку). 3. Третий параметр — функция обратного вызова.У функции обратного вызова есть параметр err (ошибка), который выполняется после закрытия файла.

demo:

fs.mkdir('./mkdir',function(err){
  if(err) return;
  console.log('创建目录成功');
})

Уведомление: В Windows использование fs.mkdir() в корневом каталоге (даже с рекурсивными аргументами) приводит к ошибке:

fs.mkdir('/', { recursive: true }, (err) => {
  // => [Error: EPERM: operation not permitted, mkdir 'C:\']
});

2. fs.rmdir удалить каталог

fs.rmdir(path,callback)
  1. Первый параметр: путь к каталогу
  2. Третий параметр функции обратного вызова, функция обратного вызова имеет параметр err (ошибка), который выполняется после закрытия файла.

demo:

const fs = require('fs');
fs.rmdir('./mkdir',function(err){
  if(err) return;
  console.log('删除目录成功');
})

Примечание. Использование fs.rmdir() в файле (не в каталоге) приведет к ошибке ENOENT в Windows и ошибке ENOTDIR в POSIX.

3. fs.readdir читает каталог

fs.readdir(path, [options], callback)
  1. Первый параметр: путь к каталогу
  2. Второй параметр [опции] Необязательный параметр опций может быть строкой, указывающей кодировку, или объектом со свойством кодирования, указывающим кодировку символов, используемую для имени файла, переданного в функцию обратного вызова. Если для кодировки задано значение 'buffer', возвращаемое имя файла является объектом Buffer.

Если для параметра options.withFileTypes установлено значение true, массив файлов будет содержать объекты fs.Dirent. 3. Третий параметр функции обратного вызова, функция обратного вызова имеет два параметра, первый err (ошибка), второй возвращаемые данные представляет собой массив, включая все файлы в папке, представляет собой массив имен файлов в каталоге (исключая'.'и'..').

demo:

const fs = require('fs');
fs.readdir('./file',function(err,data){
  if(err) return;
  //data为一个数组
  console.log('读取的数据为:'+data[0]);
});

Практическая подготовка:

Скучно говорить только об API, связанных с файлами, давайте поговорим о некоторых конкретных приложениях fs в Node.js.

«Пример: как модуль fs реализует копирование файлов»

Примеры копирования файлов включают копирование небольших файлов и копирование больших файлов (упомянутый ранее модуль fs также может выполнять копирование файлов).

небольшая копия файла

Небольшая копия файла В дополнение к API, предоставленному самой fs, мы также можем завершить пример копирования, читая и записывая, как показано ниже:

// 文件拷贝 将data.txt文件中的内容拷贝到copyData.txt
// 读取文件
const fileName1 = path.resolve(__dirname, 'data.txt')
fs.readFile(fileName1, function (err, data) {
    if (err) {
        // 出错
        console.log(err.message)
        return
    }
    // 得到文件内容
    var dataStr = data.toString()

    // 写入文件
    const fileName2 = path.resolve(__dirname, 'copyData.txt')
    fs.writeFile(fileName2, dataStr, function (err) {
        if (err) {
            // 出错
            console.log(err.message)
            return
        }
        console.log('拷贝成功')
    })
})

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

копия большого файла

Если нереально читать и записывать большой файл в несколько сотен мегабайт за раз, необходимо читать и записывать несколько раз.Далее использовать расширенный метод работы с файлами для реализации функции копирования для больших файлов и неизвестных размеров файлов. Конечно, помимо этого метода можно реализовать и модуль stream, о котором я говорил в предыдущей статье, и производительность будет лучше, но я не буду здесь повторять описание, в этой статье в основном речь пойдет о модуле fs.

demo:

// copy 方法
function copy(src, dest, size = 16 * 1024, callback) {
  // 打开源文件
  fs.open(src, 'r', (err, readFd) => {
    // 打开目标文件
    fs.open(dest, 'w', (err, writeFd) => {
      let buf = Buffer.alloc(size);
      let readed = 0; // 下次读取文件的位置
      let writed = 0; // 下次写入文件的位置

      (function next() {
        // 读取
        fs.read(readFd, buf, 0, size, readed, (err, bytesRead) => {
          readed += bytesRead;

          // 如果都不到内容关闭文件
          if (!bytesRead) fs.close(readFd, err => console.log('关闭源文件'));

          // 写入
          fs.write(writeFd, buf, 0, bytesRead, writed, (err, bytesWritten) => {
            // 如果没有内容了同步缓存,并关闭文件后执行回调
            if (!bytesWritten) {
              fs.fsync(writeFd, err => {
                fs.close(writeFd, err => return !err && callback());
              });
            }
            writed += bytesWritten;

            // 继续读取、写入
            next();
          });
        });
      })();
    });
  });
}

В приведенном выше методе копирования мы вручную поддерживаем следующую позицию чтения и следующую позицию записи.Если позиции считанных и записанных параметров переданы в null, NodeJS автоматически сохранит эти два значения для нас.

Теперь есть файл 6.txt с содержимым "Hello" и пустой файл 7.txt, запишем содержимое 6.txt в 7.txt.

const fs = require('fs');

// buffer 的长度
const BUFFER_SIZE = 3;

// 拷贝文件内容并写入
copy('6.txt', '7.txt', BUFFER_SIZE, () => {
  fs.readFile('7.txt', 'utf8', (err, data) => {
    // 拷贝完读取 7.txt 的内容
    console.log(data); // 你好
  });
});

При выполнении файловых операций в NodeJS при многократном чтении и записи размер считываемых за один раз данных обычно составляет 64 КБ, а размер записываемых данных — 16 КБ.

Привет всем, я коала, я работаю над продвинутым и продвинутым маршрутом Node.js, и сегодня я поделюсь так многим. ", или присоединяйтесь к группе технического обмена, давайте обсудим вместе.

Присоединяйтесь к нам, чтобы учиться вместе!группа обмена обучением узлов

Если группа обмена заполнена 100 людьми, она не может автоматически присоединиться к группе.Пожалуйста, добавьте учетную запись WeChat помощника группы: узел [coder_qi] Note, и он автоматически втянет вас в группу.