Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 8fba112b

Von Sven Schöling vor mehr als 13 Jahren hinzugefügt

  • ID 8fba112bb1c6690d673d2c624d64353bca70ba0e
  • Vorgänger 2f6ebd89
  • Nachfolger f9f7b56e

CSV: Errorhandling

Parser umgeschrieben, eof muss nach getline prüfen (bekloppt).
Errorhandling aktiviert. Dokumentation aktualisiert.

Unterschiede anzeigen:

SL/Helper/Csv.pm
8 8
use Text::CSV;
9 9
use Params::Validate qw(:all);
10 10
use Rose::Object::MakeMethods::Generic scalar => [ qw(
11
   file encoding sep_char quote_char header header_acc class numberformat
12
   dateformat _io _csv _objects _parsed _data
11
   file encoding sep_char quote_char escape_char header header_acc class
12
   numberformat dateformat _io _csv _objects _parsed _data _errors
13 13
) ];
14 14

  
15 15

  
......
20 20
  my %params = validate(@_, {
21 21
    sep_char      => { default => ';' },
22 22
    quote_char    => { default => '"' },
23
    escape_char   => { default => '"' },
23 24
    header        => { type    => ARRAYREF, optional => 1 },
24 25
    header_acc    => { type    => HASHREF,  optional => 1 },
25 26
    file          => 1,
......
35 36
  $self->_io(IO::File->new);
36 37
  $self->_csv(Text::CSV->new({
37 38
    binary => 1,
38
    sep_char   => $self->sep_char,
39
    quote_char => $self->quote_char,
39
    sep_char    => $self->sep_char,
40
    quote_char  => $self->quote_char,
41
    escape_char => $self->escape_char,
40 42

  
41 43
  }));
44
  $self->_errors([]);
42 45

  
43 46
  return $self;
44 47
}
......
67 70
  return wantarray ? @{ $self->_objects } : $self->_objects;
68 71
}
69 72

  
73
sub errors {
74
  @{ $_[0]->_errors }
75
}
76

  
70 77
# private stuff
71 78

  
72 79
sub _open_file {
......
91 98

  
92 99
sub _parse_data {
93 100
  my ($self, %params) = @_;
94
  my @data;
101
  my (@data, @errors);
95 102

  
96 103
  $self->_csv->column_names(@{ $self->header });
97 104

  
98
  push @data, $self->_csv->getline_hr($self->_io)
99
    while !$self->_csv->eof;
105
  while (1) {
106
    my $row = $self->_csv->getline($self->_io);
107
    last if $self->_csv->eof;
108

  
109
    if ($row) {
110
      my %hr;
111
      @hr{@{ $self->header }} = @$row;
112
      push @data, \%hr;
113
    } else {
114
      push @errors, [
115
        $self->_csv->error_input,
116
        $self->_csv->error_diag,
117
        $self->_io->input_line_number,
118
      ];
119
    }
120
  }
100 121

  
101 122
  $self->_data(\@data);
123
  $self->_errors(\@errors);
124

  
125
  return if @errors;
126
  return \@data;
102 127
}
103 128

  
104 129
sub _encode_layer {
......
134 159

  
135 160
__END__
136 161

  
162
=encoding utf-8
163

  
137 164
=head1 NAME
138 165

  
139 166
SL::Helper::Csv - take care of csv file uploads
......
153 180
  )
154 181

  
155 182
  my $status  = $csv->parse;
156
  my @hrefs   = $csv->get_data;
183
  my $hrefs   = $csv->get_data;
157 184
  my @objects = $scv->get_objects;
158 185

  
159 186
=head1 DESCRIPTION
......
182 209

  
183 210
Parse the data into objects and return those.
184 211

  
212
This method will return list or arrayref depending on context.
213

  
185 214
=item C<get_data>
186 215

  
187 216
Returns an arrayref of the raw lines as hashrefs.
188 217

  
218
=item C<errors>
219

  
220
Return all errors that came up druing parsing. See error handling for detailed
221
information.
222

  
223
=back
224

  
225
=head1 PARAMS
226

  
227
=over 4
228

  
189 229
=item C<file>
190 230

  
191 231
The file which contents are to be read. Can be a name of a physical file or a
......
200 240

  
201 241
=item C<quote_char>
202 242

  
243
=item C<escape_char>
244

  
203 245
Same as in L<Text::CSV>
204 246

  
205 247
=item C<header> \@FIELDS
......
223 265

  
224 266
=back
225 267

  
226
=head1 BUGS
268
=head1 ERROR HANDLING
269

  
270
After parsing a file all errors will be accumulated into C<errors>.
271

  
272
Each entry is an arrayref with the following structure:
273

  
274
 [
275
   offending raw input,
276
   Text::CSV error code if present,
277
   Text::CSV error diagnostics if present,
278
   position in line,
279
   estimated line in file,
280
 ]
281

  
282
Note that the last entry can be off, but will give an estimate.
283

  
284
=head1 CAVEATS
285

  
286
=over 4
287

  
288
=item *
289

  
290
sep_char, quote_char, and escape_char are passed to Text::CSV on creation.
291
Changing them later has no effect currently.
292

  
293
=item *
294

  
295
Encoding errors are not dealt with properly.
296

  
297
=item *
298

  
299
Errors are not gathered.
300

  
301
=back
227 302

  
228 303
=head1 AUTHOR
229 304

  
305
Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
306

  
230 307
=cut
t/helper/csv.t
6 6
my $csv;
7 7

  
8 8
$csv = SL::Helper::Csv->new(
9
  file   => \"Kaffee;\n",
9
  file   => \"Kaffee\n",
10 10
  header => [ 'description' ],
11 11
);
12 12

  
......
111 111
);
112 112
is $csv->parse, undef, 'broken csv header won\'t get parsed';
113 113

  
114
######
115

  
116
$csv = SL::Helper::Csv->new(
117
  file   => \<<EOL,
118
description;partnumber;sellprice;lastcost_as_number;
119
"Kaf"fee";;0.12;1,221.52
120
Beer;1123245;0.12;1.5234
121
EOL
122
  numberformat => '1,000.00',
123
  class  => 'SL::DB::Part',
124
);
125
is $csv->parse, undef, 'broken csv content won\'t get parsed';
126
is_deeply $csv->errors, [ '"Kaf"fee";;0.12;1,221.52'."\n", 2023, 'EIQ - QUO character not allowed', 5, 2 ], 'error';
114 127

  
115 128
done_testing();
116 129
# vim: ft=perl

Auch abrufbar als: Unified diff