graff has asked for the wisdom of the Perl Monks concerning the following question:

I want to use Text::xSV to handle some csv-type data. Problem is: the data is coming in via LWP::Simple, and I'd rather not take the trouble to save it to disk so that I can read it back as a file with Text::xSV.

It appears (based on the module's pod), that the only way to start the csv parsing process with this module is to "open a csv file". So, since the "file" starts out as a scalar variable in my case, I'd like to know if there's some way to associate a "file handle" with the scalar value, so that I can initialize the Text::xSV object with that file handle as input.

In other words, I want to fill in the blank in the example snippet below:

use strict; use Encode; # I'm getting utf8 data use LWP::Simple; use Text::xSV; my $fh; my $csv_url = "http://someplace/that/sends/data.csv"; my $content = decode( 'utf8', get( $csv_url )); # HERE IS THE BLANK TO FILL IN: # associate $fh (as file handle) with $content (as file data) # then: my $csv = Text::xSV( fh => $fh ); # or something like that(?) $csv->read_header; while ( $csv->get_row ) { # and so on }
BTW, please don't mention Text::CSV. That module has not been updated since it was uploaded to CPAN nine years ago. It's old, it's ugly, and it can only handle ASCII data (even accented characters in Latin1 will produce a "parse error", let alone anything like wide-characters). Unless/until Text::CSV is updated with significant improvements, I won't use or recommend it (and I regret having recommended it in the past). I wish I had time to fix it, since it's often the first one that folks find for doing csv work, but Text::xSV is already there, and hard to improve on.

I've already established that Text::xSV will handle utf8 wide character data without difficulty. I just would like to feed it input from a scalar (or an array of lines, whatever).

TIA

(updated the code snippet to fix the "Text::xSV->new" call, which originally had a couple different mistakes in it.)

(updated commentary on Text::CSV thanks to the behavior-modification powers of XP)

Replies are listed 'Best First'.
Re: Treating a scalar as an "input file"
by Hofmator (Curate) on Aug 11, 2006 at 06:50 UTC
    my $fh = IO::Scalar->new(\$content);

    See IO::Scalar.

    -- Hofmator

Re: Treating a scalar as an "input file"
by Ieronim (Friar) on Aug 11, 2006 at 06:56 UTC
    Since Perl 5.8:
    open(my $fh,'+<', \$content);

         s;;Just-me-not-h-Ni-m-P-Ni-lm-I-ar-O-Ni;;tr?IerONim-?HAcker ?d;print
Re: Treating a scalar as an "input file"
by davido (Cardinal) on Aug 11, 2006 at 15:11 UTC

    It takes some "fine print" reading to find it, but here's the relevant commentary in open:

    Since v5.8.0, perl has built using PerlIO by default. Unless you've changed this (i.e. Configure -Uuseperlio), you can open file handles to "in memory" files held in Perl scalars via:

    open($fh, '>', \$variable) || ..

    Of course in your case you'll want to open the in memory file for reading, not writing. Then all you'll have to do is pass that filehandle to Text::xSV as you demonstrated in your original post. That ought to do the trick.


    Dave

Re: Treating a scalar as an "input file"
by diotalevi (Canon) on Aug 11, 2006 at 15:24 UTC

    I wouldn't recommend Text::CSV either but mostly because it never worked well for me. Text::CSV_XS *is* maintained and by our very own jZed who has a bunch of other modules as well. Text::xSV is by tilly. I never bothered with it because I already had something spiffy.

    Of course, updates per year aren't important either. If the author of Text::CSV had handled the parsing difficulties nince years ago, it's be perfectly fine to have no updates for all that time. You only update something when it needs changes.

    use Text::CSV_XS; # which is maintained by jZed and well loved by all # Read it as a handle w/ binary if newlines might be embedded in your +data my $csv = Text::CSV_XS->new( binary => 1 ); open my $fh, \ $your_string; while ( my $columns = $csv->getline( $fh ) ) { ... } # Or just read it like a string if you never have newlines inside a va +lue. while ( $str =~ /(.+)/g ) { my $line = $1; my $columns = $csv->parse( $line ); }

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊