2015-05-06 4 views
0

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

var transformer = require('./transformer'), 
    fs = require('fs'), 
    file = process.argv[2]; 

if (!file) { 
    throw 'no file specified\n'; 
} 

fs.readFile(file, 'utf-8', function (err, data) { 
    if (err) { 
     throw err; 
    } 

    transformer.transform(data, function (text) { 
     console.log(text); 
    }); 
}); 

Это прекрасно работает:

$ node transform.js myfile.txt 

и это работает :

$ node transform.js myfile.txt > anotherfile.txt 

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

$ node transform.js myfile.txt > myfile.txt 

То же самое с помощью tee:

$ node transform.js myfile.txt | tee myfile.txt 

Любопытно, что это работает:

$ node transform.js myfile.txt >> myfile.txt 

Но я не хочу, чтобы добавить в файл - Я хочу, чтобы переписать его содержимое.

Я думаю, что проблема в том, что fs.readFile является асинхронным, а также асинхронно console.log - т. Е. Он получает куски данных, а не все данные одновременно. Я думаю, что я могу использовать fs.readFileSync, но каков правильный способ справиться с этим?

+0

Как вы думаете, дескриптор файла по-прежнему открыт, когда вы проверяете блокнот ?, если im не ошибается, пока открыт дескриптор файла, данные буквально не записываются в файл, хотя во время шагов отладки он, вероятно, мог сказать письмо уже было сделано. (с точки зрения C#), также блокноты, как известно, ненадежны (во время проверки глаз) из-за того, что вы можете удалить блокнот, даже если сам файл открыт. –

+0

Это не связано с nodejs. Это то, как работает оболочка. Традиционным способом сделать это будет 'node transform.js myfile> tmp; mv tmp myfile' – slebetman

ответ

1

Проблема не на самом деле в узле, а в оболочке. Когда вы перенаправляете >, первое, что делает оболочка, - это открыть файл для записи, опорожнения файла. Ваша программа переходит к чтению из этого пустого файла, и в вашем случае пустой ввод означает пустой вывод.

Это тоже приведет к пустой файл независимо от исходного содержимого myfile.txt:

$ cat myfile.txt > myfile.txt 

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

Как примечание @slebetman в комментарии, другое решение - cat myfile.txt > tmp; mv tmp myfile.txt (или мое предпочтение: cat myfile.txt > tmp && mv tmp myfile.txt).

+0

Традиционное решение в оболочке - 'cat myfile.txt> tmp; mv tmp myfile.txt' – slebetman

+0

Спасибо, я добавил это как вариант в конец ответа. – Trott

1

Проблема заключается в том

  • вы открываете файл для чтения,
  • затем открыть файл для записи (опорожнения),
  • затем чтение из пустого файла.
  • преобразования ничего
  • ничего не писать

То, что я думаю, что вы хотите вместо этого заключается в следующем:

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

Там в несколько способов сделать это:

1) Прочитайте файл синхронно. Node.js 0.12 supports this.

var transformer = require('./transformer'), 
    fs = require('fs'), 
    file = process.argv[2]; 

if (!file) { 
    throw 'no file specified\n'; 
} 

fs.readFileSync(file, 'utf-8', function (err, data) { 
    if (err) { 
     throw err; 
    } 

    transformer.transform(data, function (text) { 
     console.log(text); 
    }); 
}); 

2) Используйте "потоки"

Это действительно лучший способ. Особенно, если вы хотите узнать Node.js

Лучший способ узнать о потоках из NodeSchool: http://nodeschool.io/#workshoppers Попробуйте stream-adventure.

К концу вы получите таких проблем.

Удачи вам!

+0

Мне любопытно, почему downvote? Это потому, что ни одно из предлагаемых решений не решит проблему? –

+0

Все решения здесь (моя и Тротт) работают. Тротт работал в bash, что хорошо, как простейшая вещь, возможно, работа. Возможности использования рудника для решения проблемы. Это зависит от того, что вы хотите сделать. Почему нисходящий? Потому что ненавистникам нужно ненавидеть :-) –

Смежные вопросы