2017-01-05 2 views
0

Я хочу, чтобы прочитать байты из файла, вот пример кода:Nodejs readable.read() возвращают нуль

var fs = require('fs'); 

var stream= fs.createReadStream('./lib'); 
console.log(stream.read(10)); 

возвращение нуль.

Я думаю, это потому, что метод read() напрямую получает данные из внутреннего буфера. Если в буфере недостаточно данных, возвращается null. Метод read() - это вызов синхронизации, при этом никакой обратный вызов не передается, поэтому дизайн имеет смысл. Однако я не знаю, когда внутренний буфер может иметь достаточно данных, чтобы мой вызов read() мог возвращать данные, так как теперь он приостановлен?

Update1:

событие readable это хороший способ, чтобы начать работу. Но если я хочу прочитать большой файл, а число чтения>65536, null вернется.

var fs = require('fs'); 

var stream = fs.createReadStream('./lib'); 
stream.on('readable', function() { 
    var buffer = stream.read(65537); 
    console.log(buffer.length); 

}); 

То, что я хочу точно, stream.read() всегда может возвращать данные до EOF.

ответ

1

Подождите, readable события огня, прежде чем пытаться читать:

var fs = require('fs'); 

var stream= fs.createReadStream('./lib'); 
stream.on('readable', function() { 
    var buffer = stream.read(10); 
    if (buffer) { 
    console.log(buffer.toString()); 
    } 
}); 
+0

Спасибо за предоставленную хорошую точку. Я обновил свой пост и, пожалуйста, взгляните. Кажется, что «читаемое» событие не может решить эту проблему. – BartMao

0

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

fs.readFile(FILENAME, (err, data) => { 
    console.log(Buffer.isBuffer(data)); 
    console.log(data.length); 
}) 

поток, с другой стороны, будет излучать data событие всякий раз, когда у него есть данные для вас. По умолчанию highWaterMark для этого потока составляет 64 КБ.

var stream = fs.createReadStream(FILENAME); 
var results = [] 

stream.on('data', function (chunk) { 
    // For text files chunk is string 
    // for binary files chunk is an instance of Buffer 

    // do something with this chunk... 

    results.push(`Chunk ${results.length} OK`) 
}); 

stream.on('end', function() { 
    console.log(results); 
}) 
+0

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

+0

Возможно, вам следует разместить код того, что вы на самом деле пытаетесь сделать? Откуда вы звоните .read()? – djones

+0

Я хочу проанализировать формат файла. Используйте gif-файл в качестве примера, первые 3 байта представляют собой заголовок файла, а следующая 3 представляет версию, а затем множество разных блоков данных с незафиксированными размерами. Моя текущая идея вызывает .read (3), .read (3), .read (xx) ... индивидуально. Если один из прочитанных (xx) встретит конец буфера (65536 по умолчанию), этот вызов вернет значение null. – BartMao

0

Согласно официальному document:

После того, как внутренний буфер сливают, а 'читабельными событие будет срабатывать еще раз, когда больше данных доступно.

Я могу использовать async/await, чтобы readable.read() всегда мог возвращать данные, если не на EOF.

let rs = fs.createReadStream('./resources/1.gif'); 

async function readable(): Promise<{}> { 
    return new Promise(r => rs.on('readable', r)); 
} 

async function readBytes(num: number = 0): Promise<Buffer> { 
    let buf = rs.read(num); 
    if (buf) { 
     return new Promise<Buffer>(r => r(buf)); 
    } 
    else { 
     return new Promise<Buffer>(r => { 
      this.readable().then(() => { 
       this.readBytes(num).then(b => r(b)); 
      }); 
     }); 
    } 
} 

async function main() { 
    console.log('begin'); 
    console.log((await readBytes(10)).length); 
    console.log((await readBytes(65535)).length); 
    console.log((await readBytes(100000)).length); 
    console.log((await readBytes(10)).length); 
    console.log('end'); 
} 

main(); 

Выходы:

begin 
10 
65535 
100000 
10 
end