Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use Text::CSV_XS to parse a csv-format string without writing it to disk?

I am getting a "csv file" from a vendor (using their API), but what they do is just spew the whole thing into their response. It wouldn't be a significant problem except that, of course, some of those pesky humans entered the data and put in "features" like line breaks. What I am doing now is creating a file for the raw data and then reopening it to read the data:

open RAW, ">", "$rawfile" or die "ERROR: Could not open $rawfile for write: $! \n";
print RAW $response->content;
close RAW;

my $csv = Text::CSV_XS->new({ binary=>1,always_quote=>1,eol=>$/ });
open my $fh, "<", "$rawfile" or die "ERROR: Could not open $rawfile for read: $! \n";

while ( $line = $csv->getline ($fh) ) { ...

Somehow this seems ... inelegant. It seems that I ought to be able to just read the data from the $response->content (multiline string) as if it were a file. But I'm drawing a total blank on how do this. A pointer would be greatly appreciated. Thanks, Paul

like image 212
Paul R N Avatar asked Mar 23 '20 17:03

Paul R N


People also ask

How to Pars CSV files in Python?

Parsing CSV files in Python is quite easy. Python has an inbuilt CSV library which provides the functionality of both readings and writing the data from and to CSV files. There are a variety of formats available for CSV files in the library which makes data processing user-friendly. Reading CSV files using the inbuilt Python CSV module.

How do I configure the CSV parser in the toolbox?

You can insert and configure the CSV parser node as follows: Click the (+) icon, go to the Toolbox tab, and then click CSV parser. Figure 2. Selecting the CSV parser from the Toolbox tab (Click image to view full size.) Use the CSV Input field to indicate which data from the previous action or event should be parsed.

How do I use the output of a CSV parser node?

The output from a CSV parser node is an array. So, to use this output in a subsequent node in the flow, you'd typically include a For each node after the CSV parser node to iterate through the array, or you could manipulate the array data by using JSONata.

What is the CSV file format?

"How To: The Comma Separated Value (CSV) File Format" ( 3) provides an overview of the CSV format in the most widely used applications and explains how it can best be used and supported. CSV is a delimited data format that has fields/columns separated by the comma character and records/rows separated by newlines.


2 Answers

You could use a string filehandle:

my $data = $response->content;
open my $fh, "<", \$data or croak "unable to open string filehandle : $!";
my $csv = Text::CSV_XS->new({ binary=>1,always_quote=>1,eol=>$/ });
while ( $line = $csv->getline ($fh) ) { ... }
like image 169
GMB Avatar answered Sep 19 '22 15:09

GMB


Yes, you can use Text::CSV_XS on a string, via its functional interface

use warnings;
use strict;
use feature 'say';

use Text::CSV_XS qw(csv);  # must use _XS version

my $csv = qq(a,line\nand,another);

my $aoa = csv(in => \$csv) 
    or die Text::CSV->error_diag; 

say "@$_" for @aoa;    

Note that this indeed needs Text::CSV_XS (normally Text::CSV works but not with this).

I don't know why this isn't available in the OO interface (or perhaps is but is not documented).


While the above parses the string directly as asked, one can also lessen the "inelegant" aspect in your example by writing content directly to a file as it's acquired, what most libraries support like with :content_file option in LWP::UserAgent::get method.

Let me also note that most of the time you want the library to decode content, so for LWP::UA to use decoded_content (see HTTP::Response).

like image 24
zdim Avatar answered Sep 19 '22 15:09

zdim