waffles123
waffles123

Reputation: 19

write into a csv file in multiple cells

I am coding in perl, how can you write into a csv file multiple variables and put each one in a separate cell in the same line. this a part of my Code:

#!/usr/bin/perl
use feature qw(say);
use strict;
use warnings;
use constant BUFSIZE => 6;
my $year += 1900;

my $input_file = 'path\ZONE0.txt';
my $outputfile = 'path\outputfile.csv';
open (my $BIN, "<:raw", $input_file) or die "can't open the file $input_file: $!";
my $buffer;
open(FH, '>>', $outputfile) or die $!;
while (1) {
    my $bytes_read = sysread $BIN, $buffer, BUFSIZE;
    die "Could not read file $input_file: $!" if !defined $bytes_read;
    last if $bytes_read <= 0;
    my @decimal= map { unpack "C", $_ } split //, $buffer;
    
    my $start= $decimal[0];
    
    my $DevType = $decimal[1];
    my @hexDevType = sprintf("0x%x", $DevType); 
    
    my @DevUID =($decimal[5], $decimal[4], $decimal[3], $decimal[2]);
    my @hexDevUID = map { sprintf("0x%x",$_) } @DevUID; 
    print FH $start, ' ' , print FH $DevType,' ',  @hexDevUID , "\n";
}

close $BIN;

this results in puting all the variable next to each other in one cell, which is not what I want. can you help me separate the variables.

Upvotes: 0

Views: 254

Answers (2)

Polar Bear
Polar Bear

Reputation: 6798

Bellow is modified OPs code which does not utilize any CVS modules for output.

Added error handling code for read error and insufficient number of read bytes for further processing.

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

use constant BUFSIZE => 6;

my($buffer,$bytes_read);
my $infile  = shift || 'path\ZONE0.txt';
my $outfile = 'path\outputfile.csv';

open my $in, '<:raw', $infile
    or die "Can't open $infile: $!";

open my $out, '+>>', $outfile
    or die "Can't open $outfile: $!";

do {
    $bytes_read = sysread $in, $buffer, BUFSIZE;
    
    die "Error: read from $infile: $!"  unless defined $bytes_read;
    error_handler($bytes_read)          unless $bytes_read == 6;

    my @decimal = map { ord } split //, $buffer;
    my($start,$DevType) = @decimal[0,1];
    my @hexDevUID = map { sprintf("0x%02x",$_) } @decimal[5,4,3,2];
    
    say $out join(',',($start,$DevType,@hexDevUID));
} while ( $bytes_read );

sub error_handler {
    my $bytes = shift;
    
    close $out;
    close $in;
    
    say "
        Error: called error_handler(\$read_bytes)
            Action: Emergency file closure to preserve data
            Cause:  Read insufficient $bytes bytes
    " unless $bytes == 0;

    exit $bytes ? 1 : 0;
}

The loop can be rewritten with use of unpack like following

do {
    $bytes_read = sysread $in, $buffer, BUFSIZE;
    
    die "Error: read from $infile: $!"  unless defined $bytes_read;
    error_handler($bytes_read)          unless $bytes_read == 6;

    my($start,$DevType,@devUID) = unpack('CCC4',$buffer);
    my @hexDevUID = reverse map { sprintf "0x%02x", $_ } @devUID;
    
    say $out join(',',($start,$DevType,@hexDevUID));
} while ( $bytes_read );

Upvotes: 1

Dave Cross
Dave Cross

Reputation: 69244

CSV files don't have cells. I suspect you're opening the file in a spreadsheet program.

The secret of a CSV file is that the values are separated by commas. So you need to put commas between any values that you want to appear in separate cells in your spreadsheet.

It looks like your data is in @hexDevUID. The simplest way is to turn that into a comma-separated string using join():

join(',', @hexDevUID)

But the more robust approach will be to use Text::CSV_XS.

Upvotes: 4

Related Questions