запись в CSV-файл в нескольких ячейках

#csv #perl

#csv #perl

Вопрос:

Я пишу на perl, как вы можете записать в файл csv несколько переменных и поместить каждую из них в отдельную ячейку в одной строке. это часть моего кода:

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

my $input_file = 'pathZONE0.txt';
my $outputfile = 'pathoutputfile.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;
  

это приводит к размещению всех переменных рядом друг с другом в одной ячейке, чего я не хочу. можете ли вы помочь мне разделить переменные.

Комментарии:

1. вы можете использовать модуль Perl Text::CSV_XS для создания файла CSV вместо того, чтобы просто печатать их с помощью обработчика файлов.

2. Также для запроса — это приводит к размещению всех переменных рядом друг с другом в одной ячейке , вы можете объединить @hexDevUID содержимое массива запятой ( , ) и сохранить его в скалярной переменной и распечатать в файле csv.

3. Если вы напечатаете инструкцию печати, как вы делаете в print FH $start, ' ' , print FH $DevType ... , это добавит 1 в печать, потому что успешная инструкция печати возвращает 1. Он также будет печатать сообщения в обратном порядке. Например. print "foo", print "bar" фактически будет печатать barfoo1 .

4. print join(",", @decimal[0,1,5,4,3,2]), "n"; может заменить последние 6 строк вашего while цикла. (Игнорирование значений в @hexDevType , которые вы не используете в своем коде).

Ответ №1:

В файлах CSV нет ячеек. Я подозреваю, что вы открываете файл в программе для работы с электронными таблицами.

Секрет файла CSV заключается в том, что значения разделяются запятыми. Итак, вам нужно поставить запятые между любыми значениями, которые вы хотите отобразить в отдельных ячейках вашей электронной таблицы.

Похоже, что ваши данные находятся в @hexDevUID . Самый простой способ — превратить это в строку, разделенную запятыми, используя join() :

 join(',', @hexDevUID)
  

Но более надежным подходом будет использование Text::CSV_XS.

Ответ №2:

Ниже приведен модифицированный операционный код, который не использует никаких CVS модулей для вывода.

Добавлен код обработки ошибок для ошибки чтения и недостаточного количества прочитанных байтов для дальнейшей обработки.

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

use constant BUFSIZE => 6;

my($buffer,$bytes_read);
my $infile  = shift || 'pathZONE0.txt';
my $outfile = 'pathoutputfile.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("0xx",$_) } @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;
}
  

Цикл может быть переписан с использованием распаковки следующим образом

 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 "0xx", $_ } @devUID;
    
    say $out join(',',($start,$DevType,@hexDevUID));
} while ( $bytes_read );
  

Комментарии:

1. Спасибо за ваши усилия. Я добавлю обработку ошибок в свой код, поскольку он работает просто отлично. Однако это не то, что я просил, мне нужны файлы CSV, и мне нужно, чтобы мои данные были упорядочены по ячейкам. это то, с чем я борюсь в данный момент.

2. @waffles123 — Вы пытались открыть файл CSV в MS Excel, Open Office / Libre Office? Как только файл будет открыт, вы увидите данные в отдельных ячейках. Я надеюсь, что вы откроете файл как файл CSV.