commons-csv-1.2-src/checkstyle.xml0100644 0000000 0000000 00000005126 12565700105 022130 0ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/LICENSE-header.txt0100644 0000000 0000000 00000001463 12565677765 022352 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ commons-csv-1.2-src/LICENSE.txt0100644 0000000 0000000 00000026450 12565700104 021075 0ustar00BUILTIN\Administrators0000000 0000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. commons-csv-1.2-src/NOTICE.txt0100644 0000000 0000000 00000002106 12565700104 020764 0ustar00BUILTIN\Administrators0000000 0000000 Apache Commons CSV Copyright 2005-2015 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). src/main/resources/contract.txt This file was downloaded from http://www.ferc.gov/docs-filing/eqr/soft-tools/sample-csv/contract.txt and contains neither copyright notice nor license. src/main/resources/transaction.txt This file was downloaded from http://www.ferc.gov/docs-filing/eqr/soft-tools/sample-csv/transaction.txt and contains neither copyright notice nor license. src/test/resources/CSVFileParser/bom.csv src/test/resources/CSVFileParser/test.csv src/test/resources/CSVFileParser/test_default.txt src/test/resources/CSVFileParser/test_default_comment.txt src/test/resources/CSVFileParser/test_rfc4180.txt src/test/resources/CSVFileParser/test_rfc4180_trim.txt src/test/resources/CSVFileParser/testCSV85.csv src/test/resources/CSVFileParser/testCSV85_default.txt src/test/resources/CSVFileParser/testCSV85_ignoreEmpty.txt These files are used as test data and test result specifications. commons-csv-1.2-src/pom.xml0100644 0000000 0000000 00000043706 12565700247 020602 0ustar00BUILTIN\Administrators0000000 0000000 4.0.0 org.apache.commons commons-parent 38 org.apache.commons commons-csv 1.2 Apache Commons CSV http://commons.apache.org/proper/commons-csv/ The Apache Commons CSV library provides a simple interface for reading and writing CSV files of various types. junit junit 4.12 test commons-io commons-io 2.4 test com.h2database h2 1.4.182 test bayard Henri Yandell bayard@apache.org The Apache Software Foundation Martin van den Bemt mvdb mvdb@apache.org The Apache Software Foundation Yonik Seeley yonik yonik@apache.org The Apache Software Foundation Emmanuel Bourg ebourg ebourg@apache.org Apache Gary Gregory ggregory ggregory@apache.org http://www.garygregory.com -5 Benedikt Ritter britter britter@apache.org The Apache Software Foundation Bob Smith scm:svn:http://svn.apache.org/repos/asf/commons/proper/csv/trunk scm:svn:https://svn.apache.org/repos/asf/commons/proper/csv/trunk http://svn.apache.org/viewvc/commons/proper/csv/trunk jira http://issues.apache.org/jira/browse/CSV apache.website Apache Commons Site scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-csv/ 1.2 (Java 6.0+) RC1 csv CSV 12313222 1.6 1.6 UTF-8 UTF-8 UTF-8 2.16 ${basedir}/LICENSE-header.txt LICENSE.txt, NOTICE.txt org.apache.maven.plugins maven-scm-publish-plugin 1.1 archives/** maven-compiler-plugin **/*Benchmark* maven-assembly-plugin src/main/assembly/bin.xml src/main/assembly/src.xml gnu org.apache.maven.plugins maven-surefire-plugin **/perf/PerformanceTest.java org.apache.maven.plugins maven-checkstyle-plugin ${checkstyle.version} ${basedir}/checkstyle.xml false org.apache.rat apache-rat-plugin ${commons.rat.version} src/test/resources/CSVFileParser/bom.csv src/test/resources/CSVFileParser/test.csv src/test/resources/CSVFileParser/test_default.txt src/test/resources/CSVFileParser/test_default_comment.txt src/test/resources/CSVFileParser/test_rfc4180.txt src/test/resources/CSVFileParser/test_rfc4180_trim.txt src/test/resources/CSVFileParser/testCSV85.csv src/test/resources/CSVFileParser/testCSV85_default.txt src/test/resources/CSVFileParser/testCSV85_ignoreEmpty.txt src/test/resources/ferc.gov/contract.txt src/test/resources/ferc.gov/transaction.txt org.apache.maven.plugins maven-checkstyle-plugin ${checkstyle.version} ${basedir}/checkstyle.xml false checkstyle org.apache.maven.plugins maven-pmd-plugin 3.5 ${maven.compiler.target} org.codehaus.mojo findbugs-maven-plugin 3.0.2 org.codehaus.mojo taglist-maven-plugin 2.4 Needs Work TODO exact FIXME exact XXX exact Noteable Markers NOTE exact NOPMD exact NOSONAR exact org.codehaus.mojo javancss-maven-plugin 2.0 org.apache.rat apache-rat-plugin ${commons.rat.version} src/test/resources/CSVFileParser/bom.csv src/test/resources/CSVFileParser/test.csv src/test/resources/CSVFileParser/test_default.txt src/test/resources/CSVFileParser/test_default_comment.txt src/test/resources/CSVFileParser/test_rfc4180.txt src/test/resources/CSVFileParser/test_rfc4180_trim.txt src/test/resources/CSVFileParser/testCSV85.csv src/test/resources/CSVFileParser/testCSV85_default.txt src/test/resources/CSVFileParser/testCSV85_ignoreEmpty.txt src/test/resources/ferc.gov/contract.txt src/test/resources/ferc.gov/transaction.txt setup-checkout site-content org.apache.maven.plugins maven-antrun-plugin 1.8 prepare-checkout pre-site run benchmark org.openjdk.jmh jmh-core 1.5.2 test org.openjdk.jmh jmh-generator-annprocess 1.5.2 test genjava gj-csv 1.0 test net.sourceforge.javacsv javacsv 2.0 test com.opencsv opencsv 3.1 test net.sf.supercsv super-csv 2.2.1 org.skife.kasparov csv 1.0 org.apache.commons commons-lang3 3.4 true org.apache maven-compiler-plugin **/* org.codehaus.mojo exec-maven-plugin benchmark test exec test java -classpath org.openjdk.jmh.Main -rf json -rff target/jmh-result.json ${benchmark} commons-csv-1.2-src/RELEASE-NOTES.txt0100644 0000000 0000000 00000015636 12565677765 022017 0ustar00BUILTIN\Administrators0000000 0000000 Apache Commons CSV Version 1.2 Release Notes INTRODUCTION: This document contains the release notes for the 1.2 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. CSV requires at least Java 6. The Apache Commons CSV library provides a simple interface for reading and writing CSV files of various types. Feature and bug fix release Changes in this version include: NEW FEATURES ============== o CSV-157: Add enum CSVFormat.Predefined that contains the default CSVFormat values. FIXED BUGS ============ o CSV-145: CSVFormat.with* methods clear the header comments Thanks to Frank Ulbricht. o CSV-156: Incorrect Javadoc on QuoteMode.NONE Thanks to Jason Steenstra-Pickens. Historical list of changes: http://commons.apache.org/proper/commons-csv/changes-report.html For complete information on Apache Commons CSV, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons CSV website: http://commons.apache.org/proper/commons-csv/ Have fun! -Apache Commons CSV team ------------------------------------------------------------------------------ Apache Commons CSV Version 1.1 Release Notes INTRODUCTION: This document contains the release notes for the 1.1 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. CSV requires at least Java 6. The Apache Commons CSV library provides a simple interface for reading and writing CSV files of various types. This is our second release. Changes in this version include: New features: o [CSV-129] Add CSVFormat#with 0-arg methods matching boolean arg methods. o [CSV-131] Save positions of records to enable random access. Thanks to Holger Stratmann. o [CSV-139] CSVPrinter.printRecord(ResultSet) with metadata. Fixed Bugs: o [CSV-140] QuoteMode.NON_NUMERIC doesn't work with CSVPrinter.printRecords(ResultSet). Thanks to Damjan Jovanovic. o [CSV-130] CSVFormat#withHeader doesn't work well with #printComment, add withHeaderComments(String...). Thanks to Sergei Lebedev. o [CSV-128] CSVFormat.EXCEL should ignore empty header names. o [CSV-132] Incorrect Javadoc referencing org.apache.commons.csv.CSVFormat withQuote(). Thanks to Sascha Szott. Changes: o [CSV-124] Improve toString() implementation of CSVRecord. Thanks to Kalyan. o [CSV-134] Unified parameter validation. Thanks to wu wen. Historical list of changes: http://commons.apache.org/proper/commons-csv/changes-report.html For complete information on Apache Commons CSV, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons CSV website: http://commons.apache.org/proper/commons-csv/ Have fun! -Apache Commons CSV team ------------------------------------------------------------------------------- Apache Commons CSV Version 1.0 Release Notes INTRODUCTION: This document contains the release notes for the 1.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. CSV requires at least Java 6.0. The Apache Commons CSV library provides a simple interface for reading and writing CSV files of various types. First release Changes in this version include: NEW FEATURES ============ o CSV-121: IllegalArgumentException thrown when the header contains duplicate names when the column names are empty. Thanks to Sebastian Hardt. o CSV-120: CSVFormat#withHeader doesn't work with CSVPrinter Thanks to Sergei Lebedev. o CSV-119: CSVFormat is missing a print(...) method Thanks to Sergei Lebedev. o CSV-105: Add Map conversion API to CSVRecord o CSV-52: Keep track of record number o CSV-92: Need a way to extract parsed headers, e.g. for use in formatting output o CSV-65: Header support o CSV-48: Predefined format for MYSQL FIXED BUGS ========== o CSV-125: No longer works with Java 6 o CSV-122: NullPointerException when empty header string and and null string of "". Thanks to Mike Lewis. o CSV-118: CSVRecord.toMap() throws NPE on formats with no headers. Thanks to Enrique Lara. o CSV-113: Check whether ISE/IAE are being used appropriately o CSV-114: CSVFormat constructor should reject a header array with duplicate entries o CSV-112: HeaderMap is inconsistent when it is parsed from an input with duplicate columns names o CSV-111: CSVRecord.toMap() fails if row length shorter than header length o CSV-106: CSVFormat.format allways append null o CSV-100: CSVParser: getHeaderMap throws NPE o CSV-53: CSVRecord does not verify that the length of the header mapping matches the number of values o CSV-54: Confusing semantic of the ignore leading/trailing spaces parameters o CSV-34: CSVFormat describes itself as immutable, but it is not - in particular it is not thread-safe o CSV-36: Endless loops in CSV parser o CSV-13: NullPointerException in CSVPrinter.print()/println() o CSV-23: Excel strategy uses wrong separator CHANGES ======= o CSV-117: Validate format parameters in constructor o CSV-42: Lots of possible changes Thanks to Bob Smith. o CSV-78: Use Character instead of char for char fields except delimiter o CSV-99: Revert Builder implementation in CSVFormat o CSV-93: Allow the handling of NULL values o CSV-68: Use the Builder pattern for CSVFormat o CSV-84: Clarify comment handling o CSV-25: CSVParser.nextValue() seems pointless o CSV-97: Allow the String value for null to be customized for the CSV printer o CSV-88: Not possible to create a CSVFormat from scratch o CSV-94: Lexer should only use char fields o CSV-71: Add convenience methods to CSVLexer o CSV-59: Is CharBuffer really needed, now that StringBuilder is available? o CSV-55: Replace while(true)-loop in CSVParser.getRecord with do-while-loop o CSV-45: CSVPrinter overhaul o CSV-49: CSVStrategy has modifiable public static variables Thanks to Bob Smith. o CSV-46: Reduce visibility of methods in internal classes o CSV-26: ExtendedBufferedReader does too much o CSV-27: Decide whether to keep the csv.writer subpackage Historical list of changes: http://commons.apache.org/proper/commons-csv/changes-report.html For complete information on Apache Commons CSV, including instructions on how to submit bug reports, patches, or suggestions for improvement, see the Apache Apache Commons CSV website: http://commons.apache.org/proper/commons-csv/ Have fun! -Apache Commons CSV team commons-csv-1.2-src/src/0040755 0000000 0000000 00000000000 12565677764 020066 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/changes/0040755 0000000 0000000 00000000000 12565677765 021477 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/main/0040755 0000000 0000000 00000000000 12565677764 021012 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/main/assembly/0040755 0000000 0000000 00000000000 12565700104 022600 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/main/java/0040755 0000000 0000000 00000000000 12565677764 021733 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/main/java/org/0040755 0000000 0000000 00000000000 12565677764 022522 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/main/java/org/apache/0040755 0000000 0000000 00000000000 12565677764 023743 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/main/java/org/apache/commons/0040755 0000000 0000000 00000000000 12565677764 025416 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/main/java/org/apache/commons/csv/0040755 0000000 0000000 00000000000 12565700105 026161 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/site/0040755 0000000 0000000 00000000000 12565700105 021002 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/site/resources/0040755 0000000 0000000 00000000000 12565700105 023014 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/site/resources/images/0040755 0000000 0000000 00000000000 12565700105 024261 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/site/xdoc/0040755 0000000 0000000 00000000000 12565700105 021737 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/0040755 0000000 0000000 00000000000 12565677764 021045 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/java/0040755 0000000 0000000 00000000000 12565677764 021766 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/java/org/0040755 0000000 0000000 00000000000 12565677764 022555 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/java/org/apache/0040755 0000000 0000000 00000000000 12565677764 023776 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/java/org/apache/commons/0040755 0000000 0000000 00000000000 12565677764 025451 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/java/org/apache/commons/csv/0040755 0000000 0000000 00000000000 12565700104 026213 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/java/org/apache/commons/csv/perf/0040755 0000000 0000000 00000000000 12565700103 027146 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/resources/0040755 0000000 0000000 00000000000 12565677764 023057 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/resources/CSVFileParser/0040755 0000000 0000000 00000000000 12565677765 025470 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/test/resources/ferc.gov/0040755 0000000 0000000 00000000000 12565677765 024571 5ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/changes/changes.xml0100644 0000000 0000000 00000020666 12565677765 023640 0ustar00BUILTIN\Administrators0000000 0000000 Release Notes CSVFormat.with* methods clear the header comments Incorrect Javadoc on QuoteMode.NONE Add enum CSVFormat.Predefined that contains the default CSVFormat values. QuoteMode.NON_NUMERIC doesn't work with CSVPrinter.printRecords(ResultSet) CSVFormat#withHeader doesn't work well with #printComment, add withHeaderComments(String...) CSVFormat.EXCEL should ignore empty header names Incorrect Javadoc referencing org.apache.commons.csv.CSVFormat withQuote() Improve toString() implementation of CSVRecord Unified parameter validation Add CSVFormat#with 0-arg methods matching boolean arg methods Save positions of records to enable random access CSVPrinter.printRecord(ResultSet) with metadata No longer works with Java 6 NullPointerException when empty header string and and null string of "" Validate format parameters in constructor IllegalArgumentException thrown when the header contains duplicate names when the column names are empty. CSVFormat#withHeader doesn't work with CSVPrinter CSVFormat is missing a print(...) method CSVRecord.toMap() throws NPE on formats with no headers. Check whether ISE/IAE are being used appropriately CSVFormat constructor should reject a header array with duplicate entries HeaderMap is inconsistent when it is parsed from an input with duplicate columns names CSVRecord.toMap() fails if row length shorter than header length CSVFormat.format allways append null Add Map conversion API to CSVRecord CSVParser: getHeaderMap throws NPE Lots of possible changes Use Character instead of char for char fields except delimiter Revert Builder implementation in CSVFormat CSVRecord does not verify that the length of the header mapping matches the number of values Allow the handling of NULL values Use the Builder pattern for CSVFormat Clarify comment handling CSVParser.nextValue() seems pointless Allow the String value for null to be customized for the CSV printer Not possible to create a CSVFormat from scratch Keep track of record number Lexer should only use char fields Need a way to extract parsed headers, e.g. for use in formatting output Header support Confusing semantic of the ignore leading/trailing spaces parameters Add convenience methods to CSVLexer Is CharBuffer really needed, now that StringBuilder is available? Replace while(true)-loop in CSVParser.getRecord with do-while-loop CSVFormat describes itself as immutable, but it is not - in particular it is not thread-safe Endless loops in CSV parser NullPointerException in CSVPrinter.print()/println() CSVPrinter overhaul Excel strategy uses wrong separator CSVStrategy has modifiable public static variables Predefined format for MYSQL Reduce visibility of methods in internal classes ExtendedBufferedReader does too much Decide whether to keep the csv.writer subpackage commons-csv-1.2-src/src/changes/release-notes.vm0100644 0000000 0000000 00000007440 12565677765 024613 0ustar00BUILTIN\Administrators0000000 0000000 ## Licensed to the Apache Software Foundation (ASF) under one ## or more contributor license agreements. See the NOTICE file ## distributed with this work for additional information ## regarding copyright ownership. The ASF licenses this file ## to you under the Apache License, Version 2.0 (the ## "License"); you may not use this file except in compliance ## with the License. You may obtain a copy of the License at ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## Unless required by applicable law or agreed to in writing, ## software distributed under the License is distributed on an ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ## KIND, either express or implied. See the License for the ## specific language governing permissions and limitations ## under the License. ## ${project.name} Version ${version} Release Notes INTRODUCTION: This document contains the release notes for the ${version} version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. CSV requires at least Java 7.0. $introduction.replaceAll("(? bin tar.gz zip LICENSE.txt NOTICE.txt RELEASE-NOTES.txt target ${artifactId}-${version}.jar target/site/apidocs apidocs **/* target ${artifactId}-${version}-sources.jar commons-csv-1.2-src/src/main/assembly/src.xml0100644 0000000 0000000 00000002711 12565700104 024107 0ustar00BUILTIN\Administrators0000000 0000000 src tar.gz zip ${artifactId}-${version}-src LICENSE* NOTICE* RELEASE-NOTES.txt pom.xml findbugs-exclude-filter.xml checkstyle*.xml src **/*Benchmark.java commons-csv-1.2-src/src/main/java/org/apache/commons/csv/Assertions.java0100644 0000000 0000000 00000002473 12565700105 031161 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; /** * Utility class for input parameter validation * * @version $Id: Assertions.java 1559908 2014-01-21 02:44:30Z ggregory $ */ final class Assertions { private Assertions() { // can not be instantiated } public static void notNull(final Object parameter, final String parameterName) { if (parameter == null) { throw new IllegalArgumentException("Parameter '" + parameterName + "' must not be null!"); } } } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/Constants.java0100644 0000000 0000000 00000004325 12565700105 031001 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; /** * Constants for this package. * * @version $Id: Constants.java 1582822 2014-03-28 16:52:17Z sebb $ */ final class Constants { static final char BACKSPACE = '\b'; static final char COMMA = ','; /** * Starts a comment, the remainder of the line is the comment. */ static final char COMMENT = '#'; static final char CR = '\r'; static final Character DOUBLE_QUOTE_CHAR = Character.valueOf('"'); static final char BACKSLASH = '\\'; static final char FF = '\f'; static final char LF = '\n'; static final char SP = ' '; static final char TAB = '\t'; /** ASCII record separator */ static final char RS = 30; /** ASCII unit separator */ static final char US = 31; static final String EMPTY = ""; /** The end of stream symbol */ static final int END_OF_STREAM = -1; /** Undefined state for the lookahead char */ static final int UNDEFINED = -2; /** According to RFC 4180, line breaks are delimited by CRLF */ static final String CRLF = "\r\n"; /** * Unicode line separator. */ static final String LINE_SEPARATOR = "\u2028"; /** * Unicode paragraph separator. */ static final String PARAGRAPH_SEPARATOR = "\u2029"; /** * Unicode next line. */ static final String NEXT_LINE = "\u0085"; } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/CSVFormat.java0100644 0000000 0000000 00000131455 12565700105 030636 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.BACKSLASH; import static org.apache.commons.csv.Constants.COMMA; import static org.apache.commons.csv.Constants.CR; import static org.apache.commons.csv.Constants.CRLF; import static org.apache.commons.csv.Constants.DOUBLE_QUOTE_CHAR; import static org.apache.commons.csv.Constants.LF; import static org.apache.commons.csv.Constants.TAB; import java.io.IOException; import java.io.Reader; import java.io.Serializable; import java.io.StringWriter; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; /** * Specifies the format of a CSV file and parses input. * *

Using predefined formats

* *

* You can use one of the predefined formats: *

* * * *

* For example: *

* *
 * CSVParser parser = CSVFormat.EXCEL.parse(reader);
 * 
* *

* The {@link CSVParser} provides static methods to parse other input types, for example: *

* *
 * CSVParser parser = CSVParser.parse(file, StandardCharsets.US_ASCII, CSVFormat.EXCEL);
 * 
* *

Defining formats

* *

* You can extend a format by calling the {@code with} methods. For example: *

* *
 * CSVFormat.EXCEL.withNullString("N/A").withIgnoreSurroundingSpaces(true);
 * 
* *

Defining column names

* *

* To define the column names you want to use to access records, write: *

* *
 * CSVFormat.EXCEL.withHeader("Col1", "Col2", "Col3");
 * 
* *

* Calling {@link #withHeader(String...)} let's you use the given names to address values in a {@link CSVRecord}, and * assumes that your CSV source does not contain a first record that also defines column names. * * If it does, then you are overriding this metadata with your names and you should skip the first record by calling * {@link #withSkipHeaderRecord(boolean)} with {@code true}. *

* *

Parsing

* *

* You can use a format directly to parse a reader. For example, to parse an Excel file with columns header, write: *

* *
 * Reader in = ...;
 * CSVFormat.EXCEL.withHeader("Col1", "Col2", "Col3").parse(in);
 * 
* *

* For other input types, like resources, files, and URLs, use the static methods on {@link CSVParser}. *

* *

Referencing columns safely

* *

* If your source contains a header record, you can simplify your code and safely reference columns, by using * {@link #withHeader(String...)} with no arguments: *

* *
 * CSVFormat.EXCEL.withHeader();
 * 
* *

* This causes the parser to read the first record and use its values as column names. * * Then, call one of the {@link CSVRecord} get method that takes a String column name argument: *

* *
 * String value = record.get("Col1");
 * 
* *

* This makes your code impervious to changes in column order in the CSV file. *

* *

Notes

* *

* This class is immutable. *

* * @version $Id: CSVFormat.java 1695190 2015-08-11 02:14:33Z ggregory $ */ public final class CSVFormat implements Serializable { /** * Predefines formats. * * @since 1.2 */ public static enum Predefined { /** * @see CSVFormat#DEFAULT */ Default(CSVFormat.DEFAULT), /** * @see CSVFormat#EXCEL */ Excel(CSVFormat.EXCEL), /** * @see CSVFormat#MYSQL */ MySQL(CSVFormat.MYSQL), /** * @see CSVFormat#RFC4180 */ RFC4180(CSVFormat.RFC4180), /** * @see CSVFormat#TDF */ TDF(CSVFormat.TDF); private final CSVFormat format; private Predefined(CSVFormat format) { this.format = format; } /** * Gets the format. * * @return the format. */ public CSVFormat getFormat() { return format; } }; private static final long serialVersionUID = 1L; private final char delimiter; private final Character quoteCharacter; // null if quoting is disabled private final QuoteMode quoteMode; private final Character commentMarker; // null if commenting is disabled private final Character escapeCharacter; // null if escaping is disabled private final boolean ignoreSurroundingSpaces; // Should leading/trailing spaces be ignored around values? private final boolean allowMissingColumnNames; private final boolean ignoreEmptyLines; private final String recordSeparator; // for outputs private final String nullString; // the string to be used for null values private final String[] header; // array of header column names private final String[] headerComments; // array of header comment lines private final boolean skipHeaderRecord; /** * Standard comma separated format, as for {@link #RFC4180} but allowing empty lines. * *

* Settings are: *

* * @see Predefined#Default */ public static final CSVFormat DEFAULT = new CSVFormat(COMMA, DOUBLE_QUOTE_CHAR, null, null, null, false, true, CRLF, null, null, null, false, false); /** * Comma separated format as defined by RFC 4180. * *

* Settings are: *

* * @see Predefined#RFC4180 */ public static final CSVFormat RFC4180 = DEFAULT.withIgnoreEmptyLines(false); /** * Excel file format (using a comma as the value delimiter). Note that the actual value delimiter used by Excel is * locale dependent, it might be necessary to customize this format to accommodate to your regional settings. * *

* For example for parsing or generating a CSV file on a French system the following format will be used: *

* *
     * CSVFormat fmt = CSVFormat.EXCEL.withDelimiter(';');
     * 
* *

* Settings are: *

* *

* Note: this is currently like {@link #RFC4180} plus {@link #withAllowMissingColumnNames(boolean) * withAllowMissingColumnNames(true)}. *

* @see Predefined#Excel */ public static final CSVFormat EXCEL = DEFAULT.withIgnoreEmptyLines(false).withAllowMissingColumnNames(); /** * Tab-delimited format. * *

* Settings are: *

* * @see Predefined#TDF */ public static final CSVFormat TDF = DEFAULT.withDelimiter(TAB).withIgnoreSurroundingSpaces(); /** * Default MySQL format used by the {@code SELECT INTO OUTFILE} and {@code LOAD DATA INFILE} operations. * *

* This is a tab-delimited format with a LF character as the line separator. Values are not quoted and special * characters are escaped with '\'. *

* *

* Settings are: *

* * * @see Predefined#MySQL * @see * http://dev.mysql.com/doc/refman/5.1/en/load-data.html */ public static final CSVFormat MYSQL = DEFAULT.withDelimiter(TAB).withEscape(BACKSLASH).withIgnoreEmptyLines(false) .withQuote(null).withRecordSeparator(LF); /** * Returns true if the given character is a line break character. * * @param c * the character to check * * @return true if c is a line break character */ private static boolean isLineBreak(final char c) { return c == LF || c == CR; } /** * Returns true if the given character is a line break character. * * @param c * the character to check, may be null * * @return true if c is a line break character (and not null) */ private static boolean isLineBreak(final Character c) { return c != null && isLineBreak(c.charValue()); } /** * Creates a new CSV format with the specified delimiter. * *

* Use this method if you want to create a CSVFormat from scratch. All fields but the delimiter will be initialized * with null/false. *

* * @param delimiter * the char used for value separation, must not be a line break character * @return a new CSV format. * @throws IllegalArgumentException * if the delimiter is a line break character * * @see #DEFAULT * @see #RFC4180 * @see #MYSQL * @see #EXCEL * @see #TDF */ public static CSVFormat newFormat(final char delimiter) { return new CSVFormat(delimiter, null, null, null, null, false, false, null, null, null, null, false, false); } /** * Gets one of the predefined formats from {@link CSVFormat.Predefined}. * * @param format * name * @return one of the predefined formats * @since 1.2 */ public static CSVFormat valueOf(final String format) { return CSVFormat.Predefined.valueOf(format).getFormat(); } /** * Creates a customized CSV format. * * @param delimiter * the char used for value separation, must not be a line break character * @param quoteChar * the Character used as value encapsulation marker, may be {@code null} to disable * @param quoteMode * the quote mode * @param commentStart * the Character used for comment identification, may be {@code null} to disable * @param escape * the Character used to escape special characters in values, may be {@code null} to disable * @param ignoreSurroundingSpaces * {@code true} when whitespaces enclosing values should be ignored * @param ignoreEmptyLines * {@code true} when the parser should skip empty lines * @param recordSeparator * the line separator to use for output * @param nullString * the line separator to use for output * @param headerComments * the comments to be printed by the Printer before the actual CSV data * @param header * the header * @param skipHeaderRecord * TODO * @param allowMissingColumnNames * TODO * @throws IllegalArgumentException * if the delimiter is a line break character */ private CSVFormat(final char delimiter, final Character quoteChar, final QuoteMode quoteMode, final Character commentStart, final Character escape, final boolean ignoreSurroundingSpaces, final boolean ignoreEmptyLines, final String recordSeparator, final String nullString, final Object[] headerComments, final String[] header, final boolean skipHeaderRecord, final boolean allowMissingColumnNames) { this.delimiter = delimiter; this.quoteCharacter = quoteChar; this.quoteMode = quoteMode; this.commentMarker = commentStart; this.escapeCharacter = escape; this.ignoreSurroundingSpaces = ignoreSurroundingSpaces; this.allowMissingColumnNames = allowMissingColumnNames; this.ignoreEmptyLines = ignoreEmptyLines; this.recordSeparator = recordSeparator; this.nullString = nullString; this.headerComments = toStringArray(headerComments); this.header = header == null ? null : header.clone(); this.skipHeaderRecord = skipHeaderRecord; validate(); } private String[] toStringArray(final Object[] values) { if (values == null) { return null; } final String[] strings = new String[values.length]; for (int i = 0; i < values.length; i++) { final Object value = values[i]; strings[i] = value == null ? null : value.toString(); } return strings; } @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final CSVFormat other = (CSVFormat) obj; if (delimiter != other.delimiter) { return false; } if (quoteMode != other.quoteMode) { return false; } if (quoteCharacter == null) { if (other.quoteCharacter != null) { return false; } } else if (!quoteCharacter.equals(other.quoteCharacter)) { return false; } if (commentMarker == null) { if (other.commentMarker != null) { return false; } } else if (!commentMarker.equals(other.commentMarker)) { return false; } if (escapeCharacter == null) { if (other.escapeCharacter != null) { return false; } } else if (!escapeCharacter.equals(other.escapeCharacter)) { return false; } if (nullString == null) { if (other.nullString != null) { return false; } } else if (!nullString.equals(other.nullString)) { return false; } if (!Arrays.equals(header, other.header)) { return false; } if (ignoreSurroundingSpaces != other.ignoreSurroundingSpaces) { return false; } if (ignoreEmptyLines != other.ignoreEmptyLines) { return false; } if (skipHeaderRecord != other.skipHeaderRecord) { return false; } if (recordSeparator == null) { if (other.recordSeparator != null) { return false; } } else if (!recordSeparator.equals(other.recordSeparator)) { return false; } return true; } /** * Formats the specified values. * * @param values * the values to format * @return the formatted values */ public String format(final Object... values) { final StringWriter out = new StringWriter(); try { new CSVPrinter(out, this).printRecord(values); return out.toString().trim(); } catch (final IOException e) { // should not happen because a StringWriter does not do IO. throw new IllegalStateException(e); } } /** * Returns the character marking the start of a line comment. * * @return the comment start marker, may be {@code null} */ public Character getCommentMarker() { return commentMarker; } /** * Returns the character delimiting the values (typically ';', ',' or '\t'). * * @return the delimiter character */ public char getDelimiter() { return delimiter; } /** * Returns the escape character. * * @return the escape character, may be {@code null} */ public Character getEscapeCharacter() { return escapeCharacter; } /** * Returns a copy of the header array. * * @return a copy of the header array; {@code null} if disabled, the empty array if to be read from the file */ public String[] getHeader() { return header != null ? header.clone() : null; } /** * Returns a copy of the header comment array. * * @return a copy of the header comment array; {@code null} if disabled. */ public String[] getHeaderComments() { return headerComments != null ? headerComments.clone() : null; } /** * Specifies whether missing column names are allowed when parsing the header line. * * @return {@code true} if missing column names are allowed when parsing the header line, {@code false} to throw an * {@link IllegalArgumentException}. */ public boolean getAllowMissingColumnNames() { return allowMissingColumnNames; } /** * Specifies whether empty lines between records are ignored when parsing input. * * @return {@code true} if empty lines between records are ignored, {@code false} if they are turned into empty * records. */ public boolean getIgnoreEmptyLines() { return ignoreEmptyLines; } /** * Specifies whether spaces around values are ignored when parsing input. * * @return {@code true} if spaces around values are ignored, {@code false} if they are treated as part of the value. */ public boolean getIgnoreSurroundingSpaces() { return ignoreSurroundingSpaces; } /** * Gets the String to convert to and from {@code null}. * * * @return the String to convert to and from {@code null}. No substitution occurs if {@code null} */ public String getNullString() { return nullString; } /** * Returns the character used to encapsulate values containing special characters. * * @return the quoteChar character, may be {@code null} */ public Character getQuoteCharacter() { return quoteCharacter; } /** * Returns the quote policy output fields. * * @return the quote policy */ public QuoteMode getQuoteMode() { return quoteMode; } /** * Returns the record separator delimiting output records. * * @return the record separator */ public String getRecordSeparator() { return recordSeparator; } /** * Returns whether to skip the header record. * * @return whether to skip the header record. */ public boolean getSkipHeaderRecord() { return skipHeaderRecord; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + delimiter; result = prime * result + ((quoteMode == null) ? 0 : quoteMode.hashCode()); result = prime * result + ((quoteCharacter == null) ? 0 : quoteCharacter.hashCode()); result = prime * result + ((commentMarker == null) ? 0 : commentMarker.hashCode()); result = prime * result + ((escapeCharacter == null) ? 0 : escapeCharacter.hashCode()); result = prime * result + ((nullString == null) ? 0 : nullString.hashCode()); result = prime * result + (ignoreSurroundingSpaces ? 1231 : 1237); result = prime * result + (ignoreEmptyLines ? 1231 : 1237); result = prime * result + (skipHeaderRecord ? 1231 : 1237); result = prime * result + ((recordSeparator == null) ? 0 : recordSeparator.hashCode()); result = prime * result + Arrays.hashCode(header); return result; } /** * Specifies whether comments are supported by this format. * * Note that the comment introducer character is only recognized at the start of a line. * * @return {@code true} is comments are supported, {@code false} otherwise */ public boolean isCommentMarkerSet() { return commentMarker != null; } /** * Returns whether escape are being processed. * * @return {@code true} if escapes are processed */ public boolean isEscapeCharacterSet() { return escapeCharacter != null; } /** * Returns whether a nullString has been defined. * * @return {@code true} if a nullString is defined */ public boolean isNullStringSet() { return nullString != null; } /** * Returns whether a quoteChar has been defined. * * @return {@code true} if a quoteChar is defined */ public boolean isQuoteCharacterSet() { return quoteCharacter != null; } /** * Parses the specified content. * *

* See also the various static parse methods on {@link CSVParser}. *

* * @param in * the input stream * @return a parser over a stream of {@link CSVRecord}s. * @throws IOException * If an I/O error occurs */ public CSVParser parse(final Reader in) throws IOException { return new CSVParser(in, this); } /** * Prints to the specified output. * *

* See also {@link CSVPrinter}. *

* * @param out * the output * @return a printer to an output * @throws IOException * thrown if the optional header cannot be printed. */ public CSVPrinter print(final Appendable out) throws IOException { return new CSVPrinter(out, this); } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("Delimiter=<").append(delimiter).append('>'); if (isEscapeCharacterSet()) { sb.append(' '); sb.append("Escape=<").append(escapeCharacter).append('>'); } if (isQuoteCharacterSet()) { sb.append(' '); sb.append("QuoteChar=<").append(quoteCharacter).append('>'); } if (isCommentMarkerSet()) { sb.append(' '); sb.append("CommentStart=<").append(commentMarker).append('>'); } if (isNullStringSet()) { sb.append(' '); sb.append("NullString=<").append(nullString).append('>'); } if (recordSeparator != null) { sb.append(' '); sb.append("RecordSeparator=<").append(recordSeparator).append('>'); } if (getIgnoreEmptyLines()) { sb.append(" EmptyLines:ignored"); } if (getIgnoreSurroundingSpaces()) { sb.append(" SurroundingSpaces:ignored"); } sb.append(" SkipHeaderRecord:").append(skipHeaderRecord); if (headerComments != null) { sb.append(' '); sb.append("HeaderComments:").append(Arrays.toString(headerComments)); } if (header != null) { sb.append(' '); sb.append("Header:").append(Arrays.toString(header)); } return sb.toString(); } /** * Verifies the consistency of the parameters and throws an IllegalArgumentException if necessary. * * @throws IllegalArgumentException */ private void validate() throws IllegalArgumentException { if (isLineBreak(delimiter)) { throw new IllegalArgumentException("The delimiter cannot be a line break"); } if (quoteCharacter != null && delimiter == quoteCharacter.charValue()) { throw new IllegalArgumentException("The quoteChar character and the delimiter cannot be the same ('" + quoteCharacter + "')"); } if (escapeCharacter != null && delimiter == escapeCharacter.charValue()) { throw new IllegalArgumentException("The escape character and the delimiter cannot be the same ('" + escapeCharacter + "')"); } if (commentMarker != null && delimiter == commentMarker.charValue()) { throw new IllegalArgumentException("The comment start character and the delimiter cannot be the same ('" + commentMarker + "')"); } if (quoteCharacter != null && quoteCharacter.equals(commentMarker)) { throw new IllegalArgumentException("The comment start character and the quoteChar cannot be the same ('" + commentMarker + "')"); } if (escapeCharacter != null && escapeCharacter.equals(commentMarker)) { throw new IllegalArgumentException("The comment start and the escape character cannot be the same ('" + commentMarker + "')"); } if (escapeCharacter == null && quoteMode == QuoteMode.NONE) { throw new IllegalArgumentException("No quotes mode set but no escape character is set"); } // validate header if (header != null) { final Set dupCheck = new HashSet(); for (final String hdr : header) { if (!dupCheck.add(hdr)) { throw new IllegalArgumentException("The header contains a duplicate entry: '" + hdr + "' in " + Arrays.toString(header)); } } } } /** * Sets the comment start marker of the format to the specified character. * * Note that the comment start character is only recognized at the start of a line. * * @param commentMarker * the comment start marker * @return A new CSVFormat that is equal to this one but with the specified character as the comment start marker * @throws IllegalArgumentException * thrown if the specified character is a line break */ public CSVFormat withCommentMarker(final char commentMarker) { return withCommentMarker(Character.valueOf(commentMarker)); } /** * Sets the comment start marker of the format to the specified character. * * Note that the comment start character is only recognized at the start of a line. * * @param commentMarker * the comment start marker, use {@code null} to disable * @return A new CSVFormat that is equal to this one but with the specified character as the comment start marker * @throws IllegalArgumentException * thrown if the specified character is a line break */ public CSVFormat withCommentMarker(final Character commentMarker) { if (isLineBreak(commentMarker)) { throw new IllegalArgumentException("The comment start marker character cannot be a line break"); } return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the delimiter of the format to the specified character. * * @param delimiter * the delimiter character * @return A new CSVFormat that is equal to this with the specified character as delimiter * @throws IllegalArgumentException * thrown if the specified character is a line break */ public CSVFormat withDelimiter(final char delimiter) { if (isLineBreak(delimiter)) { throw new IllegalArgumentException("The delimiter cannot be a line break"); } return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the escape character of the format to the specified character. * * @param escape * the escape character * @return A new CSVFormat that is equal to his but with the specified character as the escape character * @throws IllegalArgumentException * thrown if the specified character is a line break */ public CSVFormat withEscape(final char escape) { return withEscape(Character.valueOf(escape)); } /** * Sets the escape character of the format to the specified character. * * @param escape * the escape character, use {@code null} to disable * @return A new CSVFormat that is equal to this but with the specified character as the escape character * @throws IllegalArgumentException * thrown if the specified character is a line break */ public CSVFormat withEscape(final Character escape) { if (isLineBreak(escape)) { throw new IllegalArgumentException("The escape character cannot be a line break"); } return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escape, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the header of the format. The header can either be parsed automatically from the input file with: * *
     * CSVFormat format = aformat.withHeader();
     * 
* * or specified manually with: * *
     * CSVFormat format = aformat.withHeader("name", "email", "phone");
     * 
*

* The header is also used by the {@link CSVPrinter}.. *

* * @param header * the header, {@code null} if disabled, empty if parsed automatically, user specified otherwise. * * @return A new CSVFormat that is equal to this but with the specified header * @see #withSkipHeaderRecord(boolean) */ public CSVFormat withHeader(final String... header) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the header of the format. The header can either be parsed automatically from the input file with: * *
     * CSVFormat format = aformat.withHeader();
     * 
* * or specified manually with: * *
     * CSVFormat format = aformat.withHeader(resultSet);
     * 
*

* The header is also used by the {@link CSVPrinter}.. *

* * @param resultSet * the resultSet for the header, {@code null} if disabled, empty if parsed automatically, user specified * otherwise. * * @return A new CSVFormat that is equal to this but with the specified header * @throws SQLException * SQLException if a database access error occurs or this method is called on a closed result set. * @since 1.1 */ public CSVFormat withHeader(final ResultSet resultSet) throws SQLException { return withHeader(resultSet != null ? resultSet.getMetaData() : null); } /** * Sets the header of the format. The header can either be parsed automatically from the input file with: * *
     * CSVFormat format = aformat.withHeader();
     * 
* * or specified manually with: * *
     * CSVFormat format = aformat.withHeader(metaData);
     * 
*

* The header is also used by the {@link CSVPrinter}.. *

* * @param metaData * the metaData for the header, {@code null} if disabled, empty if parsed automatically, user specified * otherwise. * * @return A new CSVFormat that is equal to this but with the specified header * @throws SQLException * SQLException if a database access error occurs or this method is called on a closed result set. * @since 1.1 */ public CSVFormat withHeader(final ResultSetMetaData metaData) throws SQLException { String[] labels = null; if (metaData != null) { final int columnCount = metaData.getColumnCount(); labels = new String[columnCount]; for (int i = 0; i < columnCount; i++) { labels[i] = metaData.getColumnLabel(i + 1); } } return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, labels, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the header comments of the format. The comments will be printed first, before the headers. This setting is * ignored by the parser. * *
     * CSVFormat format = aformat.withHeaderComments("Generated by Apache Commons CSV 1.1.", new Date());
     * 
* * @param headerComments * the headerComments which will be printed by the Printer before the actual CSV data. * * @return A new CSVFormat that is equal to this but with the specified header * @see #withSkipHeaderRecord(boolean) * @since 1.1 */ public CSVFormat withHeaderComments(final Object... headerComments) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the missing column names behavior of the format to {@code true} * * @return A new CSVFormat that is equal to this but with the specified missing column names behavior. * @see #withAllowMissingColumnNames(boolean) * @since 1.1 */ public CSVFormat withAllowMissingColumnNames() { return this.withAllowMissingColumnNames(true); } /** * Sets the missing column names behavior of the format. * * @param allowMissingColumnNames * the missing column names behavior, {@code true} to allow missing column names in the header line, * {@code false} to cause an {@link IllegalArgumentException} to be thrown. * @return A new CSVFormat that is equal to this but with the specified missing column names behavior. */ public CSVFormat withAllowMissingColumnNames(final boolean allowMissingColumnNames) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the empty line skipping behavior of the format to {@code true}. * * @return A new CSVFormat that is equal to this but with the specified empty line skipping behavior. * @since {@link #withIgnoreEmptyLines(boolean)} * @since 1.1 */ public CSVFormat withIgnoreEmptyLines() { return this.withIgnoreEmptyLines(true); } /** * Sets the empty line skipping behavior of the format. * * @param ignoreEmptyLines * the empty line skipping behavior, {@code true} to ignore the empty lines between the records, * {@code false} to translate empty lines to empty records. * @return A new CSVFormat that is equal to this but with the specified empty line skipping behavior. */ public CSVFormat withIgnoreEmptyLines(final boolean ignoreEmptyLines) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the trimming behavior of the format to {@code true}. * * @return A new CSVFormat that is equal to this but with the specified trimming behavior. * @see #withIgnoreSurroundingSpaces(boolean) * @since 1.1 */ public CSVFormat withIgnoreSurroundingSpaces() { return this.withIgnoreSurroundingSpaces(true); } /** * Sets the trimming behavior of the format. * * @param ignoreSurroundingSpaces * the trimming behavior, {@code true} to remove the surrounding spaces, {@code false} to leave the * spaces as is. * @return A new CSVFormat that is equal to this but with the specified trimming behavior. */ public CSVFormat withIgnoreSurroundingSpaces(final boolean ignoreSurroundingSpaces) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Performs conversions to and from null for strings on input and output. *
    *
  • * Reading: Converts strings equal to the given {@code nullString} to {@code null} when reading * records.
  • *
  • * Writing: Writes {@code null} as the given {@code nullString} when writing records.
  • *
* * @param nullString * the String to convert to and from {@code null}. No substitution occurs if {@code null} * * @return A new CSVFormat that is equal to this but with the specified null conversion string. */ public CSVFormat withNullString(final String nullString) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the quoteChar of the format to the specified character. * * @param quoteChar * the quoteChar character * @return A new CSVFormat that is equal to this but with the specified character as quoteChar * @throws IllegalArgumentException * thrown if the specified character is a line break */ public CSVFormat withQuote(final char quoteChar) { return withQuote(Character.valueOf(quoteChar)); } /** * Sets the quoteChar of the format to the specified character. * * @param quoteChar * the quoteChar character, use {@code null} to disable * @return A new CSVFormat that is equal to this but with the specified character as quoteChar * @throws IllegalArgumentException * thrown if the specified character is a line break */ public CSVFormat withQuote(final Character quoteChar) { if (isLineBreak(quoteChar)) { throw new IllegalArgumentException("The quoteChar cannot be a line break"); } return new CSVFormat(delimiter, quoteChar, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the output quote policy of the format to the specified value. * * @param quoteModePolicy * the quote policy to use for output. * * @return A new CSVFormat that is equal to this but with the specified quote policy */ public CSVFormat withQuoteMode(final QuoteMode quoteModePolicy) { return new CSVFormat(delimiter, quoteCharacter, quoteModePolicy, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets the record separator of the format to the specified character. * *

* Note: This setting is only used during printing and does not affect parsing. Parsing currently * only works for inputs with '\n', '\r' and "\r\n" *

* * @param recordSeparator * the record separator to use for output. * * @return A new CSVFormat that is equal to this but with the the specified output record separator */ public CSVFormat withRecordSeparator(final char recordSeparator) { return withRecordSeparator(String.valueOf(recordSeparator)); } /** * Sets the record separator of the format to the specified String. * *

* Note: This setting is only used during printing and does not affect parsing. Parsing currently * only works for inputs with '\n', '\r' and "\r\n" *

* * @param recordSeparator * the record separator to use for output. * * @return A new CSVFormat that is equal to this but with the the specified output record separator * @throws IllegalArgumentException * if recordSeparator is none of CR, LF or CRLF */ public CSVFormat withRecordSeparator(final String recordSeparator) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } /** * Sets skipping the header record to {@code true}. * * @return A new CSVFormat that is equal to this but with the the specified skipHeaderRecord setting. * @see #withSkipHeaderRecord(boolean) * @see #withHeader(String...) * @since 1.1 */ public CSVFormat withSkipHeaderRecord() { return this.withSkipHeaderRecord(true); } /** * Sets whether to skip the header record. * * @param skipHeaderRecord * whether to skip the header record. * * @return A new CSVFormat that is equal to this but with the the specified skipHeaderRecord setting. * @see #withHeader(String...) */ public CSVFormat withSkipHeaderRecord(final boolean skipHeaderRecord) { return new CSVFormat(delimiter, quoteCharacter, quoteMode, commentMarker, escapeCharacter, ignoreSurroundingSpaces, ignoreEmptyLines, recordSeparator, nullString, headerComments, header, skipHeaderRecord, allowMissingColumnNames); } } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/CSVParser.java0100644 0000000 0000000 00000046274 12565700104 030645 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import static org.apache.commons.csv.Token.Type.*; /** * Parses CSV files according to the specified format. * * Because CSV appears in many different dialects, the parser supports many formats by allowing the * specification of a {@link CSVFormat}. * * The parser works record wise. It is not possible to go back, once a record has been parsed from the input stream. * *

Creating instances

*

* There are several static factory methods that can be used to create instances for various types of resources: *

*
    *
  • {@link #parse(java.io.File, Charset, CSVFormat)}
  • *
  • {@link #parse(String, CSVFormat)}
  • *
  • {@link #parse(java.net.URL, java.nio.charset.Charset, CSVFormat)}
  • *
*

* Alternatively parsers can also be created by passing a {@link Reader} directly to the sole constructor. * * For those who like fluent APIs, parsers can be created using {@link CSVFormat#parse(java.io.Reader)} as a shortcut: *

*
 * for(CSVRecord record : CSVFormat.EXCEL.parse(in)) {
 *     ...
 * }
 * 
* *

Parsing record wise

*

* To parse a CSV input from a file, you write: *

* *
 * File csvData = new File("/path/to/csv");
 * CSVParser parser = CSVParser.parse(csvData, CSVFormat.RFC4180);
 * for (CSVRecord csvRecord : parser) {
 *     ...
 * }
 * 
* *

* This will read the parse the contents of the file using the * RFC 4180 format. *

* *

* To parse CSV input in a format like Excel, you write: *

* *
 * CSVParser parser = CSVParser.parse(csvData, CSVFormat.EXCEL);
 * for (CSVRecord csvRecord : parser) {
 *     ...
 * }
 * 
* *

* If the predefined formats don't match the format at hands, custom formats can be defined. More information about * customising CSVFormats is available in {@link CSVFormat CSVFormat JavaDoc}. *

* *

Parsing into memory

*

* If parsing record wise is not desired, the contents of the input can be read completely into memory. *

* *
 * Reader in = new StringReader("a;b\nc;d");
 * CSVParser parser = new CSVParser(in, CSVFormat.EXCEL);
 * List<CSVRecord> list = parser.getRecords();
 * 
* *

* There are two constraints that have to be kept in mind: *

* *
    *
  1. Parsing into memory starts at the current position of the parser. If you have already parsed records from * the input, those records will not end up in the in memory representation of your CSV data.
  2. *
  3. Parsing into memory may consume a lot of system resources depending on the input. For example if you're * parsing a 150MB file of CSV data the contents will be read completely into memory.
  4. *
* *

Notes

*

* Internal parser state is completely covered by the format and the reader-state. *

* * @version $Id: CSVParser.java 1695167 2015-08-10 21:08:58Z ggregory $ * * @see package documentation for more details */ public final class CSVParser implements Iterable, Closeable { /** * Creates a parser for the given {@link File}. * *

Note: This method internally creates a FileReader using * {@link java.io.FileReader#FileReader(java.io.File)} which in turn relies on the default encoding of the JVM that * is executing the code. If this is insufficient create a URL to the file and use * {@link #parse(URL, Charset, CSVFormat)}

* * @param file * a CSV file. Must not be null. * @param charset * A charset * @param format * the CSVFormat used for CSV parsing. Must not be null. * @return a new parser * @throws IllegalArgumentException * If the parameters of the format are inconsistent or if either file or format are null. * @throws IOException * If an I/O error occurs */ public static CSVParser parse(final File file, final Charset charset, final CSVFormat format) throws IOException { Assertions.notNull(file, "file"); Assertions.notNull(format, "format"); return new CSVParser(new InputStreamReader(new FileInputStream(file), charset), format); } /** * Creates a parser for the given {@link String}. * * @param string * a CSV string. Must not be null. * @param format * the CSVFormat used for CSV parsing. Must not be null. * @return a new parser * @throws IllegalArgumentException * If the parameters of the format are inconsistent or if either string or format are null. * @throws IOException * If an I/O error occurs */ public static CSVParser parse(final String string, final CSVFormat format) throws IOException { Assertions.notNull(string, "string"); Assertions.notNull(format, "format"); return new CSVParser(new StringReader(string), format); } /** * Creates a parser for the given URL. * *

* If you do not read all records from the given {@code url}, you should call {@link #close()} on the parser, unless * you close the {@code url}. *

* * @param url * a URL. Must not be null. * @param charset * the charset for the resource. Must not be null. * @param format * the CSVFormat used for CSV parsing. Must not be null. * @return a new parser * @throws IllegalArgumentException * If the parameters of the format are inconsistent or if either url, charset or format are null. * @throws IOException * If an I/O error occurs */ public static CSVParser parse(final URL url, final Charset charset, final CSVFormat format) throws IOException { Assertions.notNull(url, "url"); Assertions.notNull(charset, "charset"); Assertions.notNull(format, "format"); return new CSVParser(new InputStreamReader(url.openStream(), charset), format); } // the following objects are shared to reduce garbage private final CSVFormat format; /** A mapping of column names to column indices */ private final Map headerMap; private final Lexer lexer; /** A record buffer for getRecord(). Grows as necessary and is reused. */ private final List record = new ArrayList(); /** * The next record number to assign. */ private long recordNumber; /** * Lexer offset when the parser does not start parsing at the beginning of the source. Usually used in combination * with {@link #recordNumber}. */ private final long characterOffset; private final Token reusableToken = new Token(); /** * Customized CSV parser using the given {@link CSVFormat} * *

* If you do not read all records from the given {@code reader}, you should call {@link #close()} on the parser, * unless you close the {@code reader}. *

* * @param reader * a Reader containing CSV-formatted input. Must not be null. * @param format * the CSVFormat used for CSV parsing. Must not be null. * @throws IllegalArgumentException * If the parameters of the format are inconsistent or if either reader or format are null. * @throws IOException * If there is a problem reading the header or skipping the first record */ public CSVParser(final Reader reader, final CSVFormat format) throws IOException { this(reader, format, 0, 1); } /** * Customized CSV parser using the given {@link CSVFormat} * *

* If you do not read all records from the given {@code reader}, you should call {@link #close()} on the parser, * unless you close the {@code reader}. *

* * @param reader * a Reader containing CSV-formatted input. Must not be null. * @param format * the CSVFormat used for CSV parsing. Must not be null. * @param characterOffset * Lexer offset when the parser does not start parsing at the beginning of the source. * @param recordNumber * The next record number to assign * @throws IllegalArgumentException * If the parameters of the format are inconsistent or if either reader or format are null. * @throws IOException * If there is a problem reading the header or skipping the first record * @since 1.1 */ public CSVParser(final Reader reader, final CSVFormat format, final long characterOffset, final long recordNumber) throws IOException { Assertions.notNull(reader, "reader"); Assertions.notNull(format, "format"); this.format = format; this.lexer = new Lexer(format, new ExtendedBufferedReader(reader)); this.headerMap = this.initializeHeader(); this.characterOffset = characterOffset; this.recordNumber = recordNumber - 1; } private void addRecordValue() { final String input = this.reusableToken.content.toString(); final String nullString = this.format.getNullString(); if (nullString == null) { this.record.add(input); } else { this.record.add(input.equalsIgnoreCase(nullString) ? null : input); } } /** * Closes resources. * * @throws IOException * If an I/O error occurs */ @Override public void close() throws IOException { if (this.lexer != null) { this.lexer.close(); } } /** * Returns the current line number in the input stream. * *

* ATTENTION: If your CSV input has multi-line values, the returned number does not correspond to * the record number. *

* * @return current line number */ public long getCurrentLineNumber() { return this.lexer.getCurrentLineNumber(); } /** * Returns a copy of the header map that iterates in column order. *

* The map keys are column names. The map values are 0-based indices. *

* @return a copy of the header map that iterates in column order. */ public Map getHeaderMap() { return this.headerMap == null ? null : new LinkedHashMap(this.headerMap); } /** * Returns the current record number in the input stream. * *

* ATTENTION: If your CSV input has multi-line values, the returned number does not correspond to * the line number. *

* * @return current record number */ public long getRecordNumber() { return this.recordNumber; } /** * Parses the CSV input according to the given format and returns the content as a list of * {@link CSVRecord CSVRecords}. * *

* The returned content starts at the current parse-position in the stream. *

* * @return list of {@link CSVRecord CSVRecords}, may be empty * @throws IOException * on parse error or input read-failure */ public List getRecords() throws IOException { CSVRecord rec; final List records = new ArrayList(); while ((rec = this.nextRecord()) != null) { records.add(rec); } return records; } /** * Initializes the name to index mapping if the format defines a header. * * @return null if the format has no header. * @throws IOException if there is a problem reading the header or skipping the first record */ private Map initializeHeader() throws IOException { Map hdrMap = null; final String[] formatHeader = this.format.getHeader(); if (formatHeader != null) { hdrMap = new LinkedHashMap(); String[] headerRecord = null; if (formatHeader.length == 0) { // read the header from the first line of the file final CSVRecord nextRecord = this.nextRecord(); if (nextRecord != null) { headerRecord = nextRecord.values(); } } else { if (this.format.getSkipHeaderRecord()) { this.nextRecord(); } headerRecord = formatHeader; } // build the name to index mappings if (headerRecord != null) { for (int i = 0; i < headerRecord.length; i++) { final String header = headerRecord[i]; final boolean containsHeader = hdrMap.containsKey(header); final boolean emptyHeader = header == null || header.trim().isEmpty(); if (containsHeader && (!emptyHeader || (emptyHeader && !this.format.getAllowMissingColumnNames()))) { throw new IllegalArgumentException("The header contains a duplicate name: \"" + header + "\" in " + Arrays.toString(headerRecord)); } hdrMap.put(header, Integer.valueOf(i)); } } } return hdrMap; } /** * Gets whether this parser is closed. * * @return whether this parser is closed. */ public boolean isClosed() { return this.lexer.isClosed(); } /** * Returns an iterator on the records. * *

IOExceptions occurring during the iteration are wrapped in a * RuntimeException. * If the parser is closed a call to {@code next()} will throw a * NoSuchElementException.

*/ @Override public Iterator iterator() { return new Iterator() { private CSVRecord current; private CSVRecord getNextRecord() { try { return CSVParser.this.nextRecord(); } catch (final IOException e) { // TODO: This is not great, throw an ISE instead? throw new RuntimeException(e); } } @Override public boolean hasNext() { if (CSVParser.this.isClosed()) { return false; } if (this.current == null) { this.current = this.getNextRecord(); } return this.current != null; } @Override public CSVRecord next() { if (CSVParser.this.isClosed()) { throw new NoSuchElementException("CSVParser has been closed"); } CSVRecord next = this.current; this.current = null; if (next == null) { // hasNext() wasn't called before next = this.getNextRecord(); if (next == null) { throw new NoSuchElementException("No more CSV records available"); } } return next; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } /** * Parses the next record from the current point in the stream. * * @return the record as an array of values, or {@code null} if the end of the stream has been reached * @throws IOException * on parse error or input read-failure */ CSVRecord nextRecord() throws IOException { CSVRecord result = null; this.record.clear(); StringBuilder sb = null; final long startCharPosition = lexer.getCharacterPosition() + this.characterOffset; do { this.reusableToken.reset(); this.lexer.nextToken(this.reusableToken); switch (this.reusableToken.type) { case TOKEN: this.addRecordValue(); break; case EORECORD: this.addRecordValue(); break; case EOF: if (this.reusableToken.isReady) { this.addRecordValue(); } break; case INVALID: throw new IOException("(line " + this.getCurrentLineNumber() + ") invalid parse sequence"); case COMMENT: // Ignored currently if (sb == null) { // first comment for this record sb = new StringBuilder(); } else { sb.append(Constants.LF); } sb.append(this.reusableToken.content); this.reusableToken.type = TOKEN; // Read another token break; default: throw new IllegalStateException("Unexpected Token type: " + this.reusableToken.type); } } while (this.reusableToken.type == TOKEN); if (!this.record.isEmpty()) { this.recordNumber++; final String comment = sb == null ? null : sb.toString(); result = new CSVRecord(this.record.toArray(new String[this.record.size()]), this.headerMap, comment, this.recordNumber, startCharPosition); } return result; } } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/CSVPrinter.java0100644 0000000 0000000 00000042753 12565700105 031033 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.COMMENT; import static org.apache.commons.csv.Constants.CR; import static org.apache.commons.csv.Constants.LF; import static org.apache.commons.csv.Constants.SP; import java.io.Closeable; import java.io.Flushable; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; /** * Prints values in a CSV format. * * @version $Id: CSVPrinter.java 1695167 2015-08-10 21:08:58Z ggregory $ */ public final class CSVPrinter implements Flushable, Closeable { /** The place that the values get written. */ private final Appendable out; private final CSVFormat format; /** True if we just began a new record. */ private boolean newRecord = true; /** * Creates a printer that will print values to the given stream following the CSVFormat. *

* Currently, only a pure encapsulation format or a pure escaping format is supported. Hybrid formats (encapsulation * and escaping with a different character) are not supported. *

* * @param out * stream to which to print. Must not be null. * @param format * the CSV format. Must not be null. * @throws IOException * thrown if the optional header cannot be printed. * @throws IllegalArgumentException * thrown if the parameters of the format are inconsistent or if either out or format are null. */ public CSVPrinter(final Appendable out, final CSVFormat format) throws IOException { Assertions.notNull(out, "out"); Assertions.notNull(format, "format"); this.out = out; this.format = format; // TODO: Is it a good idea to do this here instead of on the first call to a print method? // It seems a pain to have to track whether the header has already been printed or not. if (format.getHeaderComments() != null) { for (final String line : format.getHeaderComments()) { if (line != null) { this.printComment(line); } } } if (format.getHeader() != null) { this.printRecord((Object[]) format.getHeader()); } } // ====================================================== // printing implementation // ====================================================== @Override public void close() throws IOException { if (out instanceof Closeable) { ((Closeable) out).close(); } } /** * Flushes the underlying stream. * * @throws IOException * If an I/O error occurs */ @Override public void flush() throws IOException { if (out instanceof Flushable) { ((Flushable) out).flush(); } } /** * Gets the target Appendable. * * @return the target Appendable. */ public Appendable getOut() { return this.out; } /** * Prints the string as the next value on the line. The value will be escaped or encapsulated as needed. * * @param value * value to be output. * @throws IOException * If an I/O error occurs */ public void print(final Object value) throws IOException { // null values are considered empty String strValue; if (value == null) { final String nullString = format.getNullString(); strValue = nullString == null ? Constants.EMPTY : nullString; } else { strValue = value.toString(); } this.print(value, strValue, 0, strValue.length()); } private void print(final Object object, final CharSequence value, final int offset, final int len) throws IOException { if (!newRecord) { out.append(format.getDelimiter()); } if (format.isQuoteCharacterSet()) { // the original object is needed so can check for Number printAndQuote(object, value, offset, len); } else if (format.isEscapeCharacterSet()) { printAndEscape(value, offset, len); } else { out.append(value, offset, offset + len); } newRecord = false; } /* * Note: must only be called if escaping is enabled, otherwise will generate NPE */ private void printAndEscape(final CharSequence value, final int offset, final int len) throws IOException { int start = offset; int pos = offset; final int end = offset + len; final char delim = format.getDelimiter(); final char escape = format.getEscapeCharacter().charValue(); while (pos < end) { char c = value.charAt(pos); if (c == CR || c == LF || c == delim || c == escape) { // write out segment up until this char if (pos > start) { out.append(value, start, pos); } if (c == LF) { c = 'n'; } else if (c == CR) { c = 'r'; } out.append(escape); out.append(c); start = pos + 1; // start on the current char after this one } pos++; } // write last segment if (pos > start) { out.append(value, start, pos); } } /* * Note: must only be called if quoting is enabled, otherwise will generate NPE */ // the original object is needed so can check for Number private void printAndQuote(final Object object, final CharSequence value, final int offset, final int len) throws IOException { boolean quote = false; int start = offset; int pos = offset; final int end = offset + len; final char delimChar = format.getDelimiter(); final char quoteChar = format.getQuoteCharacter().charValue(); QuoteMode quoteModePolicy = format.getQuoteMode(); if (quoteModePolicy == null) { quoteModePolicy = QuoteMode.MINIMAL; } switch (quoteModePolicy) { case ALL: quote = true; break; case NON_NUMERIC: quote = !(object instanceof Number); break; case NONE: // Use the existing escaping code printAndEscape(value, offset, len); return; case MINIMAL: if (len <= 0) { // always quote an empty token that is the first // on the line, as it may be the only thing on the // line. If it were not quoted in that case, // an empty line has no tokens. if (newRecord) { quote = true; } } else { char c = value.charAt(pos); // TODO where did this rule come from? if (newRecord && (c < '0' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a') || (c > 'z'))) { quote = true; } else if (c <= COMMENT) { // Some other chars at the start of a value caused the parser to fail, so for now // encapsulate if we start in anything less than '#'. We are being conservative // by including the default comment char too. quote = true; } else { while (pos < end) { c = value.charAt(pos); if (c == LF || c == CR || c == quoteChar || c == delimChar) { quote = true; break; } pos++; } if (!quote) { pos = end - 1; c = value.charAt(pos); // Some other chars at the end caused the parser to fail, so for now // encapsulate if we end in anything less than ' ' if (c <= SP) { quote = true; } } } } if (!quote) { // no encapsulation needed - write out the original value out.append(value, start, end); return; } break; default: throw new IllegalStateException("Unexpected Quote value: " + quoteModePolicy); } if (!quote) { // no encapsulation needed - write out the original value out.append(value, start, end); return; } // we hit something that needed encapsulation out.append(quoteChar); // Pick up where we left off: pos should be positioned on the first character that caused // the need for encapsulation. while (pos < end) { final char c = value.charAt(pos); if (c == quoteChar) { // write out the chunk up until this point // add 1 to the length to write out the encapsulator also out.append(value, start, pos + 1); // put the next starting position on the encapsulator so we will // write it out again with the next string (effectively doubling it) start = pos; } pos++; } // write the last segment out.append(value, start, pos); out.append(quoteChar); } /** * Prints a comment on a new line among the delimiter separated values. * *

* Comments will always begin on a new line and occupy a least one full line. The character specified to start * comments and a space will be inserted at the beginning of each new line in the comment. *

* * If comments are disabled in the current CSV format this method does nothing. * * @param comment * the comment to output * @throws IOException * If an I/O error occurs */ public void printComment(final String comment) throws IOException { if (!format.isCommentMarkerSet()) { return; } if (!newRecord) { println(); } out.append(format.getCommentMarker().charValue()); out.append(SP); for (int i = 0; i < comment.length(); i++) { final char c = comment.charAt(i); switch (c) { case CR: if (i + 1 < comment.length() && comment.charAt(i + 1) == LF) { i++; } //$FALL-THROUGH$ break intentionally excluded. case LF: println(); out.append(format.getCommentMarker().charValue()); out.append(SP); break; default: out.append(c); break; } } println(); } /** * Outputs the record separator. * * @throws IOException * If an I/O error occurs */ public void println() throws IOException { final String recordSeparator = format.getRecordSeparator(); if (recordSeparator != null) { out.append(recordSeparator); } newRecord = true; } /** * Prints the given values a single record of delimiter separated values followed by the record separator. * *

* The values will be quoted if needed. Quotes and newLine characters will be escaped. This method adds the record * separator to the output after printing the record, so there is no need to call {@link #println()}. *

* * @param values * values to output. * @throws IOException * If an I/O error occurs */ public void printRecord(final Iterable values) throws IOException { for (final Object value : values) { print(value); } println(); } /** * Prints the given values a single record of delimiter separated values followed by the record separator. * *

* The values will be quoted if needed. Quotes and newLine characters will be escaped. This method adds the record * separator to the output after printing the record, so there is no need to call {@link #println()}. *

* * @param values * values to output. * @throws IOException * If an I/O error occurs */ public void printRecord(final Object... values) throws IOException { for (final Object value : values) { print(value); } println(); } /** * Prints all the objects in the given collection handling nested collections/arrays as records. * *

* If the given collection only contains simple objects, this method will print a single record like * {@link #printRecord(Iterable)}. If the given collections contains nested collections/arrays those nested elements * will each be printed as records using {@link #printRecord(Object...)}. *

* *

* Given the following data structure: *

* *
     * 
     * List<String[]> data = ...
     * data.add(new String[]{ "A", "B", "C" });
     * data.add(new String[]{ "1", "2", "3" });
     * data.add(new String[]{ "A1", "B2", "C3" });
     * 
     * 
* *

* Calling this method will print: *

* *
     * 
     * A, B, C
     * 1, 2, 3
     * A1, B2, C3
     * 
     * 
* * @param values * the values to print. * @throws IOException * If an I/O error occurs */ public void printRecords(final Iterable values) throws IOException { for (final Object value : values) { if (value instanceof Object[]) { this.printRecord((Object[]) value); } else if (value instanceof Iterable) { this.printRecord((Iterable) value); } else { this.printRecord(value); } } } /** * Prints all the objects in the given array handling nested collections/arrays as records. * *

* If the given array only contains simple objects, this method will print a single record like * {@link #printRecord(Object...)}. If the given collections contains nested collections/arrays those nested * elements will each be printed as records using {@link #printRecord(Object...)}. *

* *

* Given the following data structure: *

* *
     * 
     * String[][] data = new String[3][]
     * data[0] = String[]{ "A", "B", "C" };
     * data[1] = new String[]{ "1", "2", "3" };
     * data[2] = new String[]{ "A1", "B2", "C3" };
     * 
     * 
* *

* Calling this method will print: *

* *
     * 
     * A, B, C
     * 1, 2, 3
     * A1, B2, C3
     * 
     * 
* * @param values * the values to print. * @throws IOException * If an I/O error occurs */ public void printRecords(final Object... values) throws IOException { for (final Object value : values) { if (value instanceof Object[]) { this.printRecord((Object[]) value); } else if (value instanceof Iterable) { this.printRecord((Iterable) value); } else { this.printRecord(value); } } } /** * Prints all the objects in the given JDBC result set. * * @param resultSet * result set the values to print. * @throws IOException * If an I/O error occurs * @throws SQLException * if a database access error occurs */ public void printRecords(final ResultSet resultSet) throws SQLException, IOException { final int columnCount = resultSet.getMetaData().getColumnCount(); while (resultSet.next()) { for (int i = 1; i <= columnCount; i++) { print(resultSet.getObject(i)); } println(); } } } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/CSVRecord.java0100644 0000000 0000000 00000020350 12565700105 030613 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import java.io.Serializable; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * A CSV record parsed from a CSV file. * * @version $Id: CSVRecord.java 1695167 2015-08-10 21:08:58Z ggregory $ */ public final class CSVRecord implements Serializable, Iterable { private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final long serialVersionUID = 1L; private final long characterPosition; /** The accumulated comments (if any) */ private final String comment; /** The column name to index mapping. */ private final Map mapping; /** The record number. */ private final long recordNumber; /** The values of the record */ private final String[] values; CSVRecord(final String[] values, final Map mapping, final String comment, final long recordNumber, final long characterPosition) { this.recordNumber = recordNumber; this.values = values != null ? values : EMPTY_STRING_ARRAY; this.mapping = mapping; this.comment = comment; this.characterPosition = characterPosition; } /** * Returns a value by {@link Enum}. * * @param e * an enum * @return the String at the given enum String */ public String get(final Enum e) { return get(e.toString()); } /** * Returns a value by index. * * @param i * a column index (0-based) * @return the String at the given index */ public String get(final int i) { return values[i]; } /** * Returns a value by name. * * @param name * the name of the column to be retrieved. * @return the column value, maybe null depending on {@link CSVFormat#getNullString()}. * @throws IllegalStateException * if no header mapping was provided * @throws IllegalArgumentException * if {@code name} is not mapped or if the record is inconsistent * @see #isConsistent() * @see CSVFormat#withNullString(String) */ public String get(final String name) { if (mapping == null) { throw new IllegalStateException( "No header mapping was specified, the record values can't be accessed by name"); } final Integer index = mapping.get(name); if (index == null) { throw new IllegalArgumentException(String.format("Mapping for %s not found, expected one of %s", name, mapping.keySet())); } try { return values[index.intValue()]; } catch (final ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException(String.format( "Index for header '%s' is %d but CSVRecord only has %d values!", name, index, Integer.valueOf(values.length))); } } /** * Returns the start position of this record as a character position in the source stream. This may or may not * correspond to the byte position depending on the character set. * * @return the position of this record in the source stream. */ public long getCharacterPosition() { return characterPosition; } /** * Returns the comment for this record, if any. * * @return the comment for this record, or null if no comment for this record is available. */ public String getComment() { return comment; } /** * Returns the number of this record in the parsed CSV file. * *

* ATTENTION: If your CSV input has multi-line values, the returned number does not correspond to * the current line number of the parser that created this record. *

* * @return the number of this record. * @see CSVParser#getCurrentLineNumber() */ public long getRecordNumber() { return recordNumber; } /** * Tells whether the record size matches the header size. * *

* Returns true if the sizes for this record match and false if not. Some programs can export files that fail this * test but still produce parsable files. *

* * @return true of this record is valid, false if not */ public boolean isConsistent() { return mapping == null || mapping.size() == values.length; } /** * Checks whether a given column is mapped, i.e. its name has been defined to the parser. * * @param name * the name of the column to be retrieved. * @return whether a given column is mapped. */ public boolean isMapped(final String name) { return mapping != null && mapping.containsKey(name); } /** * Checks whether a given columns is mapped and has a value. * * @param name * the name of the column to be retrieved. * @return whether a given columns is mapped and has a value */ public boolean isSet(final String name) { return isMapped(name) && mapping.get(name).intValue() < values.length; } /** * Returns an iterator over the values of this record. * * @return an iterator over the values of this record. */ @Override public Iterator iterator() { return toList().iterator(); } /** * Puts all values of this record into the given Map. * * @param map * The Map to populate. * @return the given map. */ > M putIn(final M map) { if (mapping == null) { return map; } for (final Entry entry : mapping.entrySet()) { final int col = entry.getValue().intValue(); if (col < values.length) { map.put(entry.getKey(), values[col]); } } return map; } /** * Returns the number of values in this record. * * @return the number of values. */ public int size() { return values.length; } /** * Converts the values to a List. * * TODO: Maybe make this public? * * @return a new List */ private List toList() { return Arrays.asList(values); } /** * Copies this record into a new Map. The new map is not connect * * @return A new Map. The map is empty if the record has no headers. */ public Map toMap() { return putIn(new HashMap(values.length)); } /** * Returns a string representation of the contents of this record. The result is constructed by comment, mapping, * recordNumber and by passing the internal values array to {@link Arrays#toString(Object[])}. * * @return a String representation of this record. */ @Override public String toString() { return "CSVRecord [comment=" + comment + ", mapping=" + mapping + ", recordNumber=" + recordNumber + ", values=" + Arrays.toString(values) + "]"; } String[] values() { return values; } } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java0100644 0000000 0000000 00000014111 12565700104 033344 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.CR; import static org.apache.commons.csv.Constants.END_OF_STREAM; import static org.apache.commons.csv.Constants.LF; import static org.apache.commons.csv.Constants.UNDEFINED; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; /** * A special buffered reader which supports sophisticated read access. *

* In particular the reader supports a look-ahead option, which allows you to see the next char returned by * {@link #read()}. This reader also tracks how many characters have been read with {@link #getPosition()}. *

* * @version $Id: ExtendedBufferedReader.java 1635146 2014-10-29 14:31:07Z ggregory $ */ final class ExtendedBufferedReader extends BufferedReader { /** The last char returned */ private int lastChar = UNDEFINED; /** The count of EOLs (CR/LF/CRLF) seen so far */ private long eolCounter; /** The position, which is number of characters read so far */ private long position; private boolean closed; /** * Created extended buffered reader using default buffer-size */ ExtendedBufferedReader(final Reader reader) { super(reader); } @Override public int read() throws IOException { final int current = super.read(); if (current == CR || (current == LF && lastChar != CR)) { eolCounter++; } lastChar = current; this.position++; return lastChar; } /** * Returns the last character that was read as an integer (0 to 65535). This will be the last character returned by * any of the read methods. This will not include a character read using the {@link #lookAhead()} method. If no * character has been read then this will return {@link Constants#UNDEFINED}. If the end of the stream was reached * on the last read then this will return {@link Constants#END_OF_STREAM}. * * @return the last character that was read */ int getLastChar() { return lastChar; } @Override public int read(final char[] buf, final int offset, final int length) throws IOException { if (length == 0) { return 0; } final int len = super.read(buf, offset, length); if (len > 0) { for (int i = offset; i < offset + len; i++) { final char ch = buf[i]; if (ch == LF) { if (CR != (i > 0 ? buf[i - 1] : lastChar)) { eolCounter++; } } else if (ch == CR) { eolCounter++; } } lastChar = buf[offset + len - 1]; } else if (len == -1) { lastChar = END_OF_STREAM; } position += len; return len; } /** * Calls {@link BufferedReader#readLine()} which drops the line terminator(s). This method should only be called * when processing a comment, otherwise information can be lost. *

* Increments {@link #eolCounter} *

* Sets {@link #lastChar} to {@link Constants#END_OF_STREAM} at EOF, otherwise to LF * * @return the line that was read, or null if reached EOF. */ @Override public String readLine() throws IOException { final String line = super.readLine(); if (line != null) { lastChar = LF; // needed for detecting start of line eolCounter++; } else { lastChar = END_OF_STREAM; } return line; } /** * Returns the next character in the current reader without consuming it. So the next call to {@link #read()} will * still return this value. Does not affect line number or last character. * * @return the next character * * @throws IOException * if there is an error in reading */ int lookAhead() throws IOException { super.mark(1); final int c = super.read(); super.reset(); return c; } /** * Returns the current line number * * @return the current line number */ long getCurrentLineNumber() { // Check if we are at EOL or EOF or just starting if (lastChar == CR || lastChar == LF || lastChar == UNDEFINED || lastChar == END_OF_STREAM) { return eolCounter; // counter is accurate } return eolCounter + 1; // Allow for counter being incremented only at EOL } /** * Gets the character position in the reader. * * @return the current position in the reader (counting characters, not bytes since this is a Reader) */ long getPosition() { return this.position; } public boolean isClosed() { return closed; } /** * Closes the stream. * * @throws IOException * If an I/O error occurs */ @Override public void close() throws IOException { // Set ivars before calling super close() in case close() throws an IOException. closed = true; lastChar = END_OF_STREAM; super.close(); } } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/Lexer.java0100644 0000000 0000000 00000040224 12565700105 030102 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.BACKSPACE; import static org.apache.commons.csv.Constants.CR; import static org.apache.commons.csv.Constants.END_OF_STREAM; import static org.apache.commons.csv.Constants.FF; import static org.apache.commons.csv.Constants.LF; import static org.apache.commons.csv.Constants.TAB; import static org.apache.commons.csv.Constants.UNDEFINED; import static org.apache.commons.csv.Token.Type.COMMENT; import static org.apache.commons.csv.Token.Type.EOF; import static org.apache.commons.csv.Token.Type.EORECORD; import static org.apache.commons.csv.Token.Type.INVALID; import static org.apache.commons.csv.Token.Type.TOKEN; import java.io.Closeable; import java.io.IOException; /** * Lexical analyzer. * * @version $Id: Lexer.java 1635502 2014-10-30 14:01:43Z ggregory $ */ final class Lexer implements Closeable { /** * Constant char to use for disabling comments, escapes and encapsulation. The value -2 is used because it * won't be confused with an EOF signal (-1), and because the Unicode value {@code FFFE} would be encoded as two * chars (using surrogates) and thus there should never be a collision with a real text char. */ private static final char DISABLED = '\ufffe'; private final char delimiter; private final char escape; private final char quoteChar; private final char commentStart; private final boolean ignoreSurroundingSpaces; private final boolean ignoreEmptyLines; /** The input stream */ private final ExtendedBufferedReader reader; Lexer(final CSVFormat format, final ExtendedBufferedReader reader) { this.reader = reader; this.delimiter = format.getDelimiter(); this.escape = mapNullToDisabled(format.getEscapeCharacter()); this.quoteChar = mapNullToDisabled(format.getQuoteCharacter()); this.commentStart = mapNullToDisabled(format.getCommentMarker()); this.ignoreSurroundingSpaces = format.getIgnoreSurroundingSpaces(); this.ignoreEmptyLines = format.getIgnoreEmptyLines(); } /** * Returns the next token. *

* A token corresponds to a term, a record change or an end-of-file indicator. *

* * @param token * an existing Token object to reuse. The caller is responsible to initialize the Token. * @return the next token found * @throws java.io.IOException * on stream access error */ Token nextToken(final Token token) throws IOException { // get the last read char (required for empty line detection) int lastChar = reader.getLastChar(); // read the next char and set eol int c = reader.read(); /* * Note: The following call will swallow LF if c == CR. But we don't need to know if the last char was CR or LF * - they are equivalent here. */ boolean eol = readEndOfLine(c); // empty line detection: eol AND (last char was EOL or beginning) if (ignoreEmptyLines) { while (eol && isStartOfLine(lastChar)) { // go on char ahead ... lastChar = c; c = reader.read(); eol = readEndOfLine(c); // reached end of file without any content (empty line at the end) if (isEndOfFile(c)) { token.type = EOF; // don't set token.isReady here because no content return token; } } } // did we reach eof during the last iteration already ? EOF if (isEndOfFile(lastChar) || (!isDelimiter(lastChar) && isEndOfFile(c))) { token.type = EOF; // don't set token.isReady here because no content return token; } if (isStartOfLine(lastChar) && isCommentStart(c)) { final String line = reader.readLine(); if (line == null) { token.type = EOF; // don't set token.isReady here because no content return token; } final String comment = line.trim(); token.content.append(comment); token.type = COMMENT; return token; } // important: make sure a new char gets consumed in each iteration while (token.type == INVALID) { // ignore whitespaces at beginning of a token if (ignoreSurroundingSpaces) { while (isWhitespace(c) && !eol) { c = reader.read(); eol = readEndOfLine(c); } } // ok, start of token reached: encapsulated, or token if (isDelimiter(c)) { // empty token return TOKEN("") token.type = TOKEN; } else if (eol) { // empty token return EORECORD("") // noop: token.content.append(""); token.type = EORECORD; } else if (isQuoteChar(c)) { // consume encapsulated token parseEncapsulatedToken(token); } else if (isEndOfFile(c)) { // end of file return EOF() // noop: token.content.append(""); token.type = EOF; token.isReady = true; // there is data at EOF } else { // next token must be a simple token // add removed blanks when not ignoring whitespace chars... parseSimpleToken(token, c); } } return token; } /** * Parses a simple token. *

* Simple token are tokens which are not surrounded by encapsulators. A simple token might contain escaped * delimiters (as \, or \;). The token is finished when one of the following conditions become true: *

    *
  • end of line has been reached (EORECORD)
  • *
  • end of stream has been reached (EOF)
  • *
  • an unescaped delimiter has been reached (TOKEN)
  • *
* * @param token * the current token * @param ch * the current character * @return the filled token * @throws IOException * on stream access error */ private Token parseSimpleToken(final Token token, int ch) throws IOException { // Faster to use while(true)+break than while(token.type == INVALID) while (true) { if (readEndOfLine(ch)) { token.type = EORECORD; break; } else if (isEndOfFile(ch)) { token.type = EOF; token.isReady = true; // There is data at EOF break; } else if (isDelimiter(ch)) { token.type = TOKEN; break; } else if (isEscape(ch)) { final int unescaped = readEscape(); if (unescaped == Constants.END_OF_STREAM) { // unexpected char after escape token.content.append((char) ch).append((char) reader.getLastChar()); } else { token.content.append((char) unescaped); } ch = reader.read(); // continue } else { token.content.append((char) ch); ch = reader.read(); // continue } } if (ignoreSurroundingSpaces) { trimTrailingSpaces(token.content); } return token; } /** * Parses an encapsulated token. *

* Encapsulated tokens are surrounded by the given encapsulating-string. The encapsulator itself might be included * in the token using a doubling syntax (as "", '') or using escaping (as in \", \'). Whitespaces before and after * an encapsulated token are ignored. The token is finished when one of the following conditions become true: *

    *
  • an unescaped encapsulator has been reached, and is followed by optional whitespace then:
  • *
      *
    • delimiter (TOKEN)
    • *
    • end of line (EORECORD)
    • *
    *
  • end of stream has been reached (EOF)
* * @param token * the current token * @return a valid token object * @throws IOException * on invalid state: EOF before closing encapsulator or invalid character before delimiter or EOL */ private Token parseEncapsulatedToken(final Token token) throws IOException { // save current line number in case needed for IOE final long startLineNumber = getCurrentLineNumber(); int c; while (true) { c = reader.read(); if (isEscape(c)) { final int unescaped = readEscape(); if (unescaped == Constants.END_OF_STREAM) { // unexpected char after escape token.content.append((char) c).append((char) reader.getLastChar()); } else { token.content.append((char) unescaped); } } else if (isQuoteChar(c)) { if (isQuoteChar(reader.lookAhead())) { // double or escaped encapsulator -> add single encapsulator to token c = reader.read(); token.content.append((char) c); } else { // token finish mark (encapsulator) reached: ignore whitespace till delimiter while (true) { c = reader.read(); if (isDelimiter(c)) { token.type = TOKEN; return token; } else if (isEndOfFile(c)) { token.type = EOF; token.isReady = true; // There is data at EOF return token; } else if (readEndOfLine(c)) { token.type = EORECORD; return token; } else if (!isWhitespace(c)) { // error invalid char between token and next delimiter throw new IOException("(line " + getCurrentLineNumber() + ") invalid char between encapsulated token and delimiter"); } } } } else if (isEndOfFile(c)) { // error condition (end of file before end of token) throw new IOException("(startline " + startLineNumber + ") EOF reached before encapsulated token finished"); } else { // consume character token.content.append((char) c); } } } private char mapNullToDisabled(final Character c) { return c == null ? DISABLED : c.charValue(); } /** * Returns the current line number * * @return the current line number */ long getCurrentLineNumber() { return reader.getCurrentLineNumber(); } /** * Returns the current character position * * @return the current character position */ long getCharacterPosition() { return reader.getPosition(); } // TODO escape handling needs more work /** * Handle an escape sequence. * The current character must be the escape character. * On return, the next character is available by calling {@link ExtendedBufferedReader#getLastChar()} * on the input stream. * * @return the unescaped character (as an int) or {@link Constants#END_OF_STREAM} if char following the escape is * invalid. * @throws IOException if there is a problem reading the stream or the end of stream is detected: * the escape character is not allowed at end of strem */ int readEscape() throws IOException { // the escape char has just been read (normally a backslash) final int ch = reader.read(); switch (ch) { case 'r': return CR; case 'n': return LF; case 't': return TAB; case 'b': return BACKSPACE; case 'f': return FF; case CR: case LF: case FF: // TODO is this correct? case TAB: // TODO is this correct? Do tabs need to be escaped? case BACKSPACE: // TODO is this correct? return ch; case END_OF_STREAM: throw new IOException("EOF whilst processing escape sequence"); default: // Now check for meta-characters if (isMetaChar(ch)) { return ch; } // indicate unexpected char - available from in.getLastChar() return END_OF_STREAM; } } void trimTrailingSpaces(final StringBuilder buffer) { int length = buffer.length(); while (length > 0 && Character.isWhitespace(buffer.charAt(length - 1))) { length = length - 1; } if (length != buffer.length()) { buffer.setLength(length); } } /** * Greedily accepts \n, \r and \r\n This checker consumes silently the second control-character... * * @return true if the given or next character is a line-terminator */ boolean readEndOfLine(int ch) throws IOException { // check if we have \r\n... if (ch == CR && reader.lookAhead() == LF) { // note: does not change ch outside of this method! ch = reader.read(); } return ch == LF || ch == CR; } boolean isClosed() { return reader.isClosed(); } /** * @return true if the given char is a whitespace character */ boolean isWhitespace(final int ch) { return !isDelimiter(ch) && Character.isWhitespace((char) ch); } /** * Checks if the current character represents the start of a line: a CR, LF or is at the start of the file. * * @param ch the character to check * @return true if the character is at the start of a line. */ boolean isStartOfLine(final int ch) { return ch == LF || ch == CR || ch == UNDEFINED; } /** * @return true if the given character indicates end of file */ boolean isEndOfFile(final int ch) { return ch == END_OF_STREAM; } boolean isDelimiter(final int ch) { return ch == delimiter; } boolean isEscape(final int ch) { return ch == escape; } boolean isQuoteChar(final int ch) { return ch == quoteChar; } boolean isCommentStart(final int ch) { return ch == commentStart; } private boolean isMetaChar(final int ch) { return ch == delimiter || ch == escape || ch == quoteChar || ch == commentStart; } /** * Closes resources. * * @throws IOException * If an I/O error occurs */ @Override public void close() throws IOException { reader.close(); } } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/package-info.java0100644 0000000 0000000 00000007151 12565700105 031351 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Apache Commons CSV Format Support. * *

CSV are widely used as interfaces to legacy systems or manual data-imports. * CSV stands for "Comma Separated Values" (or sometimes "Character Separated * Values"). The CSV data format is defined in * RFC 4180 * but many dialects exist.

* *

Common to all file dialects is its basic structure: The CSV data-format * is record oriented, whereas each record starts on a new textual line. A * record is build of a list of values. Keep in mind that not all records * must have an equal number of values:

*
 *       csv    := records*
 *       record := values*
 * 
* *

The following list contains the CSV aspects the Commons CSV parser supports:

*
*
Separators (for lines)
*
The record separators are hardcoded and cannot be changed. The must be '\r', '\n' or '\r\n'.
* *
Delimiter (for values)
*
The delimiter for values is freely configurable (default ',').
* *
Comments
*
Some CSV-dialects support a simple comment syntax. A comment is a record * which must start with a designated character (the commentStarter). A record * of this kind is treated as comment and gets removed from the input (default none)
* *
Encapsulator
*
Two encapsulator characters (default '"') are used to enclose -> complex values.
* *
Simple values
*
A simple value consist of all characters (except the delimiter) until * (but not including) the next delimiter or a record-terminator. Optionally * all surrounding whitespaces of a simple value can be ignored (default: true).
* *
Complex values
*
Complex values are encapsulated within a pair of the defined encapsulator characters. * The encapsulator itself must be escaped or doubled when used inside complex values. * Complex values preserve all kind of formatting (including newlines -> multiline-values)
* *
Empty line skipping
*
Optionally empty lines in CSV files can be skipped. * Otherwise, empty lines will return a record with a single empty value.
*
* *

In addition to individually defined dialects, two predefined dialects (strict-csv, and excel-csv) * can be set directly.

* *

Example usage:

*
 * Reader in = new StringReader("a,b,c");
 * for (CSVRecord record : CSVFormat.DEFAULT.parse(in)) {
 *     for (String field : record) {
 *         System.out.print("\"" + field + "\", ");
 *     }
 *     System.out.println();
 * }
 * 
*/ package org.apache.commons.csv; commons-csv-1.2-src/src/main/java/org/apache/commons/csv/QuoteMode.java0100644 0000000 0000000 00000003030 12565700105 030717 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; /** * Defines quote behavior when printing. * * @version $Id: QuoteMode.java 1694977 2015-08-10 07:05:58Z ggregory $ */ public enum QuoteMode { /** * Quotes all fields. */ ALL, /** * Quotes fields which contain special characters such as a delimiter, quotes character or any of the characters in * line separator. */ MINIMAL, /** * Quotes all non-numeric fields. */ NON_NUMERIC, /** * Never quotes fields. When the delimiter occurs in data, the printer prefixes it with the current escape * character. If the escape character is not set, format validation throws an exception. */ NONE } commons-csv-1.2-src/src/main/java/org/apache/commons/csv/Token.java0100644 0000000 0000000 00000004423 12565700105 030104 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Token.Type.INVALID; /** * Internal token representation. *

* It is used as contract between the lexer and the parser. * * @version $Id: Token.java 1509069 2013-08-01 02:04:27Z ggregory $ */ final class Token { /** length of the initial token (content-)buffer */ private static final int INITIAL_TOKEN_LENGTH = 50; enum Type { /** Token has no valid content, i.e. is in its initialized state. */ INVALID, /** Token with content, at beginning or in the middle of a line. */ TOKEN, /** Token (which can have content) when the end of file is reached. */ EOF, /** Token with content when the end of a line is reached. */ EORECORD, /** Token is a comment line. */ COMMENT } /** Token type */ Token.Type type = INVALID; /** The content buffer. */ final StringBuilder content = new StringBuilder(INITIAL_TOKEN_LENGTH); /** Token ready flag: indicates a valid token with content (ready for the parser). */ boolean isReady; void reset() { content.setLength(0); type = INVALID; isReady = false; } /** * Eases IDE debugging. * * @return a string helpful for debugging. */ @Override public String toString() { return type.name() + " [" + content.toString() + "]"; } } commons-csv-1.2-src/src/site/resources/download_csv.cgi0100644 0000000 0000000 00000000240 12565700105 026153 0ustar00BUILTIN\Administrators0000000 0000000 #!/bin/sh # Just call the standard mirrors.cgi script. It will use download.html # as the input template. exec /www/www.apache.org/dyn/mirrors/mirrors.cgi $*commons-csv-1.2-src/src/site/resources/images/logo.png0100644 0000000 0000000 00000047112 12565700105 025731 0ustar00BUILTIN\Administrators0000000 0000000 PNG  IHDRf?'sRGBbKGD pHYs  tIME , wd IDATxw]Ց:je%DDF#0x`M؟u` Nc3 dDHDPέι'Ǿ#k5iyT"dֿ^浥QBFa+euDḦ́&0m4Ø3m)ﯗab V].xOzBV3ZmMvU$tۍv5Nt% N;4.R=\\w2_+~صqlUP`C]@Pk"*H O`XtwRtz ./)S.{_[>o| {Qs9py7~(cu(PB4L>r2oG_\yx (⋹oWA+5@ݘEeeۖC2ONpxr9WpǮ$U17^7VAx=rݨ* ^ <^o#jP iUH&O3tƥ|r')J~oi,iDJż k(TBhGDE`CE>B0eD-Ii=@p/ȈY)豚ѿMB^;e\g]47~,̟K1Yw7vH.ߴ6CwtAKUc:!QC[Nk–52J*JSzF THi -PAdd[ B*#D T]|hk?a++ ir\cJxq⋌+7[kMv[ A1@eD֬paag~Z-6~.H$Ub"]H@F Z.A<!Ѵ)ީ1b|W~J{>N+csQQVi|]GhDNC*"!*(<oǞВi!Rh?"޶=5L\` !QW*SD`_$-P"ahc!{4tҁ[~yobAw@jB \6EX%nb¹A TJapgHTq-|szn8q=}602;!9(D8=FEfs9Rl{h_P Q$*^PG#|3旿4FfaD>EE~$5khz @Zsd:2XA. JE$'& DvBUxt=U_8(C+o~KC7 0}c$~' p!-K($mP݊hGpyFگؾoV*3PX-Q5JH#ję q%6yIw+jF GBZbĈ[e%CE TPxG{bO$J 'ʨGC\phq̍RrScPj%D .~Qxo"z5F>Y:R G#o'$6)W䮐ݝ{է\GsNw#͐qCTY;=Q>qtتx聇xsś466D_QɔS8st=ڳ{_xw^yz J Hȴg:b(55,}~PLp^o qu$5?%`K-ʠImK֖- \6S^5W8OR RV4JDR*bms#zS7E!xSv0Z<2)"#B8̘ qh< o|3khDTR6,A*$%ph|WU &#K]j>V#\_0 L wUĚ`I5x~,"I" aP~L#Fe{_^v!-:O0,Q%ʘq$˴R-8Gq,X@v٧ .*dC$سl3>ӑ&#SfR/E(Dar%BIɠfhhoQʧ7"jLGk {ߑ7~PF\0B_{69[w}K,{-EWI*$9-)j5MIYRȌ;euSeʕSd)S)>N{+-jlG^Xa3/>c$qiB=a6bg_ԭu& zE)q.q:g GD6c{!ꊰx=r[rD|=~e?p\ǮvGPjj.  j#y[N(RwSFrȶ е0]P"j-H@#It@+3!X\~#;Btx$ jϿ2,rvM|/[~}(>m& ;N(Ƴ+t6vN%0tNzCV>%6a~' 7?|3д  )TBvYU@ 7Wb\+\g;gNBcFTrf{^d:2 DAFxSLz^ތ.D@' TBu*HMM|8Izk45mf _Y)~7),WsGmH`Ͳx]PbɃK8y.# XH.CjPm4GY\XCþB- _2aƳka}~MۆS?pX,<՝z'\p OîlZW?z5,+;}b~@:˲l!Ah5L%KutLq?=gCi I#nK5LIŠ"TQ8@*c0GN:$?# U ?/BeQ #нJ~Գ⷇ڄ:JZIY^!6=ih Q-IER4 *q9SXa1C,7JM Bީ+QPa%+3{=Ї+r%l34HrpPf*WA.VΟ6Qz&j6w] C4LlŠLt6B#2cVBڅ)DBgzy3-h!j ?P|_ƌjϯ.*S5z&|'$33yo?`@YYuIE6l:oCsr`N~_;TΜUV4lev6耨1yE.B6C;uJt&D(K!ӫ&!{L-cߧ۪P %6 搯9i㮍\9ujtBL&G~vr 0Y|0H+X}!]brsDA=&j6GA Q#䕱@gKBTAM:Hz.~sB74kaWĬV @T A&QwDFNjUKl2#s jP ikHwMN9xբ_w۷\{s @(+*/K?U/{7P8؂vP Έzu\oEAQvmn ͻRb'~Ϧ%xgɟƪ(&)#E_EĞc=U"=2+aa%&DMQWxg5u e#df[! P3gkQ+)IC qg# Ot%mwvXw}-ɞ1J$LvBE+YeAuǸB!kI}*%CGTC 7H߿f)s)5TUʧt/>`Ky+BF/ݳҜFAs0(QUKO+B O(=]Kb~B;5lAsɟV31bf DH Nvg]P1Zpg##!-=]S 4Dt{-c'iQXZ!)[Zb i|'#).?dg>SqJH-4O*%;F( IDAT͒Y~'Gܫ\Q0 Q<^Vȩ=UN)2sm.w'e^\(/zA7μLqf8&+JY*gc9GԙJqJF 8SYOѢiu,WQ<}L8s f(gR^ZIMC蛴CѢf(a9 O9ua~3SlI} Vsk^HU` aTρte|]kFD cT+68Ʉ)e"j(x5釦V=lTB TNImN=C.0IƨAޖ˜ۍD51C}+eڰB!S!@=xi\iGv6>N;0sqSAyq݋ȧ`/k7OYq_YZͷ 6s&VZSFuDhkl ۞eVpc8b_TBQ~d!tC[*[^bJHN3lG3{li\_[on]ava TWp_*T`F_UsF9سlHc؆Y|½Qx7\~?mۧKp<`HO$X-[ճYGg{БY ??17e S2mP/)>/?X -5Vw8Zpw,rdn m l岃;궴eP?HnM?r:lv0!( ({&TO Q0Z@Y9ٸ8ZPTTJ"ݐcC,{&LؕC6EtO0~|v\c=@WiF7CETWt)l('R4 D彛iæC3!54WAEݻ _^z _`eu/_$H@h3`tBy!C"Jӥ{j*kӿaӆpAX {3!Qtmmڌ`!ln'ogesIPv9癟V‚={g[B@'_8K)h+ՠP +mA)3sqzwn]Qx'QܹRT~5Ep6m 4 'Q_08WuxquaKlcP&! vlsǙ in]]sA(dm%(V=ێ*7&"JK mCN%(Ys$A4+8O,皘ޢ. D ȍP){?fC me"C;n={v)U׵3u^}"-]dcl4f$ ;Y !'G3CkCa 8p"n*SxEpK\~^| ccw8>]<+jahMGC!&=McJXӕ\5*R:eLw |!D 8$l 2T_K[31,Ů?ͽ擞698x }/cr^0I'I7˳PB Vt|O.e"Rɔk5׾.6 :I h vE c>؁cMX,HAwpWA1CZ?"JD`G6ѣ ]\3{ zmĮ!x] ځܶ 88xE欆*NLPbof*PbY%* Ǝ<(RR(QVghc:(>0PnoRt/>X*aWϿP=_mLqЕpcɧz{2l~j3([9v>Y?96G6`? gCH$)4{ӇMgx ͧfp ^îqǺ*m"&V.2)z3$J j}ݷWwh`x9=$&\s<._*){BSf?$j}S<L5e 8սsa](]{zoh#{Lh7x`a!]{:3?v,(:!tCý A> }Ƥfu[㘌 yYޫE"cRK*1&v/}WJ(!tCFc;d۳&65Q>a,`+^]]R*NC:as@d,eCxHISϝkiwcnp&L@[Y=C&!L0 68+kb®ŧSmnQ{S-KY%g_M+%=[BQC5k\eع|[g;m<ŧWwW#;w-V 7&z 5Tۗ#gÿ>\Ms3 t~Κ|rNp7ck'_m]kdfł (I|Njc[ "DBM4/5tXX&Kd^ΐ~O:6WNLS3B?IuEu߃J,TdR!\$!Q {?JAQ :Of3H(&V]m rLYb1靬Oݶ,HUaQYSI2(x+w~G5I,D#jƤ+F]uuF~|,~cqӊ Vw|mQmZZʢJ掙˅_,eY O *+ب|^>HO,H*]{Wm]ve/;BCVx\2o! GAU(:E'-:o gdH6TA^ ['8$V7̣vla?D&OZӾS C֡ t٧>Qm 洌Eߣ``"18aJ}g utW?!̅L~oi=*L(kHtd˷̷i`0f tGق&)jWvttZ6{|Z $2 A1CmJ>C#@޾=Fָi;#rm=gI5\+)MBCo{='j̘ǶNjtJJY j.|C2C.1eO[|~ nf/ Z]x.P(wB:I=0t;` zNjHVef~mtGXrl Mٸe1 6o ㏤`R2>4P ݭbxJAeNȻ{v"Ӛ1$9KLlJ\`gWgk,6g b'JrLoɾAySL10ȼ'.c-$q}M,m؊A0o4ogL2]|莃OyqIĨCFg2}={S6&D6ZQaEQ5BB.3,ۡK&h hl%'K?XįyWtХ 5(b`x~}0S [B ,/e?!x#<v~o'7.棊j.Nit 9?:zw'"Z"D 6rJ^Y vm3 -QУ4R\zxwXǡαS%3e`Mpg`s@niudU2E Yi]߳n:7j\#0JhF"ț2dS}ΰdxmL})2A@rq(Qoo&ϗXlS@W O-{:L)m{-[H M@)$f&((-0҂I aGH#hQ2]49o7\#̅:OJWiɽ3G_)[c+k\?kξٓfp&[f cɦ]l,Y_#CSH"l j#T2ꚫɮΚ8R%D:BM6,bi+lS$2Xi1߰#{%K9,ҹ173sLlT"l51.z&מ< l[NЎ*5Mbzk (tƼU/.yOqt]#L] !'K[S>gO$/pTp y7dL}EܸcHR+OZ> E: &W[ r*-J3{doxX-C>u9lQSlE2/uyƎ/7mYKn^g?YR%)әln$0[-|~T͠xX1QaD.y@W+?~άYx]'Ѵ!'?0uG2&)c֜00hWD[sa)qş$$ad bXNM7_FnaM>Y7z߿Q|*V@#jZ%q<ܣt6:sk XSu;H 1@,<'wW cauޔʝ2U_O6vYE,*:"pXYƻnC\u .[ޟILZ8)Na-Z[ tTGvVF!R\tEx=te6V65QD[M\tEp*EB!D{#u!݋ٴop MlXeMV<5kO6fSQm!_mg,HGmC# gҒ~oQs ׳wQQp`~}m^4x6C&3BrLF;>ow>u6+`ooؖƺ-؟ϱqBMMG1!9lMp*MroD¢@*g;ku :BSf eoOfg>5ʵ_˜ 簫iR$PQ 8gF&mnG|ﱯ砫ajdŘ|S.YU?hsL)S,SxФc!G3H9!KSdcT@]@촍(!ӖSRId{ƾL-Ga.x~Aw@ v[S&[G׮.üz_Mggg/Юc\Eldp3)RD9:igC!n:ιvwE-G}w=n(vͱZժh\HC[W^}%_q<˷->5Z]Tb-\qGקwN3#H3|7ȄKDA5ѾȤ1iؤ} 3o"cNA}@'XX݊;ڱ9{o+{h@mK-÷9#ɗLJDcBf4 3%}mø;`|v%ciW.."T}D̞5 #'\(_+T]QJ|8n>dsDF6r9S"3S yA' 't3#iFh2~l5"95K)C!$H[v:sҤI̞8+ivNaK;|.>]ra5;3N|71t=#lJz"v&{J=oX$ S']q=kwe̿m>r!L np`}EFMJ Qߤ6h72#VĪt+&EvʴKqK7M!YQϭ ~]EG?`d&26k9e}8(mݽ~j*NtFmB?$j5{Ek/kc$M`E+ab :jޝ+n>,%=>G<@c {Uyy95yɍM AP4mbuZZ⺗Nۙuzvwřb[ku^ji:֎ P**rBHHH^9ϳ^XMa99s:<ԀBׄ)V%h &-`釗2c jS ybGngӦMNMFpC}\" q1ƶrBAKހ ?n1kL",+$G7xq",Ԝ?(i,,AGvD3*q;C}*o6-v>Q |X ?>$G y7Nη{ZnNoH^$њ`G2o<^4 #к~3ŽV%=ጨܸFǺ;?}L(Ց%\K64wOWq13&Π|D;Od&ϡzR5] !SǮ]o>^'8$_/T}8Ɵ[qR8x3H;%ՒbuPJc 8g9Mp"g;9}Z7.ٽv~ba4d^bfl3({%X'V>gAwk“!! <";$nč'6F*j!8P8Z ! y\ʑ5FrucE}0JD  DR zpqE,tQizT$p.tPx JQ}LgDi\8=ǮEH&̯d ,hPdS.W5.ί.p{\O5zƟ('VuDAwyosBUO~B*3T^-P9qEBMSE!!.sJŭyN+?RNiX=<#<B'\\2~>ui z.@žP*+(ry9l(_X)ӽf5pxX Q I)>ncY̳ W"yt9g(nGwf7kb$%v]b /!'M^Ԩ>I8$4Ɛa%Y>#^5nLI) 5)|HI;<JY;77onj :`y$/V@$׭geKG S!ңѡ0l?V s} I}G%N#x|t6jZ+]Lf}wST&{MWMjTBAvtؿfm2 Aokീ= |1$8əI.y19[-/laէVa ^+͚NT~.BtT %qk P |]moר*]Ū_?͗g-_v5 S2r̈>sŊXVXUxiii_<ħ~?py{iڈ]=ۑ 1MWʑMN|' B?}*n`~Ǹ}<R^QTEE%"߯ʏ+bGq?ͤF¬Pz_h$ߨs%^)-ٳ'=L B oSxyEa6$i@m4Lpd # *.̣ 1J 8Mo6nmqWnɧ Mz Cxy4tb1tQNvV.MG2-_=ͣelٲ(^Ԗ{\%##38Bĸ-[ϱeןb/yɑNI"IsX l`u%=om3.nܡClޱvotƍGS]ۏpBOOm&~'y 4md,b1O{_^]gxa =W~B@ૃ&횱猥We Ygf6p{F~rrTVVrT5V1y \2Z4yW{F=ϱgO[Nr Ŋ"%9mH/H\&DֈYΒ+p Wo7sN/m6Z[[}cp,08g _;v`ѢE28]Rb˗S]]M&*|b)`w6fX,{±X,58bbX,kp,b bXX,bXcX,58bbX,X,b bXX,bXcX,kp,bbX,X,b bXX,58bXcX,kp,bbX,X,OqWZ-IENDB`commons-csv-1.2-src/src/site/resources/images/logo.xcf0100644 0000000 0000000 00000425127 12565700105 025733 0ustar00BUILTIN\Administrators0000000 0000000 gimp xcf filefBB gimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) -l=f Commons CSV     gimp-text-layer(text "Commons CSV") (font "Becker") (font-size 50.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "en_US") (base-direction ltr) (color (color-rgb 0.000000 0.000000 0.000000)) (justify left) (box-mode dynamic) (box-unit pixels) `f !f  g3\ѨyG -K V)8~%~$S,#I%f#$i #! V"$!'O7 ZR3Xo,xB]+) gZ 1< iz CQ4^=Pi, (xۿx( dg vv nL!w N / bs Tb 1~. .~)N!6N"7NTZHFU\ ` b( 4 5 e   ]   4                  5   _   g  *   dg vvnL!w / bs ROb 1 O XN!6N"7,DNTDHF] ` b 4 5)  g  Z  1              4  ^  i  , (xۿx(iq ] g  N R 7T  F2~. .~)O!AnCe&ZBJU\ t ( B e $\ ] C 4 i    ,     3   ' 5 _ g * \ѨyG -K V)8'~'S,#I'f#%i $! V$Ѥt4'O' Z 3K$ (NoAx:B8+88 8e  }Ga<<i Jz`CCQK=PB|Գc2, h|~ew/a1,L~w Qe#<=v7$AR H I )@ {U V* ;h.\&abǚl=w0 ՚O   no 1 p d >  !"@k| z{ F RQ~ -. O @? :;  --$] GH}v0dQ?-vd   <@ a | [, Dy1^f^Vv ? # ,oЪv9   bd  ^    / .-  Z  S   !   *{{*       a    1   ^   V   #   bd ^ J Z/ .- k4 Z  S  !  t*{{*.c   <@S %V | H[, Dy $%f v ?ƒT%,oЪv9   e: wvA  b 2-}H"  Bucdce^G- n VRQ GtЩt+((((3g3 TM     C  gimp-text-layer(text "TM") (font "Sans") (font-size 8.000000) (font-size-unit pixels) (hinting yes) (antialias yes) (language "en-us") (base-direction ltr) (color (color-rgb 0.000000 0.000000 0.000000)) (justify left) (box-mode dynamic) (box-unit pixels)    #ɰ->8x88w8P8?8fSparkle     f0%1ftFq8B!1HO_r.                                                                                                                                                ')*$      #0.Pe3#      2+A )     !**        %   *   9    G        *  #             $ $   &'  6    %   <  4          );'!    #                     :      =   4 .         "V    \=   +  (/=>0((/lh(<<(66((*KhG((=N9(AF-((W\-((GM.((091((=dO(11(,,((6D6((2<2(*86((JL*((,>:((*+2:1((4WY6,3/).-((/==/((.:6*(::(0FD.((?(*0.1;2(-IdH(55(11(();K9((*:B2(::(>B2/)((= (2(2:0(FlN(33(..((9J9((8E5(29/GG*0.((+(4=1((1(080=kV(01)+,)((3@6)((2<2()99ML(11((-(*?=((/1*((08;X_:+30).-((,;A2((-99-(9DF;(//((*(>(+30((0=RhK(55(00((9K:((*:D4(7QB((-0+((,(:)((24*((1WvP(33(//(()8H9((8D4(/\U((*20((0(0=B((02*((Byb+02*+-*(()>M;+((3?4(+c`((2(.(Og((-1/+((0^yK+63(..((6QO4((-;=/7ZK((1(*+)((4cc(()27.((*Iwb277(00((C_D(()8E6EQ8,((-1,((-(4L[G((27-((BjZ<=3(..((7QM3((6B4LP;7(()21((04MM:E((13*((9c]=EA.*.,((+4?GD3((1>3((,=[S1::((/(6QP5.4E( (3:/(()IpP(La=00(()2BL;3>3():n](491,(+0-(4MT;.4.7( (26,((@rZ(4IRB.)((9FD7(3?4(6m_(+:;3/(335NN<54.(,( (13,*((6dd6-5EUF.((2?EC3(4A5:bT,(;=16/2@QP539.( (,57.((.QlI(88>\F((+8GN<(-:BRYH4(9;*/7DYS6/74,((/( (5nX(34).EU>((8GL@+77)bT6(*@A8PXOA6/(00/6/mLA4+((.30+((3]g=,73*0DS=((1ARM5867NW[I.(=OUQ6AQ8((-57/(YOKIKI@3*((*49/((,MuT(99(00=S>((*;TVB5.JJ+HaD(CcV6/=B>2(1>5()(+2=HNNLKE;0)5T>((;POG5(QQ(9VSBUfE/612:<9681(8((-6AJKLPPQG1((=k]/05--0+(>T>((>MIP>-QL(6EQj^MH8/(22:K9//H(().9HQUXZSE8,3YjD*86*20((>T>(;MO[F>M7(0LggRQN3((187:<75;[( (*2I_[POQMb}S(99(11((>T>4M\]BNN((7cuI=aR.((4@4*;U^]o( (5<33?MPhJK>(//((>XFGbX9UU(5PbX@6C[G(/PpuU:((+(37.*((-G^ZaVJD4((G]T^WGXI6PQ@II2(RlRJ?CIA=-(+0-((-68/(++0XqQ?[aR\]TI7,2LmnTeaCQQ62OYFHA4+((27>/00,0Hx_-86(/0>6LUn}:aIM=Q;0:G>:OFMT6-@i|(7PJ1)4GMB?B=2)17053(,>jm?0:70:200 JNWO;/n4(:;C4F\_B-2bbB-8RK1(,4;FLE>?END52+(2^~R(>= H;;T&&"a̐W9EAL@$%4AE=S_J5PuDK<=J[M2((-7706EKWZKLE0(RZ+A= ,<"2/DM(@31,W2h3MUNG6CglztI917==KfbB0*-2-*/1>POUQGHZp`(;9 %5&H^7/2 /OFIKsN54r~O/1((,2JhbIFE?2">C/*/:*'(T^CaqvT(/((8W[ONGFKB709ECCA>LZs8.3# #3& #C,"(&&!%_qv}L6((7QM<=?DPOLaaHKC,&Ka 0/*:9971*)*2;Y@`MoeUgokp`((7QQEE>=EK\YFPOB=FL& #"#V?_D.pPG;[&1?4+T?qlH6OO6Qf((*/2D`ZHG8-23H) IXb;tmTrj`F.#2<-! 8q_JC]X1'3(().256327G[Q<;2-3?C66;L8F,'&W2g]"q{SZvblXZ^>"(rq[HGYjaP7.633254,(*-?]YEA4-CG/O/&CC!+1!Op_6ZZ9CX\Xwwf8oUG;:XK6JX_cG%<32-(()?_XFD:AJ4 :KM&Zv^hZ9/9FP]WbsoqFMR-DLl:93((+(9VUEB=GQ3(5Y62!\fm\vsXK??U`bcF5BTqqmFQ3O=T;2/+(()+30((9WQ;8EHY&& KKAj@XQ9lsGAAKrzmH6PxUuns`~Iob,6201221,((091((9UO;PE69* RFK,McLjmg]j_@?MWO=Jm|VHNVar`Zc0'?QG?<84/-*((+12:H?21;Y]S, )+[W]qUCkfHNTa^K[^@33IomX!@(XB<7=>;:50-)((8G<23D3/#4UuA]~M6foSU]STdѽqA358;La[Xu&A^@ZEFCA@:BG?;73/-4=4/0|i".CHyk`uOLwmXVBBNq͏iQFFEJSXZnoi2CJMQD4:ACBDGNTH8;A?<7`}tjVQICCZqDZ;6FmJ#qG9,2;CGNXOED>8=AIYT7QO/@](IqhLg{WB7798532/*/=PSIb{wz`;.24i׻paejj^^deIHKgiTMc1.^*2gMQSSQD61205EG;K^XVWTmaMZdTEⴻۚ|n^kqVNVuudP@uZwc{X/P3*<@;FJFGIKOMJY`OMRJHB6CHL&9Fi~uئltzbaaGJXgef_H:KpnhH)UD5<`20215?FM`ylTMD>LWMQ^L>!RgluQ;Vhvr]ZaUQnYrETYL`,78QO1\GMMD<;=CYh_]ff`[Q^lR=@24.8UaE-ovZnaunMWQGCrw_5&K;^rbUYU'                                                                                                                                               ')*$      #0.Pe3#      2+A )     !**        %   *   9    G        *  #             $ $   &'  6    %   <  4          );'!    #                     :      =   4 .         "V    \=   +  a\ѨyG +K V'8~#~"#"iS,#I!!f#!  ' V $ OR3XoZ,]xB)+g <izQCP= @i                                                                                                                                                              /* "%    (%          A,         (   &X9   &  #    2    "8     &    !#        ?]"+! )$  +        "    !!    &  # - 5     0        3 *       !  % )     '  ,           $   '*    )   / ?(<2OaN2+-*(*.44,+IF/=h[)8WW8((2EF3((/AB06RjU/((-50((2AJC0((-4/((0436/47/(,R_9((2<2((/60)6D6()65((7(4]d;((-2-**((CK0((:dR((3=2((/6/);H6((78)((135N[H3+((-2-((++3G<((:LL=+((3>3((/6/(6L>((3;0((+@SR>060((.3-((/55B?,(3((/6/(6D=/((-:5((3YYA9.52((.4.((/6<<@@/:N<(*@>((4?3((/6/(8F9/.*((*86(4JYB=@+22(.4.((/66:3;HHM:((B(4@4((/6/(6F?2,10((68*ON?@A4(0204.((/660;V];((=A,((4@4((/6/(6D=6/(22((1<3S;6UG((+;>.((/66/(=Z_B((1@7(4@4((/6/(6D>7/((//((,;7;4;XJ((0C;(*166/((YyH(()A@4@4((/6/(6D=70((,3/(()98674MF(/791(4;66/((Eqa5((@L@4((--((/6/(6D=6/(()76((7=F34DC66/-24:>:/((?ndC6((FY;((/4-((/6/(6D=6/((3)(,3=G0>@JG/()6FJB8)/7CD11BdQ2?TB+)((6H:(@I8/((1:1(6D=6/((7(-22:@OL:6?969@=/,KhQ04?B7--((6D<.(=P;(++(2;8/6D=6/((*(3(-:OD7=QW:*(OqQ60).@K939=OO=6/((.0*((:C1((2;[ODH=B8Dj_PA1BEQY?5KVB/(/6/-21.O]?=MQA6/((2(.=A2,4CZNI;0AUg^HHF>DDV`@:G@5-/6/(/:33Y]EMO?6/((2(*8@@;/ILVF/0]oSB=D92;GKJH;9:9;/(-29?>O]\S@93*((,2.((6>EF1M@RNB`]A1*64*ELCH6,7=E@146.=77:5=KE@Orj@/((+-**--*33((3GJ:,0]=K`taCE8(..44-^xG((/7:756.7GDL][ea;)((*--*58-*)-0/+3FC?<-(;4YrF69@1..4Jn_5(/6/2;>54?;>[cJQWF8/-*((-53-*-4518KJ7;:,*1Qv|^B97F:**-Jh]I7/6/(6>9=@=@OZI65KU@30221-)((2(,/-8NO=2>>54To^UK986IC12@XcYOI=/(/98AG?CPQD<1(HR;1+0211210,22((5JH7..:FF=f>DE60/EF2ETOX]ULA56:0>OEGTXG891(BMA6((,1102?=/+((5IC/((+/AFAeP9:RB1/8B@KBEYYRGAEC6=TTPY]R?055)>RK6((3?8122@QE/((6?U=9?BPC22QU8*?g\:AEDEGPUYfn_K4(11)2WX2((*:=1./@UN921-)((7Wd4(:HI;11?aJ(+NtQ(=D4DVOShzpQ:23470(S\1((-258B?1,6KD20212548RjY2(4>EI?5[^6/1794259<3(6KD/((-4;Uhjc2)883Y^P@;G>TR;EA2@IAHZkjQ=94124CGD[kbK<;9/((15,6KD/((*6Ym[ZV1.73(ZsK23RQKRBI@6RXPU]_[C30((/:HKPSlzT@CA61,336KD/(()/69@XgWB9?384*6YXI<;]KDbN?DBWd\`_L=A=26<;57CWXglNDJH824AMRF/-7<;76@Z_G9/1IV\I>E?@GSRNPRZA>NK\e`\N<7N[I<<9:NVFR[M>3368A\hZOIA>>:00MZD9636Acirj\JYVOTEff@>FUa^nnXF:9ERYN?=:;PG48VU6$-@BemQQN<7F<9HWK6.->36MflP2vxWBnGKQjzu|eCDQT>@,%9]HS[|A%9#=uM;3?08P;bW>P: 04>bm2E7+T[BEyͲglw{~tjR==75;L=*?&:Mj5L]x!?BAZPD((56198K+D8+3049^.*!!48i†mNJH9S 2!2(>[cn/E1% $%=A9)5B@#"31"2K=D;Q8004/>8TƔyRRM3$ B@@'5 #% (G2 4C!  $<03KIKW]||{{W?`h~QI@?Bo[ffJ2 =#  Z`6GC9 5= M+@!5$2 8Y_%<17"quPDRi&S.,*+VdwHZ7 Y:XfoZ?* ("{mXsu`0BP%+XSM'F& ^?*/T?BU\bia?a0!Mw(A?\_ZnXA;I`WqowwH/1O9*O>OWJ2. HF{TtUhj\GYL=8Tc1"lUbTG?EB>/J 9}I_vO$(*5Mn_O; 2B^rf\gojfl}02V/&7A^TL76<nIHB;[vzaJa8#D<6EZI5&1:CETk{pvpYqM%1DN$ @C@3i!"2S <]^A;47;[jch;Z/)Q<,5HSP<):!=mtblpfL[oB-3 -r:#JYP[U2"D-?[FeOMOT[y{V5!*!.;?B:2@Q&( StwfG5=TRe. X:&Xz\gW!M26Wh{{]UU`}hmB5#*@!:Q^\[M@=8M$L^MNTK=9#<F/&SCT4.>/H_ &?@QlQK@P\4#>>5=]dki4D92^'$?D;974EQ@b "&LMyUZ?*QfH>4< #J)^SJXW'/I/%&1aXlo]^jP>-2Q/*;Y.,+--7PR.9&5Z7zMAVELXD*3&89BO60d]LR1(#7)^wP{lgaD92,'LE==;:8CY& V-;&?fdE?-5$?#88 B#]j~0!7 ,6^Zzk]I`p5;)/D$8,JJHILD?) !h(!0 (_lDAE&"&!>q^47An\SGAd~OCH2Fb0HIE55;A>9`2 2Q",B5:\wck'!R0B/NYr*!S*"OjmW>>Q]e@*@n= &1]_@4.2:R\L4),@                                                                                                                                                              /* "%    (%          A,         (   &X9   &  #    2    "8     &    !#        ?]"+! )$  +        "    !!    &  # - 5     0        3 *       !  % )     '  ,           $   '*    )   /  (xۿx( dg vv nL!w N bsT)7*~..~Z N!6 N"7NT(HFU\e`b 4 5  Z]  14          45  ^_      bdg                        )     )                                                                                                  %?+" + $      "*'       !  "     , #"          #       %   . %          &  &a $ $ +      '0  $    -! *       ,   !        #        !,  % !+  !   (9[J( (07:FOOMG?:7472( (+PM((/( (@ (/6@9(00,474;>74-( (8(/6( (9=,( (7>70(.3-((2:746;92+((2;1((/6/( (1?6( (/;4-/**31((,(1;957971*((*?=(/6/( (+B?((/61..1/,40((/(+4978:970)((==/6/( (A(/6/*20118/((05-((/8978:;7?A6/((:@.((/6//120038-((,64+)( (09;9J_L5-( (0A9((/6//6//-032,*(13*--( (1CYO:<;9( (-E@((/6//6/(+0.67*..(33(//( (/6/;;-7;9( (-D?((/6//6/((1;(//(66(--( (/6/(79*((*;B1((07//6/((09*/--50(*,*((/6/((.>8((.( (4L@(/;4/6/(())(.266.,.73((.(/6/((@(6( (1PG/=:36/00())(*9931(0=5((/(*(07/((:(8( ()0LO@=66/(0:2((<1*3>5((-(+-*(/70((4;/(09( (),OgJ66/((2<2**(88/0-7:/((*.,(+.+(/6/((,?;19=0( (0WqR7/((2=7,-64.107;.((0+.+(/6/((@J;1?8( (/AQm^0((3@52420229B1())(/3/+,36/((HR2(A9))((/>CEfZ-((3>=2214;?/(**(15,(8?3,((2HG1/EA,)((/@A9;SX7((6K=11/994.))-32,/?8,40((2<4?D6BN:((/@C961F_C((2BD91/?=+/-(-2-0796,(0:2((3=2(EL/;GD.((/@C96/-=\L((4@=1CC*20.4.(6=6/((2<2((3D9(/HA/2;?4.((/AD96/(-4TT/((2(3G@@<-454/)/:421((2<2(3E@./67DC.=>34.(/AE:6/((*,K^=(++((+43*(:PF3/8=1(/60.4/((2<>FA//6//QX1;@6.45AE:6/((,EcJ(+0-((150,(+JT><<90/70(46*((=XM2/6//6T\85?:(6NK:6/((/>`R)(-2-((33**()DNSR53762+(77((4FOL>6//6=SO>9A>/EOF/9QPC3*.2.22((4HJDD>0/ARN6((@+7ZtX6//642-((/;`W+((6:,()8UF29@99P?*08235+5GJED=//6@QJ2((7=Zaea907/(-3.())(-2X`5(())590,6MG08?82/CL7*42.5//6?I92=3(,_kZ[`YJ6*((.41,)(*-MeC(*+.50,>HJQJHJA24;DK8((4D8.eKHP`hVD840,1;3)((-CdN+-*22(6H?DF612023+3?MA*4SUHNF21;EN?5840;KAK68CYMCSJ=:<=>A5((.9[Y4+(446D60KJ/(2211.5/AUIIUOHG98CS]F48854;KI=/3?G@2=G@AIC@GI>353Se=(*6BD6(;K@0(11/103/2Ol]JLA39GXbN=BB8.6B88D378=A4(3FF91*0+4=F>175.322,MbUTceSF>DQ>((,.*4IMGA?H?4:3,,()9LGEry_mE70249G/(+3OYC899>E6((,04;9WqeXOVLNQI@<<@MKFRdiYI?12Mld;375:4;I<+((>-)(2CM3((90-(8EG:(():LQG9:7-GeqlE163Ba^DKXWOGl{~l]XK?M_\QNYK2,3>3())((;<0.<@Ub?3>3(())((.7G=5413EG&%Q"7R<+E.O`L3{`!Z"3H)/(''PAS@_CIUb5;YV^Y=-*((*03.GZf@1(1C]C;BC834:C-kn#9#V))+=n=893A:]DgTHYxQ_`H8:@B>>1:XM[D:=ED;,((4bC,I* *5NCLIi*< #!=+xNIQ\ubDBI?[#>DcP><:SID(2/(NH $":NKUb&&2( &TsVVirT>99/H4%0rc=M^SH() &"2LU2+0*/&,)/8# >O[B56Of`RM'($-|^NQMg^!;#*98&<$&<* ') 1==45##5<105:NAPWK/ ^s6FEP9&K5" 5C[3JC!!*'* >7?2#<#., >M1/&Dd@ >-H[VD. X5*7G?>^:,)R@.(;FeL,'3 0=.&' ($QO8  /OTB8o_V%&B , %SSJB/*'>_?6 +)3kLG#,* "#- i@JB[l).O3A&%1W..=QARK/MOMQA8HFkY*P5:TR6&1d5"("-9V]LT1R 'P5K]X[TS^D^I;5I OA!`JOe\**L" 34+DJRIN=T.Q28cdDFDEFfRs*ABa?03?AB?B1 J&R;RL5/,L#A&"9thZP+&R "M! (lkUI4-@Hj42ITG@699CHD^*[ 'F>UU!  #+:O`M(S' ,bhKF=;UZ.T&5AEAASUNFPeYh"&P#12xIL0  9F1JjA &g1"E*`]8LE((/>ZK-66-(33((@E-(=H7GC(;;((K(.5/((H(99((/(,4=5((/6/074-(().-(99((=7(,1-((38-((1(34)//(()295-((/6/(0@8((1,73((<25+(22((,<8((*1/((,73+/,((0275((/6/(-2=8((.46*((8:-85(22((<(*053.*(99(00((.2<8(/6/(-2-44((+,;:((.;5::(01)((8(+78.-/<:*00((+3?7/6/(/4-(.4.(().B=((1F=66(+2/((080((2+./7:486-*(/(()18=@*((4->99(02*((9()261,(8@0087(/174/:ICHJ5((/6/(7@FPJC>?C>2*77((:.(3(2<2::(11((;(+0;<.(BTHN@(./6/(0?>DA32/9C>99(-3.((69+((9C7-2JVL?1.47/(/74:D@9/((2AHMLECN@(11*86-1,>>57*)65((.?9((/?82<6((/6/-2>DE:((,.*(::(;=9DGGQVJ:*(1>5;;(33((<@,(/6/+>LIF69H=71(/6/-24=>A9((,0,((27-AA((*8\`EDGC>JA77(-50((5>1/6/(4JON=(8H827570-24624;7-(,0,((*9(7EC@Y^PL4(77((,?F:/(4@KM@2/8A<38A0.246/)4586,0,((1,((;P=((.4BB1+((/@9@PGNOLJA:IF,4@DF82=?2(:C19A688/((/9FA-((2RH(.4.7?822(*;CTP?2)((-=:<:((=TF6/(5716/((5<0;:*9>B;(6Zd_WFKXXNE4((9OSG7((-289@:((A[I/((::-32,((,@<>A-9CE95CV\<(/2(**(.3-/9?6)((*GTA2():9*291((+AD@@28CC>BCLN:16/((2ATUFPQA(++.4.(+6872((;K8??(.60(1:1((0?I43-((-7?8+(/63BA+.=9<:((2<2((.;@SH5GNZkM(/76A>+((257MUE>NP.,,((*6994/6/6<1/,?H90((1:1(-6AHM=;YbROK96/(BI/((135:PI>GQN+))(()58=A6/(??(,0DP8((/61/28GF;MRZnJ6HK9((@F.))((,49FQ<9CCE0(++(()9EBSN0((CC((,?S@((+3<9468@Eaa[\<:FC<2(7A3+*((37X[/6@>G<(..((8JOUL=8BL9((2WM((7F>6/,JYb]MI>@G;2=3,CD.)((14_^*.>PgN*--((:XIBH8R^D82+5XO,((.(3>3BJ0((.>eU((HJ~g232-*(/6FPM<(EULC77KcN3,(.4GC/**((*QlH+5TElO13109>41EXB)BA3>84KXNGBA<79;9>GLNB5\nR:(+=?-(3HM:-+((*bh>CBA>EpYA87@7.4?KTJ?4(3>874IPDNPRHBQPNS=:F0;-7(OCMljQG>AfgHZkI7VMN-6!# !^+%MY^9.:Jv|isjOX\[H=Ul,# & );\eUcgtwh`ny09& ((7WH;730WeDI:Xz4,1E%-   9)i+a\UwrjkI?$*& &! ##/;!@9?HJN$7+ODCCdXD?*+"*R@/*7ny}f!L=%!*+"/%1%5=KP75=8"8'5 '2AOHY]Q=-5(H;/3F\MFP+(>=HH & QI.L\BB ~V' (87 *(JgtuQP]TA3)Gg &COQO; (82*[izVM (-;T^!11U^=*209,*Wsyvr\L+0!c" (\QBPe'.;+("0!;imd4##g_'19>[X);5%&95%Kb@E6d> akk[1(-/DC*e(6G;5(&.Q-LJMPQdo`UfB;+:/IW^! C)TR7WhmSI[F7;P,!D]0b}":gM3SnQ )Z30E\wA>+5eW^R8MB_kT=\k10.TTG&5\917.HdJEHZzk^2=vH8?[wOI]gklBCGiZQ\s~Q2J+#W{c]hI2?1?3nWCLqkO@zE55e( DD^Vm^.T2"T6ZVZ]`puP*P^7 /WB/;& Hg%)6APV?UycK8$C/5g18qNzumxl`Y'9*jVTJKmԫbFbis9!WZB!08 &}? Tr]RZIG[LYe2^kC(4.vz_vlgc\Qv'BCCMn|At90;.+,ISfH? `N/w[^WIQlmM$:&TL*=XsWp^gtE2SB\cci֬=(5-/"km||xy'!!A5;?}ZVY]anyp{^) kA0|~YQ9w{ei    !$  ! !                                                  !                   &#                                                                                     /     !      0   !      *                  .       2   ,       &%   )#     , + -'"1!    f2*!  #;   ! ;"    )       %    )$*# $ %?  %, A "  7  '   #  2    )$  ""#* + ,  2   (=)  % 1! 7S:   +   & :d    ".% #1$  '[.  +2!     (xۿx(iq ]  g N 7TF2)Ce ~..~Z O!An&(BJU\et\ BC $Z] 14 i    , 45 3^_  '`    bdg   +,  66  AA  !!" "#' # &*  $ # $ '    . %/   ",   (# %#!  (    +  3 $ +  )%)!   $.     .   !" %1 !1 #1  1- "   !1!" 51    ,  6;    - $   *   & %$   *+(   , %)     + $! +  * "(*3(  < / -+ .  &! "J$:.   (  +                        "  5Q?       k*&        1&#Pk$3 '#   -%/2#"-++3   !,#/ * )  )     + 9 2  !#-! ' "!  "$'& 5+*(-  !&!(" &  !   & %   % < +&, -%  *: )   #     7  !  )#&    31' !))9,$     '  G$.    /     D  "  #   $    =$!     8 !< %'    )   "  X+     !:%  $     '    @L  %     ")+)($      %    4# !  !*    # +" %# '!,       (5}   !"(/?MSI3(>gd;((9Q@((IjI((9@<8+(6A3),((.304?=/0@HPl\3((/6;?3((;N;((@(0DC/(4=1((8;,DJ/((5?9/(/70/6@E8WS((/6;@4((;N;((::((>M7/88/((:=+2OE((-?A/(07//6/*;UYA(/6;@4(**((;O<(2<2((:MB6/11((,98+(SS((-9@6*190/6/((1Z\?/6AA((4SO0(,0,,0,(::(BN4-9?5*;E2/6/((3TI>AD6(+.+( (>TT>((/6GQ9()261,((77(.PP:@8,2D:/6/((>N8.J>144,( (>^U5((/6/9M<((8=-((07/(XeA9-4>779/((HR2)84=>831/+( (>nX(07/(3JA*.=7(()98._f:-4@40G?(**((MV1((1924;853220+((UkE70((+FN9421-((9?KD@^a@4/==6/(55(()DH.213-(().2139;96761,(6OYT<((A[B((11((/DTF/bn42@=/,0,::((K(11.((+0105@EB@CCTHEOA5bY5B@/()2584((*LJ(//( (-37:IWNZV:IZG60BO6(+2//?G>@FBC[]?/00(1<5+)(8M=(+0((0<<:KYQG^zX3GX?)(3:@I?/DS72pm/*280/@9++(GL2-(3( (0/6/((.IMBKg|_WkS73>LK@/5IJ@CiX(//083C@**(LL-2-22*( (*8=6/((CJ624SkcoqUQbeR;=G6GX@PP/55(0=H;((,QM).24:/21.*+.,)((/<J@8GB5>b_JlsQKIH::CFWS7**(.((),,)((3@B>519CJH:1/C@((6PUid@DSC//6A:0BNZfbRRI^lRG7,/-2((),7<7BJ755(-5BKECD?DOA/9QYLTkuoWXQ57=22;1-ea3@Y`Xbd~[SP@624*((+6FMM@5HF1+/6009;;@eeNdeXIMiST|f:4>6-/DB:[L(+;@:FZgmhdP=A.((0>T>)5F@4?G>357*2C@569980(GgaWST`]tn>TY)((9;=@`^AC1/+MM(.2AXgkKXFGLP`Z7(3>E:/6/((/898;Mld==DFRvcRZnvM21,0DB.TWDF112X[2.,)2AJ46*3FakVLMHBPK6/((Ain~uVXB?PMX]SIGdgC95ZW+MZC6(*1[a:320-7d4C:(4MA8KMHSyY2((96T[Lbq_RTidI[h@(/@bvYHPtl;Dsc-((8MG50421W3@I?@C7++((Tuid\WTE0(6T]M=Pa@A`]QPjzY<055A`TFbfRR831MI12*/.MrU22JWC51))(/IB(=`bTPTd|tQ==HTPPK16BOm^AFUN7FZL>KIQTXIfg9<58NiH)2=MFNB,*(/33ZwqogEYmF86;4/OR7>QOEGbW<'Cn{RCJvtAGaU|M#&JKB9IL9.1;?=76/(3>BWe^[ox\`RIB1/-H^>(*6=@@jza4S\5&/WI|-3G_?3>::FB9:@?6/((AnnPIUS89f}hqkSM:AZA((511C`lY,HF$!+Hu=O^kT63H@*?S=3LI/((6WnhJDXNAKH9ZdWbVXbl}]/'2:*5 LW'AE;:6-LF<7SI5:ADGR>((I6WcPJ[\BFcU76aW*20;\fvnM@F("9L ,%6AHZ&!)BENE*22+41Eof^D;@== *B3(3B(#C/&--=?dm=GCQG/(9L^W8/<\ePCFJ9DiaEGUD8G<11(23=c< ^:-3DO="(FF8+02HJ=@OV;+/:=GIDI]kZMTS96N\WKHDHB=;؃72#,&0[@D,M[D<>C)?D4CqqSLXY@@WT>G[F2DN]P+32--'D4 %+(.H`gc**3ii:54WdG/B.=II<_skQOS::XXBAIIy=9FaW5<;)$B3U8+ -(lhH͇sz9SMC?9F+FGQoQja:6OP<:F=/>OHCOhW;9(@>;; "B/.4.l9K\i~z|jJL(C PG9,ZB_VDOUE>E8((+DYSIpuF:,:D'8D6=*(@(bi{h^Xcj}5%,/eFPXt8EviJMQ>,((-2>PJdnURP.\56iO0 0:=bg|s\KMW`yFDNY`).*2:(,D8O$dwiRM@-((-441S8A;BHQC0@XZRIGLUUwvIOE,#IG#Drm?5:|ffIE^z^vaT;Epo>8()/@KP>5UrjaYMJ9-4?Eow7+6(; `EABZ~yUNOmb3@ZBL^O!&>B\ZdgbXKaz_C>9>?:;@JdJF!%*9@R33>lyQA9HwvPWFNxrRs@HLTrZjZ]P?F[eZPD=:.(23Nh- 421V9jUI(/8~{nLDR_Xyx|uhfywXtxksgbR]efUFT_SH:+((12aCF,A?_ZIWP>76boOWK\cS`zlkkxwp}Viq_g~TaWcmnhZNJPVLE;2263N:GSq?yI?FUx;ARC<[gdSJjllʝwaHZeK86GMB5>RWQN^j`SA34;Be5*q[C0MREcsxZ5:f]8kxJ;J][]n̈ȁqjY\iY;+05.+4835FUbiedUDKQ?SHN5kPb`h^05lmPw>;SZA1?pm|~kMG;>HA72+((.76/Bl~wg`YN*HNIRPFb{j|p?/YuS7,QVJYRM[~65HA60/ QYznc`]QCELIJLH_dp&*NIKtiluY4LsXED3hy_XQf~q'?4.>8!! )=[czxuiQHD?C^yI':P22JbkOojNdbLk{x\LllP5' (#(-166*)9_jAESV_nw|wylcc؆W?/9@SBA~e4_tYmtZMnhebLM)&2U/1>E7/;7K>05,)0FX_plJ(GcE*0E|yESp`LxvmXdYOTfy76^P3&"9Z:36>GJLMWjj`kƵ|aoTFHB*G}jga!+.?;6:EFB' !        %*+;E/! *KE      &_3747  OW^% &0  ! ' $&(/(*(    @"8!      $&&-.0+'$  &-,B1*   -   (/-,'61  +P'    (@  C+9"    q5   '#  (   1 !#5' 1! +   %<&   %   1 AZ0  g++       !*%  )J    )      (     -    $*          .  2    &  ',  !     3            &   #    ! !  ' &   &    !*  #  ")    $'<* 0 .'    (>" "      ' &   2 -  & +       &  2  (    %        ' %        F*      A  1;$     "  @  $  />Lld5,,(:<*((;fS11((DS5)((t^((DQFBfn?;CF8((>zv\E0(+((3N^E1/(+41((CK7/((D`O8/0.(?gSNK((>N8+>D553971?^dJ=/((,/,()FjR00-(44((:M@-((EaD*9711=^N6QI)((5EE53;:;905BL[l^=/((-1,4((<_^<21(22//((2H@.,(EbE((;;/ESR=3GJ6(5B599A:;51=]h[]L1*(-2-(A((6JYVE4(/22:3(*-ED20EbE((9;E\GA;17OI5B5(44;D:8/:TsmUL7.*-2-((H2(0@RVTA)*313>311@MWKAK9(33(3B@1:N^iG((+,LwY;E7()6ad8(()FH,2BXjjcNIC,.3-((4>9C>3;VO9FJ122))=J53g{M.((+.EddG4B;((DbX:((K(9Xle`WGI9.4.((4@4883>@JSFAB;842,5@@Ue41(,/E_QH>0F@(6NETO(()JI/MkjURKPJ14.((4@4634)3FNUL?85>B;-66S|hL5OB@G83ARJ.((9@UjY[YTM8QW2((4@46D6(99((Gj[>?9(DHDUN:76C56D6((-35*(.DedK:,(Wq3((.Jm6/22((LqM2376,5VM1QqfRQC8AONTE9GD66D6((3,62()@ZXOF4GycAC3.4XoD(22(9]_;12<;(5NQMooNCKH/FZHNGFT;6D6((2(88((:RRLXef\?3/KOGHMUHBD6((/1*66((4FTMpT;D86@`jJ^cJ@;?97KE+(=^j\9:<=>BHWXRDIT6(//(/=8/05-(-B[o{dHBAAGpuH@VI*/6//==>8*9942AX=KKICReKBJV]@/Ikc<<=/KFDB:Xciw`A>46ALAMvbDPJ;66//=?:7=.9@9>=G^k[ZY}E;6/ASH]_NMD;BC/8PVHL.77;B5RrWMCRH\kE7(5B]miP,(EmW//IR_q_PKOvB@//EYQQ]_L:C]YITPHPU,26:OchWYgNGU]fjaG2*99Zk;)(A\W<(`pgTJ;]|X@=66H_FMpk`^YWZZM:K]J+477wH(KqcVpuM@FLH48GXieH.0MEJBO\fuk\a_NL_YCO_L67<>\i4-:b~b634E[RJP=PcSD9G=(LtYRJG>[]_\Ngici|eHNZQT__QLV<(.URovJA59[J2(7=Jvl:(L\RVK@16V}ZGSI?Y^}ad[fgj[IZ^]eR@KL:(.;enZOLIylU;.7=O|k6(A^QC_P6VhowgLb^naVaL[iVmoLNV\O:K^?(.;auxonLTwnL8@XUWP?V{z\gi[pf[c`Q3CZI9GQFIZJJ_r]^k?=`}dhalwtpcWonovI6Fo`KQFGEakCUq]DPklR@?G*@\eyydEFZqsgy_j筝qoKGC?yZ6QR_d\^TPbUQ|uYTiqdI56;+APoo\M9Rim{NVr|n]_CAS^snu\BEz~Pbqb\gfY^ruhULB59=>SgzrTLA7E[VNd8\{u{dNPdYnsXpIPzZ|wW`y^4Z]KJ?3NX`UTHfl`rrXwS\ObuI5hjccw\y_hlfht}t`Wm`G@mv^TYWOXVfyy}~rr2ckTMaR* 7..8XH3z\7uu}HEJa}l\|ceZY__prqhYO^SG2|nqWB=I AR'AbgY#J쨙\Nr_U]VJEQJQ4l8#>=`uD,NN7=2(PdHECE>K\IJ^{UP.[ojK=HBJvnxxDCWOOSMa1B9D1SKRj_R8CYD3:JK9/=8$df^Z`YHLWjSh*4^dcvwei_KOT[[Zc][H4HlI 1Yho~tsjTala`?/UQI;BA::uVRX^_6+8tknaQ^mnfe_h*LT.S!*4#>IëעZ(AI;)"/1se_clqO@:%NNQVhgzun]p25C &&C58޻@ev[R)/.C{:fV?&Pe03`zf8@]wt}uWE 'f?* **#9㕕\T\arN*~nHSg#+F`6*LΔm[FgrNUvgiLa*3+?^==,'!H9)/ٛ}jkfiplfu{U?%P`oi?6I*7ce)WS`sm|vVTY_f;??WTt}rtdVLE.QnimF8-?;-* nhetyb@VN%]Q`QR@-!Coq|PMushinycnqfkNWM>Qcggwf_V84FH`a\BZoKbhzEE=+=:wR Jo}klmΥqottQNWM?gz[\vwVUcQL]ljNQ@9AsbUCDXvgLxj,H.,;Va^"L\lNM{VJn}|PYi`G<_\CEm{hh`X\dOA"(25vqMDjqREYP#/IMUVuS:bEHGVRA>?1\Ő}{ydIIYogKQ`dK8QvvVJs5!55*OywXedkoz}n@0%.dlYXst`CC&3IH/m\JZ_tyZCk_~U^]D>?GLJ\QSRPM7<"UDYPfyQ("z_VXnzC2*E3*'.KI;=/BD[eZT^`ghyQ@NeT?@kF0kwG(20{^O;XoWj~*<2~cnmI:,!$8/2JblWGF7!(AB5**"-ryUehd_T6GJYr286(0Msj{xZIO&@|F87lVUWJ$==-+Fnu\[F(34;2?Enymr_Zgv\NfE/*B01>:v`P&&;$T{|{gT0MU:&*DvW?D2,U>;H,$1_l^PNT_iiL"0H(LTo?%(>:*Vjsiju`c2306dN2**??JE.AS>5S_`xeox*(IH<:CUO]gN*%E=ElyHKZVpQ`:>?njYB'3=&@85!/6H%\T^nr{q`9:,P^_-;G@ *.tdhc?=DPdpjyZ|w^jsA15.&V&.SaT/.R#IaPRbe17">BumfOF7L!#eooO6Xg5?c[F_rHs=yZJK\N;*T`;YeUMHCXR[0!'@*O~5=?<475$6dXgWKB>gm[prOMe[,:h|~~Y/*:@& AYATO:GMWB--2.$e\&">GA:_SJPRJLKsrMANL?Ak~kn4_#/;=59[XTdTAQ *8+3(/cA/94d{vcga]PB?\XTDObaVwqnnYJBs^0/S?GTZGTYZO\SLQ4?$#&?-"4'DP,Y3AI2T^^ogR]|`ctV5[rR"&8>KScaJSQQVWTIK)"% $0'':@:nJ/k&/;c^wdHA^tk{}fP?Yv>"%5$,e\CclYXZX[Y(9*5DC7/($$VzR/d-::r7Z^VQj^dgHM0-+9Q?;6:EFB' !        %*+;E/! *KE      &_3747  OW^% &0  ! ' $&(/(*(    @"8!      $&&-.0+'$  &-,B1*   -   (/-,'61  +P'    (@  C+9"    q5   '#  (   1 !#5' 1! +   %<&   %   1 AZ0  g++       !*%  )J    )      (     -    $*          .  2    &  ',  !     3            &   #    ! !  ' &   &    !*  #  ")    $'<* 0 .'    (>" "      ' &   2 -  & +       &  2  (    %        ' %        F*      A  1;$     "  @  $  MB|Գc2h|~e/0ww a1,L~< =vQe  # 7H IAR ) {UV*@h\&ab; ǚl=.՚O  wno0p!" 1|dz{ >@k ~-. FR:;O@?$] e  - -                   $  !                                  $        &                                     *     1.((0BE@NN5((/<;.6ST7((+((1905B5((/6/(6D6((2;15B5((/6/(6D6((2<25B5((/6/(6D6((2<25B5((/6/(6D6( (<25B5((/6/(6D6( (,26C5((07/(6D6( (,06D6((/70(6D6( (-13D6((/6/(8F6( (.3466((/6/(6F8(**((.467/((/6/(6D6(*,*((.4570.((/6/(6D6(+0-((.456/.4((/6/(6D6(,76+((.456//5.(/63,6D6(,7;0((,1=:,:M;(1FPF86:721;=66//6//>>//8QK;AKKIC4/5:8:B=6//6//>>//K^VD@MJ9CF955:;866//6//=>0/6\NA?FLA7HK7.(/66/6//==//6/D?HJH@9484**/66/6//==//6/(7IWG1((13116/6//=?6;=/((2DI5*((5<66/606KN@IL?7:;1((CGQH@GNG:9:06LPEHLA5,((CHB@NK13CCFOLGH@/((M@::WVEI?EUH49;/( (JNHIO\PJ?4B@49;/((+/0,**((]lVH@>O*@@5:! (GPRXXWTFE[[>.//-*((R5"9GC4>CM]`Y_phL=;81--//+(:'H:T2/0@HENkr\SSK?=;761+,>@MPCBNL;8MWF@CHMLSPB<=968(%-.%7ENQGH\^E1*)1:>BEIORL?#LA9PSACX[K@:675/**0;BCEI$&A>9@G@E\^D8736>=8531,),2<*7hPdRE66P\F522458636:9542.*&-+4VjVJ\ZA5.(,23255464232/0:6?BPM_qnZE<<5-*()/3103412495AW9.4ZiMAECJM?310-*(-8?@><R`_A6<=6,(*8IQSLHNI821-18lCxoP6(178ACBD=9<<727<@LTNC@?fvI(+059>GHD;33116;BEELOD<{wwhjXA759303-->82/-*((VSTIBQUVWRJGNF0((*(W8:77?EA8121,)((                   $  !                                  $        &                                     *     }vdQ?-vdQ           (  "   %8               !    6        +(9  ! 90#>   !*                                                                                     $     86HQNOUX]]TJGMU[UKSanrQ`VP*PnNQUHLdzh_AC:((,14BTbrpccZ?132;Xfdw}5.;ke7HlTletIU^K 3%3H]Mk"GQ/,2696*,QM2)*m\9A(G4687==/,2;Najs|xfSKKPeUNVdS[Zb& /KB\/ 5G/RmYOIPdT}B.59C*(/=>:BJH@?CFFHS\biuz_S[bN?Da}/)7JW6!0MR7ATg||uN-+((6LRHAEFB4(2=8-+:I[m`[n[=[?8=BUR_I/=//J7:D_7;`dcR*(* NHMHDB8+((+2961-/6:>32K}]wc5CVN=D?Fz~]?*7B[O]nY)5=T{@C=/ZO?+*,*((29/((07:@:=GTx|\pCag4))2XsbaWMQLRɩ{3V3GEFYO?LNF8B50*<((**((/6/-2=6?=*&5.((2?;659CKH4/6DelL<>NVKdo\WgPzrrjmoWENSJ3/6DdiL7@LUJK~oarS@dLQNgvumgT>PQCDQbR64/14759B:,(/6:>3/6G^_H12F\eRIvydS87SL^XTdZOUl}rpbDHB4=KXRFC21466/((/69=3/6D\WB86@FU`NNlgG30K_e_T@F^XNUg|mr{fiswpO206CNIA+((/6/((/69<2.5F`_N?56DEFF4^xM65;LQe{AHH?]eeaEFdiLIVdrl\NNLLP@7((/6/((/69<34@SlaJ@5,(4BMB9mn>0CN52a6ELDPetZ4-PnSJH@ECQZOK\oeR(/6/((/6=F@>AOicE/((,5HUF@YU99L@(3_;EQGT_YP>3CPQ[NBH<9KI@Nf^I07/(+7BHJ>/((152CSVB3Dr~[;+(2A;7C:K32=C<;2.4CYR=/((,BXB(FQ>@<6LL6Knr]hO/338>WgD31Si8((2@?@B>-/68:1.4CYS>/((,3MX:.MR32=BKD3(9esP1((2=@P(07791.4CYR>0((8DIH3CT9(3JKDBMYPo]9I?,636MXZJ1((0Cd/770-3BXR=/((/>A?75UJ(/=LMAI]SLn~O(>E059FM4(3>?HFBQJ1((/Hc=77/-2AWQ=/((/628CB?NC/>>DKDQ_YQXjN(4;681HL,((3KVG18QJ1/6ENC70-2AWQ=/((/6/)6PO;@A>>7@LLT`VFAVW5-68;;HF-((,CVL;.8QO=/66@PQbdC30HaE(990=DA2((15;SO3(?]G);AA-2CYQ=/((/6/((/FM043()AcK(6<5921133(/7EF11:870

E>0,CC,33(+9YQ.0A9/0/284.5/7C7+1F=.;S/((/6/((080((7I@AJB:=D=/(1:7241)+2J\A*B@,1/8<44.(/?@0(?M@9C((/6/((/70((/>A8JJ5=D=/((455;22/)+CbI(@@)10;A4.((*=D1*>JB;2((/6/((/6/((/6?>4LM=D=/((75:-33(*?`K(88(//?E.((   !*                                                                                     $      ,<| [,Dya 1^f^Vv ? #,oЪv9N     !  #     '   *$+ ##        '-    !$ V0       %   #                                                              ! ! "  #  5B.PUZL{Y`# !3YZg8R) ^5 Qw_nS?<=VcJy!6bJ_dimjZNH3< ,6/gD-!"n|?R^6(?p0&(I.J]ZLYTKOi0e(DD3;HMD=Rt #J. E?)"&8)%=Rk]IOJ77D" RG8:[aK[7'?h'*2329J]|81,.O&&"" +*21C@QXI@?8ZA@  D557A_fWf`/a)?)*+)@[VY2D%78& "L@|xXVFF?9)OJ26AF=IM`a`ZHK8'/*F7,(4A<5Q9$. 6$ "zof\ai`JYikT>&4.B?QXVWNM>4) &$3975AK:)65+ !359# )(^[[ 6$?RD04<>"W]/G+ Z/R;WZjRDNUNmj;kC>9?KE.)5G%:';CL1/-5A9-1>D*;H-NM6O*2:&7Iu780OU]XRwdeyzZCO[T\Z>,1+#F0 =H6$4>3(/633:GGC!=;CThR*N.($cYHFTfVUcmmaX_[fVJDLDYqxbC:<67)<1?_?9;3(1=925:=BGA@519?8265,(+5?CSYIFFIA?QRLGCHA5J`t}uoSO_LGNP]MHZQBKPFBCECD[Y971(F[UGQm\U^TaU.F[POMJGLVL4/67NTBPuoIA@508@?7595/04HefND_{cC8146965VS@>3ITGIJ_VLPMH95EKJ<0FIEVVLNHIE98BOC79;MP;Ja]QMPNH>652-*0ADVk\IIEEGG@5:DLWSCOG@G>EE;=98AUKBTL>?>84?^bHPgZ6/78:==?@::IOHPgXVZOMD;HQE<7LK1EVK9/:5(2<<38?;I>MkpbQ;6BJBH;20*5G>2448F?+(@M>966?KG3((,12J(/3,((6OH7?7=L7((7GFRSIN@..62)8D9122CI46>1(5H;(<@,()8MK;894.)98(*64(3ENC952<@;0(*8BIDAOC7AC?40:2*/218CMH5+((=G24?3(/==/+5944HY7-(883EAA161/57/(?N@12=52?>EE/==/((?XH:4(4?EA6=816/(--/64AJ>03<1(+,9?:C<121-/:62=9,(*/76CF==/((8I9(65(6PI662;?/((--(3?;GF2581*(-63,2302138=7-27/((33,DQ@/((7G8((332COE6//A:((*,.03;KA45.2/(/241+41(+1364467;1(22/FR;((7F7((.>I@CC//66/((04,(8L<22(22(--55(44+.+(*-4604=848>?G>((7F7((?OM6@:06/,/+((+1.((5E90/(11(*,53(24-+((/1*((4??IH6DA((6E7((YZD63=@/()21(+.+))+78770,-1,(-44-/5.((/*(6LQ?/;@4.7C6((J]P0/E>((2*-+(++04,:;21)21(-/64*42((,(/=DE7(,@@:C8.-*((6HWE6:3((.0,*((**22(6611(11(++44(33(()-.*/==/17.(?H=4+.-*((6/K`=02*((*1/((4(141/)//(),41(11((/=/((4:.BL2((7/BIC841((1(-61(+760.+1.(.32--1,((.5AA/((17;HB/((?>727BB5((/(46*((9911(22(-.54)32((2@B4((-5=?D:((?3635M@((-.)((5(7/(//(**55(33((/==0)((1:1.HB((05<7(;L9((*0.((3(063/*-.)(+53)01)(/==/((/65.(:?GW\FOA_(!N( @02C) & $LH7L2 -R14=7QgWX[D@-2h&)!NGHC88C8,0#L"+YHIiQ  )" [?*=K0(#13J<2.4CG59 !C RXPUZ_; &)D]LMA=(r?%CFAqV18?>:3G8?;FG64;=30X=$N$(>3<54;N"!  6_Q[YV/3.1 5:CLBKdiRG'% 62 8*6DC70ETED&&%$ 0(.*D 9>DHSb*#1MuI?EXl[D9:!%  <0!6B9;J_[N  *$$*,-*9! $MO0N_^ 1&/JHSDHB,+3G($8CFHG?;BNQY*'(/,5<)-:+1;CP}*1]TcRPFOG2+(!"9CWZQ5-AA@<.1;;+/+9;9E..1?:*'52D30FPSRiOeC8_fRBLIJ[P>:7,-3#'PZSSC4.)-;6(:4BI4=+24523><216;`?6@D^YUXN2:ABaDJL?=CFE87BIJQOEKSpgD264428?C8*033A>H/-'1:>;36DO\J6;<@JRUK?=BB@>566.K]E2FT@B?4R_B695,*3:5@`~f=844-./-3576?B:98AC;:DHML5/62BLE<3,0/;TG:6N`NXK8FNF3((,0,(8L^]HACF>5<7)((*0??74>N@57;HK7/6/(BEE5).0=N?>GDUMC]N98,3>3(,0,(093FYA6<;=?FE:74-.5//:=966KL:*(6B7/,(/70,BXI4-).6:>8;?4(:GBB76D8((>/(-.LcE56<:B>(/2BS<((+:E6*16/(/10+?^G((+48HA(++?K:.(+.6><8/((-8UY7((3(+2;HKDDHOQD=;1*-1,(><;G_K,)+.,;J8((,DH641.+(:L:((.5GV>((1(-8:63(,00=SE+(,/+((-22/8AHL<;8574>QD;?>@>;4HG1.(/=F:-1456/(3>70,.8OM0(11((-2-*1@HJ;1:1*.5:>DFJEVB34/2416:OVD8/58?;*(5A4((6E7(,0HT8(22((+0-(/:IK8281((-;B@??M@085.0-**4@HF=8@B?A3/642-(*-6<1),AU?(//((+.+(/6CO?6=3(**(-693+(G0)34-/-,.;72644@22;;?A64/:8((,0/,-0>O]I)((/6KM9(//((-/1/,,((/I((6<5/((01)((8(/6:C=96*((*1)(/9A((=C.((+1.((67)((/6:>4*28/( (+2/((/6;9((2>4((2(/81((/6:>3()1>6( (-1/+**(/6/<< -      %      "        1  .  #     '       &  #                                           " # 56' (: #  " !    ,    a    1  ^  V   #  4#        !"3     o;   %<!  $ ;/  k14     &&     J#+  &    ' 1  (     #      j/'!     &B92>#&q/ &    # 1"#4 !       ,                                                                                                                                                      .]=??QDJ^G 13kzlkjS2@3T,0ZtiSHFR]cae+*N?'!T~V[Mb`v LOVGLAC)(("K1^haG3; 5oYEII=41>sz|OMLr~SVI ,00N('-%=.SLWQLL!'=d4=lݲkTTF>IH91%O:Rx''S&@=  -*  &3?AG`F85(/Q-&F`piqk^[_:"B`/FziV-(2%:)1 9&IJSeO< P4+YN|hbjtz:!>\MtTN--KlG&$*k`75;DFGD& & -;~IavluJ1HxfexlTg@&E^E;1F   4%h@O6()3/"-  +3YpZn}gcYF*Lmfptn+>*=;5# )"%*2'6D6(7>!  'ocn{RA]vccnTNb^Útt-?$/ .: /*(#KR9RL(+(6D:778C5<#0DcYRN=INQWD+[`NȔkoNQ:?&TIE$2W$"=gQ163*(:PJEThO8bI(`/G6CL_U?C65WzcZKqiIEjviljunSSZ\-++,,CA().5GVM>:;5,(3CP[P>:QaO]gUUPFa_NW_((*,4C@:>89FFE9*1/(3>3+LjeUJY[D:?;6NLJJC=:FT8(,Fg((3<1((-=IC;>X\D6+(+.+/DC6Q\;((2FO\WKK94?B?ElhDA3>P@A?,8HH813L((|;?49;7BG:0(KX5))+.+-252@YO@4(.BOGYbK60>=1>_\;:OB9TFHH(668HF6<206SP69;244((3PL/(-0+-2-.>/3DdV-,@VHQJIH(/708XH5KBDYI*((*75(2=:aZ(+/F]XC?<+)98-DO34^R*-+2O`M574(77228I,/@A5964><9?2((@E-+0-(/6/,@K=@G=JcY<3PP/4?3(BV?-*(1BK\J99(4455(9((>>,/-1CLF;21.=B2.-*/6/(.BLJF;QG((5RF21((:D@7?7-/14SZ;@QK6/==/AXP9((CL1.2,*:@>;=8BL2?A*(()>=((1:=4(()6F?/**-5HYF?[W6/==/2ADHB/((OO(,51/55?8>>6@?C@2(91;2(1:63.((4MA(**,;L@6R[F=DA02<5+4QE(,PL(+41441=4::/6AHF89J99(09122((/6E>((,;BB>DP;?RE33<2)+*HS39N=()0/883<14;09=7IOI9;;/70(22((/6/8<,,69C45QR6/DM9191((*,5=eY((+=>12/31;;56;LOD/C>/((-1,((.5/((+BL@3/NU60>B8=A0((;AY]2(()>=22(2299,FT:7>6I/((-(.4.((KX5/DXC/>>12E=((:MKB<2((=>32(11:?WI(44/B((.4.((2MJ6DMF==/;=1((2VO+2<2,:<60(-1-KXE7(.5/7((.4.((2<;ESM>=C=//661*((-a\((2<;554+()2?YK25+)8M-((.4.((2<22Z`8:H=/07/,/30((1bY((2J@00((@NF:-85(Mc((-3.((1;2/E`L1JJ//70()+53((?W@((AK80*(6L?/;599=^J  4#        !"3     o;   %<!  $ ;/  k14     &&     J#+  &    ' 1  (     #      j/'!     &B92>#&q/ &    # 1"#4 !       ,                                                                                                                                                      * J Z/.^ k - Z S !  t*{{*,c? %      (4  3 ( !  % 7/  "!   $     2#  %      J                  !            &        ; 9         9-                                  #    !     %               $       #                                                                dLgjw>!&:2MIO_bR>:6/3LcR=DMOQk؅V<^gRNsh'Tkyyi%'B>G`M8""27,58P^VPNKGA;:WugOGJSMTqbR"/I7AEN6[{uS"&'#CJPoL:2+8,"85UMQ>25IVTpnUJ:9?VoZdD"<-%B;-Kd$5M!P:C,!30.'(&*#.! ,A]SJR]R=HcQ632?Pcs`K\`M^ZfU1$RA&/00KpYLd{*Sd?3+E5  *( /-=>QBOI8@JTcN2-1:>Up\ST_dM[~_]):T2::F:Cf];CPQUHI`gR6<6$ ?DqcB4;<.,LoY8339C[s]DA?MIC`nD!5JBGJ;3H:4A?HG*-3=E%G"00*?,B2245:3+;E7F`vLl=Ga[?/8/" *&WEA"A*4BG L892*()/LgQ6=HHCWmQ7522INJ`eoLJJdAB9):&8O!&}]JCFE"29B%5+*2J[izcLJ?34:HjaEDLYMQM>kh_jxjRCNUQOJECZ_\qgLGBAEKKUsmTZe[ZgO==9?=BH^gKDa`RPKFPgS9;75ALXXMM@04MD3C]YRze=QGGN]vV<;5?F;Dzt9**()5HOV^Wrj_[O]j{b@B=0((6MHMJ3:MTHBFprTWaP:Y[;DrnUF560/EL;Ta|YKTK<>AVK;ZrdWN>>SD,A`LNI3((*0N]=/FK:POIMIpQ^hPS[baUJMlrE0QR>AG`f[MC:8KOG3?BLNDKVA3OOD.3I[W?/:8.4WwT5/((6D6((->KRL@HnqZa_oeNUe\@*Jj\:(1ESDThA+74)38:@4((/6//MRGINOC4(=TJ6[e@QPGRHh`=3AD1/6UH9XJ9D6-2O}l<+(44(:F:.((/6//6JYL?BTC((-TO/8TiH8F<7GU[MBFILKG>3/HPJ?936G>GZQMR>(/33>7((&/6//6;\^==JB.(-:MG6=GQH9903NJGUG59H@7;;8HS9)=?.<_hB.6RU3*=B0-,(/6//6;H^Q;@B6(-2BH:6C<@J2054IBC]E5<;5/.13DH((;B2Be\6*.?NE9E>(//07//6;BLND@499-2-JQ66@@;/190/6:>:6NR3(084,/APE/8C3(@E.2KN74LQ6(+1.((J/)>fT+((6HAA:(0FE64469=:6,/6GE-/C<((:>,8QC8=BN;((22((7T/=RL:+((:SI1)(CR75<9<85:IE/(,A=/6/CC/6@9((-??C8>76J<((11((7F;=R=15,((+@M>./?A?@<<849>E:(+4976/)DJ6373((EJ3::*-585/(3GC/13*((,C?@P8*.,((.((FM/(77((*.7BME/(117M>((?L5(()((56)((4=)6K=(( %      (4  3 ( !  % 7/  "!   $     2#  %      J                  !            &        ; 9         9-                                  #    !     %               $       #                                                                S %<| 4H[,DyV " $%fv ?ƒT#,oЪv9A     2&"    R6&  ,  $ +     6  !       %         !      $    '  &  !$ (  &$"y- #      94V      (    #     &       !     #        !                         '                                       #>obh& -*3~a\EEVkwz`\}T9/ :AD>4JMHipYd"L2+*/-*).;^[Nq#/uvNSH$#!."QzVbj5`i]@.%>G* &HJ$;CAB59KY3Qj%';A875?<+IsI*!0o^-2kYabRe90j]J7 I? -w9KSFBCF@Ra^J< -lxd80@dUIA)'f~r 3/0m0 ?v%28* <2 cB_k\T\WMCFIT"&*jc=0028U`*0"aq' ))D_,6&2./21 ;XimtfscJE?B@UA8?(1S\<1LRelULC5,(,0=><\S(3-# *9A,=96EVdVR`l*Z:&= /9'fnio?U*Q:YZXWMs{K6//0,,04:EBp+eMd.5:MbT=91<18?COc\EGodwmk4O,P2Rp|aH\NWM[PCDdiP@562,((0IHJHLMIBH`0WEA7?;=692BYS@>HH@?eRxmlRErcicXZUVTDEGMTN@2214=L?:TV?*>FECCD;6JGQJ67OUA?F;0=NP[`P^hz||t`7A\dZQMIAJJ4)+028FHEGOSJ7(2:ITB;4-@?STBDLCDNF>EKHKLGGNlyclzt\EPXQWVDNJIT@1-)/=A9=]aHI>**3VY>9/(/7?Hb_NQ[P@GRB4@B?HZl^MPJRh]MQXWL;IFI^N;26ED30AZM:D=318\W;6*()9HQhpaZ\PC>713@E9JYGIQ>0Icg{xH^eHCKKAGUE5>SS>8ILF8/59817R_SC0((7m[GZdGBOI;78587BYJ69E;,CQcl}iMC:LaQIJ@DEPL013,(M;ML:60,0M^G;5>@CNA=DY[MHD8ImM5IA-/?WO=JPFDD;8EC:AJBGRRWA376/\47MQ:(9K:(>XJ:5-25CKBDAQaeXD7(HkQ71.;8FD@3-;BGVJ5.((,;FC>75I`eUHB5/QjK5;>GVL@@DH>7937MO<6-5A:-MjV>.((=D7:559IYH=D<1:VseB//IW=((,(8?;@KGDNG=6522RU1((6@L]SN>((DI-22++>PG;A=,4?c^9IKI;((+(3-2PP3((,HF*11((6@IID=+.BCWweL3(,5<:/-1,(.H<1285*(()439IA2)/>7+23BVE(,CVF9>D9)3>6/9511)21((G;67CKQZA0;4.24421/,43:@>8(/76.--@\P(;N@213?C7/9D6:://(11((:GEDPK/2FF;1AZD;9)((+01/0;:AB?:(-.76..JX\ON?1-(-05>7.9CE8,/+//((4?PZP=1?H8//(AZP=.((,5AEAG?-+/<7**GXz~I/,((*+,35-+=K9)10+0-(+AbZ;1.8C7()9VyL?1,((/-(5@>311(11(,K`K9.(//,7IILWN8(*/-00(()Qc;(()AA*/=7(**88-[=AXPA?821154/,-95(3@9,-28:8D_\=0+(00--((4LQ9((.89/0=5((,84*F+1KQB?;1(*/420;>3+(3D9->@/1O`H020(--*-+((1;CG6((43/73+(/82)62,FB3><1((.,>>//0/=E=B8/=LH=751(++(//((,;76D6((72,183(-15199)CD*39.((,(88(,0/5IRD8==<7>D6.()-,00((8<,6D6(*86/2,/>8(*,977(8G7(..(()*-62((*5DEIOE516CC1/-(00--((2<2(6C506.*20/;4((-9425+.IC((,53*((0667FVC.+8H?/21(..))((/:3((5AA5((22-33-(.52+85*HF((-94((.4.4B=?@0(9B<960(*,*((+85((4OC((11*-85(,.4     2&"    R6&  ,  $ +     6  !       %         !      $    '  &  !$ (  &$"y- #      94V      (    #     &       !     #        !                         '                                       A  b2: w v}H" Bu - c dce^G- nVRQ GtЩt+c                                 S[oW;3+1>H?5349:68?C@700.)((Q>LYL8((3D?313537;97;??910/b]JQ^H,((3<1(/5323327:74:B>YVA>SbK.)((1:1((*03233227;7YE>>@S^E853-1:1((,121122kfWL94/*((3PZC::<-)(*9>44653.)((/:MQA38;/:C8/-,*((-4534773,(.7GOO<45*(2<5-00*))((.674463;IFBG>3.((/6/,.*))(()06/=LG9EQC3((/5.( (02@EBELVH/-+).3-( (8)4DE@:FUD52/.24-( (7(3@>433@L;/276573,)((6(0992423>>3,11/7@8..*((<929>:6/223<1(()-59456/+,-*(=A/9HF:100+1;2((-440--24.+88(4DB56972)2<2((-(*./,/:;.19:47885)(2<2( (,BI?05><6.00((2<2( (8FB5@GC6/0/,((2<2((2?=3>C@9<<5/((2<2((9=?77>?=?:7721,((2<2((/2DF:>EE?65621231/5<2((,@@/5@B:7731.03101;2.,)( (/6,,((66(/85,//( (/**((14++12,//**((+85(*20,,++( (+((9(2)--)( (2((4(0(//( (                                 (3g3 fShadow     ffDwگ&b4 }Ib -'"½ƽŹ~{yyz|˽yqjfb`__`acgkrzȷth_XSPONNOQTX`jwǴxh[QJGFFGHIJJIHFEFHLUasȴs`RHB@ACGLORSSQNJFCBCHSdy͸q\MB<78>JXhwzoe`aiyҼiRA7667ASiʻ з|_H95;Ja{ȹo ʯrWB77BUo˻|hX ĩkP>6:I`||fTG ׿dK;7>PjʶjUE< Ի~`H:8CWsët[H<8 Ҹz\F::G^{ѺfO?8: жwZE:Ng gN=8?O δtXC:>Nh ԼaI<:CW ϴuXD:=Mf ҹ{]G;;H^ жwZD:Mf ӻ}_G:8CXtɱtXD;>Ng ֿcJ;7?QkŭsWC:=Mf çiO=6:I`}οrXD:O ǭsXD738EWlǾxcN>7:F   Oٵ¼ÿƙ}{{}}{{}}{{}|qida__adiq|}yxvtqnieb`_`diqyyrkfb`_`dkvbXRNLKKLNRXboƱsf_[ZYYXVTQNLJJKOU\chllje`ZVQNKJJLR\j}MFCBBCCBBCFMXh|ͼr^OFCBDFHIIHFC@=<ADFFDA>=?GTg}ųdN>5248=CGJKJFA;520148<@CFHJLLJFA;769DU:=CKQTTQJC=:FMSXZYTLC:439G.()057E[vðz]E5/4C[vðz^H:9r«rWC9;H^wkR@8;CVojSB:CVnjSB:CVnkSB8=Lc}lTB=CVṟrVC=CVṟrVC=ZrrZF:8@RjmTC=CVṟrVC=CVṟrVC=   F¼ÿ˿}{{}}{{}´}yxvtqnieb`_`diqyyrkfb`_`dkvνısf_[ZYYXVTQNLJJKOU\chllje`ZVQNKJJLR\j}μo}ʻr^OFCBDFHIIHFC@=<5248=CGJKJFA;520148<@CFHJLLJFA;769DUkî}fTG]w½vZC3+*.6?IQWZYUMC8/)&'+07>FMSXZYTLC:439G]wƵjUE.()0MfCUonUCNgCUnnUC=CVr˰qVCOCUonUC=CVṟrVC=CVṟrVC=CTmjQ@7:F    ÿþ¼ø}{{}}{{}Ƹ|qida__adiq||xwuspmiea__`dkv±tlfbXRNLKKLNRXboDzsf^ZYXXWUSQNKJJLR\k~¯teZSOMFCBBCCBBCFMXh|Ҿs^OFBBCEGHHGEB?==@GUg~ın\OGBB?=>ADFFDA>=?GTg}˷dM>4137=BGJJIE@:65:DUlĶoZI?::>:=CKQTTQJC=:.')01,-4>ӼcK=;EZuoUB;ASnƫmRA;BTnw_J;2/16fM>;DXsoUC;DXroUC;DXsoUC=CVr˰qVC8=MepUC=CVṟrVC=CUo¼ZrrZF:8@SlpUC=CVṟrVC=CUo½o -(%#"!½ ƽŹ~{yyz|˽yqjfb`__`acgkrzȷth_XSPONNOQTX`jwǴxh[QJGFFGHIJJIHFEFHLUa ȴs`RHB@ACGLORSSQNJFCBCHR ͸q\MB<78>JXhwzoe`_ҼiRA7667ASiMMOQU\hxз|_H95;Ja{ſCDFGGHJPZi~ʯrWB77BUoCHKMMLKKNWexĩkP>6:I`|LTZ]][XVW]i{׿dK;7>PjYenrsqnjimvԻ~`H:8CWsguҸz\F::G^{oжwZE:Ng YhuδtXC:>Nh JU`jrzϴuXD:=Mf =DLSZair|жwZD:BFKQYdrѸy\E::G^|;::;>DM[mӻ}_G:8CXtID@<85462+,6Ic϶y]F84;J`z }kXE6-+3D^}վgN<45@Rh¸s_K:/,3D]|ǭsXD738EWlǾN" Ŀᶸ¹ᘚݹ|zyxyz{}ĽΠǹunhdb`__`bdhmt|Ͻ~pd\VRPOOPRUZcn{}tqvqveXOIFFGHJKKHJIGFEFJP[hy{k`[`mɲauq_PFA@BFJORTUTRPLHECDHP]m~r`RKNZoԾZk~q]MA<<@GPX`eijifb]WQLIJP\k|p\KBBL`z̳z[iys`M@98>HUbnx}vog_ZX[dqs^J>;BTmèmdo{xfRB75:FVhyzrnnt{cM>7PjiPkTA419I`zľôgN=6:H`}и}`HmU@308I`{rWB77BWrȯrWB¶rWA306E[t߀˶}`I:6=OhhN=®x\E5/2?Qg~jP>69G_{ζ{^G9̸dJ8//7EWj|ɰuYD87AVqŬqUA7nS?2-09FTcp|ѺcJ;6=NgϼgN=6˳{`I90.19BLW`hpw~émR?79G]yƲy]G97ԿpYF9202774458;>AEHLQW]eo{ѼeL<6AFLT_m~ĪnT@79EZttZE97@¯xj^TMHDA><:97767:?HTdx˴y]G97@QiiQ?79GĴzpg`ZTPKGC?:63238AObyҽfN=6;I]ts]I;6=Nɼ~vpjd^WPIA93//4?PgƬqVB77ARfvveRA77BVǾ{sj`TH=3..5CYtͶ{_H95:GWfoofWG:59H_ƿ{l\L=2-0;NiԿiO=45>JV]]VJ>54=Oiýr]J:0.6HaȯsWB515=FLKF=515BWsƻmVB4/4D]{и~`H7.-27;;71-.7H`~ԍ˼y_H814C[y§jO;.((*,,*((.;Ojð~cK:26D\zʱtX@/%!  !%/@Xu{aJ:38G_~һaG2$$2FarZF95;LeĩkO7&&7Ok 﫜 wrv m`\bq oZNLUf `LBCNb} TB;?Md J;7?Pj C87BWr >69H_| :6=Oi 7BWs 6:Ia~ 6>Pj 8DYu ;Jc ?RmE[wLeTo]zgq{   йfN=54;GYlzvy~jUC87>Ŭv]I;4599=CKS[aeggea[TNIGHP]o}gSD;Űm[MD>=>AFJNQSSQOKHECEJUdxzeSFïscVMGDCDFGIJJIHGFGINWctzgWò}od[UQONMMNNOPRUZblzǸnǸvnhda_^^__adgms|˼|zyxxz|ú阚ʿ鶸 P   EMawvaM>7:FZtnUC=DWṟrWD>DWṟrWD>BQbr~~rbQB97?NepWE?FXt̲tXF?FXt̲tXF?;DO[ejje[OD;7;GZrtZICI[vͳv[ICI[vͳv[IC9DWṟrWD=DUnsYE97>EWppWE?FXt̲tXF?FXt̲tXF?EWpeN>79IZssZICI[vͳv[ICI[vͳv[ICI[trZG;7O`xw`OIOa{϶{aOIOa{϶{aOIO`yiTD;YiiYTYjҺjYTYjҺjYTYj˿|eSFiwwidixxidixxidix̼{gW}Ǿ|x}ɳ}x}ɳ}x}̻oɼͼ¶¶³ʿ     EMawvaM>7:F[vqVD>DWṟrWD=CUnBQbr~~rbQB97?OfƾrXE?FXt̲tXF?EVn;DO[ejje[OD;7;GZs®u[ICI[vͳv[ICHYqulijnsv999=CKS[aeggea[TNIFGNOOMID?<<@K[qŰm[MD>=>AFJNQSSQOKHECEJSHHGEDCDHP]pïscVMGDCDFGIJJIHGFGINVbNMMNPT\guò}od[UQONMMNNOPRUZakx__`cgmv Ǹvnhda_^^__adgms|yy{~ |zyxxz| ú㘚Ƕ 䶸 %C   w|zsqt{zdP@77ATn̳vX>**>Xvdmwvka\\ajtwfUF;7:;EUlƬoR:((:RoXft~}qcTIBACHNU\afhihd^WNF@=>ESf~ζ|_F3& &3F_|`o~{k[NE@>@CGKORTTSQMIEBACJUfzoVC5//5CVop{k]QJECCDFHIJKJIHGFGKR\k|̵jXKDDKXjއsg]WRONMMNNOPSW^huípe__eq栭¾xpjfca__^^_`beipxѿ}}|zyxxz|ļýÿ    d(((3g3 f Background     ff #/;GS_kw                  (((3g3 fSelection Mask copy 2fR*3*?*KfB@!O$%&N''(d)0*/\ѨyG -K V)8~%~$S,#I%f#$i #! V"$!'O7 ZR3Xo,xB]+) gZ 1< iz CQ4^=Pi, (xۿx( dg vv nL!w N / bs Tb 1~. .~)N!6N"7NTZHFU\ ` b( 4 5 e   ]   4                  5   _   g  *   dg vvnL!w / bs ROb 1 O XN!6N"7,DNTDHF] ` b 4 5)  g  Z  1              4  ^  i  , (xۿx(iq ] g  N R 7T  F2~. .~)O!AnCe&ZBJU\ t ( B e $\ ] C 4 i    ,     3   ' 5 _ g * \ѨyG -K V)8'~'S,#I'f#%i $! V$Ѥt4'O' Z 3K$ (NoAx:B8+88 8e  }Ga<<i Jz`CCQK=PB|Գc2, h|~ew/a1,L~w Qe#<=v7$AR H I )@ {U V* ;h.\&abǚl=w0 ՚O   no 1 p d >  !"@k| z{ F RQ~ -. O @? :;  --$] GH}v0dQ?-vd<@ a | [, Dy1^f^Vv ? # ,oЪv9bd  ^    / .-  Z  S   !   *{{*    a    1   ^   V   #bd ^ J Z/ .- k4 Z  S  !  t*{{*.c<@S %V | H[, Dy $%f v ?ƒT%,oЪv9e: wvA  b 2-}H"  Bucdce^G- n VRQ GtЩt+(3g3 commons-csv-1.2-src/src/site/resources/profile.jacoco0100644 0000000 0000000 00000000000 12565700105 025617 0ustar00BUILTIN\Administrators0000000 0000000 commons-csv-1.2-src/src/site/site.xml0100644 0000000 0000000 00000004461 12565700105 022472 0ustar00BUILTIN\Administrators0000000 0000000 Apache Commons CSV /images/logo.png /index.html Commons CSV&trade; logo commons-csv-1.2-src/src/site/xdoc/cvs-usage.xml0100644 0000000 0000000 00000003626 12565700105 024362 0ustar00BUILTIN\Administrators0000000 0000000 Source repository Commons Documentation Team

Apache Commons CSV is hosted on the Apache subversion repository.

The project URL is:
http://svn.apache.org/repos/asf/commons/sandbox/csv/trunk

The best way to view the repository is via the subversion viewer.

The alternative is to use the native subversion display.

For more information on subversion and creating patches see the Apache Contributors Guide.

commons-csv-1.2-src/src/site/xdoc/download_csv.xml0100644 0000000 0000000 00000015472 12565700105 025151 0ustar00BUILTIN\Administrators0000000 0000000 Download Apache Commons CSV Commons Documentation Team

We recommend you use a mirror to download our release builds, but you must verify the integrity of the downloaded files using signatures downloaded from our main distribution directories. Recent releases (48 hours) may not yet be available from the mirrors.

You are currently using [preferred]. If you encounter a problem with this mirror, please select another mirror. If all mirrors are failing, there are backup mirrors (at the end of the mirrors list) that should be available.

[if-any logo][end]

Other mirrors:

The KEYS link links to the code signing keys used to sign the product. The PGP link downloads the OpenPGP compatible signature from our main site. The MD5 link downloads the checksum from the main site.

commons-csv-1.2-bin.tar.gz md5 pgp
commons-csv-1.2-bin.zip md5 pgp
commons-csv-1.2-src.tar.gz md5 pgp
commons-csv-1.2-src.zip md5 pgp

Older releases can be obtained from the archives.

commons-csv-1.2-src/src/site/xdoc/examples.xml0100644 0000000 0000000 00000002224 12565700105 024274 0ustar00BUILTIN\Administrators0000000 0000000 Code Examples Commons Documentation Team
  
commons-csv-1.2-src/src/site/xdoc/index.xml0100644 0000000 0000000 00000015447 12565700105 023600 0ustar00BUILTIN\Administrators0000000 0000000 Home Commons Documentation Team

Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format.

The most common CSV formats are predefined in the CSVFormat class:

Custom formats can be created using a fluent style API.

An overview of the functionality is provided in the user guide. Various project reports are also available.

The Javadoc API documents are available online:

The subversion repository can be browsed.

See the Download Page for the latest releases.

Change reports are also available.

For previous releases, see the Apache Archive

Alternatively, you can pull it from a Maven repository:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.2</version>
</dependency>

For other dependency access methods, see Dependency Information

The latest code can be checked out from our Subversion repository at http://svn.apache.org/repos/asf/commons/proper/csv/trunk/. You can build the component using Apache Maven using mvn clean package.

The commons developer mailing list is the main channel of communication for contributors. Please remember that the lists are shared between all commons components, so prefix your email by [csv].

You can also visit the #apache-commons IRC channel on irc.freenode.net or peruse JIRA. Specific links of interest for JIRA are:

Alternatively you can go through the Needs Work tags in the TagList report.

If you'd like to offer up pull requests via GitHub rather than applying patches to JIRA, we have a GitHub mirror.

The commons mailing lists act as the main support forum. The user list is suitable for most library usage queries. The dev list is intended for the development discussion. Please remember that the lists are shared between all commons components, so prefix your email by [csv].

Bug reports and enhancements are also welcomed via the JIRA issue tracker. Please read the instructions carefully.

Commons CSV was started to unify a common and simple interface for reading and writing CSV files under an ASL license. It has been bootstrapped by a code donation from Netcetera in Switzerland. There are three pre-existing BSD compatible CSV parsers which this component will hopefully make redundant (authors willing):

In addition to the code from Netcetera (org.apache.commons.csv), Martin van den Bemt has added an additional writer API.

Other CSV implementations:

commons-csv-1.2-src/src/site/xdoc/issue-tracking.xml0100644 0000000 0000000 00000013355 12565700105 025415 0ustar00BUILTIN\Administrators0000000 0000000 Commons CSV Issue tracking Commons Documentation Team

Commons CSV uses ASF JIRA for tracking issues. See the Commons CSV JIRA project page.

To use JIRA you may need to create an account (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically created and you can use the Forgot Password page to get a new password).

If you would like to report a bug, or raise an enhancement request with Commons CSV please do the following:

  1. Search existing open bugs. If you find your issue listed then please add a comment with your details.
  2. Search the mailing list archive(s). You may find your issue or idea has already been discussed.
  3. Decide if your issue is a bug or an enhancement.
  4. Submit either a bug report or enhancement request.

Please also remember these points:

  • the more information you provide, the better we can help you
  • test cases are vital, particularly for any proposed enhancements
  • the developers of Commons CSV are all unpaid volunteers

For more information on subversion and creating patches see the Apache Contributors Guide.

You may also find these links useful:

commons-csv-1.2-src/src/site/xdoc/mail-lists.xml0100644 0000000 0000000 00000023013 12565700105 024533 0ustar00BUILTIN\Administrators0000000 0000000 Apache Commons CSV Mailing Lists Commons Documentation Team

Apache Commons CSV shares mailing lists with all the other Commons Components. To make it easier for people to only read messages related to components they are interested in, the convention in Commons is to prefix the subject line of messages with the component's name, for example:

  • [csv] Problem with the ...

Questions related to the usage of Apache Commons CSV should be posted to the User List.
The Developer List is for questions and discussion related to the development of Apache Commons CSV.
Please do not cross-post; developers are also subscribed to the user list.
You must be subscribed to post to the mailing lists. Follow the Subscribe links below to subscribe.

Note: please don't send patches or attachments to any of the mailing lists. Patches are best handled via the Issue Tracking system. Otherwise, please upload the file to a public server and include the URL in the mail.

Please prefix the subject line of any messages for Apache Commons CSV with [csv] - thanks!

Name Subscribe Unsubscribe Post Archive Other Archives
Commons User List

Questions on using Apache Commons CSV.

Subscribe Unsubscribe Post mail-archives.apache.org markmail.org
www.mail-archive.com
news.gmane.org
Commons Developer List

Discussion of development of Apache Commons CSV.

Subscribe Unsubscribe Post mail-archives.apache.org markmail.org
www.mail-archive.com
news.gmane.org
Commons Issues List

Only for e-mails automatically generated by the issue tracking system.

Subscribe Unsubscribe read only mail-archives.apache.org markmail.org
www.mail-archive.com
Commons Commits List

Only for e-mails automatically generated by the source control sytem.

Subscribe Unsubscribe read only mail-archives.apache.org markmail.org
www.mail-archive.com

Other mailing lists which you may find useful include:

Name Subscribe Unsubscribe Post Archive Other Archives
Apache Announce List

General announcements of Apache project releases.

Subscribe Unsubscribe read only mail-archives.apache.org markmail.org
old.nabble.com
www.mail-archive.com
news.gmane.org
commons-csv-1.2-src/src/site/xdoc/user-guide.xml0100644 0000000 0000000 00000006201 12565700105 024526 0ustar00BUILTIN\Administrators0000000 0000000 User Guide Commons Documentation Team

To parse an Excel CSV file, write:

Reader in = new FileReader("path/to/file.csv"); Iterable<CSVRecord> records = CSVFormat.EXCEL.parse(in); for (CSVRecord record : records) { String lastName = record.get("Last Name"); String firstName = record.get("First Name"); }

To handle files that start with a Byte Order Mark (BOM) like some Excel CSV files, you need an extra step to deal with these optional bytes. You can use the BOMInputStream class from Apache Commons IO for example:

final URL url = ...; final Reader reader = new InputStreamReader(new BOMInputStream(url.openStream()), "UTF-8"); final CSVParser parser = new CSVParser(reader, CSVFormat.EXCEL.withHeader()); try { for (final CSVRecord record : parser) { final String string = record.get("SomeColumn"); ... } } finally { parser.close(); reader.close(); }

You might find it handy to create something like this:

/** * Creates a reader capable of handling BOMs. */ public InputStreamReader newReader(final InputStream inputStream) { return new InputStreamReader(new BOMInputStream(inputStream), StandardCharsets.UTF_8); }

To print a CSV file with headers, you specify the headers in the format:

final Appendable out = ...; final CSVPrinter printer = CSVFormat.DEFAULT.withHeader("H1", "H2").print(out)

To print a CSV file with JDBC column labels, you specify the ResultSet in the format:

final ResultSet resultSet = ...; final CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet).print(out)
commons-csv-1.2-src/src/test/java/org/apache/commons/csv/AssertionsTest.java0100644 0000000 0000000 00000002410 12565700104 032042 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import org.junit.Test; /** * @version $Id: AssertionsTest.java 1518808 2013-08-29 20:25:19Z britter $ */ public class AssertionsTest { @Test public void testNotNull() throws Exception { Assertions.notNull(new Object(), "object"); } @Test(expected = IllegalArgumentException.class) public void testNotNullNull() throws Exception { Assertions.notNull(null, "object"); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/CSVFileParserTest.java0100644 0000000 0000000 00000016423 12565700103 032330 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FilenameFilter; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; /** * Parse tests using test files * * @version $Id: CSVFileParserTest.java 1624048 2014-09-10 16:05:45Z brentworden $ */ @RunWith(Parameterized.class) public class CSVFileParserTest { private static final File BASE = new File("src/test/resources/CSVFileParser"); private final BufferedReader testData; private final String testName; public CSVFileParserTest(final File file) throws FileNotFoundException { this.testName = file.getName(); this.testData = new BufferedReader(new FileReader(file)); } private String readTestData() throws IOException { String line; do { line = testData.readLine(); } while (line != null && line.startsWith("#")); return line; } @Parameters public static Collection generateData() { final List list = new ArrayList(); final FilenameFilter filenameFilter = new FilenameFilter() { @Override public boolean accept(final File dir, final String name) { return name.startsWith("test") && name.endsWith(".txt"); } }; final File[] files = BASE.listFiles(filenameFilter); for (final File f : files) { list.add(new Object[] { f }); } return list; } @Test public void testCSVFile() throws Exception { String line = readTestData(); assertNotNull("file must contain config line", line); final String[] split = line.split(" "); assertTrue(testName + " require 1 param", split.length >= 1); // first line starts with csv data file name CSVFormat format = CSVFormat.newFormat(',').withQuote('"'); boolean checkComments = false; for (int i = 1; i < split.length; i++) { final String option = split[i]; final String[] option_parts = option.split("=", 2); if ("IgnoreEmpty".equalsIgnoreCase(option_parts[0])) { format = format.withIgnoreEmptyLines(Boolean.parseBoolean(option_parts[1])); } else if ("IgnoreSpaces".equalsIgnoreCase(option_parts[0])) { format = format.withIgnoreSurroundingSpaces(Boolean.parseBoolean(option_parts[1])); } else if ("CommentStart".equalsIgnoreCase(option_parts[0])) { format = format.withCommentMarker(option_parts[1].charAt(0)); } else if ("CheckComments".equalsIgnoreCase(option_parts[0])) { checkComments = true; } else { fail(testName + " unexpected option: " + option); } } line = readTestData(); // get string version of format assertEquals(testName + " Expected format ", line, format.toString()); // Now parse the file and compare against the expected results // We use a buffered reader internally so no need to create one here. final CSVParser parser = CSVParser.parse(new File(BASE, split[0]), Charset.defaultCharset(), format); for (final CSVRecord record : parser) { String parsed = Arrays.toString(record.values()); if (checkComments) { final String comment = record.getComment().replace("\n", "\\n"); if (comment != null) { parsed += "#" + comment; } } final int count = record.size(); assertEquals(testName, readTestData(), count + ":" + parsed); } parser.close(); } @Test public void testCSVUrl() throws Exception { String line = readTestData(); assertNotNull("file must contain config line", line); final String[] split = line.split(" "); assertTrue(testName + " require 1 param", split.length >= 1); // first line starts with csv data file name CSVFormat format = CSVFormat.newFormat(',').withQuote('"'); boolean checkComments = false; for (int i = 1; i < split.length; i++) { final String option = split[i]; final String[] option_parts = option.split("=", 2); if ("IgnoreEmpty".equalsIgnoreCase(option_parts[0])) { format = format.withIgnoreEmptyLines(Boolean.parseBoolean(option_parts[1])); } else if ("IgnoreSpaces".equalsIgnoreCase(option_parts[0])) { format = format.withIgnoreSurroundingSpaces(Boolean.parseBoolean(option_parts[1])); } else if ("CommentStart".equalsIgnoreCase(option_parts[0])) { format = format.withCommentMarker(option_parts[1].charAt(0)); } else if ("CheckComments".equalsIgnoreCase(option_parts[0])) { checkComments = true; } else { fail(testName + " unexpected option: " + option); } } line = readTestData(); // get string version of format assertEquals(testName + " Expected format ", line, format.toString()); // Now parse the file and compare against the expected results final URL resource = ClassLoader.getSystemResource("CSVFileParser/" + split[0]); final CSVParser parser = CSVParser.parse(resource, Charset.forName("UTF-8"), format); for (final CSVRecord record : parser) { String parsed = Arrays.toString(record.values()); if (checkComments) { final String comment = record.getComment().replace("\n", "\\n"); if (comment != null) { parsed += "#" + comment; } } final int count = record.size(); assertEquals(testName, readTestData(), count + ":" + parsed); } parser.close(); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java0100644 0000000 0000000 00000003251 12565700104 033506 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import org.junit.Assert; import org.junit.Test; /** * Tests {@link CSVFormat.Predefined}. */ public class CSVFormatPredefinedTest { private void test(final CSVFormat format, final String enumName) { Assert.assertEquals(format, CSVFormat.Predefined.valueOf(enumName).getFormat()); Assert.assertEquals(format, CSVFormat.valueOf(enumName)); } @Test public void testDefault() { test(CSVFormat.DEFAULT, "Default"); } @Test public void testExcel() { test(CSVFormat.EXCEL, "Excel"); } @Test public void testMySQL() { test(CSVFormat.MYSQL, "MySQL"); } @Test public void testRFC4180() { test(CSVFormat.RFC4180, "RFC4180"); } @Test public void testTDF() { test(CSVFormat.TDF, "TDF"); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/CSVFormatTest.java0100644 0000000 0000000 00000037550 12565700103 031530 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.CSVFormat.RFC4180; import static org.apache.commons.csv.Constants.CR; import static org.apache.commons.csv.Constants.CRLF; import static org.apache.commons.csv.Constants.LF; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Arrays; import org.junit.Test; /** * * * @version $Id: CSVFormatTest.java 1621004 2014-08-28 00:28:02Z ggregory $ */ public class CSVFormatTest { private static void assertNotEquals(final Object right, final Object left) { assertFalse(right.equals(left)); assertFalse(left.equals(right)); } private static CSVFormat copy(final CSVFormat format) { return format.withDelimiter(format.getDelimiter()); } @Test(expected = IllegalArgumentException.class) public void testDelimiterSameAsCommentStartThrowsException() { CSVFormat.DEFAULT.withDelimiter('!').withCommentMarker('!'); } @Test(expected = IllegalArgumentException.class) public void testDelimiterSameAsEscapeThrowsException() { CSVFormat.DEFAULT.withDelimiter('!').withEscape('!'); } @Test(expected = IllegalArgumentException.class) public void testDuplicateHeaderElements() { CSVFormat.DEFAULT.withHeader("A", "A"); } @Test public void testEquals() { final CSVFormat right = CSVFormat.DEFAULT; final CSVFormat left = copy(right); assertFalse(right.equals(null)); assertFalse(right.equals("A String Instance")); assertEquals(right, right); assertEquals(right, left); assertEquals(left, right); assertEquals(right.hashCode(), right.hashCode()); assertEquals(right.hashCode(), left.hashCode()); } @Test public void testEqualsCommentStart() { final CSVFormat right = CSVFormat.newFormat('\'') .withQuote('"') .withCommentMarker('#') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right .withCommentMarker('!'); assertNotEquals(right, left); } @Test public void testEqualsDelimiter() { final CSVFormat right = CSVFormat.newFormat('!'); final CSVFormat left = CSVFormat.newFormat('?'); assertNotEquals(right, left); } @Test public void testEqualsEscape() { final CSVFormat right = CSVFormat.newFormat('\'') .withQuote('"') .withCommentMarker('#') .withEscape('+') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right .withEscape('!'); assertNotEquals(right, left); } @Test public void testEqualsHeader() { final CSVFormat right = CSVFormat.newFormat('\'') .withRecordSeparator(CR) .withCommentMarker('#') .withEscape('+') .withHeader("One", "Two", "Three") .withIgnoreEmptyLines() .withIgnoreSurroundingSpaces() .withQuote('"') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right .withHeader("Three", "Two", "One"); assertNotEquals(right, left); } @Test public void testEqualsIgnoreEmptyLines() { final CSVFormat right = CSVFormat.newFormat('\'') .withCommentMarker('#') .withEscape('+') .withIgnoreEmptyLines() .withIgnoreSurroundingSpaces() .withQuote('"') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right .withIgnoreEmptyLines(false); assertNotEquals(right, left); } @Test public void testEqualsIgnoreSurroundingSpaces() { final CSVFormat right = CSVFormat.newFormat('\'') .withCommentMarker('#') .withEscape('+') .withIgnoreSurroundingSpaces() .withQuote('"') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right .withIgnoreSurroundingSpaces(false); assertNotEquals(right, left); } @Test public void testEqualsQuoteChar() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"'); final CSVFormat left = right.withQuote('!'); assertNotEquals(right, left); } @Test public void testEqualsQuotePolicy() { final CSVFormat right = CSVFormat.newFormat('\'') .withQuote('"') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right .withQuoteMode(QuoteMode.MINIMAL); assertNotEquals(right, left); } @Test public void testEqualsRecordSeparator() { final CSVFormat right = CSVFormat.newFormat('\'') .withRecordSeparator(CR) .withCommentMarker('#') .withEscape('+') .withIgnoreEmptyLines() .withIgnoreSurroundingSpaces() .withQuote('"') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right .withRecordSeparator(LF); assertNotEquals(right, left); } @Test public void testEqualsNullString() { final CSVFormat right = CSVFormat.newFormat('\'') .withRecordSeparator(CR) .withCommentMarker('#') .withEscape('+') .withIgnoreEmptyLines() .withIgnoreSurroundingSpaces() .withQuote('"') .withQuoteMode(QuoteMode.ALL) .withNullString("null"); final CSVFormat left = right .withNullString("---"); assertNotEquals(right, left); } @Test public void testEqualsSkipHeaderRecord() { final CSVFormat right = CSVFormat.newFormat('\'') .withRecordSeparator(CR) .withCommentMarker('#') .withEscape('+') .withIgnoreEmptyLines() .withIgnoreSurroundingSpaces() .withQuote('"') .withQuoteMode(QuoteMode.ALL) .withNullString("null") .withSkipHeaderRecord(); final CSVFormat left = right .withSkipHeaderRecord(false); assertNotEquals(right, left); } @Test(expected = IllegalArgumentException.class) public void testEscapeSameAsCommentStartThrowsException() { CSVFormat.DEFAULT.withEscape('!').withCommentMarker('!'); } @Test(expected = IllegalArgumentException.class) public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType() { // Cannot assume that callers won't use different Character objects CSVFormat.DEFAULT.withEscape(new Character('!')).withCommentMarker(new Character('!')); } @Test public void testFormat() { final CSVFormat format = CSVFormat.DEFAULT; assertEquals("", format.format()); assertEquals("a,b,c", format.format("a", "b", "c")); assertEquals("\"x,y\",z", format.format("x,y", "z")); } @Test public void testGetHeader() throws Exception { final String[] header = new String[]{"one", "two", "three"}; final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(header); // getHeader() makes a copy of the header array. final String[] headerCopy = formatWithHeader.getHeader(); headerCopy[0] = "A"; headerCopy[1] = "B"; headerCopy[2] = "C"; assertFalse(Arrays.equals(formatWithHeader.getHeader(), headerCopy)); assertNotSame(formatWithHeader.getHeader(), headerCopy); } @Test public void testNullRecordSeparatorCsv106() { final CSVFormat format = CSVFormat.newFormat(';').withSkipHeaderRecord().withHeader("H1", "H2"); final String formatStr = format.format("A", "B"); assertNotNull(formatStr); assertFalse(formatStr.endsWith("null")); } @Test(expected = IllegalArgumentException.class) public void testQuoteCharSameAsCommentStartThrowsException() { CSVFormat.DEFAULT.withQuote('!').withCommentMarker('!'); } @Test(expected = IllegalArgumentException.class) public void testQuoteCharSameAsCommentStartThrowsExceptionForWrapperType() { // Cannot assume that callers won't use different Character objects CSVFormat.DEFAULT.withQuote(new Character('!')).withCommentMarker('!'); } @Test(expected = IllegalArgumentException.class) public void testQuoteCharSameAsDelimiterThrowsException() { CSVFormat.DEFAULT.withQuote('!').withDelimiter('!'); } @Test(expected = IllegalArgumentException.class) public void testQuotePolicyNoneWithoutEscapeThrowsException() { CSVFormat.newFormat('!').withQuoteMode(QuoteMode.NONE); } @Test public void testRFC4180() { assertEquals(null, RFC4180.getCommentMarker()); assertEquals(',', RFC4180.getDelimiter()); assertEquals(null, RFC4180.getEscapeCharacter()); assertFalse(RFC4180.getIgnoreEmptyLines()); assertEquals(Character.valueOf('"'), RFC4180.getQuoteCharacter()); assertEquals(null, RFC4180.getQuoteMode()); assertEquals("\r\n", RFC4180.getRecordSeparator()); } @SuppressWarnings("boxing") // no need to worry about boxing here @Test public void testSerialization() throws Exception { final ByteArrayOutputStream out = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(out); oos.writeObject(CSVFormat.DEFAULT); oos.flush(); oos.close(); final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray())); final CSVFormat format = (CSVFormat) in.readObject(); assertNotNull(format); assertEquals("delimiter", CSVFormat.DEFAULT.getDelimiter(), format.getDelimiter()); assertEquals("encapsulator", CSVFormat.DEFAULT.getQuoteCharacter(), format.getQuoteCharacter()); assertEquals("comment start", CSVFormat.DEFAULT.getCommentMarker(), format.getCommentMarker()); assertEquals("record separator", CSVFormat.DEFAULT.getRecordSeparator(), format.getRecordSeparator()); assertEquals("escape", CSVFormat.DEFAULT.getEscapeCharacter(), format.getEscapeCharacter()); assertEquals("trim", CSVFormat.DEFAULT.getIgnoreSurroundingSpaces(), format.getIgnoreSurroundingSpaces()); assertEquals("empty lines", CSVFormat.DEFAULT.getIgnoreEmptyLines(), format.getIgnoreEmptyLines()); } @Test public void testWithCommentStart() throws Exception { final CSVFormat formatWithCommentStart = CSVFormat.DEFAULT.withCommentMarker('#'); assertEquals( Character.valueOf('#'), formatWithCommentStart.getCommentMarker()); } @Test(expected = IllegalArgumentException.class) public void testWithCommentStartCRThrowsException() { CSVFormat.DEFAULT.withCommentMarker(CR); } @Test public void testWithDelimiter() throws Exception { final CSVFormat formatWithDelimiter = CSVFormat.DEFAULT.withDelimiter('!'); assertEquals('!', formatWithDelimiter.getDelimiter()); } @Test(expected = IllegalArgumentException.class) public void testWithDelimiterLFThrowsException() { CSVFormat.DEFAULT.withDelimiter(LF); } @Test public void testWithEscape() throws Exception { final CSVFormat formatWithEscape = CSVFormat.DEFAULT.withEscape('&'); assertEquals(Character.valueOf('&'), formatWithEscape.getEscapeCharacter()); } @Test(expected = IllegalArgumentException.class) public void testWithEscapeCRThrowsExceptions() { CSVFormat.DEFAULT.withEscape(CR); } @Test public void testWithHeader() throws Exception { final String[] header = new String[]{"one", "two", "three"}; // withHeader() makes a copy of the header array. final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(header); assertArrayEquals(header, formatWithHeader.getHeader()); assertNotSame(header, formatWithHeader.getHeader()); header[0] = "A"; header[1] = "B"; header[2] = "C"; assertFalse(Arrays.equals(formatWithHeader.getHeader(), header)); } @Test public void testWithIgnoreEmptyLines() throws Exception { assertFalse(CSVFormat.DEFAULT.withIgnoreEmptyLines(false).getIgnoreEmptyLines()); assertTrue(CSVFormat.DEFAULT.withIgnoreEmptyLines().getIgnoreEmptyLines()); } @Test public void testWithIgnoreSurround() throws Exception { assertFalse(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(false).getIgnoreSurroundingSpaces()); assertTrue(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces().getIgnoreSurroundingSpaces()); } @Test public void testWithNullString() throws Exception { final CSVFormat formatWithNullString = CSVFormat.DEFAULT.withNullString("null"); assertEquals("null", formatWithNullString.getNullString()); } @Test public void testWithQuoteChar() throws Exception { final CSVFormat formatWithQuoteChar = CSVFormat.DEFAULT.withQuote('"'); assertEquals(Character.valueOf('"'), formatWithQuoteChar.getQuoteCharacter()); } @Test(expected = IllegalArgumentException.class) public void testWithQuoteLFThrowsException() { CSVFormat.DEFAULT.withQuote(LF); } @Test public void testWithQuotePolicy() throws Exception { final CSVFormat formatWithQuotePolicy = CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL); assertEquals(QuoteMode.ALL, formatWithQuotePolicy.getQuoteMode()); } @Test public void testWithRecordSeparatorCR() throws Exception { final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CR); assertEquals(String.valueOf(CR), formatWithRecordSeparator.getRecordSeparator()); } @Test public void testWithRecordSeparatorLF() throws Exception { final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(LF); assertEquals(String.valueOf(LF), formatWithRecordSeparator.getRecordSeparator()); } @Test public void testWithRecordSeparatorCRLF() throws Exception { final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CRLF); assertEquals(CRLF, formatWithRecordSeparator.getRecordSeparator()); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/CSVParserTest.java0100644 0000000 0000000 00000117263 12565700103 031534 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.CR; import static org.apache.commons.csv.Constants.CRLF; import static org.apache.commons.csv.Constants.LF; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.PipedReader; import java.io.PipedWriter; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.apache.commons.io.input.BOMInputStream; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; /** * CSVParserTest * * The test are organized in three different sections: The 'setter/getter' section, the lexer section and finally the * parser section. In case a test fails, you should follow a top-down approach for fixing a potential bug (its likely * that the parser itself fails if the lexer has problems...). * * @version $Id: CSVParserTest.java 1695167 2015-08-10 21:08:58Z ggregory $ */ public class CSVParserTest { private static final String CSV_INPUT = "a,b,c,d\n" + " a , b , 1 2 \n" + "\"foo baar\", b,\n" // + " \"foo\n,,\n\"\",,\n\\\"\",d,e\n"; + " \"foo\n,,\n\"\",,\n\"\"\",d,e\n"; // changed to use standard CSV escaping private static final String CSV_INPUT_1 = "a,b,c,d"; private static final String CSV_INPUT_2 = "a,b,1 2"; private static final String[][] RESULT = { { "a", "b", "c", "d" }, { "a", "b", "1 2" }, { "foo baar", "b", "" }, { "foo\n,,\n\",,\n\"", "d", "e" } }; @Test public void testBackslashEscaping() throws IOException { // To avoid confusion over the need for escaping chars in java code, // We will test with a forward slash as the escape char, and a single // quote as the encapsulator. final String code = "one,two,three\n" // 0 + "'',''\n" // 1) empty encapsulators + "/',/'\n" // 2) single encapsulators + "'/'','/''\n" // 3) single encapsulators encapsulated via escape + "'''',''''\n" // 4) single encapsulators encapsulated via doubling + "/,,/,\n" // 5) separator escaped + "//,//\n" // 6) escape escaped + "'//','//'\n" // 7) escape escaped in encapsulation + " 8 , \"quoted \"\" /\" // string\" \n" // don't eat spaces + "9, /\n \n" // escaped newline + ""; final String[][] res = { { "one", "two", "three" }, // 0 { "", "" }, // 1 { "'", "'" }, // 2 { "'", "'" }, // 3 { "'", "'" }, // 4 { ",", "," }, // 5 { "/", "/" }, // 6 { "/", "/" }, // 7 { " 8 ", " \"quoted \"\" /\" / string\" " }, { "9", " \n " }, }; final CSVFormat format = CSVFormat.newFormat(',').withQuote('\'').withRecordSeparator(CRLF).withEscape('/') .withIgnoreEmptyLines(); final CSVParser parser = CSVParser.parse(code, format); final List records = parser.getRecords(); assertTrue(records.size() > 0); Utils.compare("Records do not match expected result", res, records); parser.close(); } @Test public void testBackslashEscaping2() throws IOException { // To avoid confusion over the need for escaping chars in java code, // We will test with a forward slash as the escape char, and a single // quote as the encapsulator. final String code = "" + " , , \n" // 1) + " \t , , \n" // 2) + " // , /, , /,\n" // 3) + ""; final String[][] res = { { " ", " ", " " }, // 1 { " \t ", " ", " " }, // 2 { " / ", " , ", " ," }, // 3 }; final CSVFormat format = CSVFormat.newFormat(',').withRecordSeparator(CRLF).withEscape('/') .withIgnoreEmptyLines(); final CSVParser parser = CSVParser.parse(code, format); final List records = parser.getRecords(); assertTrue(records.size() > 0); Utils.compare("", res, records); parser.close(); } @Test @Ignore public void testBackslashEscapingOld() throws IOException { final String code = "one,two,three\n" + "on\\\"e,two\n" + "on\"e,two\n" + "one,\"tw\\\"o\"\n" + "one,\"t\\,wo\"\n" + "one,two,\"th,ree\"\n" + "\"a\\\\\"\n" + "a\\,b\n" + "\"a\\\\,b\""; final String[][] res = { { "one", "two", "three" }, { "on\\\"e", "two" }, { "on\"e", "two" }, { "one", "tw\"o" }, { "one", "t\\,wo" }, // backslash in quotes only escapes a delimiter (",") { "one", "two", "th,ree" }, { "a\\\\" }, // backslash in quotes only escapes a delimiter (",") { "a\\", "b" }, // a backslash must be returnd { "a\\\\,b" } // backslash in quotes only escapes a delimiter (",") }; final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } @Test @Ignore("CSV-107") public void testBOM() throws IOException { final URL url = ClassLoader.getSystemClassLoader().getResource("CSVFileParser/bom.csv"); final CSVParser parser = CSVParser.parse(url, Charset.forName("UTF-8"), CSVFormat.EXCEL.withHeader()); try { for (final CSVRecord record : parser) { final String string = record.get("Date"); Assert.assertNotNull(string); // System.out.println("date: " + record.get("Date")); } } finally { parser.close(); } } @Test public void testBOMInputStream() throws IOException { final URL url = ClassLoader.getSystemClassLoader().getResource("CSVFileParser/bom.csv"); final Reader reader = new InputStreamReader(new BOMInputStream(url.openStream()), "UTF-8"); final CSVParser parser = new CSVParser(reader, CSVFormat.EXCEL.withHeader()); try { for (final CSVRecord record : parser) { final String string = record.get("Date"); Assert.assertNotNull(string); // System.out.println("date: " + record.get("Date")); } } finally { parser.close(); reader.close(); } } @Test public void testCarriageReturnEndings() throws IOException { final String code = "foo\rbaar,\rhello,world\r,kanu"; final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT); final List records = parser.getRecords(); assertEquals(4, records.size()); parser.close(); } @Test public void testCarriageReturnLineFeedEndings() throws IOException { final String code = "foo\r\nbaar,\r\nhello,world\r\n,kanu"; final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT); final List records = parser.getRecords(); assertEquals(4, records.size()); parser.close(); } @Test(expected = NoSuchElementException.class) public void testClose() throws Exception { final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z"); final CSVParser parser = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in); final Iterator records = parser.iterator(); assertTrue(records.hasNext()); parser.close(); assertFalse(records.hasNext()); records.next(); } @Test public void testCSV57() throws Exception { final CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT); final List list = parser.getRecords(); assertNotNull(list); assertEquals(0, list.size()); parser.close(); } @Test public void testDefaultFormat() throws IOException { final String code = "" + "a,b#\n" // 1) + "\"\n\",\" \",#\n" // 2) + "#,\"\"\n" // 3) + "# Final comment\n"// 4) ; final String[][] res = { { "a", "b#" }, { "\n", " ", "#" }, { "#", "" }, { "# Final comment" } }; CSVFormat format = CSVFormat.DEFAULT; assertFalse(format.isCommentMarkerSet()); CSVParser parser = CSVParser.parse(code, format); List records = parser.getRecords(); assertTrue(records.size() > 0); Utils.compare("Failed to parse without comments", res, records); final String[][] res_comments = { { "a", "b#" }, { "\n", " ", "#" }, }; format = CSVFormat.DEFAULT.withCommentMarker('#'); parser.close(); parser = CSVParser.parse(code, format); records = parser.getRecords(); Utils.compare("Failed to parse with comments", res_comments, records); parser.close(); } @Test public void testEmptyFile() throws Exception { final CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT); assertNull(parser.nextRecord()); parser.close(); } @Test public void testEmptyLineBehaviourCSV() throws Exception { final String[] codes = { "hello,\r\n\r\n\r\n", "hello,\n\n\n", "hello,\"\"\r\n\r\n\r\n", "hello,\"\"\n\n\n" }; final String[][] res = { { "hello", "" } // CSV format ignores empty lines }; for (final String code : codes) { final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } } @Test public void testEmptyLineBehaviourExcel() throws Exception { final String[] codes = { "hello,\r\n\r\n\r\n", "hello,\n\n\n", "hello,\"\"\r\n\r\n\r\n", "hello,\"\"\n\n\n" }; final String[][] res = { { "hello", "" }, { "" }, // Excel format does not ignore empty lines { "" } }; for (final String code : codes) { final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } } @Test @Ignore public void testStartWithEmptyLinesThenHeaders() throws Exception { final String[] codes = {"\r\n\r\n\r\nhello,\r\n\r\n\r\n", "hello,\n\n\n", "hello,\"\"\r\n\r\n\r\n", "hello,\"\"\n\n\n"}; final String[][] res = {{"hello", ""}, {""}, // Excel format does not ignore empty lines {""}}; for (final String code : codes) { final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } } @Test public void testEndOfFileBehaviorCSV() throws Exception { final String[] codes = { "hello,\r\n\r\nworld,\r\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\r\n", "hello,\r\n\r\nworld,\"\"", "hello,\r\n\r\nworld,\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\n", "hello,\r\n\r\nworld,\"\"" }; final String[][] res = { { "hello", "" }, // CSV format ignores empty lines { "world", "" } }; for (final String code : codes) { final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } } @Test public void testEndOfFileBehaviourExcel() throws Exception { final String[] codes = { "hello,\r\n\r\nworld,\r\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\r\n", "hello,\r\n\r\nworld,\"\"", "hello,\r\n\r\nworld,\n", "hello,\r\n\r\nworld,", "hello,\r\n\r\nworld,\"\"\n", "hello,\r\n\r\nworld,\"\"" }; final String[][] res = { { "hello", "" }, { "" }, // Excel format does not ignore empty lines { "world", "" } }; for (final String code : codes) { final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } } @Test public void testExcelFormat1() throws IOException { final String code = "value1,value2,value3,value4\r\na,b,c,d\r\n x,,," + "\r\n\r\n\"\"\"hello\"\"\",\" \"\"world\"\"\",\"abc\ndef\",\r\n"; final String[][] res = { { "value1", "value2", "value3", "value4" }, { "a", "b", "c", "d" }, { " x", "", "", "" }, { "" }, { "\"hello\"", " \"world\"", "abc\ndef", "" } }; final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } @Test public void testExcelFormat2() throws Exception { final String code = "foo,baar\r\n\r\nhello,\r\n\r\nworld,\r\n"; final String[][] res = { { "foo", "baar" }, { "" }, { "hello", "" }, { "" }, { "world", "" } }; final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL); final List records = parser.getRecords(); assertEquals(res.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < res.length; i++) { assertArrayEquals(res[i], records.get(i).values()); } parser.close(); } /** * Tests an exported Excel worksheet with a header row and rows that have more columns than the headers */ @Test public void testExcelHeaderCountLessThanData() throws Exception { final String code = "A,B,C,,\r\na,b,c,d,e\r\n"; final CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL.withHeader()); try { for (final CSVRecord record : parser.getRecords()) { Assert.assertEquals("a", record.get("A")); Assert.assertEquals("b", record.get("B")); Assert.assertEquals("c", record.get("C")); } } finally { parser.close(); } } @Test public void testForEach() throws Exception { final List records = new ArrayList(); final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); for (final CSVRecord record : CSVFormat.DEFAULT.parse(in)) { records.add(record); } assertEquals(3, records.size()); assertArrayEquals(new String[] { "a", "b", "c" }, records.get(0).values()); assertArrayEquals(new String[] { "1", "2", "3" }, records.get(1).values()); assertArrayEquals(new String[] { "x", "y", "z" }, records.get(2).values()); } @Test public void testGetHeaderMap() throws Exception { final CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C")); final Map headerMap = parser.getHeaderMap(); final Iterator columnNames = headerMap.keySet().iterator(); // Headers are iterated in column order. Assert.assertEquals("A", columnNames.next()); Assert.assertEquals("B", columnNames.next()); Assert.assertEquals("C", columnNames.next()); final Iterator records = parser.iterator(); // Parse to make sure getHeaderMap did not have a side-effect. for (int i = 0; i < 3; i++) { assertTrue(records.hasNext()); final CSVRecord record = records.next(); assertEquals(record.get(0), record.get("A")); assertEquals(record.get(1), record.get("B")); assertEquals(record.get(2), record.get("C")); } assertFalse(records.hasNext()); parser.close(); } @Test(expected = IllegalArgumentException.class) public void testDuplicateHeaders() throws Exception { CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader(new String[] {})); } @Test public void testGetLine() throws IOException { final CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces()); for (final String[] re : RESULT) { assertArrayEquals(re, parser.nextRecord().values()); } assertNull(parser.nextRecord()); parser.close(); } @Test public void testGetLineNumberWithCR() throws Exception { this.validateLineNumbers(String.valueOf(CR)); } @Test public void testGetLineNumberWithCRLF() throws Exception { this.validateLineNumbers(CRLF); } @Test public void testGetLineNumberWithLF() throws Exception { this.validateLineNumbers(String.valueOf(LF)); } @Test public void testGetRecordPositionWithCRLF() throws Exception { this.validateRecordPosition(CRLF); } @Test public void testGetRecordPositionWithLF() throws Exception { this.validateRecordPosition(String.valueOf(LF)); } @Test public void testGetOneLine() throws IOException { final CSVParser parser = CSVParser.parse(CSV_INPUT_1, CSVFormat.DEFAULT); final CSVRecord record = parser.getRecords().get(0); assertArrayEquals(RESULT[0], record.values()); parser.close(); } /** * Tests reusing a parser to process new string records one at a time as they are being discovered. See [CSV-110]. * * @throws IOException */ @Test public void testGetOneLineOneParser() throws IOException { final PipedWriter writer = new PipedWriter(); final PipedReader reader = new PipedReader(writer); final CSVFormat format = CSVFormat.DEFAULT; final CSVParser parser = new CSVParser(reader, format); try { writer.append(CSV_INPUT_1); writer.append(format.getRecordSeparator()); final CSVRecord record1 = parser.nextRecord(); assertArrayEquals(RESULT[0], record1.values()); writer.append(CSV_INPUT_2); writer.append(format.getRecordSeparator()); final CSVRecord record2 = parser.nextRecord(); assertArrayEquals(RESULT[1], record2.values()); } finally { parser.close(); } } @Test public void testGetRecordNumberWithCR() throws Exception { this.validateRecordNumbers(String.valueOf(CR)); } @Test public void testGetRecordNumberWithCRLF() throws Exception { this.validateRecordNumbers(CRLF); } @Test public void testGetRecordNumberWithLF() throws Exception { this.validateRecordNumbers(String.valueOf(LF)); } @Test public void testGetRecords() throws IOException { final CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces()); final List records = parser.getRecords(); assertEquals(RESULT.length, records.size()); assertTrue(records.size() > 0); for (int i = 0; i < RESULT.length; i++) { assertArrayEquals(RESULT[i], records.get(i).values()); } parser.close(); } @Test public void testGetRecordWithMultiLineValues() throws Exception { final CSVParser parser = CSVParser.parse("\"a\r\n1\",\"a\r\n2\"" + CRLF + "\"b\r\n1\",\"b\r\n2\"" + CRLF + "\"c\r\n1\",\"c\r\n2\"", CSVFormat.DEFAULT.withRecordSeparator(CRLF)); CSVRecord record; assertEquals(0, parser.getRecordNumber()); assertEquals(0, parser.getCurrentLineNumber()); assertNotNull(record = parser.nextRecord()); assertEquals(3, parser.getCurrentLineNumber()); assertEquals(1, record.getRecordNumber()); assertEquals(1, parser.getRecordNumber()); assertNotNull(record = parser.nextRecord()); assertEquals(6, parser.getCurrentLineNumber()); assertEquals(2, record.getRecordNumber()); assertEquals(2, parser.getRecordNumber()); assertNotNull(record = parser.nextRecord()); assertEquals(8, parser.getCurrentLineNumber()); assertEquals(3, record.getRecordNumber()); assertEquals(3, parser.getRecordNumber()); assertNull(record = parser.nextRecord()); assertEquals(8, parser.getCurrentLineNumber()); assertEquals(3, parser.getRecordNumber()); parser.close(); } @Test public void testHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withHeader().parse(in).iterator(); for (int i = 0; i < 2; i++) { assertTrue(records.hasNext()); final CSVRecord record = records.next(); assertEquals(record.get(0), record.get("a")); assertEquals(record.get(1), record.get("b")); assertEquals(record.get(2), record.get("c")); } assertFalse(records.hasNext()); } @Test public void testHeaderMissing() throws Exception { final Reader in = new StringReader("a,,c\n1,2,3\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withHeader().parse(in).iterator(); for (int i = 0; i < 2; i++) { assertTrue(records.hasNext()); final CSVRecord record = records.next(); assertEquals(record.get(0), record.get("a")); assertEquals(record.get(2), record.get("c")); } assertFalse(records.hasNext()); } @Test(expected = IllegalArgumentException.class) public void testHeadersMissingException() throws Exception { final Reader in = new StringReader("a,,c,,d\n1,2,3,4\nx,y,z,zz"); CSVFormat.DEFAULT.withHeader().parse(in).iterator(); } @Test public void testHeadersMissing() throws Exception { final Reader in = new StringReader("a,,c,,d\n1,2,3,4\nx,y,z,zz"); CSVFormat.DEFAULT.withHeader().withAllowMissingColumnNames().parse(in).iterator(); } @Test public void testHeaderMissingWithNull() throws Exception { final Reader in = new StringReader("a,,c,,d\n1,2,3,4\nx,y,z,zz"); CSVFormat.DEFAULT.withHeader().withNullString("").withAllowMissingColumnNames().parse(in).iterator(); } @Test public void testHeaderComment() throws Exception { final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in).iterator(); for (int i = 0; i < 2; i++) { assertTrue(records.hasNext()); final CSVRecord record = records.next(); assertEquals(record.get(0), record.get("a")); assertEquals(record.get(1), record.get("b")); assertEquals(record.get(2), record.get("c")); } assertFalse(records.hasNext()); } @Test public void testIgnoreEmptyLines() throws IOException { final String code = "\nfoo,baar\n\r\n,\n\n,world\r\n\n"; // String code = "world\r\n\n"; // String code = "foo;baar\r\n\r\nhello;\r\n\r\nworld;\r\n"; final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT); final List records = parser.getRecords(); assertEquals(3, records.size()); parser.close(); } @Test(expected = IllegalArgumentException.class) public void testInvalidFormat() throws Exception { final CSVFormat invalidFormat = CSVFormat.DEFAULT.withDelimiter(CR); new CSVParser(null, invalidFormat).close(); } @Test public void testIterator() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); final Iterator iterator = CSVFormat.DEFAULT.parse(in).iterator(); assertTrue(iterator.hasNext()); try { iterator.remove(); fail("expected UnsupportedOperationException"); } catch (final UnsupportedOperationException expected) { // expected } assertArrayEquals(new String[] { "a", "b", "c" }, iterator.next().values()); assertArrayEquals(new String[] { "1", "2", "3" }, iterator.next().values()); assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); assertArrayEquals(new String[] { "x", "y", "z" }, iterator.next().values()); assertFalse(iterator.hasNext()); try { iterator.next(); fail("NoSuchElementException expected"); } catch (final NoSuchElementException e) { // expected } } @Test public void testLineFeedEndings() throws IOException { final String code = "foo\nbaar,\nhello,world\n,kanu"; final CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT); final List records = parser.getRecords(); assertEquals(4, records.size()); parser.close(); } @Test public void testMappedButNotSetAsOutlook2007ContactExport() throws Exception { final Reader in = new StringReader("a,b,c\n1,2\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withHeader("A", "B", "C").withSkipHeaderRecord() .parse(in).iterator(); CSVRecord record; // 1st record record = records.next(); assertTrue(record.isMapped("A")); assertTrue(record.isMapped("B")); assertTrue(record.isMapped("C")); assertTrue(record.isSet("A")); assertTrue(record.isSet("B")); assertFalse(record.isSet("C")); assertEquals("1", record.get("A")); assertEquals("2", record.get("B")); assertFalse(record.isConsistent()); // 2nd record record = records.next(); assertTrue(record.isMapped("A")); assertTrue(record.isMapped("B")); assertTrue(record.isMapped("C")); assertTrue(record.isSet("A")); assertTrue(record.isSet("B")); assertTrue(record.isSet("C")); assertEquals("x", record.get("A")); assertEquals("y", record.get("B")); assertEquals("z", record.get("C")); assertTrue(record.isConsistent()); assertFalse(records.hasNext()); } @Test // TODO this may lead to strange behavior, throw an exception if iterator() has already been called? public void testMultipleIterators() throws Exception { final CSVParser parser = CSVParser.parse("a,b,c" + CR + "d,e,f", CSVFormat.DEFAULT); final Iterator itr1 = parser.iterator(); final Iterator itr2 = parser.iterator(); final CSVRecord first = itr1.next(); assertEquals("a", first.get(0)); assertEquals("b", first.get(1)); assertEquals("c", first.get(2)); final CSVRecord second = itr2.next(); assertEquals("d", second.get(0)); assertEquals("e", second.get(1)); assertEquals("f", second.get(2)); parser.close(); } @Test(expected = IllegalArgumentException.class) public void testNewCSVParserNullReaderFormat() throws Exception { new CSVParser(null, CSVFormat.DEFAULT).close(); } @Test(expected = IllegalArgumentException.class) public void testNewCSVParserReaderNullFormat() throws Exception { new CSVParser(new StringReader(""), null).close(); } @Test public void testNoHeaderMap() throws Exception { final CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT); Assert.assertNull(parser.getHeaderMap()); parser.close(); } @Test(expected = IllegalArgumentException.class) public void testParseFileNullFormat() throws Exception { CSVParser.parse(new File(""), Charset.defaultCharset(), null); } @Test(expected = IllegalArgumentException.class) public void testParseNullFileFormat() throws Exception { CSVParser.parse((File) null, Charset.defaultCharset(), CSVFormat.DEFAULT); } @Test(expected = IllegalArgumentException.class) public void testParseNullStringFormat() throws Exception { CSVParser.parse((String) null, CSVFormat.DEFAULT); } @Test(expected = IllegalArgumentException.class) public void testParseNullUrlCharsetFormat() throws Exception { CSVParser.parse((File) null, Charset.defaultCharset(), CSVFormat.DEFAULT); } @Test(expected = IllegalArgumentException.class) public void testParserUrlNullCharsetFormat() throws Exception { final CSVParser parser = CSVParser.parse(new URL("http://commons.apache.org"), null, CSVFormat.DEFAULT); parser.close(); } @Test(expected = IllegalArgumentException.class) public void testParseStringNullFormat() throws Exception { CSVParser.parse("csv data", null); } @Test(expected = IllegalArgumentException.class) public void testParseUrlCharsetNullFormat() throws Exception { final CSVParser parser = CSVParser.parse(new URL("http://commons.apache.org"), Charset.defaultCharset(), null); parser.close(); } @Test public void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withHeader("A", "B", "C").parse(in).iterator(); for (int i = 0; i < 3; i++) { assertTrue(records.hasNext()); final CSVRecord record = records.next(); assertTrue(record.isMapped("A")); assertTrue(record.isMapped("B")); assertTrue(record.isMapped("C")); assertFalse(record.isMapped("NOT MAPPED")); assertEquals(record.get(0), record.get("A")); assertEquals(record.get(1), record.get("B")); assertEquals(record.get(2), record.get("C")); } assertFalse(records.hasNext()); } @Test public void testProvidedHeaderAuto() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withHeader().parse(in).iterator(); for (int i = 0; i < 2; i++) { assertTrue(records.hasNext()); final CSVRecord record = records.next(); assertTrue(record.isMapped("a")); assertTrue(record.isMapped("b")); assertTrue(record.isMapped("c")); assertFalse(record.isMapped("NOT MAPPED")); assertEquals(record.get(0), record.get("a")); assertEquals(record.get(1), record.get("b")); assertEquals(record.get(2), record.get("c")); } assertFalse(records.hasNext()); } @Test public void testRoundtrip() throws Exception { final StringWriter out = new StringWriter(); final CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT); final String input = "a,b,c\r\n1,2,3\r\nx,y,z\r\n"; for (final CSVRecord record : CSVParser.parse(input, CSVFormat.DEFAULT)) { printer.printRecord(record); } assertEquals(input, out.toString()); printer.close(); } @Test public void testSkipAutoHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withHeader().parse(in).iterator(); final CSVRecord record = records.next(); assertEquals("1", record.get("a")); assertEquals("2", record.get("b")); assertEquals("3", record.get("c")); } @Test public void testSkipSetHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); final Iterator records = CSVFormat.DEFAULT.withHeader("a", "b", "c").withSkipHeaderRecord() .parse(in).iterator(); final CSVRecord record = records.next(); assertEquals("1", record.get("a")); assertEquals("2", record.get("b")); assertEquals("3", record.get("c")); } private void validateLineNumbers(final String lineSeparator) throws IOException { final CSVParser parser = CSVParser.parse("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.DEFAULT.withRecordSeparator(lineSeparator)); assertEquals(0, parser.getCurrentLineNumber()); assertNotNull(parser.nextRecord()); assertEquals(1, parser.getCurrentLineNumber()); assertNotNull(parser.nextRecord()); assertEquals(2, parser.getCurrentLineNumber()); assertNotNull(parser.nextRecord()); // Still 2 because the last line is does not have EOL chars assertEquals(2, parser.getCurrentLineNumber()); assertNull(parser.nextRecord()); // Still 2 because the last line is does not have EOL chars assertEquals(2, parser.getCurrentLineNumber()); parser.close(); } private void validateRecordNumbers(final String lineSeparator) throws IOException { final CSVParser parser = CSVParser.parse("a" + lineSeparator + "b" + lineSeparator + "c", CSVFormat.DEFAULT.withRecordSeparator(lineSeparator)); CSVRecord record; assertEquals(0, parser.getRecordNumber()); assertNotNull(record = parser.nextRecord()); assertEquals(1, record.getRecordNumber()); assertEquals(1, parser.getRecordNumber()); assertNotNull(record = parser.nextRecord()); assertEquals(2, record.getRecordNumber()); assertEquals(2, parser.getRecordNumber()); assertNotNull(record = parser.nextRecord()); assertEquals(3, record.getRecordNumber()); assertEquals(3, parser.getRecordNumber()); assertNull(record = parser.nextRecord()); assertEquals(3, parser.getRecordNumber()); parser.close(); } private void validateRecordPosition(final String lineSeparator) throws IOException { final String nl = lineSeparator; // used as linebreak in values for better distinction final String code = "a,b,c" + lineSeparator + "1,2,3" + lineSeparator + // to see if recordPosition correctly points to the enclosing quote "'A" + nl + "A','B" + nl + "B',CC" + lineSeparator + // unicode test... not very relevant while operating on strings instead of bytes, but for // completeness... "\u00c4,\u00d6,\u00dc" + lineSeparator + "EOF,EOF,EOF"; final CSVFormat format = CSVFormat.newFormat(',').withQuote('\'').withRecordSeparator(lineSeparator); CSVParser parser = CSVParser.parse(code, format); CSVRecord record; assertEquals(0, parser.getRecordNumber()); assertNotNull(record = parser.nextRecord()); assertEquals(1, record.getRecordNumber()); assertEquals(code.indexOf('a'), record.getCharacterPosition()); assertNotNull(record = parser.nextRecord()); assertEquals(2, record.getRecordNumber()); assertEquals(code.indexOf('1'), record.getCharacterPosition()); assertNotNull(record = parser.nextRecord()); final long positionRecord3 = record.getCharacterPosition(); assertEquals(3, record.getRecordNumber()); assertEquals(code.indexOf("'A"), record.getCharacterPosition()); assertEquals("A" + lineSeparator + "A", record.get(0)); assertEquals("B" + lineSeparator + "B", record.get(1)); assertEquals("CC", record.get(2)); assertNotNull(record = parser.nextRecord()); assertEquals(4, record.getRecordNumber()); assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition()); assertNotNull(record = parser.nextRecord()); assertEquals(5, record.getRecordNumber()); assertEquals(code.indexOf("EOF"), record.getCharacterPosition()); parser.close(); // now try to read starting at record 3 parser = new CSVParser(new StringReader(code.substring((int) positionRecord3)), format, positionRecord3, 3); assertNotNull(record = parser.nextRecord()); assertEquals(3, record.getRecordNumber()); assertEquals(code.indexOf("'A"), record.getCharacterPosition()); assertEquals("A" + lineSeparator + "A", record.get(0)); assertEquals("B" + lineSeparator + "B", record.get(1)); assertEquals("CC", record.get(2)); assertNotNull(record = parser.nextRecord()); assertEquals(4, record.getRecordNumber()); assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition()); assertEquals("\u00c4", record.get(0)); parser.close(); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/CSVPrinterTest.java0100644 0000000 0000000 00000057225 12565700103 031724 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.CR; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Random; import org.junit.Test; /** * * * @version $Id: CSVPrinterTest.java 1695167 2015-08-10 21:08:58Z ggregory $ */ public class CSVPrinterTest { private final String recordSeparator = CSVFormat.DEFAULT.getRecordSeparator(); private static String printable(final String s) { final StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { final char ch = s.charAt(i); if (ch <= ' ' || ch >= 128) { sb.append("(").append((int) ch).append(")"); } else { sb.append(ch); } } return sb.toString(); } private void doOneRandom(final CSVFormat format) throws Exception { final Random r = new Random(); final int nLines = r.nextInt(4) + 1; final int nCol = r.nextInt(3) + 1; // nLines=1;nCol=2; final String[][] lines = new String[nLines][]; for (int i = 0; i < nLines; i++) { final String[] line = new String[nCol]; lines[i] = line; for (int j = 0; j < nCol; j++) { line[j] = randStr(); } } final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, format); for (int i = 0; i < nLines; i++) { // for (int j=0; j parseResult = parser.getRecords(); Utils.compare("Printer output :" + printable(result), lines, parseResult); parser.close(); } private void doRandom(final CSVFormat format, final int iter) throws Exception { for (int i = 0; i < iter; i++) { doOneRandom(format); } } private String randStr() { final Random r = new Random(); final int sz = r.nextInt(20); // sz = r.nextInt(3); final char[] buf = new char[sz]; for (int i = 0; i < sz; i++) { // stick in special chars with greater frequency char ch; final int what = r.nextInt(20); switch (what) { case 0: ch = '\r'; break; case 1: ch = '\n'; break; case 2: ch = '\t'; break; case 3: ch = '\f'; break; case 4: ch = ' '; break; case 5: ch = ','; break; case 6: ch = '"'; break; case 7: ch = '\''; break; case 8: ch = '\\'; break; default: ch = (char) r.nextInt(300); break; // default: ch = 'a'; break; } buf[i] = ch; } return new String(buf); } @Test public void testDisabledComment() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printComment("This is a comment"); assertEquals("", sw.toString()); printer.close(); } @Test public void testExcelPrintAllArrayOfArrays() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL); printer.printRecords((Object[]) new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } }); assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString()); printer.close(); } @Test public void testExcelPrintAllArrayOfLists() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL); printer.printRecords((Object[]) new List[] { Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2") }); assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString()); printer.close(); } @Test public void testExcelPrintAllIterableOfArrays() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL); printer.printRecords(Arrays.asList(new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } })); assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString()); printer.close(); } @Test public void testExcelPrintAllIterableOfLists() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL); printer.printRecords(Arrays.asList(new List[] { Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2") })); assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString()); printer.close(); } @Test public void testExcelPrinter1() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL); printer.printRecord("a", "b"); assertEquals("a,b" + recordSeparator, sw.toString()); printer.close(); } @Test public void testExcelPrinter2() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL); printer.printRecord("a,b", "b"); assertEquals("\"a,b\",b" + recordSeparator, sw.toString()); printer.close(); } private Connection geH2Connection() throws SQLException, ClassNotFoundException { Class.forName("org.h2.Driver"); return DriverManager.getConnection("jdbc:h2:mem:my_test;", "sa", ""); } @Test public void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); final Connection connection = geH2Connection(); try { setUpTable(connection); final Statement stmt = connection.createStatement(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecords(stmt.executeQuery("select ID, NAME from TEST")); assertEquals("1,r1" + recordSeparator + "2,r2" + recordSeparator, sw.toString()); printer.close(); } finally { connection.close(); } } @Test public void testJdbcPrinterWithResultSet() throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); Class.forName("org.h2.Driver"); final Connection connection = geH2Connection(); try { setUpTable(connection); @SuppressWarnings("resource") // Closed when the connection is closed. final Statement stmt = connection.createStatement(); @SuppressWarnings("resource") // Closed when the connection is closed. final ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST"); final CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet).print(sw); printer.printRecords(resultSet); assertEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator, sw.toString()); printer.close(); } finally { connection.close(); } } @Test public void testJdbcPrinterWithResultSetMetaData() throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); Class.forName("org.h2.Driver"); final Connection connection = geH2Connection(); try { setUpTable(connection); @SuppressWarnings("resource") // Closed when the connection is closed. final Statement stmt = connection.createStatement(); @SuppressWarnings("resource") // Closed when the connection is closed. final ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST"); final CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet.getMetaData()).print(sw); printer.printRecords(resultSet); assertEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator, sw.toString()); printer.close(); } finally { connection.close(); } } private void setUpTable(final Connection connection) throws SQLException { final Statement statement = connection.createStatement(); try { statement.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))"); statement.execute("insert into TEST values(1, 'r1')"); statement.execute("insert into TEST values(2, 'r2')"); } finally { statement.close(); } } @Test public void testMultiLineComment() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#')); printer.printComment("This is a comment\non multiple lines"); assertEquals("# This is a comment" + recordSeparator + "# on multiple lines" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrinter1() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a", "b"); assertEquals("a,b" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrinter2() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a,b", "b"); assertEquals("\"a,b\",b" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrinter3() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a, b", "b "); assertEquals("\"a, b\",\"b \"" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrinter4() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a", "b\"c"); assertEquals("a,\"b\"\"c\"" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrinter5() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a", "b\nc"); assertEquals("a,\"b\nc\"" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrinter6() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a", "b\r\nc"); assertEquals("a,\"b\r\nc\"" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrinter7() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a", "b\\c"); assertEquals("a,b\\c" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrint() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = CSVFormat.DEFAULT.print(sw); printer.printRecord("a", "b\\c"); assertEquals("a,b\\c" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrintNullValues() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT); printer.printRecord("a", null, "b"); assertEquals("a,,b" + recordSeparator, sw.toString()); printer.close(); } @Test public void testPrintCustomNullValues() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withNullString("NULL")); printer.printRecord("a", null, "b"); assertEquals("a,NULL,b" + recordSeparator, sw.toString()); printer.close(); } @Test public void testParseCustomNullValues() throws IOException { final StringWriter sw = new StringWriter(); final CSVFormat format = CSVFormat.DEFAULT.withNullString("NULL"); final CSVPrinter printer = new CSVPrinter(sw, format); printer.printRecord("a", null, "b"); printer.close(); final String csvString = sw.toString(); assertEquals("a,NULL,b" + recordSeparator, csvString); final Iterable iterable = format.parse(new StringReader(csvString)); final Iterator iterator = iterable.iterator(); final CSVRecord record = iterator.next(); assertEquals("a", record.get(0)); assertEquals(null, record.get(1)); assertEquals("b", record.get(2)); assertFalse(iterator.hasNext()); ((CSVParser) iterable).close(); } @Test public void testQuoteAll() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL)); printer.printRecord("a", "b\nc", "d"); assertEquals("\"a\",\"b\nc\",\"d\"" + recordSeparator, sw.toString()); printer.close(); } @Test public void testQuoteNonNumeric() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.NON_NUMERIC)); printer.printRecord("a", "b\nc", Integer.valueOf(1)); assertEquals("\"a\",\"b\nc\",1" + recordSeparator, sw.toString()); printer.close(); } @Test public void testRandom() throws Exception { final int iter = 10000; doRandom(CSVFormat.DEFAULT, iter); doRandom(CSVFormat.EXCEL, iter); doRandom(CSVFormat.MYSQL, iter); } @Test public void testPlainQuoted() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\'')); printer.print("abc"); assertEquals("abc", sw.toString()); printer.close(); } @Test public void testSingleLineComment() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#')); printer.printComment("This is a comment"); assertEquals("# This is a comment" + recordSeparator, sw.toString()); printer.close(); } @Test public void testSingleQuoteQuoted() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\'')); printer.print("a'b'c"); printer.print("xyz"); assertEquals("'a''b''c',xyz", sw.toString()); printer.close(); } @Test public void testDelimeterQuoted() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\'')); printer.print("a,b,c"); printer.print("xyz"); assertEquals("'a,b,c',xyz", sw.toString()); printer.close(); } @Test public void testDelimeterQuoteNONE() throws IOException { final StringWriter sw = new StringWriter(); final CSVFormat format = CSVFormat.DEFAULT.withEscape('!').withQuoteMode(QuoteMode.NONE); final CSVPrinter printer = new CSVPrinter(sw, format); printer.print("a,b,c"); printer.print("xyz"); assertEquals("a!,b!,c,xyz", sw.toString()); printer.close(); } @Test public void testEOLQuoted() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\'')); printer.print("a\rb\nc"); printer.print("x\by\fz"); assertEquals("'a\rb\nc',x\by\fz", sw.toString()); printer.close(); } @Test public void testPlainEscaped() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!')); printer.print("abc"); printer.print("xyz"); assertEquals("abc,xyz", sw.toString()); printer.close(); } @Test public void testDelimiterEscaped() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null)); printer.print("a,b,c"); printer.print("xyz"); assertEquals("a!,b!,c,xyz", sw.toString()); printer.close(); } @Test public void testEOLEscaped() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!')); printer.print("a\rb\nc"); printer.print("x\fy\bz"); assertEquals("a!rb!nc,x\fy\bz", sw.toString()); printer.close(); } @Test public void testPlainPlain() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null)); printer.print("abc"); printer.print("xyz"); assertEquals("abc,xyz", sw.toString()); printer.close(); } @Test public void testDelimiterPlain() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null)); printer.print("a,b,c"); printer.print("xyz"); assertEquals("a,b,c,xyz", sw.toString()); printer.close(); } @Test public void testHeader() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null) .withHeader("C1", "C2", "C3")); printer.printRecord("a", "b", "c"); printer.printRecord("x", "y", "z"); assertEquals("C1,C2,C3\r\na,b,c\r\nx,y,z\r\n", sw.toString()); printer.close(); } @Test public void testHeaderCommentExcel() throws IOException { final StringWriter sw = new StringWriter(); final Date now = new Date(); final CSVFormat format = CSVFormat.EXCEL; final CSVPrinter csvPrinter = printWithHeaderComments(sw, now, format); assertEquals("# Generated by Apache Commons CSV 1.1\r\n# " + now + "\r\nCol1,Col2\r\nA,B\r\nC,D\r\n", sw.toString()); csvPrinter.close(); } @Test public void testHeaderCommentTdf() throws IOException { final StringWriter sw = new StringWriter(); final Date now = new Date(); final CSVFormat format = CSVFormat.TDF; final CSVPrinter csvPrinter = printWithHeaderComments(sw, now, format); assertEquals("# Generated by Apache Commons CSV 1.1\r\n# " + now + "\r\nCol1\tCol2\r\nA\tB\r\nC\tD\r\n", sw.toString()); csvPrinter.close(); } private CSVPrinter printWithHeaderComments(final StringWriter sw, final Date now, final CSVFormat baseFormat) throws IOException { CSVFormat format = baseFormat; // Use withHeaderComments first to test CSV-145 format = format.withHeaderComments("Generated by Apache Commons CSV 1.1", now); format = format.withCommentMarker('#'); format = format.withHeader("Col1", "Col2"); final CSVPrinter csvPrinter = format.print(sw); csvPrinter.printRecord("A", "B"); csvPrinter.printRecord("C", "D"); csvPrinter.close(); return csvPrinter; } @Test public void testEOLPlain() throws IOException { final StringWriter sw = new StringWriter(); final CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null)); printer.print("a\rb\nc"); printer.print("x\fy\bz"); assertEquals("a\rb\nc,x\fy\bz", sw.toString()); printer.close(); } @Test(expected = IllegalArgumentException.class) public void testInvalidFormat() throws Exception { final CSVFormat invalidFormat = CSVFormat.DEFAULT.withDelimiter(CR); new CSVPrinter(new StringWriter(), invalidFormat).close(); } @Test(expected = IllegalArgumentException.class) public void testNewCSVPrinterNullAppendableFormat() throws Exception { new CSVPrinter(null, CSVFormat.DEFAULT).close(); } @Test(expected = IllegalArgumentException.class) public void testNewCsvPrinterAppendableNullFormat() throws Exception { new CSVPrinter(new StringWriter(), null).close(); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/CSVRecordTest.java0100644 0000000 0000000 00000015316 12565700104 031513 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class CSVRecordTest { private enum EnumFixture { UNKNOWN_COLUMN } private String[] values; private CSVRecord record, recordWithHeader; private Map header; @Before public void setUp() throws Exception { values = new String[] { "A", "B", "C" }; record = new CSVRecord(values, null, null, 0, -1); header = new HashMap(); header.put("first", Integer.valueOf(0)); header.put("second", Integer.valueOf(1)); header.put("third", Integer.valueOf(2)); recordWithHeader = new CSVRecord(values, header, null, 0, -1); } @Test public void testGetInt() { assertEquals(values[0], record.get(0)); assertEquals(values[1], record.get(1)); assertEquals(values[2], record.get(2)); } @Test public void testGetString() { assertEquals(values[0], recordWithHeader.get("first")); assertEquals(values[1], recordWithHeader.get("second")); assertEquals(values[2], recordWithHeader.get("third")); } @Test(expected = IllegalArgumentException.class) public void testGetStringInconsistentRecord() { header.put("fourth", Integer.valueOf(4)); recordWithHeader.get("fourth"); } @Test(expected = IllegalStateException.class) public void testGetStringNoHeader() { record.get("first"); } @Test(expected = IllegalArgumentException.class) public void testGetUnmappedEnum() { assertNull(recordWithHeader.get(EnumFixture.UNKNOWN_COLUMN)); } @Test(expected = IllegalArgumentException.class) public void testGetUnmappedName() { assertNull(recordWithHeader.get("fourth")); } @Test(expected = ArrayIndexOutOfBoundsException.class) public void testGetUnmappedNegativeInt() { assertNull(recordWithHeader.get(Integer.MIN_VALUE)); } @Test(expected = ArrayIndexOutOfBoundsException.class) public void testGetUnmappedPositiveInt() { assertNull(recordWithHeader.get(Integer.MAX_VALUE)); } @Test public void testIsConsistent() { assertTrue(record.isConsistent()); assertTrue(recordWithHeader.isConsistent()); header.put("fourth", Integer.valueOf(4)); assertFalse(recordWithHeader.isConsistent()); } @Test public void testIsMapped() { assertFalse(record.isMapped("first")); assertTrue(recordWithHeader.isMapped("first")); assertFalse(recordWithHeader.isMapped("fourth")); } @Test public void testIsSet() { assertFalse(record.isSet("first")); assertTrue(recordWithHeader.isSet("first")); assertFalse(recordWithHeader.isSet("fourth")); } @Test public void testIterator() { int i = 0; for (final String value : record) { assertEquals(values[i], value); i++; } } @Test public void testPutInMap() { final Map map = new ConcurrentHashMap(); this.recordWithHeader.putIn(map); this.validateMap(map, false); // Test that we can compile with assigment to the same map as the param. final TreeMap map2 = recordWithHeader.putIn(new TreeMap()); this.validateMap(map2, false); } @Test public void testRemoveAndAddColumns() throws IOException { // do: final CSVPrinter printer = new CSVPrinter(new StringBuilder(), CSVFormat.DEFAULT); final Map map = recordWithHeader.toMap(); map.remove("OldColumn"); map.put("ZColumn", "NewValue"); // check: final ArrayList list = new ArrayList(map.values()); Collections.sort(list); printer.printRecord(list); Assert.assertEquals("A,B,C,NewValue" + CSVFormat.DEFAULT.getRecordSeparator(), printer.getOut().toString()); printer.close(); } @Test public void testToMap() { final Map map = this.recordWithHeader.toMap(); this.validateMap(map, true); } @Test public void testToMapWithShortRecord() throws Exception { final CSVParser parser = CSVParser.parse("a,b", CSVFormat.DEFAULT.withHeader("A", "B", "C")); final CSVRecord shortRec = parser.iterator().next(); shortRec.toMap(); } @Test public void testToMapWithNoHeader() throws Exception { final CSVParser parser = CSVParser.parse("a,b", CSVFormat.newFormat(',')); final CSVRecord shortRec = parser.iterator().next(); final Map map = shortRec.toMap(); assertNotNull("Map is not null.", map); assertTrue("Map is empty.", map.isEmpty()); } private void validateMap(final Map map, final boolean allowsNulls) { assertTrue(map.containsKey("first")); assertTrue(map.containsKey("second")); assertTrue(map.containsKey("third")); assertFalse(map.containsKey("fourth")); if (allowsNulls) { assertFalse(map.containsKey(null)); } assertEquals("A", map.get("first")); assertEquals("B", map.get("second")); assertEquals("C", map.get("third")); assertEquals(null, map.get("fourth")); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java0100644 0000000 0000000 00000017666 12565700104 034261 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.END_OF_STREAM; import static org.apache.commons.csv.Constants.UNDEFINED; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.io.StringReader; import org.junit.Test; /** * * * @version $Id: ExtendedBufferedReaderTest.java 1582813 2014-03-28 16:37:54Z sebb $ */ public class ExtendedBufferedReaderTest { @Test public void testEmptyInput() throws Exception { final ExtendedBufferedReader br = getBufferedReader(""); assertEquals(END_OF_STREAM, br.read()); assertEquals(END_OF_STREAM, br.lookAhead()); assertEquals(END_OF_STREAM, br.getLastChar()); assertNull(br.readLine()); assertEquals(0, br.read(new char[10], 0, 0)); br.close(); } @Test public void testReadLookahead1() throws Exception { final ExtendedBufferedReader br = getBufferedReader("1\n2\r3\n"); assertEquals(0, br.getCurrentLineNumber()); assertEquals('1', br.lookAhead()); assertEquals(UNDEFINED, br.getLastChar()); assertEquals(0, br.getCurrentLineNumber()); assertEquals('1', br.read()); // Start line 1 assertEquals('1', br.getLastChar()); assertEquals(1, br.getCurrentLineNumber()); assertEquals('\n', br.lookAhead()); assertEquals(1, br.getCurrentLineNumber()); assertEquals('1', br.getLastChar()); assertEquals('\n', br.read()); assertEquals(1, br.getCurrentLineNumber()); assertEquals('\n', br.getLastChar()); assertEquals(1, br.getCurrentLineNumber()); assertEquals('2', br.lookAhead()); assertEquals(1, br.getCurrentLineNumber()); assertEquals('\n', br.getLastChar()); assertEquals(1, br.getCurrentLineNumber()); assertEquals('2', br.read()); // Start line 2 assertEquals(2, br.getCurrentLineNumber()); assertEquals('2', br.getLastChar()); assertEquals('\r', br.lookAhead()); assertEquals(2, br.getCurrentLineNumber()); assertEquals('2', br.getLastChar()); assertEquals('\r', br.read()); assertEquals('\r', br.getLastChar()); assertEquals(2, br.getCurrentLineNumber()); assertEquals('3', br.lookAhead()); assertEquals('\r', br.getLastChar()); assertEquals('3', br.read()); // Start line 3 assertEquals('3', br.getLastChar()); assertEquals(3, br.getCurrentLineNumber()); assertEquals('\n', br.lookAhead()); assertEquals(3, br.getCurrentLineNumber()); assertEquals('3', br.getLastChar()); assertEquals('\n', br.read()); assertEquals(3, br.getCurrentLineNumber()); assertEquals('\n', br.getLastChar()); assertEquals(3, br.getCurrentLineNumber()); assertEquals(END_OF_STREAM, br.lookAhead()); assertEquals('\n', br.getLastChar()); assertEquals(END_OF_STREAM, br.read()); assertEquals(END_OF_STREAM, br.getLastChar()); assertEquals(END_OF_STREAM, br.read()); assertEquals(END_OF_STREAM, br.lookAhead()); assertEquals(3, br.getCurrentLineNumber()); br.close(); } @Test public void testReadLookahead2() throws Exception { final char[] ref = new char[5]; final char[] res = new char[5]; final ExtendedBufferedReader br = getBufferedReader("abcdefg"); ref[0] = 'a'; ref[1] = 'b'; ref[2] = 'c'; assertEquals(3, br.read(res, 0, 3)); assertArrayEquals(ref, res); assertEquals('c', br.getLastChar()); assertEquals('d', br.lookAhead()); ref[4] = 'd'; assertEquals(1, br.read(res, 4, 1)); assertArrayEquals(ref, res); assertEquals('d', br.getLastChar()); br.close(); } @Test public void testReadLine() throws Exception { ExtendedBufferedReader br = getBufferedReader(""); assertNull(br.readLine()); br.close(); br = getBufferedReader("\n"); assertEquals("",br.readLine()); assertNull(br.readLine()); br.close(); br = getBufferedReader("foo\n\nhello"); assertEquals(0, br.getCurrentLineNumber()); assertEquals("foo",br.readLine()); assertEquals(1, br.getCurrentLineNumber()); assertEquals("",br.readLine()); assertEquals(2, br.getCurrentLineNumber()); assertEquals("hello",br.readLine()); assertEquals(3, br.getCurrentLineNumber()); assertNull(br.readLine()); assertEquals(3, br.getCurrentLineNumber()); br.close(); br = getBufferedReader("foo\n\nhello"); assertEquals('f', br.read()); assertEquals('o', br.lookAhead()); assertEquals("oo",br.readLine()); assertEquals(1, br.getCurrentLineNumber()); assertEquals('\n', br.lookAhead()); assertEquals("",br.readLine()); assertEquals(2, br.getCurrentLineNumber()); assertEquals('h', br.lookAhead()); assertEquals("hello",br.readLine()); assertNull(br.readLine()); assertEquals(3, br.getCurrentLineNumber()); br.close(); br = getBufferedReader("foo\rbaar\r\nfoo"); assertEquals("foo",br.readLine()); assertEquals('b', br.lookAhead()); assertEquals("baar",br.readLine()); assertEquals('f', br.lookAhead()); assertEquals("foo",br.readLine()); assertNull(br.readLine()); br.close(); } /* * Test to illustrate https://issues.apache.org/jira/browse/CSV-75 * */ @Test public void testReadChar() throws Exception { final String LF="\n"; final String CR="\r"; final String CRLF=CR+LF; final String LFCR=LF+CR;// easier to read the string below final String test="a" + LF + "b" + CR + "c" + LF + LF + "d" + CR + CR + "e" + LFCR + "f "+ CRLF; // EOL eol EOL EOL eol eol EOL+CR EOL final int EOLeolct = 9; ExtendedBufferedReader br; br = getBufferedReader(test); assertEquals(0, br.getCurrentLineNumber()); while (br.readLine() != null) { // consume all } assertEquals(EOLeolct, br.getCurrentLineNumber()); br.close(); br = getBufferedReader(test); assertEquals(0, br.getCurrentLineNumber()); while (br.read() != -1) { // consume all } assertEquals(EOLeolct, br.getCurrentLineNumber()); br.close(); br = getBufferedReader(test); assertEquals(0, br.getCurrentLineNumber()); final char[] buff = new char[10]; while (br.read(buff, 0, 3) != -1) { // consume all } assertEquals(EOLeolct, br.getCurrentLineNumber()); br.close(); } private ExtendedBufferedReader getBufferedReader(final String s) { return new ExtendedBufferedReader(new StringReader(s)); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/FercGovTest.java0100644 0000000 0000000 00000010476 12565700104 031256 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import java.io.IOException; import java.net.URL; import java.nio.charset.Charset; import java.util.List; import org.junit.Assert; import org.junit.Test; /** * Real world examples from http://www.ferc.gov/docs-filing/eqr/soft-tools/sample-csv.asp */ public class FercGovTest { private enum ContractColumnNames { contract_id, seller_company_name, customer_company_name, customer_duns_number, contract_affiliate, FERC_tariff_reference, contract_service_agreement_id, contract_execution_date, contract_commencement_date, contract_termination_date, actual_termination_date, extension_provision_description, class_name, term_name, increment_name, increment_peaking_name, product_type_name, product_name, quantity, units_for_contract, rate, rate_minimum, rate_maximum, rate_description, units_for_rate, point_of_receipt_control_area, point_of_receipt_specific_location, point_of_delivery_control_area, point_of_delivery_specific_location, begin_date, end_date, time_zone; } private static final Charset US_ASCII = Charset.forName("US-ASCII"); @Test public void testContractFile() throws IOException { final URL contractData = ClassLoader.getSystemClassLoader().getResource("ferc.gov/contract.txt"); final CSVParser parser = CSVParser.parse(contractData, US_ASCII, CSVFormat.DEFAULT.withHeader()); try { final List records = parser.getRecords(); CSVRecord record = records.get(0); Assert.assertEquals(22, records.size()); // first record Assert.assertEquals("C71", record.get(ContractColumnNames.contract_id)); Assert.assertEquals("The Electric Company", record.get(ContractColumnNames.seller_company_name)); Assert.assertEquals("ES", record.get(ContractColumnNames.time_zone)); // last record record = records.get(records.size() - 1); // first record Assert.assertEquals("C78", record.get(ContractColumnNames.contract_id)); Assert.assertEquals("The Electric Company", record.get(ContractColumnNames.seller_company_name)); Assert.assertEquals("EP", record.get(ContractColumnNames.time_zone)); } finally { parser.close(); } } @Test public void testTransactionFile() throws IOException { final URL transactionData = ClassLoader.getSystemClassLoader().getResource("ferc.gov/transaction.txt"); final CSVParser parser = CSVParser.parse(transactionData, US_ASCII, CSVFormat.DEFAULT.withHeader()); try { final List records = parser.getRecords(); Assert.assertEquals(24, records.size()); CSVRecord record = records.get(0); // first record Assert.assertEquals("T1", record.get("transaction_unique_identifier")); Assert.assertEquals("The Electric Company", record.get("seller_company_name")); Assert.assertEquals("880386", record.get("transaction_charge")); // last record record = records.get(records.size() - 1); Assert.assertEquals("T15", record.get("transaction_unique_identifier")); Assert.assertEquals("The Electric Company", record.get("seller_company_name")); Assert.assertEquals("1800", record.get("transaction_charge")); } finally { parser.close(); } } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/LexerTest.java0100644 0000000 0000000 00000046330 12565700104 031000 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.Constants.BACKSPACE; import static org.apache.commons.csv.Constants.CR; import static org.apache.commons.csv.Constants.FF; import static org.apache.commons.csv.Constants.LF; import static org.apache.commons.csv.Constants.TAB; import static org.apache.commons.csv.Token.Type.COMMENT; import static org.apache.commons.csv.Token.Type.EOF; import static org.apache.commons.csv.Token.Type.EORECORD; import static org.apache.commons.csv.Token.Type.TOKEN; import static org.apache.commons.csv.TokenMatchers.hasContent; import static org.apache.commons.csv.TokenMatchers.matches; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.io.StringReader; import org.junit.Before; import org.junit.Test; /** * * * @version $Id: LexerTest.java 1621004 2014-08-28 00:28:02Z ggregory $ */ public class LexerTest { private CSVFormat formatWithEscaping; @Before public void setUp() { formatWithEscaping = CSVFormat.DEFAULT.withEscape('\\'); } private Lexer getLexer(final String input, final CSVFormat format) { return new Lexer(format, new ExtendedBufferedReader(new StringReader(input))); } @Test public void testSurroundingSpacesAreDeleted() throws IOException { final String code = "noSpaces, leadingSpaces,trailingSpaces , surroundingSpaces , ,,"; final Lexer parser = getLexer(code, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces()); assertThat(parser.nextToken(new Token()), matches(TOKEN, "noSpaces")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "leadingSpaces")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "trailingSpaces")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "surroundingSpaces")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); } @Test public void testSurroundingTabsAreDeleted() throws IOException { final String code = "noTabs,\tleadingTab,trailingTab\t,\tsurroundingTabs\t,\t\t,,"; final Lexer parser = getLexer(code, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces()); assertThat(parser.nextToken(new Token()), matches(TOKEN, "noTabs")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "leadingTab")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "trailingTab")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "surroundingTabs")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); } @Test public void testIgnoreEmptyLines() throws IOException { final String code = "first,line,\n"+ "\n"+ "\n"+ "second,line\n"+ "\n"+ "\n"+ "third line \n"+ "\n"+ "\n"+ "last, line \n"+ "\n"+ "\n"+ "\n"; final CSVFormat format = CSVFormat.DEFAULT.withIgnoreEmptyLines(); final Lexer parser = getLexer(code, format); assertThat(parser.nextToken(new Token()), matches(TOKEN, "first")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "line")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "second")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "line")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "third line ")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "last")); assertThat(parser.nextToken(new Token()), matches(EORECORD, " line ")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); } @Test public void testComments() throws IOException { final String code = "first,line,\n"+ "second,line,tokenWith#no-comment\n"+ "# comment line \n"+ "third,line,#no-comment\n"+ "# penultimate comment\n"+ "# Final comment\n"; final CSVFormat format = CSVFormat.DEFAULT.withCommentMarker('#'); final Lexer parser = getLexer(code, format); assertThat(parser.nextToken(new Token()), matches(TOKEN, "first")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "line")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "second")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "line")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "tokenWith#no-comment")); assertThat(parser.nextToken(new Token()), matches(COMMENT, "comment line")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "third")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "line")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "#no-comment")); assertThat(parser.nextToken(new Token()), matches(COMMENT, "penultimate comment")); assertThat(parser.nextToken(new Token()), matches(COMMENT, "Final comment")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); } @Test public void testCommentsAndEmptyLines() throws IOException { final String code = "1,2,3,\n"+ // 1 "\n"+ // 1b "\n"+ // 1c "a,b x,c#no-comment\n"+ // 2 "#foo\n"+ // 3 "\n"+ // 4 "\n"+ // 4b "d,e,#no-comment\n"+ // 5 "\n"+ // 5b "\n"+ // 5c "# penultimate comment\n"+ // 6 "\n"+ // 6b "\n"+ // 6c "# Final comment\n"; // 7 final CSVFormat format = CSVFormat.DEFAULT.withCommentMarker('#').withIgnoreEmptyLines(false); assertFalse("Should not ignore empty lines", format.getIgnoreEmptyLines()); final Lexer parser = getLexer(code, format); assertThat(parser.nextToken(new Token()), matches(TOKEN, "1")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "2")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "3")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 1 assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 1b assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 1c assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "b x")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "c#no-comment")); // 2 assertThat(parser.nextToken(new Token()), matches(COMMENT, "foo")); // 3 assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 4 assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 4b assertThat(parser.nextToken(new Token()), matches(TOKEN, "d")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "e")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "#no-comment")); // 5 assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 5b assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 5c assertThat(parser.nextToken(new Token()), matches(COMMENT, "penultimate comment")); // 6 assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 6b assertThat(parser.nextToken(new Token()), matches(EORECORD, "")); // 6c assertThat(parser.nextToken(new Token()), matches(COMMENT, "Final comment")); // 7 assertThat(parser.nextToken(new Token()), matches(EOF, "")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); } // simple token with escaping not enabled @Test public void testBackslashWithoutEscaping() throws IOException { /* file: a,\,,b * \,, */ final String code = "a,\\,,b\\\n\\,,"; final CSVFormat format = CSVFormat.DEFAULT; assertFalse(format.isEscapeCharacterSet()); final Lexer parser = getLexer(code, format); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); // an unquoted single backslash is not an escape char assertThat(parser.nextToken(new Token()), matches(TOKEN, "\\")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "b\\")); // an unquoted single backslash is not an escape char assertThat(parser.nextToken(new Token()), matches(TOKEN, "\\")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "")); assertThat(parser.nextToken(new Token()), matches(EOF, "")); } // simple token with escaping enabled @Test public void testBackslashWithEscaping() throws IOException { /* file: a,\,,b * \,, */ final String code = "a,\\,,b\\\\\n\\,,\\\nc,d\\\r\ne"; final CSVFormat format = formatWithEscaping.withIgnoreEmptyLines(false); assertTrue(format.isEscapeCharacterSet()); final Lexer parser = getLexer(code, format); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(TOKEN, ",")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "b\\")); assertThat(parser.nextToken(new Token()), matches(TOKEN, ",")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "\nc")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "d\r")); assertThat(parser.nextToken(new Token()), matches(EOF, "e")); } // encapsulator tokenizer (single line) @Test public void testNextToken4() throws IOException { /* file: a,"foo",b * a, " foo",b * a,"foo " ,b // whitespace after closing encapsulator * a, " foo " ,b */ final String code = "a,\"foo\",b\na, \" foo\",b\na,\"foo \" ,b\na, \" foo \" ,b"; final Lexer parser = getLexer(code, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces()); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "foo")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "b")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(TOKEN, " foo")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "b")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "foo ")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "b")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(TOKEN, " foo ")); // assertTokenEquals(EORECORD, "b", parser.nextToken(new Token())); assertThat(parser.nextToken(new Token()), matches(EOF, "b")); } // encapsulator tokenizer (multi line, delimiter in string) @Test public void testNextToken5() throws IOException { final String code = "a,\"foo\n\",b\n\"foo\n baar ,,,\"\n\"\n\t \n\""; final Lexer parser = getLexer(code, CSVFormat.DEFAULT); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "foo\n")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "b")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "foo\n baar ,,,")); assertThat(parser.nextToken(new Token()), matches(EOF, "\n\t \n")); } // change delimiters, comment, encapsulater @Test public void testNextToken6() throws IOException { /* file: a;'b and \' more * ' * !comment;;;; * ;; */ final String code = "a;'b and '' more\n'\n!comment;;;;\n;;"; final CSVFormat format = CSVFormat.DEFAULT.withQuote('\'').withCommentMarker('!').withDelimiter(';'); final Lexer parser = getLexer(code, format); assertThat(parser.nextToken(new Token()), matches(TOKEN, "a")); assertThat(parser.nextToken(new Token()), matches(EORECORD, "b and ' more\n")); } // From CSV-1 @Test public void testDelimiterIsWhitespace() throws IOException { final String code = "one\ttwo\t\tfour \t five\t six"; final Lexer parser = getLexer(code, CSVFormat.TDF); assertThat(parser.nextToken(new Token()), matches(TOKEN, "one")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "two")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "four")); assertThat(parser.nextToken(new Token()), matches(TOKEN, "five")); assertThat(parser.nextToken(new Token()), matches(EOF, "six")); } @Test public void testEscapedCR() throws Exception { final Lexer lexer = getLexer("character\\" + CR + "Escaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + CR + "Escaped")); } @Test public void testCR() throws Exception { final Lexer lexer = getLexer("character" + CR + "NotEscaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character")); assertThat(lexer.nextToken(new Token()), hasContent("NotEscaped")); } @Test public void testEscapedLF() throws Exception { final Lexer lexer = getLexer("character\\" + LF + "Escaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + LF + "Escaped")); } @Test public void testLF() throws Exception { final Lexer lexer = getLexer("character" + LF + "NotEscaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character")); assertThat(lexer.nextToken(new Token()), hasContent("NotEscaped")); } @Test // TODO is this correct? Do we expect TAB to be unescaped? public void testEscapedTab() throws Exception { final Lexer lexer = getLexer("character\\" + TAB + "Escaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + TAB + "Escaped")); } @Test public void testTab() throws Exception { final Lexer lexer = getLexer("character" + TAB + "NotEscaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + TAB + "NotEscaped")); } @Test // TODO is this correct? Do we expect BACKSPACE to be unescaped? public void testEscapedBackspace() throws Exception { final Lexer lexer = getLexer("character\\" + BACKSPACE + "Escaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + BACKSPACE + "Escaped")); } @Test public void testBackspace() throws Exception { final Lexer lexer = getLexer("character" + BACKSPACE + "NotEscaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + BACKSPACE + "NotEscaped")); } @Test // TODO is this correct? Do we expect FF to be unescaped? public void testEscapedFF() throws Exception { final Lexer lexer = getLexer("character\\" + FF + "Escaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + FF + "Escaped")); } @Test public void testFF() throws Exception { final Lexer lexer = getLexer("character" + FF + "NotEscaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character" + FF + "NotEscaped")); } @Test public void testEscapedMySqlNullValue() throws Exception { // MySQL uses \N to symbolize null values. We have to restore this final Lexer lexer = getLexer("character\\NEscaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character\\NEscaped")); } @Test public void testEscapedCharacter() throws Exception { final Lexer lexer = getLexer("character\\aEscaped", formatWithEscaping); assertThat(lexer.nextToken(new Token()), hasContent("character\\aEscaped")); } @Test public void testEscapedControlCharacter() throws Exception { // we are explicitly using an escape different from \ here final Lexer lexer = getLexer("character!rEscaped", CSVFormat.DEFAULT.withEscape('!')); assertThat(lexer.nextToken(new Token()), hasContent("character" + CR + "Escaped")); } @Test public void testEscapedControlCharacter2() throws Exception { final Lexer lexer = getLexer("character\\rEscaped", CSVFormat.DEFAULT.withEscape('\\')); assertThat(lexer.nextToken(new Token()), hasContent("character" + CR + "Escaped")); } @Test(expected = IOException.class) public void testEscapingAtEOF() throws Exception { final String code = "escaping at EOF is evil\\"; final Lexer lexer = getLexer(code, formatWithEscaping); lexer.nextToken(new Token()); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java0100644 0000000 0000000 00000012033 12565700103 033106 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv.perf; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.util.zip.GZIPInputStream; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVRecord; import org.apache.commons.io.IOUtils; import org.junit.BeforeClass; import org.junit.Test; /** * Tests performance. * * To run this test, use: mvn test -Dtest=PeformanceTest * * @version $Id: PerformanceTest.java 1592639 2014-05-05 22:03:17Z sebb $ */ @SuppressWarnings("boxing") // test code public class PerformanceTest { private final int max = 10; private static final File BIG_FILE = new File(System.getProperty("java.io.tmpdir"), "worldcitiespop.txt"); @BeforeClass public static void setUpClass() throws FileNotFoundException, IOException { if (BIG_FILE.exists()) { System.out.println(String.format("Found test fixture %s: %,d bytes.", BIG_FILE, BIG_FILE.length())); return; } System.out.println("Decompressing test fixture " + BIG_FILE + "..."); final InputStream input = new GZIPInputStream(new FileInputStream("src/test/resources/perf/worldcitiespop.txt.gz")); final OutputStream output = new FileOutputStream(BIG_FILE); IOUtils.copy(input, output); System.out.println(String.format("Decompressed test fixture %s: %,d bytes.", BIG_FILE, BIG_FILE.length())); input.close(); output.close(); } private BufferedReader getBufferedReader() throws IOException { return new BufferedReader(new FileReader(BIG_FILE)); } private long parse(final Reader in, final boolean traverseColumns) throws IOException { final CSVFormat format = CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(false); long recordCount = 0; for (final CSVRecord record : format.parse(in)) { recordCount++; if (traverseColumns) { for (@SuppressWarnings("unused") final String value : record) { // do nothing for now } } } return recordCount; } private void println(final String s) { System.out.println(s); } private long readAll(final BufferedReader in) throws IOException { long count = 0; while (in.readLine() != null) { count++; } return count; } public long testParseBigFile(final boolean traverseColumns) throws Exception { final long startMillis = System.currentTimeMillis(); final long count = this.parse(this.getBufferedReader(), traverseColumns); final long totalMillis = System.currentTimeMillis() - startMillis; this.println(String.format("File parsed in %,d milliseconds with Commons CSV: %,d lines.", totalMillis, count)); return totalMillis; } @Test public void testParseBigFileRepeat() throws Exception { long bestTime = Long.MAX_VALUE; for (int i = 0; i < this.max; i++) { bestTime = Math.min(this.testParseBigFile(false), bestTime); } this.println(String.format("Best time out of %,d is %,d milliseconds.", this.max, bestTime)); } @Test public void testReadBigFile() throws Exception { long bestTime = Long.MAX_VALUE; for (int i = 0; i < this.max; i++) { final BufferedReader in = this.getBufferedReader(); final long startMillis = System.currentTimeMillis(); long count = 0; try { count = this.readAll(in); } finally { in.close(); } final long totalMillis = System.currentTimeMillis() - startMillis; bestTime = Math.min(totalMillis, bestTime); this.println(String.format("File read in %,d milliseconds: %,d lines.", totalMillis, count)); } this.println(String.format("Best time out of %,d is %,d milliseconds.", this.max, bestTime)); } }commons-csv-1.2-src/src/test/java/org/apache/commons/csv/PerformanceTest.java0100644 0000000 0000000 00000026203 12565700103 032156 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Constructor; import java.util.zip.GZIPInputStream; import org.apache.commons.io.IOUtils; /** * Basic test harness. * * Requires test file to be downloaded separately. * * @version $Id: PerformanceTest.java 1582817 2014-03-28 16:44:41Z sebb $ */ @SuppressWarnings("boxing") public class PerformanceTest { private static final String[] PROPS = { "java.version", // Java Runtime Environment version "java.vendor", // Java Runtime Environment vendor // "java.vm.specification.version", // Java Virtual Machine specification version // "java.vm.specification.vendor", // Java Virtual Machine specification vendor // "java.vm.specification.name", // Java Virtual Machine specification name "java.vm.version", // Java Virtual Machine implementation version // "java.vm.vendor", // Java Virtual Machine implementation vendor "java.vm.name", // Java Virtual Machine implementation name // "java.specification.version", // Java Runtime Environment specification version // "java.specification.vendor", // Java Runtime Environment specification vendor // "java.specification.name", // Java Runtime Environment specification name "os.name", // Operating system name "os.arch", // Operating system architecture "os.version", // Operating system version }; private static int max = 10; private static int num = 0; // number of elapsed times recorded private static long[] elapsedTimes = new long[max]; private static final CSVFormat format = CSVFormat.EXCEL; private static final File BIG_FILE = new File(System.getProperty("java.io.tmpdir"), "worldcitiespop.txt"); public static void main(final String [] args) throws Exception { if (BIG_FILE.exists()) { System.out.println(String.format("Found test fixture %s: %,d bytes.", BIG_FILE, BIG_FILE.length())); } else { System.out.println("Decompressing test fixture " + BIG_FILE + "..."); final InputStream input = new GZIPInputStream(new FileInputStream("src/test/resources/perf/worldcitiespop.txt.gz")); final OutputStream output = new FileOutputStream(BIG_FILE); IOUtils.copy(input, output); input.close(); output.close(); System.out.println(String.format("Decompressed test fixture %s: %,d bytes.", BIG_FILE, BIG_FILE.length())); } final int argc = args.length; String tests[]; if (argc > 0) { max=Integer.parseInt(args[0]); } if (argc > 1) { tests = new String[argc-1]; for (int i = 1; i < argc; i++) { tests[i-1]=args[i]; } } else { tests=new String[]{"file", "split", "extb", "exts", "csv", "lexreset", "lexnew"}; } for(final String p : PROPS) { System.out.println(p+"="+System.getProperty(p)); } System.out.println("Max count: "+max+"\n"); for(final String test : tests) { if ("file".equals(test)) { testReadBigFile(false); } else if ("split".equals(test)) { testReadBigFile(true); } else if ("csv".equals(test)) { testParseCommonsCSV(); } else if ("lexreset".equals(test)) { testCSVLexer(false, test); } else if ("lexnew".equals(test)) { testCSVLexer(true, test); } else if (test.startsWith("CSVLexer")) { testCSVLexer(false, test); } else if ("extb".equals(test)) { testExtendedBuffer(false); } else if ("exts".equals(test)) { testExtendedBuffer(true); } else { System.out.println("Invalid test name: "+test); } } } private static BufferedReader getReader() throws IOException { return new BufferedReader(new FileReader(BIG_FILE)); } // Container for basic statistics private static class Stats { final int count; final int fields; Stats(final int c, final int f) { count=c; fields=f; } } // Display end stats; store elapsed for average private static void show(final String msg, final Stats s, final long start) { final long elapsed = System.currentTimeMillis() - start; System.out.printf("%-20s: %5dms " + s.count + " lines "+ s.fields + " fields%n",msg,elapsed); elapsedTimes[num++]=elapsed; } // calculate and show average private static void show(){ long tot = 0; if (num > 1) { for(int i=1; i < num; i++) { // skip first test tot += elapsedTimes[i]; } System.out.printf("%-20s: %5dms%n%n", "Average(not first)", tot/(num-1)); } num=0; // ready for next set } private static void testReadBigFile(final boolean split) throws Exception { for (int i = 0; i < max; i++) { final BufferedReader in = getReader(); final long t0 = System.currentTimeMillis(); final Stats s = readAll(in, split); in.close(); show(split?"file+split":"file", s, t0); } show(); } private static Stats readAll(final BufferedReader in, final boolean split) throws IOException { int count = 0; int fields = 0; String record; while ((record=in.readLine()) != null) { count++; fields+= split ? record.split(",").length : 1; } return new Stats(count, fields); } private static void testExtendedBuffer(final boolean makeString) throws Exception { for (int i = 0; i < max; i++) { final ExtendedBufferedReader in = new ExtendedBufferedReader(getReader()); final long t0 = System.currentTimeMillis(); int read; int fields = 0; int lines = 0; if (makeString) { StringBuilder sb = new StringBuilder(); while((read=in.read()) != -1) { sb.append((char)read); if (read == ',') { // count delimiters sb.toString(); sb = new StringBuilder(); fields++; } else if (read == '\n') { sb.toString(); sb = new StringBuilder(); lines++; } } } else { while((read=in.read()) != -1) { if (read == ',') { // count delimiters fields++; } else if (read == '\n') { lines++; } } } fields += lines; // EOL is a delimiter too in.close(); show("Extended"+(makeString?" toString":""), new Stats(lines, fields), t0); } show(); } private static void testParseCommonsCSV() throws Exception { for (int i = 0; i < max; i++) { final BufferedReader reader = getReader(); final CSVParser parser = new CSVParser(reader, format); final long t0 = System.currentTimeMillis(); final Stats s = iterate(parser); reader.close(); show("CSV", s, t0); parser.close(); } show(); } private static Constructor getLexerCtor(final String clazz) throws Exception { @SuppressWarnings("unchecked") final Class lexer = (Class) Class.forName("org.apache.commons.csv." + clazz); return lexer.getConstructor(new Class[]{CSVFormat.class, ExtendedBufferedReader.class}); } private static void testCSVLexer(final boolean newToken, final String test) throws Exception { Token token = new Token(); String dynamic = ""; for (int i = 0; i < max; i++) { final ExtendedBufferedReader input = new ExtendedBufferedReader(getReader()); Lexer lexer = null; if (test.startsWith("CSVLexer")) { dynamic="!"; lexer = getLexerCtor(test).newInstance(new Object[]{format, input}); } else { lexer = new Lexer(format, input); } int count = 0; int fields = 0; final long t0 = System.currentTimeMillis(); do { if (newToken) { token = new Token(); } else { token.reset(); } lexer.nextToken(token); switch(token.type) { case EOF: break; case EORECORD: fields++; count++; break; case INVALID: throw new IOException("invalid parse sequence <"+token.content.toString()+">"); case TOKEN: fields++; break; case COMMENT: // not really expecting these break; default: throw new IllegalStateException("Unexpected Token type: " + token.type); } } while (!token.type.equals(Token.Type.EOF)); final Stats s = new Stats(count, fields); input.close(); show(lexer.getClass().getSimpleName()+dynamic+" "+(newToken ? "new" : "reset"), s, t0); } show(); } private static Stats iterate(final Iterable it) { int count = 0; int fields = 0; for (final CSVRecord record : it) { count++; fields+=record.size(); } return new Stats(count, fields); } }commons-csv-1.2-src/src/test/java/org/apache/commons/csv/TokenMatchers.java0100644 0000000 0000000 00000006465 12565700103 031634 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.hamcrest.core.AllOf.allOf; import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.TypeSafeDiagnosingMatcher; /** * Collection of matchers for asserting the type and content of tokens. */ final class TokenMatchers { public static Matcher hasType(final Token.Type expectedType) { return new TypeSafeDiagnosingMatcher() { @Override public void describeTo(final Description description) { description.appendText("token has type "); description.appendValue(expectedType); } @Override protected boolean matchesSafely(final Token item, final Description mismatchDescription) { mismatchDescription.appendText("token type is "); mismatchDescription.appendValue(item.type); return item.type == expectedType; } }; } public static Matcher hasContent(final String expectedContent) { return new TypeSafeDiagnosingMatcher() { @Override public void describeTo(final Description description) { description.appendText("token has content "); description.appendValue(expectedContent); } @Override protected boolean matchesSafely(final Token item, final Description mismatchDescription) { mismatchDescription.appendText("token content is "); mismatchDescription.appendValue(item.content.toString()); return expectedContent.equals(item.content.toString()); } }; } public static Matcher isReady() { return new TypeSafeDiagnosingMatcher() { @Override public void describeTo(final Description description) { description.appendText("token is ready "); } @Override protected boolean matchesSafely(final Token item, final Description mismatchDescription) { mismatchDescription.appendText("token is not ready "); return item.isReady; } }; } public static Matcher matches(final Token.Type expectedType, final String expectedContent) { return allOf(hasType(expectedType), hasContent(expectedContent)); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/TokenMatchersTest.java0100644 0000000 0000000 00000005002 12565700103 032456 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.commons.csv; import static org.apache.commons.csv.TokenMatchers.hasContent; import static org.apache.commons.csv.TokenMatchers.hasType; import static org.apache.commons.csv.TokenMatchers.isReady; import static org.apache.commons.csv.TokenMatchers.matches; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; public class TokenMatchersTest { private Token token; @Before public void setUp() { token = new Token(); token.type = Token.Type.TOKEN; token.isReady = true; token.content.append("content"); } @Test public void testHasType() { assertFalse(hasType(Token.Type.COMMENT).matches(token)); assertFalse(hasType(Token.Type.EOF).matches(token)); assertFalse(hasType(Token.Type.EORECORD).matches(token)); assertTrue(hasType(Token.Type.TOKEN).matches(token)); } @Test public void testHasContent() { assertFalse(hasContent("This is not the token's content").matches(token)); assertTrue(hasContent("content").matches(token)); } @Test public void testIsReady() { assertTrue(isReady().matches(token)); token.isReady = false; assertFalse(isReady().matches(token)); } @Test public void testMatches() { assertTrue(matches(Token.Type.TOKEN, "content").matches(token)); assertFalse(matches(Token.Type.EOF, "content").matches(token)); assertFalse(matches(Token.Type.TOKEN, "not the content").matches(token)); assertFalse(matches(Token.Type.EORECORD, "not the content").matches(token)); } } commons-csv-1.2-src/src/test/java/org/apache/commons/csv/Utils.java0100644 0000000 0000000 00000003353 12565700103 030156 0ustar00BUILTIN\Administrators0000000 0000000 /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.commons.csv; import java.util.List; import org.junit.Assert; /** * Utility methods for test cases * * @version $Id: Utils.java 1512617 2013-08-10 10:46:03Z britter $ */ final class Utils { private Utils() { } /** * Checks if the 2d array has the same contents as the list of records. * * @param message the message to be displayed * @param expected the 2d array of expected results * @param actual the List of {@link CSVRecord} entries, each containing an array of values */ public static void compare(final String message, final String[][] expected, final List actual) { Assert.assertEquals(message+" - outer array size", expected.length, actual.size()); for(int i = 0; i < expected.length; i++) { Assert.assertArrayEquals(message+" (entry "+i+")",expected[i], actual.get(i).values()); } } } commons-csv-1.2-src/src/test/resources/CSVFileParser/bom.csv0100644 0000000 0000000 00000026767 12565677765 027001 0ustar00BUILTIN\Administrators0000000 0000000 Date, Open, High, Low, Close, Volume 14-Mar-14,223.80,225.20,220.85,221.51,79448141 13-Mar-14,230.00,230.00,224.40,224.42,59454628 12-Mar-14,226.30,230.75,225.70,228.98,92063054 11-Mar-14,230.00,230.30,225.30,226.25,115683458 10-Mar-14,238.00,239.15,229.65,234.07,122233521 7-Mar-14,247.05,247.90,238.65,241.76,72149744 6-Mar-14,247.10,248.00,244.95,246.13,38479187 5-Mar-14,248.70,248.70,246.05,247.25,33422662 4-Mar-14,246.00,249.15,245.50,249.00,55887707 3-Mar-14,246.80,247.90,243.30,243.57,38515161 28-Feb-14,248.00,250.80,244.00,248.75,70580422 27-Feb-14,245.00,247.45,241.90,246.46,63017830 26-Feb-14,247.30,247.50,244.65,246.17,71169978 25-Feb-14,247.45,248.45,246.00,246.73,141715245 24-Feb-14,242.40,252.30,241.70,250.71,201291941 21-Feb-14,432.48,434.04,424.60,433.58,148375843 20-Feb-14,408.80,422.40,408.80,420.90,62717982 19-Feb-14,408.01,410.67,407.64,409.48,60138594 18-Feb-14,409.93,410.94,401.13,410.67,57689586 17-Feb-14,400.40,410.76,400.40,407.92,34948169 14-Feb-14,404.80,405.62,398.48,400.40,71398625 13-Feb-14,403.33,405.99,400.03,405.99,51378293 12-Feb-14,407.92,407.92,403.24,405.17,45534228 11-Feb-14,408.01,408.92,405.26,412.59,42097343 10-Feb-14,408.80,409.40,403.50,407.00,37863358 7-Feb-14,408.83,411.40,406.36,407.00,35905011 6-Feb-14,401.50,412.96,399.21,410.48,61205228 5-Feb-14,400.49,403.33,395.36,401.59,53039135 4-Feb-14,405.08,405.08,400.68,404.42,47940389 3-Feb-14,412.59,416.62,406.08,407.18,39601653 31-Jan-14,414.79,416.44,404.52,415.34,50676461 30-Jan-14,416.72,416.99,411.31,413.69,33483235 29-Jan-14,416.20,422.00,404.10,414.90,86504585 28-Jan-14,411.31,411.95,407.28,409.38,38288593 27-Jan-14,402.42,413.05,395.54,409.84,126613069 24-Jan-14,430.92,433.40,424.51,426.34,45439876 23-Jan-14,430.83,433.22,427.35,428.91,38787292 22-Jan-14,435.97,437.80,434.50,435.32,28594170 21-Jan-14,439.91,440.18,435.23,435.78,30762826 20-Jan-14,441.47,441.92,436.98,439.91,21929419 17-Jan-14,436.33,440.18,432.02,440.00,48251104 16-Jan-14,436.30,436.30,432.70,434.90,28778333 15-Jan-14,434.32,437.16,430.19,437.16,28286009 14-Jan-14,425.61,432.67,424.51,432.48,21566893 13-Jan-14,429.82,432.02,426.52,428.54,27788310 10-Jan-14,432.94,435.97,430.19,430.19,30322741 9-Jan-14,433.68,438.26,431.11,432.12,33451996 8-Jan-14,434.70,435.80,432.30,432.70,25758032 7-Jan-14,431.93,436.98,431.93,436.15,18025877 6-Jan-14,430.47,434.50,427.81,432.39,23218942 3-Jan-14,434.22,435.88,432.12,432.12,18474832 2-Jan-14,435.32,436.33,433.58,434.87,19805863 31-Dec-13,435.51,437.07,433.49,434.50,8296419 30-Dec-13,437.16,438.81,429.64,433.95,14285625 27-Dec-13,434.96,436.33,434.04,436.24,12714245 24-Dec-13,431.80,436.30,431.80,433.40,4184696 23-Dec-13,431.93,433.86,430.83,432.94,16352042 20-Dec-13,429.92,431.48,427.81,430.28,57341389 19-Dec-13,421.30,428.36,420.84,428.36,35970749 18-Dec-13,419.47,421.48,417.54,417.82,25804973 17-Dec-13,414.33,419.56,414.33,419.01,35613878 16-Dec-13,413.14,419.74,412.87,417.45,29372183 13-Dec-13,418.28,419.28,413.05,416.50,35921722 12-Dec-13,420.93,421.67,418.09,419.19,28187680 11-Dec-13,423.87,425.88,422.12,422.58,24753867 10-Dec-13,427.17,430.56,421.58,422.95,36383855 9-Dec-13,424.78,429.64,422.22,427.99,46763275 6-Dec-13,417.63,423.22,416.17,423.22,32740697 5-Dec-13,411.68,414.52,410.76,414.42,24268700 4-Dec-13,414.70,415.89,410.30,412.32,25698144 3-Dec-13,413.88,416.17,413.05,413.97,26141212 2-Dec-13,416.53,417.54,413.97,414.33,20349286 29-Nov-13,418.09,421.85,415.80,415.80,19658853 28-Nov-13,419.01,422.40,418.28,419.01,9820144 27-Nov-13,418.73,423.13,418.73,419.74,17996367 26-Nov-13,420.29,422.22,418.09,419.65,37949969 25-Nov-13,422.40,424.42,420.02,421.21,15405526 22-Nov-13,422.95,423.78,418.64,419.92,17947371 21-Nov-13,413.14,421.76,413.05,421.58,25122277 20-Nov-13,419.28,420.20,414.98,416.53,29176784 19-Nov-13,426.80,427.17,424.23,425.42,21599573 18-Nov-13,423.96,429.64,422.58,429.64,27856553 15-Nov-13,424.97,429.46,421.94,424.14,28581844 14-Nov-13,424.97,425.24,421.76,423.50,25416262 13-Nov-13,421.30,423.04,418.00,420.57,34659167 12-Nov-13,411.77,426.34,409.66,423.96,47059321 11-Nov-13,417.36,418.92,414.42,416.81,22897931 8-Nov-13,412.78,420.84,411.12,419.38,34052600 7-Nov-13,421.67,425.42,417.27,417.63,30308853 6-Nov-13,420.75,423.59,420.20,422.77,23899790 5-Nov-13,421.67,421.76,416.81,418.46,23003677 4-Nov-13,425.42,428.45,420.48,418.63,21837907 1-Nov-13,421.67,426.25,418.92,423.08,49674033 31-Oct-13,414.24,415.89,407.73,411.58,53067328 30-Oct-13,413.97,416.53,412.96,414.52,21974624 29-Oct-13,413.40,414.90,412.10,414.90,34758458 28-Oct-13,416.44,416.44,412.50,413.42,29478382 25-Oct-13,417.18,418.46,414.24,415.71,21921080 24-Oct-13,421.48,421.67,417.18,419.65,20775076 23-Oct-13,417.27,420.48,-,420.02,25171502 22-Oct-13,417.82,420.29,415.43,417.91,22723103 21-Oct-13,418.00,420.57,414.42,417.82,19841727 18-Oct-13,420.75,421.48,416.81,417.45,45652897 17-Oct-13,412.50,420.40,411.80,420.40,60827755 16-Oct-13,405.62,412.50,405.08,412.50,45028759 15-Oct-13,407.82,407.82,403.70,407.00,35628198 14-Oct-13,404.25,407.92,403.70,406.18,24712313 11-Oct-13,400.86,404.16,400.03,402.97,32995013 10-Oct-13,396.20,399.50,394.40,398.60,39830809 9-Oct-13,397.28,398.75,392.42,394.17,50429913 8-Oct-13,399.85,402.69,396.55,400.49,35340757 7-Oct-13,403.30,403.50,399.80,401.10,26759235 4-Oct-13,403.98,409.20,402.69,405.28,28012688 3-Oct-13,403.30,409.20,402.40,407.00,51880581 2-Oct-13,398.75,401.41,397.38,401.41,28905843 1-Oct-13,397.80,399.70,395.30,399.70,42941595 30-Sep-13,394.35,398.48,393.07,396.00,47358640 27-Sep-13,399.21,400.49,395.82,398.20,28700702 26-Sep-13,397.30,401.90,396.20,400.60,41265303 25-Sep-13,393.98,400.40,393.25,398.48,76289511 24-Sep-13,383.99,391.05,383.72,390.68,44032828 20-Sep-13,381.30,385.00,381.30,382.20,67551001 19-Sep-13,388.67,388.85,381.61,384.54,63339203 18-Sep-13,389.12,390.13,386.28,387.48,29782183 17-Sep-13,390.13,392.06,386.74,387.29,35592196 16-Sep-13,390.50,392.61,388.12,392.15,35269666 13-Sep-13,386.28,389.86,385.46,389.03,34400807 12-Sep-13,383.62,385.18,381.52,385.18,37467823 11-Sep-13,383.72,385.37,383.08,385.28,52682994 10-Sep-13,387.57,387.84,374.00,381.15,57106663 9-Sep-13,385.55,387.11,383.99,385.73,40386916 6-Sep-13,383.17,386.47,381.52,386.38,47033452 5-Sep-13,383.17,389.40,381.42,386.01,73594815 4-Sep-13,375.83,379.78,374.82,379.50,68148208 3-Sep-13,386.74,390.22,366.85,377.46,135932047 2-Sep-13,394.17,395.54,389.86,390.87,76638367 30-Aug-13,376.84,382.71,376.48,378.12,80513834 29-Aug-13,379.50,380.23,371.62,376.39,188765402 28-Aug-13,346.68,348.06,343.29,346.46,33248523 27-Aug-13,348.98,352.46,348.33,348.52,31125051 23-Aug-13,348.06,351.91,347.23,351.10,24578043 22-Aug-13,348.15,350.90,347.14,348.42,25900749 21-Aug-13,349.52,351.63,348.06,348.33,27366031 20-Aug-13,345.86,351.45,345.58,348.70,32903144 19-Aug-13,351.54,352.92,347.14,348.06,28303154 16-Aug-13,352.46,354.66,350.26,352.55,38352941 15-Aug-13,357.78,358.88,351.82,353.56,30270841 14-Aug-13,362.08,364.01,357.87,358.05,21229405 13-Aug-13,360.89,363.46,359.33,362.45,19494821 12-Aug-13,361.72,363.28,357.78,359.70,18822519 9-Aug-13,360.98,368.41,359.06,361.55,43677760 8-Aug-13,362.36,363.37,359.06,360.80,24776144 7-Aug-13,362.18,365.93,361.99,362.45,33580337 6-Aug-13,363.55,364.10,360.89,363.28,24983926 5-Aug-13,366.70,368.10,361.50,363.00,16989806 2-Aug-13,367.58,367.95,364.38,365.48,21337148 1-Aug-13,363.64,367.03,362.82,367.03,33025460 31-Jul-13,357.04,363.28,357.04,362.08,30482471 30-Jul-13,357.50,359.00,356.00,357.70,19026523 29-Jul-13,354.40,358.00,354.40,351.40,20846115 26-Jul-13,354.66,356.31,350.90,353.01,18770154 25-Jul-13,355.58,356.77,352.00,354.75,22412197 24-Jul-13,357.50,357.87,352.64,354.93,25641277 23-Jul-13,356.86,358.05,353.65,354.22,36831293 22-Jul-13,355.67,357.22,352.00,353.50,26885235 19-Jul-13,351.45,355.48,350.26,355.39,49037908 18-Jul-13,351.18,353.96,349.43,350.81,35646491 17-Jul-13,354.48,356.31,349.80,352.55,21671333 16-Jul-13,359.33,369.69,354.66,354.66,32986361 15-Jul-13,355.70,358.40,354.80,358.40,25328806 12-Jul-13,352.82,357.27,352.65,355.30,27502877 11-Jul-13,354.57,355.65,350.90,351.18,31299470 10-Jul-13,355.48,356.12,346.30,352.92,30936616 9-Jul-13,354.02,356.30,351.63,355.58,25496990 8-Jul-13,354.66,354.77,350.90,351.82,18749856 5-Jul-13,354.84,357.13,349.98,351.54,32607046 4-Jul-13,344.58,355.48,343.98,355.48,32039614 3-Jul-13,344.76,345.95,341.37,343.48,28236710 2-Jul-13,347.42,348.98,341.73,348.15,25858968 1-Jul-13,346.13,348.24,336.05,345.77,30190358 28-Jun-13,343.75,346.41,336.05,344.39,64494483 27-Jun-13,337.15,343.66,334.95,341.64,42446288 26-Jun-13,331.10,336.32,329.27,336.14,38229026 25-Jun-13,326.52,331.25,322.67,330.37,45167515 24-Jun-13,321.38,327.01,320.10,322.48,41335403 21-Jun-13,327.34,330.46,322.36,322.39,113908603 20-Jun-13,328.99,341.11,324.50,325.88,39427257 19-Jun-13,336.78,348.36,332.02,332.66,33505655 18-Jun-13,332.38,342.01,330.92,337.98,38916344 17-Jun-13,332.02,349.60,331.83,334.95,47938619 14-Jun-13,329.82,333.68,327.80,330.09,42642737 13-Jun-13,325.92,331.19,323.86,327.62,61363681 12-Jun-13,338.52,350.33,330.46,331.83,70383374 11-Jun-13,348.79,353.83,348.79,352.00,34778890 10-Jun-13,349.25,353.01,347.72,351.54,28965683 7-Jun-13,345.68,353.47,344.88,351.72,37685799 6-Jun-13,345.31,349.16,344.12,344.94,32431998 5-Jun-13,350.26,351.27,343.11,343.75,37100233 4-Jun-13,348.15,352.55,347.32,352.09,28930739 3-Jun-13,348.87,350.48,344.76,345.77,31723495 31-May-13,353.47,355.58,349.25,351.91,49628091 30-May-13,352.37,356.68,352.37,353.83,24478655 29-May-13,361.17,361.17,352.73,353.74,37389944 28-May-13,356.40,365.00,356.40,362.40,31785542 24-May-13,355.58,358.60,354.57,356.68,32896400 23-May-13,356.58,358.91,350.77,354.84,48202449 22-May-13,366.67,367.86,360.07,360.80,44293037 21-May-13,362.54,366.58,359.33,366.48,51113058 20-May-13,362.72,364.55,357.32,362.27,25352128 17-May-13,361.50,364.80,360.60,362.40,32633400 16-May-13,358.78,364.47,358.32,361.26,32026414 15-May-13,354.93,359.24,353.10,357.87,32100471 14-May-13,355.70,355.70,349.80,354.80,38391682 13-May-13,356.77,357.13,354.11,354.75,26806933 10-May-13,351.54,356.68,351.54,356.31,33788309 9-May-13,353.01,353.56,350.56,352.73,29322022 8-May-13,356.58,357.22,352.92,353.92,28272019 7-May-13,355.67,357.41,353.38,356.31,29908481 3-May-13,354.38,356.76,351.70,355.30,32943983 2-May-13,356.49,359.00,353.19,355.58,29251651 1-May-13,360.80,362.48,358.78,359.42,20444981 30-Apr-13,360.43,361.62,357.50,359.70,44018132 29-Apr-13,361.26,361.99,358.78,360.89,27660513 26-Apr-13,358.51,362.47,357.81,361.53,22893819 25-Apr-13,357.50,365.00,356.60,360.10,48598882 24-Apr-13,357.50,357.96,353.28,354.20,33735551 23-Apr-13,355.58,357.96,353.19,357.59,30599486 22-Apr-13,357.41,358.51,355.21,357.13,22649070 19-Apr-13,355.30,358.51,352.46,354.29,48215117 18-Apr-13,345.77,362.08,345.12,352.92,52850299 17-Apr-13,350.62,350.72,344.48,346.96,29221515 16-Apr-13,347.97,351.36,346.59,348.15,23531448 15-Apr-13,348.61,351.54,345.95,350.17,22673809 12-Apr-13,346.96,352.09,346.22,349.34,26729284 11-Apr-13,346.70,350.00,346.10,348.00,24281869 10-Apr-13,344.02,347.97,340.91,346.87,29362052 9-Apr-13,342.80,346.90,341.40,343.80,34120577 8-Apr-13,334.86,340.45,333.30,338.80,32855908 5-Apr-13,338.62,340.45,333.02,334.77,34563170 4-Apr-13,339.17,344.39,336.78,338.80,33511201 3-Apr-13,339.17,348.42,339.17,339.77,65595027 2-Apr-13,342.28,363.43,341.49,352.00,125095815 28-Mar-13,339.99,344.48,339.62,342.10,40735457 27-Mar-13,345.40,345.41,335.04,341.00,52111317 26-Mar-13,343.57,344.94,339.62,344.21,31713045 25-Mar-13,342.83,350.08,342.19,343.20,63715204 22-Mar-13,335.50,338.98,335.32,336.32,33247573 21-Mar-13,339.08,339.70,334.49,336.51,37082832 20-Mar-13,342.83,343.75,339.30,340.63,39619389 19-Mar-13,339.08,346.41,338.98,343.93,52624276 18-Mar-13,330.09,341.26,330.09,339.08,46650521 commons-csv-1.2-src/src/test/resources/CSVFileParser/README.txt0100644 0000000 0000000 00000002061 12565677765 027162 0ustar00BUILTIN\Administrators0000000 0000000 This directory contains test files for the CSVFileParserTest class. Files are of two types: - test*.txt: these are test control and expected results - test*.csv: these are the test input files, in various CSV formats Test Control files (test*.txt) ============================== The first line of this file consists of several space-separated fields: - name of CSV data file (in same directory) - (optional) settings to be applied to the default parsing format, which is delim=',' encap='"' The settings have the form (see test source file for full details): IgnoreEmpty=true|false IgnoreSpaces=true|false CommentStart=char CheckComments - whether the test should check comment fields as well The second line is the expected output from invoking CSVFormat#toString() on the parsing format Subsequent lines are of the form: n:[output] where n is the expected result of CSVRecord#size, and [output] is the expected output from invoking CSVRecord#toString() on the parsed records. Lines beginning with # are ignored, and can be used for comments.commons-csv-1.2-src/src/test/resources/CSVFileParser/test.csv0100644 0000000 0000000 00000000366 12565677765 027166 0ustar00BUILTIN\Administrators0000000 0000000 A,B,C,"D" # plain values a,b,c,d # spaces before and after e ,f , g,h # quoted: with spaces before and after " i ", " j " , " k "," l " # empty values ,,, # empty quoted values "","","","" # 3 empty lines # EOF on next line commons-csv-1.2-src/src/test/resources/CSVFileParser/testCSV85.csv0100644 0000000 0000000 00000000142 12565677765 027707 0ustar00BUILTIN\Administrators0000000 0000000 # Comment 1 a,b,c,e,f # Very Long # Comment 2 g,h,i,j,k # Very Long # Comment 3 l,m,n,o,pcommons-csv-1.2-src/src/test/resources/CSVFileParser/testCSV85_default.txt0100644 0000000 0000000 00000000442 12565677765 031442 0ustar00BUILTIN\Administrators0000000 0000000 testCSV85.csv CommentStart=# CheckComments Delimiter=<,> QuoteChar=<"> CommentStart=<#> SkipHeaderRecord:false # Comment 1 5:[a, b, c, e, f]#Comment 1 # Very Long # Comment 2 5:[g, h, i, j, k]#Very Long\nComment 2 # Very Long 1:[]#Very Long # Comment 3 5:[l, m, n, o, p]#Comment 3commons-csv-1.2-src/src/test/resources/CSVFileParser/testCSV85_ignoreEmpty.txt0100644 0000000 0000000 00000000501 12565677765 032314 0ustar00BUILTIN\Administrators0000000 0000000 testCSV85.csv CommentStart=# IgnoreEmpty=true CheckComments Delimiter=<,> QuoteChar=<"> CommentStart=<#> EmptyLines:ignored SkipHeaderRecord:false # Comment 1 5:[a, b, c, e, f]#Comment 1 # Very Long # Comment 2 5:[g, h, i, j, k]#Very Long\nComment 2 # Very Long # Comment 3 5:[l, m, n, o, p]#Very Long\nComment 3commons-csv-1.2-src/src/test/resources/CSVFileParser/test_default.txt0100644 0000000 0000000 00000000607 12565677765 030714 0ustar00BUILTIN\Administrators0000000 0000000 test.csv IgnoreEmpty=true Delimiter=<,> QuoteChar=<"> EmptyLines:ignored SkipHeaderRecord:false 4:[A, B, C, D] 1:[# plain values] 4:[a, b, c, d] 1:[# spaces before and after] 4:[ e , f , g, h ] 1:[# quoted: with spaces before and after] 4:[ i , " j " , " k ", l ] 1:[# empty values] 4:[, , , ] 1:[# empty quoted values] 4:[, , , ] 1:[# 3 empty lines] 1:[# EOF on next line]commons-csv-1.2-src/src/test/resources/CSVFileParser/test_default_comment.txt0100644 0000000 0000000 00000000354 12565677765 032435 0ustar00BUILTIN\Administrators0000000 0000000 test.csv IgnoreEmpty=true CommentStart=# Delimiter=<,> QuoteChar=<"> CommentStart=<#> EmptyLines:ignored SkipHeaderRecord:false 4:[A, B, C, D] 4:[a, b, c, d] 4:[ e , f , g, h ] 4:[ i , " j " , " k ", l ] 4:[, , , ] 4:[, , , ]commons-csv-1.2-src/src/test/resources/CSVFileParser/test_rfc4180.txt0100644 0000000 0000000 00000000565 12565677765 030362 0ustar00BUILTIN\Administrators0000000 0000000 test.csv Delimiter=<,> QuoteChar=<"> SkipHeaderRecord:false 4:[A, B, C, D] 1:[# plain values] 4:[a, b, c, d] 1:[# spaces before and after] 4:[ e , f , g, h ] 1:[# quoted: with spaces before and after] 4:[ i , " j " , " k ", l ] 1:[# empty values] 4:[, , , ] 1:[# empty quoted values] 4:[, , , ] 1:[# 3 empty lines] 1:[] 1:[] 1:[] 1:[# EOF on next line]commons-csv-1.2-src/src/test/resources/CSVFileParser/test_rfc4180_trim.txt0100644 0000000 0000000 00000000625 12565677765 031412 0ustar00BUILTIN\Administrators0000000 0000000 test.csv IgnoreSpaces=true Delimiter=<,> QuoteChar=<"> SurroundingSpaces:ignored SkipHeaderRecord:false 4:[A, B, C, D] 1:[# plain values] 4:[a, b, c, d] 1:[# spaces before and after] 4:[e, f, g, h] 1:[# quoted: with spaces before and after] 4:[ i , j , k , l ] 1:[# empty values] 4:[, , , ] 1:[# empty quoted values] 4:[, , , ] 1:[# 3 empty lines] 1:[] 1:[] 1:[] 1:[# EOF on next line]commons-csv-1.2-src/src/test/resources/ferc.gov/contract.txt0100644 0000000 0000000 00000014317 12565677765 027152 0ustar00BUILTIN\Administrators0000000 0000000 contract_id,seller_company_name,customer_company_name,customer_duns_number,contract_affiliate,FERC_tariff_reference,contract_service_agreement_id,contract_execution_date,contract_commencement_date,contract_termination_date,actual_termination_date,extension_provision_description,class_name,term_name,increment_name,increment_peaking_name,product_type_name,product_name,quantity,units_for_contract,rate,rate_minimum,rate_maximum,rate_description,units_for_rate,point_of_receipt_control_area,point_of_receipt_specific_location,point_of_delivery_control_area,point_of_delivery_specific_location,begin_date,end_date,time_zone C71,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Original Volume No. 10,2,2/15/2001,2/15/2001,,,Evergreen,N/A,N/A,N/A,N/A,MB,ENERGY,0,, , , ,Market Based,,,,,,,,ES C72,The Electric Company,Utility A,38495837,n,FERC Electric Tariff Original Volume No. 10,15,7/25/2001,8/1/2001,,,Evergreen,N/A,N/A,N/A,N/A,MB,ENERGY,0,, , , ,Market Based,,,,,,,,ES C73,The Electric Company,Utility B,493758794,N,FERC Electric Tariff Original Volume No. 10,7,6/8/2001,7/6/2001,,,Evergreen,N/A,N/A,N/A,N/A,MB,ENERGY,0,, , , ,Market Based,,,, , ,,,ep C74,The Electric Company,Utility C,594739573,n,FERC Electric Tariff Original Volume No. 10,25,6/8/2001,7/6/2001,,,Evergreen,N/A,N/A,N/A,N/A,MB,ENERGY,0,, , , ,Market Based,,,, , ,,,ep C75,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Third Revised Volume No. 7,94,2/13/2001,7/1/2001,12/31/2006,,None,F,LT,M,P,T,ENERGY,2000,KWh,.1475, , ,Max amount of capacity and energy to be transmitted. Bill based on monthly max delivery to City.,$/KWh,PJM,Point A,PJM,Point B,,,ep C75,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Third Revised Volume No. 7,94,2/13/2001,7/1/2001,12/31/2006,,None,F,LT,M,P,T,point-to-point agreement,2000,KW,0.01, , ,,$/kw-mo,PJM,Point A,PJM,Point B,,,ep C75,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Third Revised Volume No. 7,94,2/13/2001,7/1/2001,12/31/2006,,None,F,LT,M,P,T,network,2000,KW,0.2, , ,,$/kw-mo,PJM,Point A,PJM,Point B,,,ep C75,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Third Revised Volume No. 7,94,2/13/2001,7/1/2001,12/31/2006,,None,F,LT,M,P,T,BLACK START SERVICE,2000,KW,0.22, , ,,$/kw-mo,PJM,Point A,PJM,Point B,,,ep C75,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Third Revised Volume No. 7,94,2/13/2001,7/1/2001,12/31/2006,,None,F,LT,M,P,T,CAPACITY,2000,KW,0.04, , ,,$/kw-mo,PJM,Point A,PJM,Point B,,,ep C75,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Third Revised Volume No. 7,94,2/13/2001,7/1/2001,12/31/2006,,None,F,LT,M,P,T,regulation & frequency response,2000,KW,0.1, , ,,$/kw-mo,PJM,Point A,PJM,Point B,,,ep C75,The Electric Company,The Power Company,456543333,N,FERC Electric Tariff Third Revised Volume No. 7,94,2/13/2001,7/1/2001,12/31/2006,,None,F,LT,M,P,T,real power transmission loss,2000,KW,7, , ,,$/kw-mo,PJM,Point A,PJM,Point B,,,ep C76,The Electric Company,The Power Company,456534333,N,FERC Electric Tariff Original Volume No. 10,132,12/15/2001,1/1/2002,12/31/2004,12/31/2004,None,F,LT,M,FP,MB,CAPACITY,70,MW,3750, , ,70MW for each and every hour over the term of the agreement (7x24 schedule).,$/MW,,,,,,,ep C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,35, , ,,$/MWH,,,PJM,Bus 4321,20020101,20030101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,37, , ,,$/MWH,,,PJM,Bus 4321,20030101,20040101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,39, , ,,$/MWH,,,PJM,Bus 4321,20040101,20050101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,41, , ,,$/MWH,,,PJM,Bus 4321,20050101,20060101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,43, , ,,$/MWH,,,PJM,Bus 4321,20060101,20070101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,45, , ,,$/MWH,,,PJM,Bus 4321,20070101,20080101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,47, , ,,$/MWH,,,PJM,Bus 4321,20080101,20090101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,49, , ,,$/MWH,,,PJM,Bus 4321,20090101,20100101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,51, , ,,$/MWH,,,PJM,Bus 4321,20100101,20110101,EP C78,The Electric Company,"The Electric Marketing Co., LLC",23456789,Y,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,1/2/1992,1/2/1992,1/1/2012,,Renewable annually by mutual agreement after termination date.,UP,LT,Y,FP,CB,ENERGY,0,MWH,53, , ,,$/MWH,,,PJM,Bus 4321,20110101,20120101,EP commons-csv-1.2-src/src/test/resources/ferc.gov/readme.txt0100644 0000000 0000000 00000000130 12565677765 026556 0ustar00BUILTIN\Administrators0000000 0000000 Real world examples from http://www.ferc.gov/docs-filing/eqr/soft-tools/sample-csv.asp commons-csv-1.2-src/src/test/resources/ferc.gov/transaction.txt0100644 0000000 0000000 00000011544 12565677765 027661 0ustar00BUILTIN\Administrators0000000 0000000 transaction_unique_identifier,seller_company_name,customer_company_name,customer_duns_number,tariff_reference,contract_service_agreement,trans_id,transaction_begin_date,transaction_end_date,time_zone,point_of_delivery_control_area,specific location,class_name,term_name,increment_name,increment_peaking_name,product_name,transaction_quantity,price,units,total_transmission_charge,transaction_charge T1,The Electric Company,"The Electric Marketing Co., LLC",23456789,FERC Electric Tariff Original Volume No. 2,Service Agreement 1,8700,200401010000,200403312359,ES,PJM,BUS 4321,UP,LT,Y,FP,ENERGY,22574,39,$/MWH,0,880386 T2,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8701,200401010000,200402010000,CS,DPL,Green Sub Busbar,F,ST,M,FP,ENERGY,16800,32,$/MWH,0,537600 T3,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8702,200402010000,200403010000,CS,DPL,Green Sub Busbar,F,ST,M,FP,ENERGY,16800,32,$/MWH,0,537600 T4,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8703,200403010000,200404010000,CS,DPL,Green Sub Busbar,F,ST,M,FP,ENERGY,16800,32,$/MWH,0,537600 T5,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8704,200401111600,200401121559,CS,AEP,Tile Busbar,F,ST,D,FP,ENERGY,1200,50,$/MWH,0,60000 T6,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8801,200402011300,20040215061900,ES,HUB,Entergy (into),NF,ST,H,FP,ENERGY,1875,13.75,$/MWH,6675,32456.25 T7,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8802,20040202110000,200402021800,ES,HUB,PJM-W,NF,ST,H,FP,BOOKED OUT POWER,350,32,$/MWH,0,11200 T8,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8803,20040203060500,20040210112200,ES,HUB,PJM-W,NF,ST,H,FP,ENERGY,1875,44,$/MWH,0,82500 T9,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,2,8804,20040211062300,20040219081200,PP,HUB,Four Corners,NF,ST,H,FP,ENERGY,1875,48,$/MWH,0,90000 T10,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,132,7125,20040109081100,20040309082300,CS,HUB,AEP (into),F,ST,H,OP,ENERGY,150,22,$/MWH,4264,7564 T10,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,132,7125,20040201010000,20040225080800,CS,HUB,AEP (into),F,ST,H,OP,ENERGY,150,28,$/MWH,0,4200 T10,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,132,7125,20040108111100,20040301121200,CS,HUB,AEP (into),F,ST,H,OP,ENERGY,150,44,$/MWH,0,6600 T10,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,132,7125,20040322112200,20040325120000,CS,HUB,AEP (into),F,ST,H,OP,ENERGY,150,44,$/MWH,0,6600 T10,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,132,7125,20040323191900,20040328191700,CS,HUB,AEP (into),F,ST,H,OP,ENERGY,150,58,$/MWH,0,8700 T10,The Electric Company,The Power Company,45653333,FERC Electric Tariff Original Volume No. 10,132,7125,20040111010000,20040122022200,CS,HUB,AEP (into),F,ST,H,OP,CAPACITY,150,20,$/MW-DAY,0,3000 T11,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403150800,200403150859,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,100,50,$/MWH,0,5000 T11,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403150800,200403150859,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,-10,60,$/MWH,0,-600 T12,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403150900,200403150959,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,100,55,$/MWH,0,5500 T12,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403150900,200403150959,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,-5,59,$/MWH,0,-295 T13,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403151000,200403151059,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,100,62,$/MWH,0,6200 T13,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403151000,200403151059,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,-10,60,$/MWH,0,-600 T14,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403151100,200403151159,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,100,62,$/MWH,0,6200 T14,The Electric Company,Utility A,38495837,FERC Electric Tariff Original Volume No. 10,15,8711,200403151100,200403151159,ES,ISNE,NEPOOL Mass HUB,F,ST,H,P,Energy,-10,59,$/MWH,0,-590 T15,The Electric Company,Utility B,493758794,FERC Electric Tariff Original Volume No. 10,7,8712,200402140200,200402140259,EP,NYIS,Zone A,F,ST,H,FP,Booked out power,60,30,$/MWH,0,1800