Запись файлов в Node.js


1646

Я пытался найти способ записи в файл при использовании Node.js, но безуспешно. Как я могу это сделать?

Ответы:


2466

Есть много деталей в API файловой системы . Наиболее распространенный способ:

const fs = require('fs');

fs.writeFile("/tmp/test", "Hey there!", function(err) {
    if(err) {
        return console.log(err);
    }
    console.log("The file was saved!");
}); 

// Or
fs.writeFileSync('/tmp/test-sync', 'Hey there!');

26
Я протестировал этот скрипт с помощью Node и попытался изменить путь к файлу на «/ home /», но у меня появилась следующая ошибка: { [Error: EACCES, open '/home/test.txt'] errno: 3, code: 'EACCES', path: '/home/test.txt' } Как я могу изменить этот скрипт, чтобы он работал вне /tmp?
— Андерсон Грин,

130
Также обратите внимание, что вы можете использовать fs.writeFileSync (...), чтобы выполнить то же самое синхронно.
— Дэвид Эрвин

7
Может быть, он немного староват, но @AndersonGreen, вам нужно правильно запустить узел как root или chmod / home, чтобы предоставить права R / W текущему владельцу процесса узла (ваше имя пользователя жесткое), чтобы вы могли написать файл
— Denys Vitali

39
На самом деле, @DenysVitali, проблема в том, что Джейн не должна быть в состоянии записать какие-либо файлы в /home/.... Обычно этот каталог - 755 root: wheel (или любой другой). Если узел хочет записать файл как jane, его будет проще записать /home/jane/test.txt. Переход /homeна что-то более разрешительное, чем 755, является огромной ошибкой.
— Джейн Арк

7
@JaneAvriette Ну, так как он хотел сохранить файл в /homeкаталоге, я предложил chmod его. Я знаю, что это может создать проблему безопасности. Но хорошо, если пользователь хочет сохранить там, это решение. PS: Я согласен с тем, что вы сказали (:
— Денис Виталий

537

В настоящее время существует три способа записи файла:

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

    Вам нужно дождаться обратного вызова, чтобы убедиться, что буфер записан на диск. Это не буферизовано.

  2. fs.writeFile(filename, data, [encoding], callback)

    Все данные должны храниться одновременно; Вы не можете выполнять последовательные записи.

  3. fs.createWriteStream(path, [options])

    Создает WriteStream, что удобно, потому что вам не нужно ждать обратного вызова. Но опять же, это не буферизовано.

А WriteStream, как следует из названия, это поток. Поток по определению - это «буфер», содержащий данные, которые перемещаются в одном направлении (источник ► назначение). Но записываемый поток не обязательно «буферизуется». Поток «буферизуется», когда вы записываете nвремя, и время от времени n+1поток отправляет буфер ядру (потому что он заполнен и его необходимо очистить).

Другими словами: «Буфер» - это объект. Является ли он буферизованным или нет, является свойством этого объекта.

Если вы посмотрите на код, он WriteStreamнаследуется от Streamобъекта, доступного для записи . Если вы обратите внимание, вы увидите, как они сбрасывают контент; у них нет никакой системы буферизации.

Если вы пишете строку, она преобразуется в буфер, а затем отправляется на собственный слой и записывается на диск. При написании строк они не заполняют какой-либо буфер. Итак, если вы делаете:

write("a")
write("b")
write("c")

Ты делаешь:

fs.write(new Buffer("a"))
fs.write(new Buffer("b"))
fs.write(new Buffer("c"))

Это три вызова на уровне ввода / вывода. Хотя вы используете «буферы», данные не буферизируются. Буферизованный поток будет выполнять: fs.write(new Buffer ("abc"))один вызов уровня ввода / вывода.

На данный момент в Node.js v0.12 (стабильная версия объявлена ​​06/06/2015) теперь поддерживаются две функции: cork()и uncork(). Кажется, что эти функции, наконец, позволят вам буферизовать / сбрасывать вызовы записи.

Например, в Java есть некоторые классы, которые предоставляют буферизованные потоки ( BufferedOutputStream, BufferedWriter...). Если вы записываете три байта, эти байты будут храниться в буфере (памяти) вместо того, чтобы выполнять вызов ввода-вывода только для трех байтов. Когда буфер заполнен, содержимое сбрасывается и сохраняется на диск. Это улучшает производительность.

Я ничего не открываю, просто вспоминаю, как должен осуществляться доступ к диску.


5
+1 - приятное объяснение. Для записи потока важно внимательно прочитать документы. Если возвращает ложь или закрытие, важно вызвать writer.once («сток», функция () {}) или я пропустил строки, которые не были удалены после завершения процесса.
— bryanmac

4
есть ли шанс, что вы могли бы привести пример того, как использовать cork()и uncork()для тех из нас, кто хочет попробовать предварительный выпуск 0.11?
— Professormeowingtons

На данный момент Node v0.12 является стабильным.
— августа

Согласно анализу кода из GitHub, fs.writeFile представляется наиболее популярной из упомянутых вами функций. Вот реальные примеры мира для использования fs.writeFile
— drorw

Существуют ли библиотеки качества продукции для npmреализации буферизованной записи?
— nponeccop

266

Конечно, вы можете сделать его немного более продвинутым. Неблокирование, запись фрагментов, не запись всего файла сразу:

var fs = require('fs');
var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
  stream.write("My first row\n");
  stream.write("My second row\n");
  stream.end();
});

17
Какая переменная 'fd' передается в обратный вызов для stream.once?
— Скотт Теслер

1
Дескриптор файла @ScottDavidTesler, чтобы вы могли закрыть поток после того, как с ним покончено.
— Алексей Каменский

3
Когда я закрываю поток? Почему это неблокирование? Просто любопытно, я пытаюсь записать в файл журнала.
— MetaGuru

1
Я не уверен, если когда поток сбрасывается. Я предполагаю, что есть возможность очистить поток по требованию.
— Фредрик Андерссон

1
@JoLiss Тебе придется подождать.
— Фредрик Андерссон

61

Синхронная запись

fs.writeFileSync (файл, данные [, параметры])

fs = require('fs');

fs.writeFileSync("synchronous.txt", "synchronous write!")

Асинхронная запись

fs.writeFile (файл, данные [, параметры], обратный вызов)

fs = require('fs');

fs.writeFile('asynchronous.txt', 'asynchronous write!', (err) => {
  if (err) throw err;
  console.log('The file has been saved!');
});

куда

file <string> | <Buffer> | <URL> | <integer> filename or file descriptor
data <string> | <Buffer> | <Uint8Array>
options <Object> | <string>
callback <Function>

Стоит прочитать в OFFICAL File System (фс) DOCS .


53
var path = 'public/uploads/file.txt',
buffer = new Buffer("some content\n");

fs.open(path, 'w', function(err, fd) {
    if (err) {
        throw 'error opening file: ' + err;
    }

    fs.write(fd, buffer, 0, buffer.length, null, function(err) {
        if (err) throw 'error writing file: ' + err;
        fs.close(fd, function() {
            console.log('file written');
        })
    });
});

2
это демонстрирует, как написать файл, используя операции fs более низкого уровня. Например, вы можете гарантировать, что файл завершит запись на диск и выпустит дескрипторы файлов.
— Шон Гловер

Поскольку в этом примере смещение, если оно установлено на «0» (= третий параметр fs.write()), этот пример работает, только если все достаточно коротко, чтобы быть записанным в одном вызове записи.
— Манфред

31

Мне понравился индекс ./articles/file-system .

Это сработало для меня.

Смотрите также Как мне записать файлы в node.js? ,

fs = require('fs');
fs.writeFile('helloworld.txt', 'Hello World!', function (err) {
    if (err) 
        return console.log(err);
    console.log('Wrote Hello World in file helloworld.txt, just check it');
});

Содержимое helloworld.txt:

Hello World!

Обновление:
Как и в случае с Linux-узлом, запись в текущую директорию кажется, что в некоторых других нет, поэтому я добавляю этот комментарий на всякий случай:
используя его, ROOT_APP_PATH = fs.realpathSync('.'); console.log(ROOT_APP_PATH);чтобы получить место, где записан файл.


Где найти файл helloworld.txt? Я не могу найти его ни в одной папке ... спасибо.
— Кай Фенг Чу

в папке, в которой вы запускаете скрипт
— Sérgio

Это странно ... Я просто не могу найти это нигде. Это будет скрыто? Еще раз спасибо ~
— Кай Фенг Чу

6
Я только что нашел это. Используя это ROOT_APP_PATH = fs.realpathSync ('.'); console.log ( ROOT_APP_PATH ); чтобы получить мой, где файл написан. Спасибо.
— Кай Фенг Чу

@ Сержио: нам нужно закрыть writefile? Я вызываю другой процесс, и я получаю сообщение об ошибке, что файл начинает использоваться другим процессом.
— Амир

24

Ответы предоставлены, и новый способ сделать это:

const fsPromises = require('fs').promises
await fsPromises.writeFile('/path/to/file.txt', 'data to write')

см документы здесь для получения дополнительной информации


1
(node:23759) ExperimentalWarning: The fs.promises API is experimental
— jgraup

@jgraup: вы используете последнюю версию узла?
— TrevTheDev

Узелv10.15.0
— jgraup

7
Включающая функция должна быть асинхронной, иначе она не будет работать.
— Зимано

1
@wintercounter Это очень мило!
— Зимано

20

Я знаю, что заданный вопрос о «записи», но в более общем смысле «добавление» может быть полезен в некоторых случаях, поскольку его легко использовать в цикле для добавления текста в файл (независимо от того, существует файл или нет). Используйте «\ n», если вы хотите добавить строки, например:

var fs = require('fs');
for (var i=0; i<10; i++){
    fs.appendFileSync("junk.csv", "Line:"+i+"\n");
}

Поскольку он теперь доступен, я бы рекомендовал использовать constвместо var, то есть const fs = require('fs');, чтобы избежать нежелательных побочных эффектов, особенно если вы работаете с несколько большей кодовой базой.
— Манфред

11

Хорошо, это довольно просто , как Node имеет встроенные функциональные возможности для этого, это называется , fsкоторый стоит на файловой системе и в основном, NodeJS File System модуль ...

Итак, сначала запишите это в вашем файле server.js следующим образом:

var fs = require('fs');

fsимеет несколько методов для записи в файл, но я предпочитаю использовать способ appendFile, который добавит материал в файл, и если файл не существует, создаст его, код может быть таким, как показано ниже:

fs.appendFile('myFile.txt', 'Hi Ali!', function (err) {
  if (err) throw err;
  console.log('Thanks, It\'s saved to the file!');
});

3
одиночная кавычка в строке должна быть экранирована.
— Укротитель

9
 var fs = require('fs');
 fs.writeFile(path + "\\message.txt", "Hello", function(err){
 if (err) throw err;
  console.log("success");
}); 

Например: прочитать файл и записать в другой файл:

  var fs = require('fs');
    var path = process.cwd();
    fs.readFile(path+"\\from.txt",function(err,data)
                {
                    if(err)
                        console.log(err)
                    else
                        {
                            fs.writeFile(path+"\\to.text",function(erro){
                                if(erro)
                                    console.log("error : "+erro);
                                else
                                    console.log("success");
                            });
                        }
                });

Где вы записываете данные в "to.text" ??
— Рави Шанкер Редди

О чем этот ответ добавляет к множеству уже существующих ответов writeFile?
— Дан Даскалеску

9

Вы можете записать в файл, используя модуль fs (файловая система).

Вот пример того, как вы можете это сделать:

const fs = require('fs');

const writeToFile = (fileName, callback) => {
  fs.open(fileName, 'wx', (error, fileDescriptor) => {
    if (!error && fileDescriptor) {
      // Do something with the file here ...
      fs.writeFile(fileDescriptor, newData, (error) => {
        if (!error) {
          fs.close(fileDescriptor, (error) => {
            if (!error) {
              callback(false);
            } else {
              callback('Error closing the file');
            }
          });
        } else {
          callback('Error writing to new file');
        }
      });
    } else {
      callback('Could not create new file, it may already exists');
    }
  });
};

Возможно, вы также захотите избавиться от этой структуры кода callback-inside-callback с помощью Promises и async/ awaitоператоров. Это сделает асинхронную структуру кода намного более плоской. Для этого может быть использована удобная функция util.promisify (original) . Это позволяет нам переключаться с обратных вызовов на обещания. Взгляните на пример с fsфункциями ниже:

// Dependencies.
const util = require('util');
const fs = require('fs');

// Promisify "error-back" functions.
const fsOpen = util.promisify(fs.open);
const fsWrite = util.promisify(fs.writeFile);
const fsClose = util.promisify(fs.close);

// Now we may create 'async' function with 'await's.
async function doSomethingWithFile(fileName) {
  const fileDescriptor = await fsOpen(fileName, 'wx');

  // Do something with the file here...

  await fsWrite(fileDescriptor, newData);
  await fsClose(fileDescriptor);
}

1
Почему эти фрагменты, а не фрагменты кода? Они никогда не смогут работать в браузере в любом случае.
— Зимано

@Zimano Насколько я понимаю, вопрос касался nodejs, поэтому нет необходимости запускать его в браузере.
— Манфред

1
@ Манфред Точно! Я думаю, вы не поняли, что я пытался сказать; нет смысла иметь фрагменты, так как это nodejs!
— Зимано

5

Здесь мы используем w + для чтения / записи обоих действий, и если путь к файлу не найден, он будет создан автоматически.

fs.open(path, 'w+', function(err, data) {
    if (err) {
        console.log("ERROR !! " + err);
    } else {
        fs.write(data, 'content', 0, 'content length', null, function(err) {
            if (err)
                console.log("ERROR !! " + err);
            fs.close(data, function() {
                console.log('written success');
            })
        });
    }
});

Контент означает, что вы должны записать в файл и его длину, «content.length».


3

Вот пример того, как прочитать файл CSV из локального и записать файл CSV в локальный.

var csvjson = require('csvjson'),
    fs = require('fs'),
    mongodb = require('mongodb'),
    MongoClient = mongodb.MongoClient,
    mongoDSN = 'mongodb://localhost:27017/test',
    collection;

function uploadcsvModule(){
    var data = fs.readFileSync( '/home/limitless/Downloads/orders_sample.csv', { encoding : 'utf8'});
    var importOptions = {
        delimiter : ',', // optional 
        quote     : '"' // optional 
    },ExportOptions = {
        delimiter   : ",",
        wrap        : false
    }
    var myobj = csvjson.toSchemaObject(data, importOptions)
    var exportArr = [], importArr = [];
    myobj.forEach(d=>{
        if(d.orderId==undefined || d.orderId=='') {
            exportArr.push(d)
        } else {
            importArr.push(d)
        }
    })
    var csv = csvjson.toCSV(exportArr, ExportOptions);
    MongoClient.connect(mongoDSN, function(error, db) {
        collection = db.collection("orders")
        collection.insertMany(importArr, function(err,result){
            fs.writeFile('/home/limitless/Downloads/orders_sample1.csv', csv, { encoding : 'utf8'});
            db.close();
        });            
    })
}

uploadcsvModule()

1
Это вводит все виды сложностей (MongoClient, JSON и т. Д.), Которые не относятся к вопросу.
— Дан Даскалеску

3

fs.createWriteStream(path[,options])

optionsможет также включать startопцию, позволяющую записывать данные в некоторой позиции после начала файла. Для изменения файла вместо его замены может потребоваться flagsрежим, r+а не режим по умолчанию w. Кодировка может быть любой из тех, которые приняты буфером .

Если autoCloseустановлено значение true (поведение по умолчанию) 'error'или 'finish'файловый дескриптор будет закрыт автоматически. ЕслиautoClose равно false, дескриптор файла не будет закрыт, даже если произошла ошибка. Приложение должно закрыть его и убедиться в отсутствии утечки файлового дескриптора.

Нравится ReadStream , если fdуказан, WriteStream будет игнорировать pathаргумент и будет использовать указанный дескриптор файла. Это означает, что 'open'событие не будет отправлено. fdдолжно быть блокирование; неблокирующие fds должны быть переданы net.Socket .

Если optionsэто строка, то она определяет кодировку.

После прочтения этой длинной статьи. Вы должны понимать, как это работает. Итак, вот примерcreateWriteStream() .

/* The fs.createWriteStream() returns an (WritableStream {aka} internal.Writeable) and we want the encoding as 'utf'-8 */
/* The WriteableStream has the method write() */
fs.createWriteStream('out.txt', 'utf-8')
.write('hello world');

createWriteStreamуже упоминалось в нескольких ответах за годы до этого.
— Дан Даскалеску

0

Вы можете использовать библиотеку easy-file-manager

установить сначала с npm npm install easy-file-manager

Образец для загрузки и удаления файлов

var filemanager = require('easy-file-manager')
var path = "/public"
var filename = "test.jpg"
var data; // buffered image

filemanager.upload(path,filename,data,function(err){
    if (err) console.log(err);
});

filemanager.remove(path,"aa,filename,function(isSuccess){
    if (err) console.log(err);
});

2
This modules is created to save and remove files., Не ответ
— Зеленый

-1

Вы можете записать в файл следующий пример кода:

var data = [{ 'test': '123', 'test2': 'Lorem Ipsem ' }];
fs.open(datapath + '/data/topplayers.json', 'wx', function (error, fileDescriptor) {
  if (!error && fileDescriptor) {
    var stringData = JSON.stringify(data);
    fs.writeFile(fileDescriptor, stringData, function (error) {
      if (!error) {
        fs.close(fileDescriptor, function (error) {
          if (!error) {
            callback(false);
          } else {
            callback('Error in close file');
          }
        });
      } else {
        callback('Error in writing file.');
      }
    });
  }
});

1
writeFileнесколько лет назад уже давали ответ несколько раз. Что добавляет этот ответ?
— Дан Дакалеску

И зачем открывать файл? Разве ответ не должен быть о записи файлов?
— Михал
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.