31.05.2021, 17:13
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Перекодировать данные из MongoDB в файл csv
Хочу перекодировать данные из MongoDB (utf-8) в файл csv (windows-1251)...
Нашел два примера с использованием encoding и iconv-lite.
Но какие бы комбинации на пробовал - файл получается с "кракозябрами".
Может подскажите как получить файл в нужной (win) кодировке?
const mongojs = require('mongojs')
const fs = require("fs");
const tunnel = require('tunnel-ssh');
const encoding = require('encoding')
const iconv = require("iconv-lite")
const cnf = JSON.parse(fs.readFileSync('./config.json'))
const config = {
host: cnf.host,
port: cnf.port,
username: cnf.username,
agent : process.env.SSH_AUTH_SOCK,
privateKey: fs.readFileSync(cnf.keyFile),
dstPort: cnf.dstPort
};
const server = tunnel(config, function (error, server) {
if (error) return console.log("SSH не подключился", error)
const db = mongojs('test')
const cl = db.collection('product')
//const file = fs.createWriteStream('product.csv', 'ascii')
const file = fs.createWriteStream('product.csv', 'utf-8')
file.on('error', err => {
console.log('Ошибка записи файла', err)
})
const q = {}
const fld = {
title: 1
}
const cur = cl.find(q, fld).sort({title: 1})
cur.on('data', (doc) => {
//const val = iconv.decode(doc.title, "win1251")
//const val = encoding.convert(doc.title, 'WINDOWS-1251', 'UTF-8')
//file.write(val + ';\n')
file.write(doc.title + ';\n')
})
cur.on('error', err => {
end()
console.log('Ошибка чтения данных', err)
})
cur.on('end', () => {
end()
console.log('Все')
})
const end = () => {
db.close()
file.end()
}
});
|
|
02.06.2021, 14:26
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Пробую просто перекодировать строку по примерам из инета...
const encoding = require('encoding')
const iconv = require("iconv-lite")
const fs = require("fs");
const str = 'Пример текста в UTF-8'
const val1 = encoding.convert(str, 'WINDOWS-1251', 'UTF-8')
const bfr = Buffer.from(str)
const val2 = iconv.encode(bfr, "win1251")
const val3 = iconv.decode(bfr, "win1251")
console.log('1 ', val1)
console.log('2 ', val2)
console.log('3 ', val3)
const opt = { encoding: 'ascii' }
fs.appendFile('test.txt', '1. ' + val1 + '\n', opt, err => {
if (!err) console.log('Записано 1')
})
fs.appendFile('test.txt', '2. ' + val2 + '\n', opt, err => {
if (!err) console.log('Записано 2')
})
fs.appendFile('test.txt', '3. ' + val3 + '\n', opt, err => {
if (!err) console.log('Записано 3')
})
Все 3 варианта - кракозябры.
|
|
02.06.2021, 19:11
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Даже пример в самой iconv-lite не работает...
const iconv = require('iconv-lite');
const fs = require('fs')
// Convert from an encoded buffer to a js string.
let buf = Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f])
let str = iconv.decode(buf, 'win1251');
// Convert from a js string to an encoded buffer.
buf = iconv.encode('Пример строки преобразованной в буфер', 'win1251');
// Check if encoding is supported
const val = iconv.encodingExists("us-ascii")
fs.appendFile('temp.txt', 'str ' + str + '\n', {encoding: 'ascii'}, err => {
if (!err) console.log('Записано str')
})
fs.appendFile('temp.txt', 'buf ' + buf + '\n', {encoding: 'ascii'}, err => {
if (!err) console.log('Записано buf')
})
Т.е. строки с английскими буквами отображаются... А с русскими (что как раз нужно) - фигу.
|
|
02.06.2021, 21:28
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,138
|
|
iconv - замечательно работает.
Сталкивался с такой проблемой.
Любой вызов автоматического приведения типов превращает буфер в строку без реальной конвертации 8 битной кодировки cp1251 в 16 битную UTF16 используемой движком для хранения строк.
Например " 'str ' + str " токсичное выражение т.к. str должно быть приведено к строке и как следствие превращается в мусор.
Самый простой способ борьбы избегать автоматического приведения типов.
А вообще пошаговая отладка хорошо показывает в какой момент строка/буфер превращается в мусор.
|
|
02.06.2021, 21:31
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Сообщение от MallSerg
|
замечательно работает
|
Тогда поправь мой пример, так чтобы в файле были русские буквы в ВИН-кодировке...
Сообщение от MallSerg
|
Например " 'str ' + str " токсичное выражение т.к. str должно быть приведено к строке и как следствие превращается в мусор.
|
У меня нет таких строк...
Все обычные слова на русском но только в кодировке UTF-8. Это данные из MongoDB.
В примере - просто строка.
|
|
02.06.2021, 21:36
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Сообщение от MallSerg
|
Например " 'str ' + str " токсичное выражение т.к. str должно быть приведено к строке и как следствие превращается в мусор.
|
Привел все переменные "к строке"...
Но результат не поменялся.
const iconv = require('iconv-lite');
const fs = require('fs')
// Convert from an encoded buffer to a js string.
let buf = Buffer.from([0x68, 0x65, 0x6c, 0x6c, 0x6f])
let str = iconv.decode(buf, 'win1251');
// Convert from a js string to an encoded buffer.
buf = iconv.encode('Пример строки преобразованной в буфер', 'win1251');
// Check if encoding is supported
const val = iconv.encodingExists("us-ascii")
console.log('encodingExists ', val)
fs.appendFile('temp.txt', 'str ' + str.toString() + '\n', {encoding: 'ascii'}, err => {
if (!err) console.log('Записано str')
})
fs.appendFile('temp.txt', 'buf ' + buf.toString() + '\n', {encoding: 'ascii'}, err => {
if (!err) console.log('Записано buf')
})
|
|
02.06.2021, 21:53
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,138
|
|
В том то и дело что любое приведение к строке превращает буфер в мусор.
т.е. "str.toString()" превратит строку в мусор.
|
|
02.06.2021, 22:06
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Такое вот сработало!
const iconv = require('iconv-lite');
const fs = require('fs')
// Convert from a js string to an encoded buffer.
buf = iconv.encode('Пример строки преобразованной в буфер', 'win1251');
fs.appendFile('temp.txt', buf, {encoding: 'ascii'}, err => {
if (!err) console.log('Записано buf')
})
|
|
02.06.2021, 22:16
|
|
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,228
|
|
Сообщение от MallSerg
|
т.е. "str.toString()" превратит строку в мусор.
|
Пишут что вполне себе нормальное действие...
https://nodejsdev.ru/doc/buffer/#_4
|
|
03.06.2021, 00:21
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,138
|
|
Действие нормальное но работает не так как ты ожидаешь.
Проблема не в nodeJS а в движке V8 и его реализации работы со строками.
В V8 символы в строке выравниваются по границе uint16_t для оптимизации работы со строками и кирилица во внутреннем представлении кодируется двумя байтами что бы работали сравнения регулярные выражение и прочее.
И в момент когда данные буфера (char*) преобразуются во внутренне представление движка (uint16_t*) они просто выравниваются по границе uint16_t для латиницы это нормально а для символов которые должны кодироваться двумя байтами это фатально и возникает ошибка с однобайтовыми национальными кодировками (например cp1251).
>> Такое вот сработало!
Потому что буфер не приводился к строке.
|
|
|
|