如何在从 NodeJS 中的多个输入流中读取时写入单个文件

Posted

技术标签:

【中文标题】如何在从 NodeJS 中的多个输入流中读取时写入单个文件【英文标题】:How to write a single file while reading from multiple input streams in NodeJS 【发布时间】:2019-10-06 04:34:03 【问题描述】:

如何在使用 NodeJS 从不同位置读取完全相同文件的多个输入流时写入单个文件。

因为它还不清楚可能吗?

我想为下载使用更多性能假设我们有 2 个位置用于同一个文件,每个位置只能执行 10mb 的下行,所以我想从第一个位置和第二个位置并行下载一部分。用 20mb 获得它。

所以两个流都需要以某种方式加入,并且两个流都需要知道它们正在下载的范围。

我有两个例子

var http = require('http')
var fs = require('fs')

// will write to disk __dirname/file1.zip
function writeFile(fileStream)
  //...

// This example assums downloading from 2 http locations
http.request('http://location1/file1.zip').pipe(writeFile)
http.request('http://location2/file1.zip').pipe(writeFile)
var fs = require('fs')

// will write to disk __dirname/file1.zip
function writeFile(fileStream)
  //...


// this example is reading the same file from 2 diffrent disks
fs.readfFile('/mount/volume1/file1.zip').pipe(writeFile)
fs.readfFile('/mount/volume2/file1.zip').pipe(writeFile)

我认为它会如何工作

ReadStream 需要在重新读取每个文件的下一个块之前检查是否已经写入了定义的内容范围,也许它们应该从文件中的随机位置开始读取。

如果总文件内容长度为 X,我们会将其分成更小的块并创建一个映射,其中每个条目都有固定的内容长度,以便我们知道我们得到了哪些部分以及我们总共下载了哪些部分。

我自己试着回答这个问题

我们可以尝试简单的乐观加注

let SIZE = 64; // 64 byte intervals
let buffers = []
let bytesRead = 0  

function readParallel(filepath,callback)
fs.open(filepath, 'r', function(err, fd) 
  fs.fstat(fd, function(err, stats) 
    let bufferSize = stats.size;


    while (bytesRead < bufferSize) 
      let size = Math.min(SIZE, bufferSize - bytesRead);
      let buffer = new Buffer(size),
      let position = bytesRead
      let length = size
      let offset = bytesRead


      let read = fs.readSync(fd, buffer, offset, length, position);
      buffers.push(buffer);  
      bytesRead += read;
    

  );
);

// At the End: buffers.concat() ==== "File Content"

fs.createReadStream() 有一个选项,你可以通过它来指定开始

let f = fs.createReadStream("myfile.txt", start: 1000);

您也可以使用fs.open() 打开一个普通的文件描述符,然后使用fs.read() 的位置参数从您希望流定位的位置之前一个字节的fs.read() 打开一个字节,然后您可以传递该文件描述符到fs.createReadStream() 作为一个选项,并且流将从该文件描述符和位置开始(尽管显然fs.createReadStream()start 选项更简单一些)。

【问题讨论】:

【参考方案1】:

csv-parse 与来自CSV Project 的csv-stringify 结合使用。

const fs = require('fs');
const parse = require('csv-parse');
const stringify = require('csv-stringify')

const stringifier = stringify();
const writeFile = fs.createWriteStream('out.csv');

fs.createReadStream('file1.csv').pipe(parse()).pipe(stringifier).pipe(writeFile);
fs.createReadStream('file2.csv').pipe(parse()).pipe(stringifier).pipe(writeFile);

在这里,我分别解析每个文件(对每个源使用不同的parse 流),然后将两者通过管道连接到连接它们的相同stringify 流,然后写入目标。

【讨论】:

问题是我们谈论的是完全相同的文件,所以它应该简单地从两个位置下载以捆绑 IO。 有什么问题?您可以读取同一个文件两次。只需重命名file2.csv =&gt; file1.csv 就可以了。 问题是我想通过从两个位置并行读取来输出双 IO,而结果是相同的单个文件,如果我从一个位置下载相同的文件系统读写。 所以你想要一些函数来同步两个可读流并确保只输出其中一个?那你为什么需要这两种资源呢?请编辑您的答案并澄清这一点。 好的,现在我明白了。执行这样的任务是相当复杂的。仅供参考,有一款名为 BitTorrent 的免费软件专为此类任务而设计。

以上是关于如何在从 NodeJS 中的多个输入流中读取时写入单个文件的主要内容,如果未能解决你的问题,请参考以下文章

如何从 BluetoothChat 的输入/输出流中读取/写入原始十六进制字节?

如何将多个图像作为输入传递给python脚本

如何从 Python 中的文件/流中懒惰地读取多个 JSON 值?

如何同时从 grpc 流中读取和写入

我如何懒惰地从Rust中的文件/流中读取多个JSON值?

复制文件