Запис файлів у Node.js


1645

Я намагався знайти спосіб запису у файл під час використання Node.js, але не мав успіху. Як я можу це зробити?

Відповіді:


2463

В 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!');

25
Я перевірив цей скрипт за допомогою Node, і я спробував змінити шлях до файлу на "/ home /", але я отримав таку помилку: { [Error: EACCES, open '/home/test.txt'] errno: 3, code: 'EACCES', path: '/home/test.txt' } Як я можу змінити цей скрипт, щоб він працював поза /tmp?
— Андерсон Грін

129
Також зауважте, що ви можете використовувати fs.writeFileSync (...), щоб виконати те саме, що синхронізується.
— Девід Ервін

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

38
Власне, @DenysVitali, проблема полягає в тому, що Джейн не має змоги записувати жодні файли в /home/.... Як правило, цей каталог має 755 root: wheel (або що завгодно). Якщо вузол хоче записати файл як jane, записати його буде простіше /home/jane/test.txt. Перехід /homeна щось більш дозвільне, ніж 755, - це величезна помилка.
— дуга jane

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

536

В даний час існує три способи написання файлу:

  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 (стабільна версія оголошена 02.06.2015) тепер підтримується дві функції: cork()і uncork(). Здається, що ці функції, нарешті, дозволять вам захистити або записувати дзвінки запису.

Наприклад, у Java є деякі класи, які надають буферизовані потоки ( BufferedOutputStream, BufferedWriter...). Якщо ви пишете три байти, ці байти будуть зберігатися в буфері (пам'яті), а не робити дзвінок вводу-виводу лише на три байти. Коли буфер заповнений, вміст очищається та зберігається на диску. Це покращує продуктивність.

Я нічого не відкриваю, просто пам'ятаю, як слід робити доступ до диска.


5
+1 - приємне пояснення. Для потоку записів важливо уважно прочитати документи. Якщо повертається помилково або закривається, важливо зателефонувати по письменнику.once ('drain', function () {}) або я пропустив рядки, які не дренувалися, коли процес закінчився.
— bryanmac

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

На сьогодні Node v0.12 стабільний.
— Август

Відповідно до аналізу коду від GitHub, здається, fs.writeFile є найпопулярнішою із згаданих вами функцій. Ось приклади реального світу для використання fs.writeFile
— drorw

Чи існують бібліотеки якості виробництва для npmвпровадження буферизованого написання?
— nponeccop

265

Ви, звичайно, можете зробити це трохи більш вдосконаленим. Не блокуючи, записуйте шматочки та фрагменти, не записуйте весь файл одразу:

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 На це доведеться чекати.
— Фредрік Андерссон

60

Синхронне записування

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 .


52
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()), цей приклад працює лише в тому випадку, якщо все достатньо коротке, щоб записатись в один виклик запису.
— Манфред

30

Мені сподобався індекс ./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? Я не можу його знайти в жодних папках ... дякую.
— Kai Feng Chew

в папці , яку ви запустите скрипт
— Серджіу

Це дивно ... Я просто ніде його не можу знайти. Чи буде це приховано? ще раз дякую ~
— Kai Feng Chew

6
Я щойно це знайшов. Використовуючи цей ROOT_APP_PATH = fs.realpathSync ('.'); console.log ( ROOT_APP_PATH ); щоб отримати мій, де записаний файл. Дякую.
— Кай Фенг Чеу

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

23

Надані відповіді датовані, і новіший спосіб зробити це:

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
Функція закривання повинна бути асинхронізованою, інакше це не працюватиме.
— Zimano

1
@wintercounter Це дуже солодко!
— Зімано

18

Я знаю, що запитання про "написати", але в більш загальному сенсі "додавання" може бути корисним в деяких випадках, оскільки це легко використовувати в циклі, щоб додати текст у файл (чи існує файл чи ні). Використовуйте "\ 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');уникати небажаних побічних ефектів, особливо якщо ви працюєте з дещо більшою базою коду.
— Манфред

10

Гаразд, це дуже просто, оскільки Node має вбудований функціонал для цього, він називається, fsякий означає файлову систему і, в основному, модуль файлової системи NodeJS ...

Тому спочатку вимагайте цього у вашому файлі 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
одиничну цитату в рядку слід уникати.
— Тамер

8
 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?
— Дан Даскалеску

7

Ви можете записати у файл, використовуючи модуль 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');
    }
  });
};

Можливо, ви також хочете позбутися цієї структури коду зворотного виклику всередині виклику, використовуючи Обіцянки та async/ awaitоператори. Це зробить асинхронну структуру коду набагато більш простою. Для цього може бути використана зручна функція util.promisify (оригінальна) . Це дозволяє нам переходити від зворотних викликів до обіцянок. Погляньте на приклад із 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

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

1
@Manfred Рівно! Я думаю, ти неправильно зрозумів, що я намагався сказати; немає сенсу робити фрагменти, оскільки це nodejs!
— Zimano

4

Тут ми використовуємо 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'.


2

Ось зразок того, як читати файл 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 тощо), які не стосуються цього питання.
— Дан Даскалеску

2

fs.createWriteStream(path[,options])

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

Якщо 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.