Saya mencoba membaca file besar satu per satu. Saya menemukan pertanyaan tentang Quora yang membahas masalah ini, tetapi saya kehilangan beberapa koneksi untuk membuat semuanya cocok.
var Lazy=require("lazy");
new Lazy(process.stdin)
.lines
.forEach(
function(line) {
console.log(line.toString());
}
);
process.stdin.resume();
Bagian yang ingin saya ketahui adalah bagaimana saya bisa membaca satu baris pada satu waktu dari sebuah file, bukan STDIN seperti dalam sampel ini.
Saya mencoba:
fs.open('./VeryBigFile.csv', 'r', '0666', Process);
function Process(err, fd) {
if (err) throw err;
// DO lazy read
}
tapi itu tidak berhasil. Saya tahu bahwa dalam keadaan darurat saya dapat kembali menggunakan sesuatu seperti PHP, tapi saya ingin mencari tahu.
Saya tidak berpikir jawaban lain akan bekerja karena file tersebut jauh lebih besar daripada server tempat saya menjalankannya memiliki memori.
fs.readSync()
. Anda dapat membaca oktet biner ke dalam buffer tetapi tidak ada cara mudah untuk menangani sebagian karakter UTF-8 atau UTF-16 tanpa memeriksa buffer sebelum menerjemahkannya ke string JavaScript dan memindai EOL. TheBuffer()
tipe tidak memiliki sebagai set kaya fungsi untuk beroperasi pada contoh sebagai string asli, tapi string asli tidak dapat berisi data biner. Tampaknya bagi saya bahwa kekurangan cara untuk membaca baris teks dari file arbitrer yang sewenang-wenang adalah kesenjangan nyata dalam node.js.if (line.length==1 && line[0] == 48) special(line);
node
API docs github.com/nodejs/node/pull/4609Jawaban:
Sejak Node.js v0.12 dan pada Node.js v4.0.0, ada modul inti readline yang stabil . Berikut cara termudah untuk membaca baris dari file, tanpa modul eksternal apa pun:
Atau sebagai alternatif:
Baris terakhir dibaca dengan benar (pada Node v0.12 atau yang lebih baru), bahkan jika tidak ada final
\n
.PEMBARUAN : contoh ini telah ditambahkan ke dokumentasi resmi API Node .
sumber
rl.on('close', cb)
Untuk operasi sederhana seperti itu seharusnya tidak ada ketergantungan pada modul pihak ketiga. Mudah saja.
sumber
line
peristiwa terjadi hanya setelah memukul\n
, yaitu, semua alternatif terlewatkan (lihat unicode.org/reports/tr18/#Line_Boundaries ). # 2, data setelah yang terakhir\n
diabaikan secara diam-diam (lihat stackoverflow.com/questions/18450197/… ). Saya akan menyebut solusi ini berbahaya karena berfungsi untuk 99% dari semua file dan untuk 99% dari data tetapi gagal diam - diam untuk sisanya. setiap kali Anda melakukannya,fs.writeFileSync( path, lines.join('\n'))
Anda telah menulis file yang hanya akan dibaca sebagian oleh solusi di atas.readline
paket berperilaku dalam cara-cara yang benar-benar aneh untuk programmer Unix / Linux yang berpengalaman.rd.on("close", ..);
dapat digunakan sebagai panggilan balik (terjadi ketika semua baris dibaca)Anda tidak harus ke
open
file, tetapi Anda harus membuatReadStream
.fs.createReadStream
Kemudian berikan aliran itu ke
Lazy
sumber
new lazy(fs.createReadStream('...')).lines.forEach(function(l) { /* ... */ }).join(function() { /* Done */ })
new lazy(...).lines.forEach(...).on('end', function() {...})
.on('end'...
setelahnya.forEach(...)
, padahal sebenarnya semua berperilaku seperti yang diharapkan ketika saya mengikat acara terlebih dahulu .ada modul yang sangat bagus untuk membaca file baris demi baris, itu disebut line-reader
dengan itu Anda cukup menulis:
Anda bahkan dapat mengulangi file dengan antarmuka "java-style", jika Anda memerlukan lebih banyak kontrol:
sumber
process/stdin
). Setidaknya, jika bisa, tentu tidak jelas dari membaca kode dan mencobanya.readline
modul inti .function(reader)
danfunction(line)
seharusnya:function(err,reader)
danfunction(err,line)
.line-reader
bacalah file secara tidak sinkron. Alternatif sinkron untuk itu adalahline-reader-sync
sumber
Pembaruan pada tahun 2019
Contoh yang luar biasa sudah diposting pada dokumentasi resmi Nodejs. sini
Ini mengharuskan Nodejs terbaru diinstal pada mesin Anda. > 11.4
sumber
await
antaracreateInterface()
panggilan dan awalfor await
loop, Anda akan secara misterius kehilangan garis dari awal file.createInterface()
segera mulai memancarkan garis di belakang layar, dan iterator async yang secara implisit dibuat denganconst line of rl
tidak dapat mulai mendengarkan garis-garis itu sampai dibuat.Topik lama, tetapi ini berfungsi:
Sederhana. Tidak perlu modul eksternal.
sumber
readline is not defined
ataufs is not defined
, menambahvar readline = require('readline');
dan membuatnyavar fs = require('fs');
berfungsi. Kalau tidak manis, kode manis. Terima kasih.Anda selalu dapat memutar pembaca baris Anda sendiri. Saya belum membuat tolok cuplikan ini, tetapi ia dengan benar membagi aliran potongan yang masuk ke dalam garis tanpa mengekor '\ n'
Saya memang datang dengan ini ketika bekerja pada skrip parsing log cepat yang diperlukan untuk mengumpulkan data selama log parsing dan saya merasa bahwa akan lebih baik untuk mencoba melakukan ini menggunakan js dan node daripada menggunakan perl atau bash.
Bagaimanapun, saya merasa bahwa skrip nodejs kecil harus mandiri dan tidak bergantung pada modul pihak ketiga sehingga setelah membaca semua jawaban untuk pertanyaan ini, masing-masing menggunakan berbagai modul untuk menangani penguraian garis, solusi nodejs asli 13 SLOC mungkin menarik.
sumber
stdin
... kecuali saya melewatkan sesuatu.ReadStream
denganfs.createReadStream('./myBigFile.csv')
dan menggunakannya sebagai gantistdin
readline
modul inti .Dengan modul operator :
sumber
var inStream = fs.createReadStream('input.txt', {flags:'r'});
Tetapi sintaks Anda lebih bersih daripada metode yang terdokumentasi dalam menggunakan .on ():carrier.carry(inStream).on('line', function(line) { ...
\r\n
dan\n
ujung garis. Jika Anda perlu berurusan dengan file uji gaya MacOS dari sebelum OS X, mereka menggunakan\r
dan operator tidak menangani ini. Anehnya, masih ada file-file seperti mengambang di alam liar. Anda mungkin juga perlu menangani Unicode BOM (tanda urutan byte) secara eksplisit, ini digunakan pada awal file teks dalam lingkup pengaruh MS Windows.readline
modul inti .Saya berakhir dengan kebocoran memori besar-besaran menggunakan Malas untuk membaca baris demi baris ketika mencoba untuk memproses baris-baris itu dan menulisnya ke aliran lain karena cara menguras / jeda / melanjutkan dalam karya simpul (lihat: http: // elegantcode .com / 2011/04/06 / mengambil-baby-steps-with-node-js-pumping-data-between-stream / (saya suka orang ini btw)). Saya belum melihat dari dekat pada Malas untuk mengerti persis mengapa, tetapi saya tidak bisa menghentikan aliran baca saya untuk memungkinkan pengeringan tanpa Malas keluar.
Saya menulis kode untuk memproses file csv besar menjadi dokumen xml, Anda dapat melihat kode di sini: https://github.com/j03m/node-csv2xml
Jika Anda menjalankan revisi sebelumnya dengan baris Malas bocor. Revisi terbaru tidak bocor sama sekali dan Anda mungkin dapat menggunakannya sebagai dasar untuk pembaca / prosesor. Meskipun saya punya beberapa barang khusus di sana.
Sunting: Saya kira saya juga harus mencatat bahwa kode saya dengan Lazy berfungsi dengan baik sampai saya menemukan diri saya menulis fragmen xml cukup besar yang menguras / jeda / melanjutkan karena suatu keharusan. Untuk potongan yang lebih kecil itu baik-baik saja.
sumber
readline
modul inti .Edit:
Gunakan aliran transformasi .
Dengan BufferedReader Anda dapat membaca baris.
sumber
readline
modul inti .Sejak memposting jawaban asli saya, saya menemukan bahwa split adalah modul node yang sangat mudah digunakan untuk membaca baris dalam file; Yang juga menerima parameter opsional.
Belum diuji pada file yang sangat besar. Beri tahu kami jika Anda melakukannya.
sumber
Saya frustrasi dengan kurangnya solusi yang komprehensif untuk ini, jadi saya mengumpulkan upaya saya sendiri ( git / npm ). Daftar fitur yang disalin:
NIH? Kamu putuskan :-)
sumber
sumber
data
panggilan untukstream.on("data")
memulai atau mengakhiri hanya dengan sebagian dari karakter UTF-8 multibyteა
yangU+10D0
terdiri dari tiga bytee1
83
90
readline
modul inti .Saya ingin mengatasi masalah yang sama ini, pada dasarnya seperti apa di Perl:
Kasus penggunaan saya hanya skrip mandiri, bukan server, jadi sinkron baik-baik saja. Ini adalah kriteria saya:
Ini adalah proyek bagi saya untuk merasakan kode jenis scripting tingkat rendah di node.js dan memutuskan seberapa layak itu sebagai pengganti bahasa scripting lain seperti Perl.
Setelah sejumlah usaha yang mengejutkan dan beberapa kesalahan mulai ini adalah kode yang saya buat. Ini cukup cepat tetapi kurang sepele daripada yang saya harapkan: (bercabang di GitHub)
Mungkin bisa dibersihkan lebih lanjut, itu adalah hasil coba-coba.
sumber
Dalam kebanyakan kasus ini seharusnya cukup:
sumber
Pembaca garis berbasis generator: https://github.com/neurosnap/gen-readlines
sumber
Jika Anda ingin membaca file baris demi baris dan menulis ini di yang lain:
sumber
Saya memiliki masalah yang sama dan muncul dengan solusi di atas terlihat mirip dengan yang lain tetapi aSync dan dapat membaca file besar dengan sangat cepat
Semoga ini bisa membantu
sumber
Saya memiliki modul kecil yang melakukan ini dengan baik dan digunakan oleh beberapa proyek lain npm readline Catatan thay di node v10 ada modul readline asli jadi saya menerbitkan kembali modul saya sebagai linebyline https://www.npmjs.com/package/ baris demi baris
jika Anda tidak ingin menggunakan modul, fungsinya sangat sederhana:
sumber
Solusi lain adalah menjalankan logika melalui nsynjs executor berurutan . Bunyinya file baris demi baris menggunakan modul node readline, dan tidak menggunakan janji atau rekursi, karena itu tidak akan gagal pada file besar. Berikut adalah tampilannya:
Kode di atas didasarkan pada contoh ini: https://github.com/amaksr/nsynjs/blob/master/examples/node-readline/index.js
sumber
Dua pertanyaan yang harus kita tanyakan pada diri sendiri saat melakukan operasi adalah:
Solusi seperti
require('fs').readFileSync()
memuat seluruh file ke dalam memori. Itu berarti jumlah memori yang diperlukan untuk melakukan operasi akan hampir setara dengan ukuran file. Kita harus menghindari ini untuk hal yang lebih besar dari50mbs
Kita dapat dengan mudah melacak jumlah memori yang digunakan oleh suatu fungsi dengan menempatkan baris kode ini setelah pemanggilan fungsi:
Saat ini cara terbaik untuk membaca baris tertentu dari file besar adalah dengan menggunakan node readline . Dokumentasi memiliki contoh luar biasa .
Meskipun kami tidak membutuhkan modul pihak ketiga untuk melakukannya. Tetapi, jika Anda menulis kode perusahaan, Anda harus menangani banyak kasus tepi. Saya harus menulis modul yang sangat ringan yang disebut Apick File Storage untuk menangani semua kasus tepi itu.
Modul Penyimpanan File Apick: https://www.npmjs.com/package/apickfs Dokumentasi: https://github.com/apickjs/apickFS#readme
Contoh file: https://1drv.ms/t/s!AtkMCsWInsSZiGptXYAFjalXOpUx
Contoh: Pasang modul
Metode ini berhasil diuji dengan file padat hingga 4 GB.
big.text adalah file teks padat dengan 163.845 baris dan berukuran 124 Mb. Script untuk membaca 10 baris berbeda dari file ini hanya menggunakan sekitar 4,63 MB Memori saja. Dan mem-parsing JSON yang valid ke Objects atau Array secara gratis. 🥳 Luar Biasa !!
Kita dapat membaca satu baris file atau ratusan baris file dengan konsumsi memori yang sangat sedikit.
sumber
saya menggunakan ini:
gunakan fungsi ini pada aliran dan dengarkan acara baris yang akan dipancarkan.
gr-
sumber
Meskipun Anda mungkin harus menggunakan
readline
modul seperti jawaban atas menyarankan,readline
tampaknya lebih berorientasi pada antarmuka baris perintah daripada membaca garis. Ini juga sedikit lebih buram tentang buffering. (Siapa pun yang membutuhkan pembaca berorientasi garis streaming mungkin ingin mengubah ukuran buffer). Modul readline adalah ~ 1000 baris sementara ini, dengan statistik dan tes, adalah 34.Inilah versi yang lebih pendek, tanpa statistik, pada 19 baris:
sumber
sumber
Saya membungkus seluruh logika pemrosesan garis harian sebagai modul npm: line-kit https://www.npmjs.com/package/line-kit
sumber
Saya menggunakan kode di bawah ini untuk membaca baris setelah memverifikasi bahwa ini bukan direktori dan tidak termasuk dalam daftar file tidak perlu diperiksa.
sumber
Saya telah melihat semua jawaban di atas, semuanya menggunakan perpustakaan pihak ketiga untuk menyelesaikannya. Ini memiliki solusi sederhana di API Node. misalnya
sumber