Scope of Change
Instead of working with integers describing the cell offsets in CSV files, we will add a class CsvMapReader to read data into a map, and a class CsvMapWriter to write data from a map to CSV files.
Rationale
Enable writing code to flexibly deal with changing field order.
Functionality
These classes will complement the "list", "bean" and "object" versions already inside the package text.csv.
Reading
Assuming the following CSV file:
id;realname;email
1549;Timm Friebe;timm@example.com
The current way to deal with this in a way that nothing breaks when the order of the fields changes is:
<?php
$reader= new CsvListReader(new TextReader($input));
$lookup= array_flip($reader->getHeaders());
while ($record= $reader->read()) {
$email= $record[$lookup['email']];
}
?>
With the new CsvMapReader class, this functionality is built in
<?php
$reader= new CsvMapReader(new TextReader($input));
$reader->setKeys($reader->getHeaders());
while ($record= $reader->read()) {
$email= $record['email'];
}
?>
Writing
Writing maps is almost the same as writing lists if we regard this on a per-line basis, since we can simply use array_values() to transform maps into lists. In the mode when we've set no headers, both versions are actually equivalent.
<?php
$writer= new CsvListWriter(new TextWriter($output));
$writer->setHeaders(array('id', 'email'));
$writer->write(array_values(array(
'id' => 1,
'email' => 'thekid@example.com'
)));
?>
The difference is that the order of the headers defines the order in which the record's values are written, so even if our passed map would contain array('email' => '...', 'id' => 1), the order in the file would still be correct with the map writer implementation; while in the list writer implementation the email address would be written to the first field in the output, and id to the second.
<?php
$writer= new CsvMapWriter(new TextWriter($output));
$writer->setHeaders(array('id', 'email'));
$writer->write(array(
'id' => 1,
'email' => 'thekid@example.com'
));
// Also yields correct result
$writer->write(array(
'email' => 'thekid@example.com',
'id' => 1
));
?>
Security considerations
None.
Speed impact
None, just two new classes.
Dependencies
None.
Related documents
http://supercsv.sourceforge.net/javadoc/org/supercsv/io/CsvMapReader.html
http://grails.org/plugin/csv
#191 The original "new CSV API" RFC
Scope of Change
Instead of working with integers describing the cell offsets in CSV files, we will add a class
CsvMapReaderto read data into a map, and a classCsvMapWriterto write data from a map to CSV files.Rationale
Enable writing code to flexibly deal with changing field order.
Functionality
These classes will complement the "list", "bean" and "object" versions already inside the package
text.csv.Reading
Assuming the following CSV file:
id;realname;email 1549;Timm Friebe;timm@example.comThe current way to deal with this in a way that nothing breaks when the order of the fields changes is:
With the new
CsvMapReaderclass, this functionality is built inWriting
Writing maps is almost the same as writing lists if we regard this on a per-line basis, since we can simply use
array_values()to transform maps into lists. In the mode when we've set no headers, both versions are actually equivalent.The difference is that the order of the headers defines the order in which the record's values are written, so even if our passed map would contain
array('email' => '...', 'id' => 1), the order in the file would still be correct with the map writer implementation; while in the list writer implementation the email address would be written to the first field in the output, and id to the second.Security considerations
None.
Speed impact
None, just two new classes.
Dependencies
None.
Related documents
http://supercsv.sourceforge.net/javadoc/org/supercsv/io/CsvMapReader.html
http://grails.org/plugin/csv
#191 The original "new CSV API" RFC