Запись файлов в 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.