У Node есть набор API -интерфейсов потока данных, которые могут обрабатывать такие файлы, как обработка сетевых потоков, что очень удобно в использовании, но он позволяет обрабатывать файлы только последовательно и не может читать и записывать файлы случайным образом. Поэтому необходимо использовать некоторые базовые операции файловой системы.
В этой главе охватывают основы обработки файлов, включая то, как открыть файл, прочитать часть файла, записать данные и закрыть файл.
Многие из API -файлов Node являются почти репликой соответствующего API файла в UNIX (POSIX). Например, используется способ использования файловых дескрипторов. Как и в UNIX, дескриптор файла также является целочисленным номером в узле, представляющий индекс объекта в таблице дескрипторов процесса.
Есть 3 дескриптора специальных файлов - 1, 2 и 3. Они представляют стандартный ввод, стандартный выходной и стандартный дескриптор файла ошибок, соответственно. Стандартный ввод, как следует из названия, представляет собой потоку только для чтения, который процессы используют для считывания данных из консоли или процесса канала. Стандартный выход и стандартные ошибки - это файловые дескрипторы, используемые только для вывода данных. Они часто используются для вывода данных в консоли, другие процессы или файлы. Стандартные ошибки отвечают за вывод сообщения об ошибке, в то время как стандартный вывод отвечает за обычный вывод процесса.
Как только процесс запускается, эти дескрипторы файлов могут быть использованы, и на самом деле они не имеют соответствующих физических файлов. Вы не можете читать и записывать данные в случайном месте. (Примечание переводчика: исходный текст - это написать и читать и читать из определенных позиций в файле.
Обычные файлы не подлежат этому ограничению. Например, в узле вы можете создавать файлы, которые могут добавлять только данные в хвост, и вы также можете создавать файлы, которые читают и записывают случайные местоположения.
Почти все операции, связанные с файлами, включают обработку путей файлов. Эта глава сначала представит эти функции инструмента, а затем объяснит подробное чтение файлов, написание и операции данных.
Процесс файла
Пути файлов разделены на два типа: относительные пути и абсолютные пути, и они используются для представления конкретных файлов. Вы можете объединить пути файлов, извлечь информацию о имени файла и даже обнаружить, существует ли файл.
В узле вы можете использовать строки для манипулирования путями файла, но это усложнит проблему. Например, вы хотите подключить разные части пути, некоторые части заканчиваются «/», но некоторые нет, а разветвитель пути также может отличаться в разных операционных системах, поэтому при их подключении код будет очень многословенным и неприятным.
К счастью, узел имеет модуль, называемый пути, который может помочь вам стандартизировать, подключить, проанализировать пути, преобразовать из абсолютных путей в относительные пути, извлекать различные части информации из путей и определять, существует ли файл. В целом, модуль Path на самом деле является просто обработкой строки, и он не будет перейти к файловой системе для проверки (path.exists function Exception).
Стандартизация путей
Нормализация их перед хранением или использованием путей, как правило, является хорошей идеей. Например, пути файлов, полученные вводами пользовательского ввода или файлов конфигурации, или пути, подключенные двумя или более путей, обычно должны быть стандартизированы. Путь может быть нормализован с использованием функции нормализации модуля Path, и он также может обрабатывать "..", "." // ". Например:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.normalize ('/foo/bar // baz/asdf/quux/..');
// => '/foo/bar/baz/asdf'
Путь подключения
Используя функцию path.join (), вы можете объединить столько строк пути. Вы можете просто передать все строки пути к функции join () в последовательности:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.join ('/foo', 'bar', 'baz/asdf', 'quux', '..');
// => '/foo/bar/baz/asdf'
Как видите, Path.join () автоматически нормализует путь внутри.
Путь
Используйте path.resolve () для разрешения нескольких путей в абсолютный путь. Его функция похожа на операции «CD» один за другим на этих путях. В отличие от параметров команды CD, эти пути могут быть файлами, и они не должны существовать в реальной жизни - метод path.resolve () не будет получать доступ к базовой файловой системе, чтобы определить, существует ли путь, это всего лишь некоторые строковые операции.
например:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.resolve ('/foo/bar', './baz');
// =>/foo/bar/baz
path.resolve ('/foo/bar', '/tmp/file/');
// =>/tmp/файл
Если результат анализа не является абсолютным путем, path.resolve () добавит текущий рабочий каталог в качестве пути к результату анализа, например:
Кода -копия выглядит следующим образом:
path.resolve ('wwwroot', 'static_files/png/', '../gif/image.gif');
// Если текущий рабочий каталог/home/my/node, он вернется
// => /home/myself/node/wwwroot/static_files/gif/image.gif '
Рассчитайте относительные пути двух абсолютных путей
path.relative () может сказать вам, если вы перепрыгнете с одного абсолютного адреса на другой абсолютный адрес, например:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.relative ('/data/orandea/test/aaa', '/data/orandea/Impl/bbb');
// => ../../Impl/bbb
Извлечь данные из пути
В качестве примера перейдите по пути "/foo/bar/myfile.txt". Если вы хотите получить все содержимое родительского каталога (/foo/bar) или прочитать другие файлы одного и того же каталога, для этого вы должны использовать path.dirname (filePath), чтобы получить часть каталога пути файла, например:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.dirname ('/foo/bar/baz/asdf/quux.txt');
// =>/foo/bar/baz/asdf
Или, если вы хотите получить имя файла из пути файла, то есть последняя часть пути файла, вы можете использовать функцию path.baseName:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.basename ('/foo/bar/baz/asdf/quux.html')
// => quux.html
Путь файла также может содержать расширение файла, обычно часть строки после последней «». символ в имени файла.
path.basename также может принять строку имени расширения в качестве второго параметра, так что возвращаемое имя файла автоматически удаляет расширение и только возвращает имя имени файла:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.basename ('/foo/bar/baz/asdf/quux.html', '.html');
// => Quux
Для этого вы должны сначала узнать расширение файла. Вы можете использовать path.extname (), чтобы получить расширение:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.extname ('/a/b/index.html');
// => '.html'
path.extname ('/a/bc/index');
// => ''
path.extname ('/a/bc/.');
// => ''
path.extname ('/a/bc/d.');
// => '.'
Проверьте, существует ли путь
До сих пор упомянутые выше операции обработки пути не имеют ничего общего с базовой файловой системой, но являются лишь некоторыми строковыми операциями. Однако иногда вам нужно определить, существует ли путь файла. Например, иногда вам нужно определить, существует ли файл или каталог. Если его не существует, вы можете использовать path.exsits ():
Кода -копия выглядит следующим образом:
var path = require ('path');
path.exists ('/etc/passwd', function (существует) {
console.log («существует:», существует);
// => true
});
path.exists ('/dos_not_exist', function (существует) {
console.log («существует:», существует);
// => false
});
Примечание. Начиная с версии Node0.8, существует перемещение от модуля Path в модуль FS и стал FS.Exists. За исключением пространства имен, больше ничего не изменилось:
Кода -копия выглядит следующим образом:
var fs = require ('fs');
fs.exists ('/dos_not_exist', function (существует) {
console.log («существует:», существует);
// => false
});
path.exists () - операция ввода/вывода. Поскольку это асинхронно, требуется функция обратного вызова. Когда операция ввода/вывода возвращается, вызывается функция обратного вызова, и результат передается в него. Вы также можете использовать его синхронную версию path.existssync (), которая имеет ту же функцию, за исключением того, что он не вызывает функцию обратного вызова, но возвращает результат напрямую:
Кода -копия выглядит следующим образом:
var path = require ('path');
path.existssync ('/etc/passwd');
// => true
Введение в модуль FS
Модуль FS содержит все связанные функции для запроса и обработки файла. Используя эти функции, вы можете запросить информацию о файле, читать, записать и закрывать файлы. Импортируйте модуль FS как это:
Кода -копия выглядит следующим образом:
var fs = require ('fs')
Информация о файле запроса
Иногда вам может потребоваться знать информацию о файле, такую как размер файла, дата создания или разрешения. Вы можете использовать функцию fs.stath для запроса мета -информации файла или каталога:
Кода -копия выглядит следующим образом:
var fs = require ('fs');
fs.stat ('/etc/passwd', function (err, stats) {
if (err) {throw err;}
console.log (stats);
});
Этот фрагмент кода будет иметь выход, аналогичный следующему
Кода -копия выглядит следующим образом:
{dev: 234881026,
Ино: 95028917,
Режим: 33188,
nlink: 1,
UID: 0,
GID: 0,
rdev: 0,
Размер: 5086,
Blksize: 4096,
блоки: 0,
Atime: пт, 18 ноября 2011 г. 22:44:47 GMT,
Mtime: Чт, 08 сентября 2011 г. 23:50:04 GMT,
Ctime: Чт, 08 сентября 2011 23:50:04 GMT}
1. Вызов fs.stat () пройдет экземпляр класса Stats в качестве параметра своей функции обратного вызова. Вы можете использовать экземпляр статистики, например, следующее:
2.stats.isfile () - вернуть true, если это стандартный файл, а не каталог, розетка, символическая ссылка или устройство, в противном случае неверно
3. stats.isdiretory () - Если это каталог, вернуть вт, в противном случае неверно
4.stats.isblockdevice () - вернуть true, если это блочное устройство. В большинстве систем UNIX блочное устройство обычно находится в каталоге /dev.
5.stats.ischracterdevice () - вернуть true, если это устройство символов
6.stats.issymbolicklink () - вернуть true, если это ссылка на файл
7.stats.isfifo () - если это FIFO (специальный тип Unix с именем труб) возвращает True
8. stats.issocket () - если это розетка Unix (Todo: Googe It)
Откройте файл
Перед чтением или обработкой файла вы должны сначала использовать функцию FS.Open для открытия файла, а затем предоставленную вами функцию обратного вызова, и получить дескриптор файла. Позже вы можете использовать этот дескриптор файла для чтения и записи открытого файла:
Кода -копия выглядит следующим образом:
var fs = require ('fs');
fs.open ('/path/to/file', 'r', function (err, fd) {
// Получил дескриптор файла FD
});
Первым параметром FS.Open является путь файла, а второй параметр - это некоторые теги, используемые для указания, в каком режиме открывается файл. Эти теги могут быть R, R+, W, W+, A или A+. Ниже приведено объяснение этих тегов (со страницы Fopen of the Unix)
1.R - Откройте файл в режиме только для чтения, начальное местоположение потока данных начинается в файле
2.R+ - Откройте файл в чтении и доступным для записи, и начальное местоположение потока данных начинается в файле
3.W - если файл существует, очистите длину файла на 0, то есть содержимое файла будет потеряно. Если его не существует, попробуйте создать его. Начальное местоположение потока данных начинается в файле
4.W+ - Откройте файл читаемым и доступным для записи. Если файл не существует, попробуйте создать его. Если файл существует, очистите длину файла на 0, то есть содержимое файла будет потеряно. Начальное местоположение потока данных начинается в файле
5.A - Откройте файл только для записи. Если файл не существует, попробуйте создать его. Начальное местоположение потока данных находится в конце файла. Каждая последующая операция записи добавляет данные к обратной стороне файла.
6.a+ - Откройте файл в читаемой и приписываемой манере. Если файл не существует, попробуйте создать его. Начальное местоположение потока данных находится в конце файла. Каждая последующая операция записи будет добавлять данные к обратной стороне файла.
Прочтите файл
После открытия файла вы можете начать читать содержимое файла, но прежде чем начать, вам нужно создать буфер для размещения данных. Этот буферный объект будет передаваться в функцию FS.Read в качестве параметра и будет заполнен данных FS.Read.
Кода -копия выглядит следующим образом:
var fs = require ('fs');
fs.open ('./ my_file.txt', 'r', функция открыта (err, fd) {
if (err) {throw err}
var readbuffer = новый буфер (1024),
bufferoffset = 0,
bufferlength = readbuffer.length,
Fieposition = 100;
fs.read (fd,
readbuffer,
Bufferoffset,
буфера,
FilePosition,
Функция read (err, readbytes) {
if (err) {throw err; }
console.log ('просто читать' + readbytes + 'байты');
if (readbytes> 0) {
console.log (readbuffer.slice (0, readbytes));
}
});
});
Приведенный выше код пытается открыть файл. После успешного открытия (вызов открытой функции) она начинает просить прочитать следующие 1024 байта данных из 100 -го байта потока файла (строка 11).
Последний параметр fs.read () - функция обратного вызова (строка 16). Когда произойдут следующие три ситуации, это будет вызвано:
1. Произошла ошибка
2. Данные были успешно прочитаны
3. Нет данных для чтения
Если возникает ошибка, первый параметр (ERR) предоставит функцию обратного вызова объектом, содержащим сообщение об ошибке, в противном случае этот параметр является нулевым. Если данные успешно прочитаны, второй параметр (readbytes) укажет размер данных, которые читаются в буфере. Если значение равно 0, это означает, что конец файла был достигнут.
ПРИМЕЧАНИЕ. Как только буферный объект передается fs.open (), управление буферным объектом передается в команду чтения. Только когда вызовет функцию обратного вызовов, будет возвращено вам управление буферным объектом. Поэтому до этого не читайте и не пишите и не позволяйте другим вызовам функций использовать этот буферный объект; В противном случае вы можете прочитать неполные данные, и, что еще хуже, вы можете написать данные в этот буферный объект одновременно.
Напишите файл
Пропустите буферный объект, содержащий данные, передавая его в fs.write (), и записать данные в открытый файл:
Кода -копия выглядит следующим образом:
var fs = require ('fs');
fs.open ('./ my_file.txt', 'a', функция открыта (err, fd) {
if (err) {throw err; }
var writebuffer = new Buffer ('написание этой строки'),
BufferPosition = 0,
bufferlength = writebuffer.length, filePosition = null;
fs.write (fd,
writebuffer,
буфера,
буфера,
FilePosition,
Функция write (err, worpion) {
if (err) {throw err; }
console.log ('написал' + написан + 'байты');
});
});
В этом примере вторая строка кода пытается открыть файл в режиме Приложения (A), а затем седьмая строка кода (Примечание переводчика: исходный текст - 9) записывает данные в файл. Буферный объект должен сопровождаться несколькими информацией в качестве параметров:
1. Буферные данные
2. Где записать данные, начинающиеся в буфере
3. Длина данных, которые будут написаны
4. Где написать данные в файл
5. Функция обратного вызова, вызванная после завершения операции, написана
В этом примере параметр filePostion является нулевым, что означает, что функция записи будет записывать данные в текущее местоположение указателя файла. Поскольку это файл, открытый в режиме добавления, указатель файла находится в конце файла.
Как и операции чтения, не используйте, какой входящий буферный объект используется во время выполнения FS.Write. Как только FS.Write начинает выполнять, он получает контроль над этим буферным объектом. Вы можете только подождать, пока функция обратного вызова не будет вызвана до повторного использования.
Закройте файл
Возможно, вы заметили, что до сих пор все примеры в этой главе не имеют кода для закрытия файла. Поскольку они являются просто небольшими и простыми примерами, когда используются только один раз, операционная система гарантирует, что все файлы закрыты, когда процесс узла заканчивается.
Однако в фактическом приложении, как только файл открывается, вы хотите убедиться, что вы в конечном итоге закрыли его. Чтобы сделать это, вам нужно отследить все эти дескрипторы открытых файлов, а затем вызовать fs.close (fd [, обратный вызов]), когда они больше не используются, чтобы в конечном итоге закрыть их. Если вы не обращаете внимания, легко пропустить определенный дескриптор файла. В следующем примере представлена функция, называемая OpenAndWriteTosystemLog, которая показывает, как тщательно закрыть файлы:
Кода -копия выглядит следующим образом:
var fs = require ('fs');
Функция OpenAndWriteTosystemLog (writebuffer, callback) {
fs.open ('./ my_file', 'a', функция открыта (err, fd) {
if (err) {return callback (err); }
функция notifyError (err) {
fs.close (fd, function () {
обратный вызов (ERR);
});
}
var bufferoffset = 0,
bufferlength = writebuffer.length,
FilePosition = NULL;
FS.Write (FD, Writebuffer, Bufferoffset, BufferLength, FilePosition,
Функция write (err, worpion) {
if (err) {return notifyError (err); }
fs.close (fd, function () {
обратный вызов (ERR);
});
}
);
});
}
OpenAndWriteTosystemlog (
новый буфер («Написание этой строки»),
функция выполнено (err) {
if (err) {
console.log («Ошибка при открытии и написании:», err.message);
возвращаться;
}
console.log («все сделано без ошибок»);
}
);
Здесь предоставлена функция, называемая OpenAndWriteTosystemLog, которая принимает буферный объект, содержащий записи данных, и функцию обратного вызова, вызванную после завершения операции или возникает ошибка. Если возникает ошибка, первый параметр функции обратного вызова будет содержать этот объект ошибки.
Обратите внимание, что внутренняя функция NotifyError, которая закрывает файл и сообщает об ошибке.
Примечание. До тех пор вы знаете, как использовать базовые атомные операции для открытия, чтения, записи и закрытия файлов. Тем не менее, Node также имеет более продвинутый набор конструкторов, который позволяет вам более простым обрабатывать файлы.
Например, вы хотите использовать безопасный способ позволить двум или более операциям записи для добавления данных в файл одновременно, и вы можете использовать Writestream.
Кроме того, если вы хотите прочитать определенную область файла, вы можете рассмотреть вопрос о использовании Readstream. Эти два варианта использования будут введены в главе 9 «Чтение и написание потоковой передачи данных».
краткое содержание
Когда вы используете файл, вам необходимо обрабатывать и извлечь информацию о пути файла в большинстве случаев. Используя модуль Path, вы можете подключать пути, стандартизировать пути, рассчитать различия в пути и преобразовать относительные пути в абсолютные пути. Вы можете извлечь компоненты пути, такие как расширения, имена файлов, каталоги и т. Д.
Node предоставляет набор базовых API в модуле FS для доступа к файловой системе, а базовый API использует дескрипторы файлов для манипулирования файлами. Вы можете открыть файл с fs.open, написать файл с помощью fs.write, прочитать файл с fs.read и закрыть файл с помощью fs.close.
Когда возникает ошибка, вам всегда следует использовать правильную логику обработки ошибок, чтобы закрыть файл - чтобы убедиться, что эти дескрипторы открытого файла закрыты до возврата вызова.