@Ivan_korolev

Как корректно считать кусками файл в UTF8 из под node.js?

Читаю файл построчно и гружу в массив list строки.
Сам файл может разрастись где-то до 2GB, а то и больше, не хотелось бы читать его целиком в память.

function rf2m(path){
	var handle=fs.openSync(path, 'r');
	var list=[], n=[], sdata='';
	do{	
		n=fs.readSync(handle, 10, null, 'utf8'); 
		sdata+=n[0]; //Дописываем к данным то, что получили после последнего '\n'
		var x=sdata.split("\n"); //Разбиваем данные на строки
		sdata=x[x.length-1]; //Пишем в переменную то, что получили после последнего '\n'
		for(var i=0; i<x.length-1;i++){
			list.push(x[i]);
			//fs.writeFileSync('log.txt', x[i]+"\n", {flag:'a'},'binary');
		}	 
		if(n[1]==0){ //Если длинна порции равна нулю
			if(x[x.length-1]!='') list.push(x[x.length-1]);
			break;
		}	
	}while(true)
	fs.closeSync(handle);
	return list;
}


Когда есть русские символы, я на выходе получаю нечто типо:
[OP]Се��гей
Инфо
��
[OP]Сергей
��нфо

В UTF8 русские символы занимают 2байта, а латиница - 1. Как решить эту проблему?
  • Вопрос задан
  • 3033 просмотра
Решения вопроса 2
printf
@printf
Ем детей.
А вот эта https://github.com/jahewson/node-byline штука работает корректно?

По-хорошему надо считывать байты (Buffer), а не строки, тогда не будет ломаться ничего. А в строку превращать непосредственно перед использованием.
Ответ написан
Комментировать
@Aves
И где только удалось откопать такую форму применения fs.read ?..
Read читает байты, поэтому читать надо в буфер, и потом преобразовывать с помощью StringDecoder:
var fs = require('fs');
var fd = fs.openSync('./text', 'r');
var decoder = new (require('string_decoder').StringDecoder)();
var buf = new Buffer(10);
var list = [], str, bytesReaded;

while (bytesReaded = fs.readSync(fd, buf, 0, 10, null)) {
    str = (list.pop() || '') + decoder.write(buf.slice(0, bytesReaded));
    list = list.concat(str.split("\n"));
}
console.log(list);

А лучше для таких вещей использовать потоки, если указать кодировку, будет читаться нужное количество символов, а не байт:
var fs = require('fs');
var list = [];
fs.createReadStream('./text', {encoding: 'utf8'})
    .on('readable', function() {
        var str, chunk;
        while (chunk = this.read(10)) {
            str = ((list.pop() ||'') + chunk);
            list = list.concat(str.split('\n'));
        }
        list[list.length-1] += (this.read() || '');
    })
    .on('end',function() {
        console.log(list);
    });
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
scapp
@scapp
JS фрилансер
"я на выходе получаю нечто" на каком выходе поподробнее
n=fs.readSync(handle, 10, null, 'utf8');
если сделать console.error(n) уже есть проблема кодировки или нет
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы