Voltar ao blog

Gerenciando CSV no Node.js usando Node-CSV

Gerenciando CSV no Node.js usando Node-CSV

Um CSV arquivo é um arquivo de texto simples que armazena dados em formato tabular. Na maioria dos casos, os arquivos CSV usam vírgulas (,) como delimitador, daí o nome CSV (Comma Separated Values). Ele é usado em situações onde a compatibilidade de dados é uma preocupação, pois os CSVs podem ser abertos com qualquer editor de texto, aplicativos de planilha e outras ferramentas especializadas. Na verdade, muitas linguagens de programação oferecem suporte integrado para CSV.

Neste guia, aprenderemos sobre o uso de CSV em um aplicativo Node.js de exemplo.

CSV no Node.js

O Node.js é um ambiente de execução JavaScript de código aberto e multiplataforma. Ele se tornou um dos backends mais populares, alimentando inúmeros serviços web em toda a internet. Até mesmo grandes empresas como Netflix e Uber usam o Node.js para alimentar seus serviços.

O Node.js também possui inúmeros módulos disponíveis para serem implantados para adicionar funcionalidades extras a um projeto. Quando se trata de CSV, existem muitos módulos disponíveis para uso, por exemplo, node-csv, fast-csv, e papaparse etc.

Como o título do guia sugere, nós vamos usar node-csv para ler arquivos CSV usando streams do Node.js. Também demonstraremos como trabalhar com os dados analisados, por exemplo, transferindo os dados para um banco de dados SQLite .

Pré-requisitos

Step 1 – Installing Necessary Software

Para este guia, criei um servidor leve executando o Ubuntu 22.04 LTS (conectado via SSH):

Agora, instalaremos o Node.js e o SQLite nele.

  • Instalando o Node.js LTS

O Node.js está disponível diretamente nos repositórios oficiais de pacotes do Ubuntu. No entanto, não é a versão mais atualizada. É por isso que vamos contar com um repositório de terceiros (Nodesource) para obter os pacotes mais recentes do Node.js.

Adicione o repositório para o Node.js LTS:

Agora, instale o Node.js LTS:

  • Instalar o SQLite

Instalaremos o SQLite diretamente dos repositórios de pacotes do Ubuntu. Execute os seguintes comandos:

Step 2 – Project Directory Setup

Nesta seção, prepararemos um diretório dedicado para o nosso projeto. Ele hospedará todos os arquivos do projeto junto com módulos adicionais.

Crie um novo diretório:

Navegue para dentro do diretório:

Em seguida, execute o seguinte comando para declarar o diretório como um projeto npm :

Assim que a pasta do projeto for inicializada, podemos começar a instalar os pacotes e módulos necessários. Primeiro, vamos instalar o node-csv:

O módulo node-csv é na verdade uma coleção de vários outros módulos: csv-generate, csv-parse (análise de arquivos CSV), csv-stringify (gravação de dados em CSV) e stream-transform.

Em seguida, precisamos do módulo para comunicação com o SQLite. O seguinte comando instalará o módulo node-sqlite3 :

O componente que precisamos para o nosso projeto é um arquivo CSV. Para fins de demonstração, usaremos o arquivo CSV de migração da Nova Zelândia:

Vamos dar uma olhada rápida no conteúdo do arquivo:

Aqui,

  • A primeira linha descreve os nomes das colunas.

  • As linhas subsequentes contêm os valores para esses campos.

  • Cada linha é separada por uma nova linha (\n).

  • Cada ponto de dados é separado por uma vírgula (,).

No entanto, o CSV não está limitado ao uso de vírgulas como delimitador. Outros delimitadores comuns incluem dois-pontos (:), pontos e vírgulas (;) e tabulações (\td).

Passo 3 – Lendo CSV

Nesta seção, demonstraremos a implementação de um programa de exemplo que lê e analisa dados do arquivo CSV.

Crie um novo arquivo JavaScript:

Abra o arquivo em seu editor de texto favorito:

Primeiro, vamos importar os módulos fs e csv-parse:

Aqui,

  • Primeiro, a variável fs recebe o objeto fs que retorna o método require() do Node.js ao importar o módulo.

  • Em seguida, o método parse é extraído do objeto retornado pelo método require() para a variável parse usando a sintaxe de desestruturação.

A seguir, vamos adicionar o código para ler o arquivo CSV:

Aqui,

  • Estamos invocando o createReadStream() do módulo fs e passando o arquivo CSV que queremos ler como argumento. Ele então cria um fluxo de leitura (readable stream) dividindo o arquivo maior em pedaços menores.

  • Após criar o fluxo, o método pipe() encaminha pedaços dos dados do fluxo para outro fluxo. Este novo fluxo é criado ao invocar o método parse() do módulo csv-module.

  • O módulo csv-module implanta um fluxo de transformação de leitura/escrita (readable/writable transform stream) que recebe um pedaço de dados e o transforma em outra forma.

  • O método parse() aceita objetos com propriedades. O objeto processa adicionalmente os dados analisados. Aqui, o objeto está recebendo as seguintes propriedades:

    • delimiter: O caractere delimitador para separar os valores. No caso do nosso CSV de destino, é a vírgula (,).

    • from_line: O número de linhas a partir de onde o analisador começará a analisar. Com o valor fornecido de 2, o analisador ignorará a linha 1 e começará na linha 2. Com essa disposição, evitamos que os nomes das colunas sejam integrados aos dados analisados.

A seguir, vamos anexar um evento de fluxo usando o método on() do Node.js:

Aqui,

  • Ao emitir um determinado evento, um evento de fluxo permite que um método consuma um pedaço de dados.

  • Quando os dados analisados pelo método parse() estão prontos para serem consumidos, ele aciona o evento data.

  • Para acessar os dados, estamos passando uma função de retorno (callback) para o método on() que recebe um parâmetro row.

  • O parâmetro row é um pedaço de dados na forma de um array (resultado da análise).

  • Finalmente, os dados são registrados no console usando console.log().

Para finalizar o programa, vamos adicionar eventos de fluxo adicionais para tratar erros e exibir uma mensagem de sucesso quando todos os dados do arquivo CSV forem consumidos. Atualize o código da seguinte forma:

Aqui,

  • O evento end é emitido quando todos os dados no arquivo CSV são consumidos. Isso resulta na chamada do console.log() método que imprime uma mensagem de sucesso.

  • O evento error é emitido ao encontrar um erro ao analisar os dados do CSV. Isso resulta na chamada do console.log() método que imprime uma mensagem de erro.

O código final deve ficar assim:

Salve o arquivo e feche o editor. Agora estamos prontos para executar o programa. Execute-o usando o Node.js:

A saída deve ser algo parecido com isto:

Observe que os dados são consumidos, transformados e impressos no console. Como é um processo contínuo, parecerá que os dados estão sendo baixados em vez de imprimir a saída de uma só vez.

Passo 4 – Transferindo Dados CSV para um Banco de Dados

Até agora, aprendemos como analisar um arquivo CSV usando o node-csv. Esta seção demonstrará a transferência dos dados analisados para um banco de dados (SQLite).

Crie um novo arquivo JavaScript para interagir com o banco de dados:

Agora, abra o arquivo em um editor de texto:

Começaremos nosso programa com os seguintes códigos:

Aqui,

  • Na primeira linha, estamos importando o módulo fs.

  • Na terceira linha, a variável filepath contém o caminho do banco de dados SQLite.

  • Neste ponto, o banco de dados ainda não existe. No entanto, ele será necessário ao trabalhar com o node-sqlite3.

Em seguida, adicione as seguintes linhas para estabelecer uma conexão com o banco de dados SQLite:

Aqui,

  • O método connectoToDatabase() estabelece uma conexão com o banco de dados.

  • Dentro de connectToDatabase(), estamos invocando o método existsSync() do módulo fs dentro de uma instrução if. A instrução if verifica a existência do banco de dados no local especificado.

    • Se a avaliação da condição for true, então a classe Database() do módulo node-sqlite3 é instanciada. Uma vez estabelecida a conexão, a função retorna um objeto e sai.

    • Se a avaliação da condição for false (o banco de dados não existe), então a execução saltará para o bloco else. Lá, a classe Database() será iniciada com dois argumentos: um caminho para o arquivo do banco de dados e um callback.

Basicamente, o banco de dados será criado se não existir. No entanto, se ocorrer algum erro durante o processo de criação, ele definirá o objeto error e imprimirá a mensagem de erro.

A seguir, vamos introduzir códigos para criar uma tabela se o banco de dados não existir:

Aqui,

  • O método connectToDatabase() invoca a função createTable() que aceita os objetos armazenados em db como argumento.

  • Fora de connectToDatabase(), definimos o método createTable() que aceita o objeto de conexão db como parâmetro.

  • O método exec() em db recebe uma instrução SQL como argumento. Dentro desta instrução SQL, definimos a criação de uma tabela migration com 7 colunas, cada coluna correspondendo aos cabeçalhos das colunas no arquivo migration_data.csv .

  • Finalmente, estamos invocando o connectToDatabase() método e exportando o objeto de conexão que ele retorna para que possamos usá-lo em outros arquivos.

Save the file and close the editor.

A seguir, vamos criar outro programa para inserir os dados analisados no banco de dados:

Insira o seguinte código em insert_data.js:

Aqui,

  • Estamos armazenando o objeto de conexão obtido de csv-to-sqlite3.js na variável db.

  • Dentro do callback do evento data (anexado ao stream do módulo fs), estamos invocando o serialize() método no objeto de conexão. Ele garante que uma instrução SQL termine de ser executada antes que a próxima comece, evitando condições de corrida no banco de dados (sistema executando operações concorrentes simultaneamente).

  • O serialize() aceita três argumentos:

    • O primeiro argumento é a instrução SQL.

    • O segundo argumento é um array.

    • O terceiro argumento é um callback que é executado quando os dados são inseridos com sucesso ou sem sucesso no banco de dados.

Estamos prontos para executar o programa. Execute insert_data.js usando o Node.js:

Dependendo do desempenho do sistema, o processo pode levar algum tempo para terminar. No entanto, após a conclusão, a saída deve ser parecida com esta:

Passo 5 – Gravando Dados em CSV

Após a última seção, temos um banco de dados contendo todos os registros que analisamos de migration_data.csv. Nesta seção, vamos ler os dados do banco de dados e gravá-los em um arquivo CSV separado.

Crie um novo arquivo JavaScript para armazenar o programa:

Primeiro, adicione as seguintes linhas para importar fs e csv-stringify  junto com o objeto de conexão do banco de dados de csv-to-sqlite3.js:

Em seguida, vamos adicionar uma variável que contém o nome do arquivo CSV no qual gravar, junto com um fluxo de gravação (writable stream):

Aqui,

  • O createWriteStream() aceita o nome do arquivo para gravação como um argumento. Vamos nomear o arquivo saved_from_db.csv.

  • A column armazena um array que contém todos os nomes do cabeçalho para os dados do CSV.

Em seguida, adicione as seguintes linhas de código para ler os dados do banco de dados e gravá-los em saved_from_db.csv:

Aqui,

  • Estamos invocando o método stringify() com um objeto como argumento. Isso resulta em um fluxo de transformação (transform stream) que converte os dados de um objeto para o formato CSV. O objeto passado para stringify() possui duas propriedades:

    • header: Aceita um valor booleano. Se o valor for true, então um cabeçalho é gerado.

    • columns: Aceita um array que contém os nomes das colunas a serem gravados na primeira linha do arquivo CSV se header for true.

  • O método each() do objeto de conexão csv-to-sqlite3 é invocado com dois argumentos: a instrução SQL (lendo dados do banco de dados) e um callback (tratando sucesso/erro).

  • A cada iteração de each(), pipe() (do fluxo stringifier) começa a enviar dados em partes para o fluxo de gravação writableStream. Cada parte de dados é então gravada em saved_from_db.csv.

  • Quando todos os dados forem gravados no arquivo CSV, uma mensagem de sucesso será exibida na tela do console.

O código final deve ficar assim:

Salve o arquivo e feche o editor. Agora podemos executar o programa usando o Node.js:

Para confirmar se os dados foram exportados com sucesso, verifique o conteúdo de saved_from_db.csv:

Considerações Finais

Neste guia, demonstramos como trabalhar com arquivos CSV no Node.js usando os módulos node-csv e node-sqlite3. Criamos vários programas para realizar diversas tarefas, por exemplo, analisar dados de um CSV, inserir os dados em um banco de dados SQLite e gravar dados em um novo arquivo CSV.

Este guia demonstra apenas uma pequena parte da capacidade do node-csv módulo. Saiba mais sobre todos os seus recursos em CSV Project. Para saber mais sobre o node-sqlite3, confira a documentação oficial no GitHub. Outro módulo que vale a pena mencionar é o event-stream para simplificar o trabalho com streams.

Interessado em expandir ainda mais seu projeto Node.js? Aqui estão alguns tutoriais de Node.js que você deve conferir:

Boa computação!

author

Preslav Dobrev

Autor · CloudSigma

Preslav Dobrev é um designer criativo na CloudSigma, focado na construção de uma identidade empresarial consistente por meio de canais de marketing tradicionais e inovadores. Ele é hábil em combinar a visão artística com o marketing estratégico para criar narrativas de marca impactantes.

Comentários

Nenhum comentário ainda. Seja o primeiro.