Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将csv解析输出保存到变量_Javascript_Node.js - Fatal编程技术网

Javascript 将csv解析输出保存到变量

Javascript 将csv解析输出保存到变量,javascript,node.js,Javascript,Node.js,我不熟悉使用csv解析,这个来自项目github的示例可以满足我的需要,但有一个例外。我希望将数据存储在变量中,而不是通过console.log输出。我曾尝试将fs行赋给一个变量,然后返回数据,而不是记录它,但这只是返回了一大堆我不理解的东西。最终目标是将CSV文件导入SQLite var fs = require('fs'); var parse = require('..'); var parser = parse({delimiter: ';'}, function(err, data)

我不熟悉使用csv解析,这个来自项目github的示例可以满足我的需要,但有一个例外。我希望将数据存储在变量中,而不是通过console.log输出。我曾尝试将fs行赋给一个变量,然后返回
数据
,而不是记录它,但这只是返回了一大堆我不理解的东西。最终目标是将CSV文件导入SQLite

var fs = require('fs');
var parse = require('..');

var parser = parse({delimiter: ';'}, function(err, data){
  console.log(data);
});

fs.createReadStream(__dirname+'/fs_read.csv').pipe(parser);
以下是我尝试过的:

const fs = require("fs");
const parse = require("./node_modules/csv-parse");

const sqlite3 = require("sqlite3");
// const db = new sqlite3.Database("testing.sqlite");

let parser = parse({delimiter: ","}, (err, data) => {
    // console.log(data);
    return data;
});

const output = fs.createReadStream(__dirname + "/users.csv").pipe(parser);
console.log(output);

这是一个让人对异步流API感到困惑的问题,似乎至少要问三件事

  • 如何获取
    输出
    以包含表示已解析CSV数据的数组
  • 由于异步API是如何运行的,
    输出将永远不会像您(和许多其他程序员)所希望的那样存在于顶级。所有整齐地组合在一个地方的数据只能存在于回调函数中。从语法上来说,下一个最好的方法是
    const output=wait somePromiseOfOutput()
    ,但这只能发生在
    异步函数中,并且只有在我们从流切换到承诺时才会发生。这一切都是可能的,我提到这一点是为了让你以后可以自己查看。我假设你想坚持使用streams

    只有在读取整个流之后,才能存在由所有行组成的数组。这就是为什么在作者的“Stream API”示例中,所有行仅在
    .on('end',…)
    回调中可用的原因。如果您想对同时存在的所有行执行任何操作,则需要在结束回调中执行

    请注意,作者:

  • 使用on-readable回调将单个记录推入以前在外部定义的空数组,该数组名为
    output
  • 使用on error回调来报告错误
  • 使用on-end回调将输出中的所有累积记录与预期结果进行比较
  • 
    ...
    常量输出=[]
    ...
    on('readable',function(){
    记录
    while(record=parser.read()){
    输出推送(记录)
    }
    })
    //抓住任何错误
    parser.on('error',函数(err){
    控制台错误(错误消息)
    })
    //完成后,测试解析的输出是否符合预期
    on('end',function(){
    主张平等(
    产出,
    [
    ['root'、'x'、'0'、'0'、'root'、'/root'、'/bin/bash'],
    ['someone'、'x'、'1022'、'1022'、''、'/home/someone'、'/bin/bash']
    ]
    )
    })
    

  • 至于与sqlite接口的目标,这实质上是构建一个定制的流端点 在这个用例中,它接受解析器的输出并将行发送到数据库

    然后,您只需将管道调用链接为

    
    fs.createReadStream(uu dirname+'/fs_read.csv')
    .pipe(解析器)
    .pipe(您的\u可写\u流)
    

    小心:此代码立即返回。它不会等待操作完成。它与node.js内部的隐藏事件循环交互。事件循环经常使来自另一种语言、习惯于更命令式风格的新开发人员感到困惑,并跳过了node.js培训的这一部分

    实现这样一个定制的可写流可能会变得复杂,留给读者作为练习。如果解析器发出一行,那么编写器就可以处理单行,这将是最简单的。确保您能够以某种方式注意到错误并抛出适当的异常,否则您将被诅咒,结果不完整,没有警告或原因

    用一个自定义函数
    writeRowToSqlite(data)
    替换
    let parser=…
    中的
    console.log(data)
    ,您无论如何都必须编写该函数才能实现自定义流。由于异步API问题,使用
    返回数据
    没有任何用处。正如您所看到的,它当然无法将数据放入输出变量


  • 至于为什么修改后的帖子中的
    输出
    不包含数据
  • 不幸的是,正如您所发现的,这通常是错误的:

    
    const output=fs.createReadStream(uu dirname+“/users.csv”).pipe(解析器);
    控制台日志(输出);
    


    这里,变量
    输出将是a,它与可读流中包含的数据不同。简单地说,这就像文件系统中有一个文件一样,您可以获取有关该文件的各种系统信息,但文件中包含的内容是通过不同的调用访问的

    我也在努力找出如何将数据从csv解析返回到调用解析的顶层。具体地说,我试图在处理结束时获取parser.info数据,以查看是否成功,但如果需要,解决方案也可以用于获取行数据

    关键是将所有流事件侦听器包装成一个承诺,并在解析器的回调中解析该承诺

    function startFileImport(myFile) {
    
      // THIS IS THE WRAPPER YOU NEED
      return new Promise((resolve, reject) => {
    
        let readStream = fs.createReadStream(myFile);
    
        let fileRows = [];
        const parser = parse({
          delimiter: ','
        });
    
        // Use the readable stream api
        parser.on('readable', function () {
          let record
          while (record = parser.read()) {
            if (record) { fileRows.push(record); }
          }
        });
    
        // Catch any error
        parser.on('error', function (err) {
          console.error(err.message)
        });
    
        parser.on('end', function () {
          const { lines } = parser.info;
          // RESOLVE OUTPUT THAT YOU WANT AT PARENT-LEVEL
          resolve({ status: 'Successfully processed lines: ', lines });
        });
    
        // This will wait until we know the readable stream is actually valid before piping                
        readStream.on('open', function () {
          // This just pipes the read stream to the response object (which goes to the client)
          readStream.pipe(parser);
        });
    
        // This catches any errors that happen while creating the readable stream (usually invalid names)
        readStream.on('error', function (err) {
          resolve({ status: null, error: 'readStream error' + err });
        });
    
      });
    }
    

    如果您的目标只是将一个csv文件导入sqlite,那么您可以放弃node.js,直接从sqlite使用。您还可以从node.js生成一个进程,该进程将运行一个shell脚本并执行导入过程。这比我预期的答案要多得多!谢谢:)看来我有很多书要读。谁会想到这么简单的概念会变得如此困难?我想我会同意你在原始帖子中的建议,只是为了让我振作起来。我将此标记为答案,因为它回答了我的问题。再次感谢。