diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..bec231c194
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,16 @@
+# 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.
+
+* text=auto
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index d6f2c05dfd..1f42db3b1a 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -1,85 +1,85 @@
-# 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.
-
-name: "CodeQL"
-
-on:
- push:
- branches: [ master ]
- pull_request:
- # The branches below must be a subset of the branches above
- branches: [ master ]
- schedule:
- - cron: '33 9 * * 4'
-
-permissions:
- contents: read
-
-jobs:
- analyze:
- name: Analyze
- runs-on: ubuntu-latest
- permissions:
- actions: read
- contents: read
- security-events: write
-
- strategy:
- fail-fast: false
- matrix:
- language: [ 'java' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
- # Learn more about CodeQL language support at https://git.io/codeql-language-support
-
- steps:
- - name: Checkout repository
+# 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.
+
+name: "CodeQL"
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ # The branches below must be a subset of the branches above
+ branches: [ master ]
+ schedule:
+ - cron: '33 9 * * 4'
+
+permissions:
+ contents: read
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'java' ]
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
+
+ steps:
+ - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
- with:
- persist-credentials: false
+ with:
+ persist-credentials: false
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
- with:
- path: ~/.m2/repository
- key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: |
- ${{ runner.os }}-maven-
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
uses: github/codeql-action/init@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # 3.28.1
- with:
- languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
+ with:
+ languages: ${{ matrix.language }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
uses: github/codeql-action/autobuild@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # 3.28.1
-
- # ℹ️ Command-line programs to run using the OS shell.
- # 📚 https://git.io/JvXDl
-
- # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
-
- #- run: |
- # make bootstrap
- # make release
-
- - name: Perform CodeQL Analysis
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://git.io/JvXDl
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # 3.28.1
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 9aec002d71..71887b86d9 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -1,52 +1,52 @@
-# 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.
-
-name: Java CI
-
-on: [push, pull_request]
-
-permissions:
- contents: read
-
-jobs:
- build:
-
- runs-on: ubuntu-latest
- continue-on-error: ${{ matrix.experimental }}
- strategy:
- matrix:
- java: [ 8, 11, 17, 21, 23 ]
- experimental: [false]
- include:
- - java: 24-ea
- experimental: true
-
- steps:
+# 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.
+
+name: Java CI
+
+on: [push, pull_request]
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+ continue-on-error: ${{ matrix.experimental }}
+ strategy:
+ matrix:
+ java: [ 8, 11, 17, 21, 23 ]
+ experimental: [false]
+ include:
+ - java: 24-ea
+ experimental: true
+
+ steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
- with:
- persist-credentials: false
+ with:
+ persist-credentials: false
- uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
- with:
- path: ~/.m2/repository
- key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
- restore-keys: |
- ${{ runner.os }}-maven-
- - name: Set up JDK ${{ matrix.java }}
+ with:
+ path: ~/.m2/repository
+ key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-maven-
+ - name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4.6.0
- with:
- distribution: 'temurin'
- java-version: ${{ matrix.java }}
- - name: Build with Maven
- run: mvn -Ddoclint=all --show-version --batch-mode --no-transfer-progress
+ with:
+ distribution: 'temurin'
+ java-version: ${{ matrix.java }}
+ - name: Build with Maven
+ run: mvn -Ddoclint=all --show-version --batch-mode --no-transfer-progress
diff --git a/src/assembly/bin.xml b/src/assembly/bin.xml
index 823014633b..f73d62f6df 100644
--- a/src/assembly/bin.xml
+++ b/src/assembly/bin.xml
@@ -1,56 +1,56 @@
-
+
- bin
-
- tar.gz
- zip
-
-
-
-
- LICENSE.txt
- NOTICE.txt
- RELEASE-NOTES.txt
-
-
-
- target
-
-
- ${artifactId}-${version}.jar
-
-
-
- target/site/apidocs
- apidocs
-
- **/*
-
-
-
-
- target
-
-
- ${artifactId}-${version}-sources.jar
-
-
-
-
+ xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 https://maven.apache.org/xsd/assembly-2.2.0.xsd">
+ bin
+
+ tar.gz
+ zip
+
+
+
+
+ LICENSE.txt
+ NOTICE.txt
+ RELEASE-NOTES.txt
+
+
+
+ target
+
+
+ ${artifactId}-${version}.jar
+
+
+
+ target/site/apidocs
+ apidocs
+
+ **/*
+
+
+
+
+ target
+
+
+ ${artifactId}-${version}-sources.jar
+
+
+
+
diff --git a/src/assembly/src.xml b/src/assembly/src.xml
index 819553428b..9f33f58f20 100644
--- a/src/assembly/src.xml
+++ b/src/assembly/src.xml
@@ -1,45 +1,45 @@
-
+
- src
-
- tar.gz
- zip
-
- ${artifactId}-${version}-src
-
-
-
- LICENSE*
- NOTICE*
- RELEASE-NOTES.txt
- pom.xml
- findbugs-exclude-filter.xml
- checkstyle*.xml
-
-
-
- src
-
- **/*Benchmark.java
-
-
-
-
-
+ xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 https://maven.apache.org/xsd/assembly-2.2.0.xsd">
+ src
+
+ tar.gz
+ zip
+
+ ${artifactId}-${version}-src
+
+
+
+ LICENSE*
+ NOTICE*
+ RELEASE-NOTES.txt
+ pom.xml
+ findbugs-exclude-filter.xml
+ checkstyle*.xml
+
+
+
+ src
+
+ **/*Benchmark.java
+
+
+
+
+
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b5359533de..a05e5d52e8 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -1,386 +1,386 @@
-
-
-
-
-
-
-
- Apache Commons CSV Release Notes
-
-
-
-
- Release history link changed from changes-report.html to changes.html #516.
-
-
- Bump com.opencsv:opencsv from 5.9 to 5.10.
-
-
-
- Required OSGi Import-Package version numbers in MANIFEST.MF #504.
- CSVParser.nextRecord() should throw CSVException (an IOException subclass) instead of IOException and IllegalStateException, no method signature changes needed.
-
- Add CSVPrinter.getRecordCount().
- Add and use CSVParser.Builder and builder() and deprecate CSVParser constructors.
- CSVFormat.Builder implements Supplier<CSVFormat>.
- Deprecate CSVFormat.Builder.build() for get().
- Track byte position #502.
-
- Bump org.apache.commons:commons-parent from 76 to 78 #486, #495.
- Bump org.codehaus.mojo:taglist-maven-plugin from 3.1.0 to 3.2.1 #493.
- Bump commons-io:commons-io from 2.17.0 to 2.18.0 #505.
- Bump commons-codec:commons-codec from 1.17.1 to 1.17.2.
- Bump org.apache.commons:commons-parent from 78 to 79.
-
-
-
- Add CSVException that extends IOException thrown on invalid input instead of IOException.
-
- Fix PMD issues for port to PMD 7.1.0.
- Fix some Javadoc links #442.
- Extract duplicated code into a method #444.
- Migrate CSVFormat#print(File, Charset) to NIO #445.
- Fix documentation for CSVFormat private constructor #466.
- CSVFormat does not support explicit " as escape char.
- Escaping is not disableable.
- Fix Javadoc warnings on Java 23.
- Improve parser performance by up to 20%, YMMV.
-
- Bump commons-codec:commons-codec from 1.16.1 to 1.17.1 #422, #449.
- Bump org.apache.commons:commons-parent from 69 to 76 #435, #452, #465, #468, #475, #482.
- Bump org.codehaus.mojo:taglist-maven-plugin from 3.0.0 to 3.1.0 #441.
- Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #450, #459, #470.
- Bump org.hamcrest:hamcrest from 2.2 to 3.0 #455.
- Bump commons-io:commons-io from 2.16.1 to 2.17.0 #476.
-
-
-
- [Javadoc] Add example to CSVFormat#setHeaderComments() #344.
- Add and use CSVFormat#setTrailingData(boolean) in CSVFormat.EXCEL for Excel compatibility #303.
- Add and use CSVFormat#setLenientEof(boolean) in CSVFormat.EXCEL for Excel compatibility #303.
-
- Replace deprecated method in user guide, update external link #324, #325.
- Document duplicate header behavior #309.
- Add missing docs #328.
- [StepSecurity] CI: Harden GitHub Actions #329, #330.
- Better error message during faulty CSV record read #347.
- Misleading error message when QuoteMode set to None #352.
- OutOfMemory for very long rows despite using column value of type Reader.
- Use try-with-resources to manage JDBC CLOB in CSVPrinter.printRecords(ResultSet).
- JDBC Blob columns are now output as Base64 instead of Object#toString(), which usually is InputStream#toString().
- Support unusual Excel use cases: Add support for trailing data after the closing quote, and EOF without a final closing quote #303.
- MongoDB CSV empty first column parsing fix #412.
-
- Bump commons-io:commons-io: from 2.11.0 to 2.16.1 #408, #413.
- Bump commons-parent from 57 to 69 #410.
- Bump h2 from 2.1.214 to 2.2.224 #333, #349, #359.
- Bump commons-lang3 from 3.12.0 to 3.14.0.
- Update exception message in CSVRecord#getNextRecord() #348.
- Bump tests using com.opencsv:opencsv from 5.8 to 5.9 #373.
-
-
-
- Minor changes #172.
- No Automatic-Module-Name prevents usage in JPMS projects without repacking the JAR.
- Fix for multi-char delimiter not working as expected #218.
- CSVRecord.get(Enum) should use Enum.name() instead of Enum.toString().
- Allow org.apache.commons.csv.IOUtils.copy(Reader, Appendable, CharBuffer) to compile on Java 11 and run on Java 8.
- CSVRecord.toList() does not give write access to the new List.
- CSVParser.getRecords() now throws UncheckedIOException instead of IOException.
- Add comments to iterator() and stream() #270.
- Fix wrong assumptions in PostgreSQL formats #265.
- Validate input to setDelimiter(String) for empty string #266.
- Bump CSVFormat#serialVersionUID from 1 to 2.
- CSVParser: Identify duplicates in null, empty and blank header names #279.
-
- Serialization in CSVFormat is not supported from one version to the next.
-
- Make CSVRecord#values() public.
- Add DuplicateHeaderMode for flexibility with header strictness. #114.
- Support for parallelism in CSVPrinter.
- Add CSVPrinter.printRecord[s](Stream).
- Add accessors for header/trailer comments #257.
- Add github/codeql-action.
-
- Bump actions/cache from 2.1.6 to 3.0.10 #196, #233, #243, #267, #271.
- Bump actions/checkout from 2.3.4 to 3.1.0 #188, #195, #220, #272.
- Bump actions/setup-java from 2 to 3.5.1.
- Bump actions/upload-artifact from 3.1.0 to 3.1.1 #280.
- Bump commons-parent from 52 to 57 #264, #288, #298, #323.
- Bump checkstyle from 8.44 to 9.2.1 #180, #190, #194, #202, #207.
- Bump junit-jupiter from 5.8.0-M1 to 5.9.1 #179, #186, #201, #244, #263.
- Bump jmh-core from 1.32 to 1.36 #176, #208, #229, #285.
- Bump jmh-generator-annprocess from 1.32 to 1.36 #175, #206, #226, #283.
- Bump mockito-core from 3.11.2 to 4.11.0 #187, #197, #204, #212, #230, #237, #251, #259, #284, #292, #297.
- Bump maven-pmd-plugin from 3.14.0 to 3.19.0 #184, #219, #238, #254, #258.
- Bump pmd from 6.36.0 to 6.52.0 #173, #189, #193, #199, #227, #233, #214, #236, #240, #247, #255, #273.
- Bump opencsv from 5.5.1 to 5.7.1 #182, #221, #260, #281.
- Bump spotbugs-maven-plugin from 4.3.0 to 4.7.3.0 #192, #198, #203, #211, #225, #234, #242, #245, #261, #275, #282.
- Bump com.github.spotbugs:spotbugs from 4.5.3 to 4.7.2.
- Bump h2 from 1.4.200 to 2.1.214 #200, #205, #213, #239.
- Bump maven-javadoc-plugin from 3.3.0 to 3.4.1.
- Bump biz.aQute.bnd:biz.aQute.bndlib from 5.3.0 to 6.3.1.
- Bump jacoco-maven-plugin from 0.8.7 to 0.8.8.
- Bump japicmp-maven-plugin from 0.15.3 to 0.16.0.
- Bump maven-checkstyle-plugin from 3.1.2 to 3.2.0 #253.
-
-
-
- Replace FindBugs with SpotBugs #56.
- Javadoc typo in CSVFormat let's -> lets #57.
- CSVFormat.printWithEscapes throws StringIndexOutOfBoundsException when value is Reader #61.
- Improve CSVFormat test coverage #63.
- Fix CSVFileParserTest.java to allow for a null return value from record.getComment() #62.
- Improve test coverage in CSVFormatTest #65.
- Removed invalid Javadoc markup for CSVFormat EXCEL #64.
- Improve CSVRecord and CSVPrinter code coverage #66.
- Improve lexer and token coverage #67.
- CSVFormat.format trims last delimiter if the delimiter is a white space #71.
- Replace org.apache.commons.csv.Assertions.notNull() with Objects.requireNonNull().
- Line number is not proper at EOF.
- Parser iterates over the last CSV Record twice.
- Minor improvements #126, #127, #130.
- Add possibility to use ResultSet header meta data as CSV header #11.
- Add test cases for withIgnoreSurroundingSpaces() and withTrim() #70.
- Update CSVParser.parse(File, Charset, CSVFormat) from IO to NIO.
- Missing separator with print(object) followed by printRecord(Object[]) #157.
- Fix EOL checking for read array in ExtendedBufferedReader #5.
- Print from Reader with embedded quotes generates incorrect output #78.
- Replace JUnit assert by simpler but equivalent calls. #159.
- Update gitignore to ignore idea and vscode #160.
- Update CSVBenchmark #165.
- Remove Whitespace Check Determines Delimiter Twice #167.
- Document and Automate CSV Benchmark Harness #166.
- Optimize Lexer Delimiter Check for One Character Delimiter #163.
- SpotBugs Error: Medium: org.apache.commons.csv.CSVParser.getHeaderNames() may expose internal representation by returning CSVParser.headerNames [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 599] EI_EXPOSE_REP.
- SpotBugs Error: Medium: new org.apache.commons.csv.CSVParser(Reader, CSVFormat, long, long) may expose internal representation by storing an externally mutable object into CSVParser.format [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 433] EI_EXPOSE_REP2.
- SpotBugs Error: Medium: new org.apache.commons.csv.CSVParser(Reader, CSVFormat, long, long) may expose internal representation by storing an externally mutable object into CSVParser.headerMap [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 437] EI_EXPOSE_REP2.
- SpotBugs Error: Medium: new org.apache.commons.csv.CSVParser(Reader, CSVFormat, long, long) may expose internal representation by storing an externally mutable object into CSVParser.headerNames [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 438] EI_EXPOSE_REP2.
- SpotBugs Error: Medium: new org.apache.commons.csv.CSVPrinter(Appendable, CSVFormat) may expose internal representation by storing an externally mutable object into CSVPrinter.format [org.apache.commons.csv.CSVPrinter] At CSVPrinter.java:[line 100] EI_EXPOSE_REP2.
- Formalize PerformanceTest #168.
- Reuse Buffers in Lexer for Delimiter Detection #162.
- Cleanup and Document Performance Test Harness #170.
- Update buffer position when reading line comment #120.
-
- Make CSVRecord#toList() public.
- Add CSVRecord#stream().
- Add CSVParser#stream().
- Make the method CSVRecord.putIn(Map) public.
- Add test cases for CSVRecord with get(Enum) and toString. #54.
- Add and use CSVFormat.Builder, deprecated CSVFormat#with methods, based on #73.
- Add support for String delimiters #76.
-
- Update org.junit.jupiter:junit-jupiter from 5.6.0 to 5.7.0, #84 #109
- Update tests from Apache Commons Lang 3.9 to 3.12.0.
- Update tests from commons-io:commons-io 2.6 to 2.11.0, #108.
- Bump actions/checkout from v1 to v2.3.4, #79, #92, #121.
- Bump commons-parent from 50 to 51 #80.
- Bump tests from opencsv from 3.1 to 5.5.1 #81, #137, #158.
- Update tests from super-csv from 2.2.1 to 2.4.0 #86.
- Bump build actions/setup-java from v1.4.0 to v2, #101, #113.
- Bump maven-pmd-plugin from 3.13.0 to 3.14.0 #122.
- Bump tests from org.mockito:mockito-core 3.2.4 -> 3.11.2; #88, #107, #110, #123, #128, #129, #156.
- Bump actions/cache from v2 to v2.1.6 #132, #153.
- Bump maven-checkstyle-plugin from 3.0.0 to 3.1.2 #131.
- Bump checkstyle from 8.29 to 8.44.
- Bump junit-jupiter from 5.7.0 to 5.8.0-M1 #133, #149.
- Bump commons.jacoco.version from 0.8.5 to 0.8.7 (Java 16).
- Bump commons.spotbugs.version from 4.0.4 to 4.3.0 (Java 16).
- Bump maven-javadoc-plugin from 3.2.0 to 3.3.0.
- Bump jmh-generator-annprocess from 1.5.2 to 1.32 #151.
- Bump PMD core from 6.29.0 to 6.36.0.
- Bump biz.aQute.bnd:biz.aQute.bndlib from 5.1.2 to 5.3.0.
-
-
- Add CSVRecord.isSet(int) method #52.
- Char escape doesn't work properly with quoting.
- Test case failures following CSVFormat#equals() update.
- CSVFormat withTrim() and withIgnoreSurroundingSpaces() need better docs.
- CSVFormat equals() and hashCode() don't use all fields.
- CSVFormat#validate() does not account for allowDuplicateHeaderNames #43.
- Post 1.7 release fixes.
- Upgrade test framework to JUnit 5 Jupiter #49, #50.
- A single empty header is allowed when not allowing empty column headers. #47.
- CSVRecord is not Serializable.
- Use test scope for supercsv #48.
- Update tests from H2 1.4.199 to 1.4.200.
- Update tests from Hamcrest 2.1 to 2.2.
- Update tests from Mockito 3.1.0 to 3.2.4.
- Fix typos in site and test #53.
- Fix typo performance test #55.
-
-
- Add predefined CSVFormats for printing MongoDB CSV and TSV.
- Fix escape character for POSTGRESQL_TEXT and POSTGRESQL_CSV formats.
- Site link "Source Repository" does not work.
- Add support for java.sql.Clob.
- Update to Java 8.
- Escape quotes in CLOBs #39.
- Cannot get headers in column order from CSVRecord.
- Update tests from H2 1.4.198 to 1.4.199.
-
-
- Add more documentation to CSVPrinter.
- Add autoFlush option for CsvPrinter. PR #24.
- The behavior of quote char using is not similar as Excel does when the first string contains CJK char(s).
- Don't quote cells just because they have UTF-8 encoded characters.
- Add API org.apache.commons.csv.CSVFormat.withSystemRecordSeparator().
- Inconsistency between Javadoc of CSVFormat DEFAULT EXCEL.
- Create CSVFormat.ORACLE preset.
- Some multi-iterator parsing peek sequences incorrectly consume elements.
- Parse method should avoid creating a redundant BufferedReader.
- Add predefined CSVFormats for printing MongoDB CSV and TSV.
-
-
- withNullString value is printed without quotes when QuoteMode.ALL is specified; add QuoteMode.ALL_NON_NULL. PR #17.
- Fix outdated comments about FileReader in CSVParser #13
- Fix incorrect method name 'withFirstRowAsHeader' in user guide.
- Negative numeric values in the first column are always quoted in minimal mode.
- Update platform requirement from Java 6 to 7.
- Do not use RuntimeException in CSVParser.iterator().new Iterator() {...}.getNextRecord()
- CSVParser: Add factory method accepting InputStream.
- Add convenience API CSVFormat.print(File, Charset)
- Add convenience API CSVFormat.print(Path, Charset)
- Add convenience API CSVParser.parse(Path, Charset, CSVFormat)
- Add convenience API CSVFormat#printer() to print to System.out
- Provide a CSV Format for printing PostgreSQL CSV and Text formats.
- Adding a placeholder in the Lexer and CSV parser to store the end-of-line string.
-
-
- Make CSVPrinter.print(Object) GC-free.
- Allow some printing operations directly from CSVFormat.
- Drop ferc.gov tests.
-
-
- Add shortcut method for using first record as header to CSVFormat
- Add withHeader(Class<? extends Enum>) to CSVFormat
- Comment line hides next record; update Javadoc to make behavior clear
- CSVPrinter doesn't skip creation of header record if skipHeaderRecord is set to true
- Add IgnoreCase option for accessing header names
- The null string should be case-sensitive when reading records
- CSVFormat.nullString should not be escaped
- CSVFormat.MYSQL nullString should be "\N"
- Fix Javadoc to say CSVFormat with() methods return a new CSVFormat
- Support for ignoring trailing delimiter.
- Support trimming leading and trailing blanks.
- Create default formats for Informix UNLOAD and UNLOAD CSV.
-
-
- 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 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
-
-
-
-
+
+
+
+
+
+
+
+ Apache Commons CSV Release Notes
+
+
+
+
+ Release history link changed from changes-report.html to changes.html #516.
+
+
+ Bump com.opencsv:opencsv from 5.9 to 5.10.
+
+
+
+ Required OSGi Import-Package version numbers in MANIFEST.MF #504.
+ CSVParser.nextRecord() should throw CSVException (an IOException subclass) instead of IOException and IllegalStateException, no method signature changes needed.
+
+ Add CSVPrinter.getRecordCount().
+ Add and use CSVParser.Builder and builder() and deprecate CSVParser constructors.
+ CSVFormat.Builder implements Supplier<CSVFormat>.
+ Deprecate CSVFormat.Builder.build() for get().
+ Track byte position #502.
+
+ Bump org.apache.commons:commons-parent from 76 to 78 #486, #495.
+ Bump org.codehaus.mojo:taglist-maven-plugin from 3.1.0 to 3.2.1 #493.
+ Bump commons-io:commons-io from 2.17.0 to 2.18.0 #505.
+ Bump commons-codec:commons-codec from 1.17.1 to 1.17.2.
+ Bump org.apache.commons:commons-parent from 78 to 79.
+
+
+
+ Add CSVException that extends IOException thrown on invalid input instead of IOException.
+
+ Fix PMD issues for port to PMD 7.1.0.
+ Fix some Javadoc links #442.
+ Extract duplicated code into a method #444.
+ Migrate CSVFormat#print(File, Charset) to NIO #445.
+ Fix documentation for CSVFormat private constructor #466.
+ CSVFormat does not support explicit " as escape char.
+ Escaping is not disableable.
+ Fix Javadoc warnings on Java 23.
+ Improve parser performance by up to 20%, YMMV.
+
+ Bump commons-codec:commons-codec from 1.16.1 to 1.17.1 #422, #449.
+ Bump org.apache.commons:commons-parent from 69 to 76 #435, #452, #465, #468, #475, #482.
+ Bump org.codehaus.mojo:taglist-maven-plugin from 3.0.0 to 3.1.0 #441.
+ Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.17.0 #450, #459, #470.
+ Bump org.hamcrest:hamcrest from 2.2 to 3.0 #455.
+ Bump commons-io:commons-io from 2.16.1 to 2.17.0 #476.
+
+
+
+ [Javadoc] Add example to CSVFormat#setHeaderComments() #344.
+ Add and use CSVFormat#setTrailingData(boolean) in CSVFormat.EXCEL for Excel compatibility #303.
+ Add and use CSVFormat#setLenientEof(boolean) in CSVFormat.EXCEL for Excel compatibility #303.
+
+ Replace deprecated method in user guide, update external link #324, #325.
+ Document duplicate header behavior #309.
+ Add missing docs #328.
+ [StepSecurity] CI: Harden GitHub Actions #329, #330.
+ Better error message during faulty CSV record read #347.
+ Misleading error message when QuoteMode set to None #352.
+ OutOfMemory for very long rows despite using column value of type Reader.
+ Use try-with-resources to manage JDBC CLOB in CSVPrinter.printRecords(ResultSet).
+ JDBC Blob columns are now output as Base64 instead of Object#toString(), which usually is InputStream#toString().
+ Support unusual Excel use cases: Add support for trailing data after the closing quote, and EOF without a final closing quote #303.
+ MongoDB CSV empty first column parsing fix #412.
+
+ Bump commons-io:commons-io: from 2.11.0 to 2.16.1 #408, #413.
+ Bump commons-parent from 57 to 69 #410.
+ Bump h2 from 2.1.214 to 2.2.224 #333, #349, #359.
+ Bump commons-lang3 from 3.12.0 to 3.14.0.
+ Update exception message in CSVRecord#getNextRecord() #348.
+ Bump tests using com.opencsv:opencsv from 5.8 to 5.9 #373.
+
+
+
+ Minor changes #172.
+ No Automatic-Module-Name prevents usage in JPMS projects without repacking the JAR.
+ Fix for multi-char delimiter not working as expected #218.
+ CSVRecord.get(Enum) should use Enum.name() instead of Enum.toString().
+ Allow org.apache.commons.csv.IOUtils.copy(Reader, Appendable, CharBuffer) to compile on Java 11 and run on Java 8.
+ CSVRecord.toList() does not give write access to the new List.
+ CSVParser.getRecords() now throws UncheckedIOException instead of IOException.
+ Add comments to iterator() and stream() #270.
+ Fix wrong assumptions in PostgreSQL formats #265.
+ Validate input to setDelimiter(String) for empty string #266.
+ Bump CSVFormat#serialVersionUID from 1 to 2.
+ CSVParser: Identify duplicates in null, empty and blank header names #279.
+
+ Serialization in CSVFormat is not supported from one version to the next.
+
+ Make CSVRecord#values() public.
+ Add DuplicateHeaderMode for flexibility with header strictness. #114.
+ Support for parallelism in CSVPrinter.
+ Add CSVPrinter.printRecord[s](Stream).
+ Add accessors for header/trailer comments #257.
+ Add github/codeql-action.
+
+ Bump actions/cache from 2.1.6 to 3.0.10 #196, #233, #243, #267, #271.
+ Bump actions/checkout from 2.3.4 to 3.1.0 #188, #195, #220, #272.
+ Bump actions/setup-java from 2 to 3.5.1.
+ Bump actions/upload-artifact from 3.1.0 to 3.1.1 #280.
+ Bump commons-parent from 52 to 57 #264, #288, #298, #323.
+ Bump checkstyle from 8.44 to 9.2.1 #180, #190, #194, #202, #207.
+ Bump junit-jupiter from 5.8.0-M1 to 5.9.1 #179, #186, #201, #244, #263.
+ Bump jmh-core from 1.32 to 1.36 #176, #208, #229, #285.
+ Bump jmh-generator-annprocess from 1.32 to 1.36 #175, #206, #226, #283.
+ Bump mockito-core from 3.11.2 to 4.11.0 #187, #197, #204, #212, #230, #237, #251, #259, #284, #292, #297.
+ Bump maven-pmd-plugin from 3.14.0 to 3.19.0 #184, #219, #238, #254, #258.
+ Bump pmd from 6.36.0 to 6.52.0 #173, #189, #193, #199, #227, #233, #214, #236, #240, #247, #255, #273.
+ Bump opencsv from 5.5.1 to 5.7.1 #182, #221, #260, #281.
+ Bump spotbugs-maven-plugin from 4.3.0 to 4.7.3.0 #192, #198, #203, #211, #225, #234, #242, #245, #261, #275, #282.
+ Bump com.github.spotbugs:spotbugs from 4.5.3 to 4.7.2.
+ Bump h2 from 1.4.200 to 2.1.214 #200, #205, #213, #239.
+ Bump maven-javadoc-plugin from 3.3.0 to 3.4.1.
+ Bump biz.aQute.bnd:biz.aQute.bndlib from 5.3.0 to 6.3.1.
+ Bump jacoco-maven-plugin from 0.8.7 to 0.8.8.
+ Bump japicmp-maven-plugin from 0.15.3 to 0.16.0.
+ Bump maven-checkstyle-plugin from 3.1.2 to 3.2.0 #253.
+
+
+
+ Replace FindBugs with SpotBugs #56.
+ Javadoc typo in CSVFormat let's -> lets #57.
+ CSVFormat.printWithEscapes throws StringIndexOutOfBoundsException when value is Reader #61.
+ Improve CSVFormat test coverage #63.
+ Fix CSVFileParserTest.java to allow for a null return value from record.getComment() #62.
+ Improve test coverage in CSVFormatTest #65.
+ Removed invalid Javadoc markup for CSVFormat EXCEL #64.
+ Improve CSVRecord and CSVPrinter code coverage #66.
+ Improve lexer and token coverage #67.
+ CSVFormat.format trims last delimiter if the delimiter is a white space #71.
+ Replace org.apache.commons.csv.Assertions.notNull() with Objects.requireNonNull().
+ Line number is not proper at EOF.
+ Parser iterates over the last CSV Record twice.
+ Minor improvements #126, #127, #130.
+ Add possibility to use ResultSet header meta data as CSV header #11.
+ Add test cases for withIgnoreSurroundingSpaces() and withTrim() #70.
+ Update CSVParser.parse(File, Charset, CSVFormat) from IO to NIO.
+ Missing separator with print(object) followed by printRecord(Object[]) #157.
+ Fix EOL checking for read array in ExtendedBufferedReader #5.
+ Print from Reader with embedded quotes generates incorrect output #78.
+ Replace JUnit assert by simpler but equivalent calls. #159.
+ Update gitignore to ignore idea and vscode #160.
+ Update CSVBenchmark #165.
+ Remove Whitespace Check Determines Delimiter Twice #167.
+ Document and Automate CSV Benchmark Harness #166.
+ Optimize Lexer Delimiter Check for One Character Delimiter #163.
+ SpotBugs Error: Medium: org.apache.commons.csv.CSVParser.getHeaderNames() may expose internal representation by returning CSVParser.headerNames [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 599] EI_EXPOSE_REP.
+ SpotBugs Error: Medium: new org.apache.commons.csv.CSVParser(Reader, CSVFormat, long, long) may expose internal representation by storing an externally mutable object into CSVParser.format [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 433] EI_EXPOSE_REP2.
+ SpotBugs Error: Medium: new org.apache.commons.csv.CSVParser(Reader, CSVFormat, long, long) may expose internal representation by storing an externally mutable object into CSVParser.headerMap [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 437] EI_EXPOSE_REP2.
+ SpotBugs Error: Medium: new org.apache.commons.csv.CSVParser(Reader, CSVFormat, long, long) may expose internal representation by storing an externally mutable object into CSVParser.headerNames [org.apache.commons.csv.CSVParser] At CSVParser.java:[line 438] EI_EXPOSE_REP2.
+ SpotBugs Error: Medium: new org.apache.commons.csv.CSVPrinter(Appendable, CSVFormat) may expose internal representation by storing an externally mutable object into CSVPrinter.format [org.apache.commons.csv.CSVPrinter] At CSVPrinter.java:[line 100] EI_EXPOSE_REP2.
+ Formalize PerformanceTest #168.
+ Reuse Buffers in Lexer for Delimiter Detection #162.
+ Cleanup and Document Performance Test Harness #170.
+ Update buffer position when reading line comment #120.
+
+ Make CSVRecord#toList() public.
+ Add CSVRecord#stream().
+ Add CSVParser#stream().
+ Make the method CSVRecord.putIn(Map) public.
+ Add test cases for CSVRecord with get(Enum) and toString. #54.
+ Add and use CSVFormat.Builder, deprecated CSVFormat#with methods, based on #73.
+ Add support for String delimiters #76.
+
+ Update org.junit.jupiter:junit-jupiter from 5.6.0 to 5.7.0, #84 #109
+ Update tests from Apache Commons Lang 3.9 to 3.12.0.
+ Update tests from commons-io:commons-io 2.6 to 2.11.0, #108.
+ Bump actions/checkout from v1 to v2.3.4, #79, #92, #121.
+ Bump commons-parent from 50 to 51 #80.
+ Bump tests from opencsv from 3.1 to 5.5.1 #81, #137, #158.
+ Update tests from super-csv from 2.2.1 to 2.4.0 #86.
+ Bump build actions/setup-java from v1.4.0 to v2, #101, #113.
+ Bump maven-pmd-plugin from 3.13.0 to 3.14.0 #122.
+ Bump tests from org.mockito:mockito-core 3.2.4 -> 3.11.2; #88, #107, #110, #123, #128, #129, #156.
+ Bump actions/cache from v2 to v2.1.6 #132, #153.
+ Bump maven-checkstyle-plugin from 3.0.0 to 3.1.2 #131.
+ Bump checkstyle from 8.29 to 8.44.
+ Bump junit-jupiter from 5.7.0 to 5.8.0-M1 #133, #149.
+ Bump commons.jacoco.version from 0.8.5 to 0.8.7 (Java 16).
+ Bump commons.spotbugs.version from 4.0.4 to 4.3.0 (Java 16).
+ Bump maven-javadoc-plugin from 3.2.0 to 3.3.0.
+ Bump jmh-generator-annprocess from 1.5.2 to 1.32 #151.
+ Bump PMD core from 6.29.0 to 6.36.0.
+ Bump biz.aQute.bnd:biz.aQute.bndlib from 5.1.2 to 5.3.0.
+
+
+ Add CSVRecord.isSet(int) method #52.
+ Char escape doesn't work properly with quoting.
+ Test case failures following CSVFormat#equals() update.
+ CSVFormat withTrim() and withIgnoreSurroundingSpaces() need better docs.
+ CSVFormat equals() and hashCode() don't use all fields.
+ CSVFormat#validate() does not account for allowDuplicateHeaderNames #43.
+ Post 1.7 release fixes.
+ Upgrade test framework to JUnit 5 Jupiter #49, #50.
+ A single empty header is allowed when not allowing empty column headers. #47.
+ CSVRecord is not Serializable.
+ Use test scope for supercsv #48.
+ Update tests from H2 1.4.199 to 1.4.200.
+ Update tests from Hamcrest 2.1 to 2.2.
+ Update tests from Mockito 3.1.0 to 3.2.4.
+ Fix typos in site and test #53.
+ Fix typo performance test #55.
+
+
+ Add predefined CSVFormats for printing MongoDB CSV and TSV.
+ Fix escape character for POSTGRESQL_TEXT and POSTGRESQL_CSV formats.
+ Site link "Source Repository" does not work.
+ Add support for java.sql.Clob.
+ Update to Java 8.
+ Escape quotes in CLOBs #39.
+ Cannot get headers in column order from CSVRecord.
+ Update tests from H2 1.4.198 to 1.4.199.
+
+
+ Add more documentation to CSVPrinter.
+ Add autoFlush option for CsvPrinter. PR #24.
+ The behavior of quote char using is not similar as Excel does when the first string contains CJK char(s).
+ Don't quote cells just because they have UTF-8 encoded characters.
+ Add API org.apache.commons.csv.CSVFormat.withSystemRecordSeparator().
+ Inconsistency between Javadoc of CSVFormat DEFAULT EXCEL.
+ Create CSVFormat.ORACLE preset.
+ Some multi-iterator parsing peek sequences incorrectly consume elements.
+ Parse method should avoid creating a redundant BufferedReader.
+ Add predefined CSVFormats for printing MongoDB CSV and TSV.
+
+
+ withNullString value is printed without quotes when QuoteMode.ALL is specified; add QuoteMode.ALL_NON_NULL. PR #17.
+ Fix outdated comments about FileReader in CSVParser #13
+ Fix incorrect method name 'withFirstRowAsHeader' in user guide.
+ Negative numeric values in the first column are always quoted in minimal mode.
+ Update platform requirement from Java 6 to 7.
+ Do not use RuntimeException in CSVParser.iterator().new Iterator() {...}.getNextRecord()
+ CSVParser: Add factory method accepting InputStream.
+ Add convenience API CSVFormat.print(File, Charset)
+ Add convenience API CSVFormat.print(Path, Charset)
+ Add convenience API CSVParser.parse(Path, Charset, CSVFormat)
+ Add convenience API CSVFormat#printer() to print to System.out
+ Provide a CSV Format for printing PostgreSQL CSV and Text formats.
+ Adding a placeholder in the Lexer and CSV parser to store the end-of-line string.
+
+
+ Make CSVPrinter.print(Object) GC-free.
+ Allow some printing operations directly from CSVFormat.
+ Drop ferc.gov tests.
+
+
+ Add shortcut method for using first record as header to CSVFormat
+ Add withHeader(Class<? extends Enum>) to CSVFormat
+ Comment line hides next record; update Javadoc to make behavior clear
+ CSVPrinter doesn't skip creation of header record if skipHeaderRecord is set to true
+ Add IgnoreCase option for accessing header names
+ The null string should be case-sensitive when reading records
+ CSVFormat.nullString should not be escaped
+ CSVFormat.MYSQL nullString should be "\N"
+ Fix Javadoc to say CSVFormat with() methods return a new CSVFormat
+ Support for ignoring trailing delimiter.
+ Support trimming leading and trailing blanks.
+ Create default formats for Informix UNLOAD and UNLOAD CSV.
+
+
+ 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 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
+
+
+
+
diff --git a/src/main/java/org/apache/commons/csv/CSVPrinter.java b/src/main/java/org/apache/commons/csv/CSVPrinter.java
index dce94692d7..67088c38a5 100644
--- a/src/main/java/org/apache/commons/csv/CSVPrinter.java
+++ b/src/main/java/org/apache/commons/csv/CSVPrinter.java
@@ -1,520 +1,520 @@
-/*
- * 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
- *
- * https://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.LF;
-import static org.apache.commons.csv.Constants.SP;
-
-import java.io.Closeable;
-import java.io.Flushable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Objects;
-import java.util.stream.Stream;
-
-import org.apache.commons.io.function.IOStream;
-
-/**
- * Prints values in a {@link CSVFormat CSV format}.
- *
- *
Values can be appended to the output by calling the {@link #print(Object)} method.
- * Values are printed according to {@link String#valueOf(Object)}.
- * To complete a record the {@link #println()} method has to be called.
- * Comments can be appended by calling {@link #printComment(String)}.
- * However a comment will only be written to the output if the {@link CSVFormat} supports comments.
- *
- *
- * The printer also supports appending a complete record at once by calling {@link #printRecord(Object...)}
- * or {@link #printRecord(Iterable)}.
- * Furthermore {@link #printRecords(Object...)}, {@link #printRecords(Iterable)} and {@link #printRecords(ResultSet)}
- * methods can be used to print several records at once.
- *
- *
- * Example:
- *
- *
- * try (CSVPrinter printer = new CSVPrinter(new FileWriter("csv.txt"), CSVFormat.EXCEL)) {
- * printer.printRecord("id", "userName", "firstName", "lastName", "birthday");
- * printer.printRecord(1, "john73", "John", "Doe", LocalDate.of(1973, 9, 15));
- * printer.println();
- * printer.printRecord(2, "mary", "Mary", "Meyer", LocalDate.of(1985, 3, 29));
- * } catch (IOException ex) {
- * ex.printStackTrace();
- * }
- *
- *
- * This code will write the following to csv.txt:
- *
- * id,userName,firstName,lastName,birthday
- * 1,john73,John,Doe,1973-09-15
- *
- * 2,mary,Mary,Meyer,1985-03-29
- *
- */
-public final class CSVPrinter implements Flushable, Closeable {
-
- /** The place that the values get written. */
- private final Appendable appendable;
-
- private final CSVFormat format;
-
- /** True if we just began a new record. */
- private boolean newRecord = true;
-
- private long recordCount;
-
- /**
- * 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 appendable
- * 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 appendable, final CSVFormat format) throws IOException {
- Objects.requireNonNull(appendable, "appendable");
- Objects.requireNonNull(format, "format");
-
- this.appendable = appendable;
- this.format = format.copy();
- // 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.
- final String[] headerComments = format.getHeaderComments();
- if (headerComments != null) {
- for (final String line : headerComments) {
- printComment(line);
- }
- }
- if (format.getHeader() != null && !format.getSkipHeaderRecord()) {
- this.printRecord((Object[]) format.getHeader());
- }
- }
-
- @Override
- public void close() throws IOException {
- close(false);
- }
-
- /**
- * Closes the underlying stream with an optional flush first.
- * @param flush whether to flush before the actual close.
- * @throws IOException
- * If an I/O error occurs
- * @since 1.6
- */
- public void close(final boolean flush) throws IOException {
- if (flush || format.getAutoFlush()) {
- flush();
- }
- if (appendable instanceof Closeable) {
- ((Closeable) appendable).close();
- }
- }
-
- /**
- * Outputs the record separator and increments the record count.
- *
- * @throws IOException
- * If an I/O error occurs
- */
- private synchronized void endOfRecord() throws IOException {
- println();
- recordCount++;
- }
-
- /**
- * Flushes the underlying stream.
- *
- * @throws IOException
- * If an I/O error occurs
- */
- @Override
- public void flush() throws IOException {
- if (appendable instanceof Flushable) {
- ((Flushable) appendable).flush();
- }
- }
-
- /**
- * Gets the target Appendable.
- *
- * @return the target Appendable.
- */
- public Appendable getOut() {
- return this.appendable;
- }
-
- /**
- * Gets the record count printed, this does not include comments or headers.
- *
- * @return the record count, this does not include comments or headers.
- * @since 1.13.0
- */
- public long getRecordCount() {
- return recordCount;
- }
-
- /**
- * 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 synchronized void print(final Object value) throws IOException {
- format.print(value, appendable, newRecord);
- newRecord = false;
- }
-
- /**
- * Prints a comment on a new line among the delimiter-separated values.
- *
- *
- * Comments will always begin on a new line and occupy at 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.
- *
- *
- * This method detects line breaks inside the comment string and inserts {@link CSVFormat#getRecordSeparator()}
- * to start a new line of the comment. Note that this might produce unexpected results for formats that do not use
- * line breaks as record separators.
- *
- * @param comment
- * the comment to output
- * @throws IOException
- * If an I/O error occurs
- */
- public synchronized void printComment(final String comment) throws IOException {
- if (comment == null || !format.isCommentMarkerSet()) {
- return;
- }
- if (!newRecord) {
- println();
- }
- appendable.append(format.getCommentMarker().charValue()); // N.B. Explicit (un)boxing is intentional
- appendable.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++;
- }
- // falls-through: break intentionally excluded.
- case LF:
- println();
- appendable.append(format.getCommentMarker().charValue()); // N.B. Explicit (un)boxing is intentional
- appendable.append(SP);
- break;
- default:
- appendable.append(c);
- break;
- }
- }
- println();
- }
-
- /**
- * Prints headers for a result set based on its metadata.
- *
- * @param resultSet The ResultSet to query for metadata.
- * @throws IOException If an I/O error occurs.
- * @throws SQLException If a database access error occurs or this method is called on a closed result set.
- * @since 1.9.0
- */
- public synchronized void printHeaders(final ResultSet resultSet) throws IOException, SQLException {
- try (IOStream stream = IOStream.of(format.builder().setHeader(resultSet).get().getHeader())) {
- stream.forEachOrdered(this::print);
- }
- println();
- }
-
- /**
- * Outputs the record separator.
- *
- * @throws IOException
- * If an I/O error occurs
- */
- public synchronized void println() throws IOException {
- format.println(appendable);
- newRecord = true;
- }
-
- /**
- * Prints the given values as 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
- */
- @SuppressWarnings("resource")
- public synchronized void printRecord(final Iterable> values) throws IOException {
- IOStream.of(values).forEachOrdered(this::print);
- endOfRecord();
- }
-
- /**
- * Prints the given values as 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 {
- printRecord(Arrays.asList(values));
- }
-
- /**
- * Prints the given values as 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
- * @since 1.10.0
- */
- @SuppressWarnings("resource") // caller closes.
- public synchronized void printRecord(final Stream> values) throws IOException {
- IOStream.adapt(values).forEachOrdered(this::print);
- endOfRecord();
- }
-
- private void printRecordObject(final Object value) throws IOException {
- 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 {@link Iterable} handling nested collections/arrays as records.
- *
- *
- * If the given Iterable only contains simple objects, this method will print a single record like
- * {@link #printRecord(Iterable)}. If the given Iterable contains nested collections/arrays those nested elements
- * will each be printed as records using {@link #printRecord(Object...)}.
- *
- *
- *
- * Given the following data structure:
- *
- *
- * {@code
- * List data = new ArrayList<>();
- * 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:
- *
- *
- *
- * {@code
- * A, B, C
- * 1, 2, 3
- * A1, B2, C3
- * }
- *
- *
- * @param values
- * the values to print.
- * @throws IOException
- * If an I/O error occurs
- */
- @SuppressWarnings("resource")
- public void printRecords(final Iterable> values) throws IOException {
- IOStream.of(values).forEachOrdered(this::printRecordObject);
- }
-
- /**
- * 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 contain nested collections or arrays, those nested
- * elements will each be printed as records using {@link #printRecord(Object...)}.
- *
- *
- *
- * Given the following data structure:
- *
- *
- * {@code
- * 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:
- *
- *
- * {@code
- * 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 {
- printRecords(Arrays.asList(values));
- }
-
- /**
- * Prints all the objects in the given JDBC result set.
- *
- * @param resultSet
- * The values to print.
- * @throws IOException
- * If an I/O error occurs.
- * @throws SQLException
- * Thrown when 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++) {
- final Object object = resultSet.getObject(i);
- if (object instanceof Clob) {
- try (Reader reader = ((Clob) object).getCharacterStream()) {
- print(reader);
- }
- } else if (object instanceof Blob) {
- try (InputStream inputStream = ((Blob) object).getBinaryStream()) {
- print(inputStream);
- }
- } else {
- print(object);
- }
- }
- endOfRecord();
- }
- }
-
- /**
- * Prints all the objects with metadata in the given JDBC result set based on the header boolean.
- *
- * @param resultSet source of row data.
- * @param printHeader whether to print headers.
- * @throws IOException If an I/O error occurs
- * @throws SQLException if a database access error occurs
- * @since 1.9.0
- */
- public void printRecords(final ResultSet resultSet, final boolean printHeader) throws SQLException, IOException {
- if (printHeader) {
- printHeaders(resultSet);
- }
- printRecords(resultSet);
- }
-
- /**
- * Prints all the objects in the given {@link Stream} handling nested collections/arrays as records.
- *
- *
- * If the given Stream only contains simple objects, this method will print a single record like
- * {@link #printRecord(Iterable)}. If the given Stream contains nested collections/arrays those nested elements
- * will each be printed as records using {@link #printRecord(Object...)}.
- *
- *
- *
- * Given the following data structure:
- *
- *
- * {@code
- * List data = new ArrayList<>();
- * data.add(new String[]{ "A", "B", "C" });
- * data.add(new String[]{ "1", "2", "3" });
- * data.add(new String[]{ "A1", "B2", "C3" });
- * Stream stream = data.stream();
- * }
- *
- *
- *
- * Calling this method will print:
- *
- *
- *
- * {@code
- * A, B, C
- * 1, 2, 3
- * A1, B2, C3
- * }
- *
- *
- * @param values
- * the values to print.
- * @throws IOException
- * If an I/O error occurs
- * @since 1.10.0
- */
- @SuppressWarnings({ "resource" }) // Caller closes.
- public void printRecords(final Stream> values) throws IOException {
- IOStream.adapt(values).forEachOrdered(this::printRecordObject);
- }
-}
+/*
+ * 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
+ *
+ * https://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.LF;
+import static org.apache.commons.csv.Constants.SP;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import org.apache.commons.io.function.IOStream;
+
+/**
+ * Prints values in a {@link CSVFormat CSV format}.
+ *
+ * Values can be appended to the output by calling the {@link #print(Object)} method.
+ * Values are printed according to {@link String#valueOf(Object)}.
+ * To complete a record the {@link #println()} method has to be called.
+ * Comments can be appended by calling {@link #printComment(String)}.
+ * However a comment will only be written to the output if the {@link CSVFormat} supports comments.
+ *
+ *
+ * The printer also supports appending a complete record at once by calling {@link #printRecord(Object...)}
+ * or {@link #printRecord(Iterable)}.
+ * Furthermore {@link #printRecords(Object...)}, {@link #printRecords(Iterable)} and {@link #printRecords(ResultSet)}
+ * methods can be used to print several records at once.
+ *
+ *
+ * Example:
+ *
+ *
+ * try (CSVPrinter printer = new CSVPrinter(new FileWriter("csv.txt"), CSVFormat.EXCEL)) {
+ * printer.printRecord("id", "userName", "firstName", "lastName", "birthday");
+ * printer.printRecord(1, "john73", "John", "Doe", LocalDate.of(1973, 9, 15));
+ * printer.println();
+ * printer.printRecord(2, "mary", "Mary", "Meyer", LocalDate.of(1985, 3, 29));
+ * } catch (IOException ex) {
+ * ex.printStackTrace();
+ * }
+ *
+ *
+ * This code will write the following to csv.txt:
+ *
+ * id,userName,firstName,lastName,birthday
+ * 1,john73,John,Doe,1973-09-15
+ *
+ * 2,mary,Mary,Meyer,1985-03-29
+ *
+ */
+public final class CSVPrinter implements Flushable, Closeable {
+
+ /** The place that the values get written. */
+ private final Appendable appendable;
+
+ private final CSVFormat format;
+
+ /** True if we just began a new record. */
+ private boolean newRecord = true;
+
+ private long recordCount;
+
+ /**
+ * 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 appendable
+ * 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 appendable, final CSVFormat format) throws IOException {
+ Objects.requireNonNull(appendable, "appendable");
+ Objects.requireNonNull(format, "format");
+
+ this.appendable = appendable;
+ this.format = format.copy();
+ // 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.
+ final String[] headerComments = format.getHeaderComments();
+ if (headerComments != null) {
+ for (final String line : headerComments) {
+ printComment(line);
+ }
+ }
+ if (format.getHeader() != null && !format.getSkipHeaderRecord()) {
+ this.printRecord((Object[]) format.getHeader());
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ close(false);
+ }
+
+ /**
+ * Closes the underlying stream with an optional flush first.
+ * @param flush whether to flush before the actual close.
+ * @throws IOException
+ * If an I/O error occurs
+ * @since 1.6
+ */
+ public void close(final boolean flush) throws IOException {
+ if (flush || format.getAutoFlush()) {
+ flush();
+ }
+ if (appendable instanceof Closeable) {
+ ((Closeable) appendable).close();
+ }
+ }
+
+ /**
+ * Outputs the record separator and increments the record count.
+ *
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ private synchronized void endOfRecord() throws IOException {
+ println();
+ recordCount++;
+ }
+
+ /**
+ * Flushes the underlying stream.
+ *
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ @Override
+ public void flush() throws IOException {
+ if (appendable instanceof Flushable) {
+ ((Flushable) appendable).flush();
+ }
+ }
+
+ /**
+ * Gets the target Appendable.
+ *
+ * @return the target Appendable.
+ */
+ public Appendable getOut() {
+ return this.appendable;
+ }
+
+ /**
+ * Gets the record count printed, this does not include comments or headers.
+ *
+ * @return the record count, this does not include comments or headers.
+ * @since 1.13.0
+ */
+ public long getRecordCount() {
+ return recordCount;
+ }
+
+ /**
+ * 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 synchronized void print(final Object value) throws IOException {
+ format.print(value, appendable, newRecord);
+ newRecord = false;
+ }
+
+ /**
+ * Prints a comment on a new line among the delimiter-separated values.
+ *
+ *
+ * Comments will always begin on a new line and occupy at 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.
+ *
+ *
+ * This method detects line breaks inside the comment string and inserts {@link CSVFormat#getRecordSeparator()}
+ * to start a new line of the comment. Note that this might produce unexpected results for formats that do not use
+ * line breaks as record separators.
+ *
+ * @param comment
+ * the comment to output
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ public synchronized void printComment(final String comment) throws IOException {
+ if (comment == null || !format.isCommentMarkerSet()) {
+ return;
+ }
+ if (!newRecord) {
+ println();
+ }
+ appendable.append(format.getCommentMarker().charValue()); // N.B. Explicit (un)boxing is intentional
+ appendable.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++;
+ }
+ // falls-through: break intentionally excluded.
+ case LF:
+ println();
+ appendable.append(format.getCommentMarker().charValue()); // N.B. Explicit (un)boxing is intentional
+ appendable.append(SP);
+ break;
+ default:
+ appendable.append(c);
+ break;
+ }
+ }
+ println();
+ }
+
+ /**
+ * Prints headers for a result set based on its metadata.
+ *
+ * @param resultSet The ResultSet to query for metadata.
+ * @throws IOException If an I/O error occurs.
+ * @throws SQLException If a database access error occurs or this method is called on a closed result set.
+ * @since 1.9.0
+ */
+ public synchronized void printHeaders(final ResultSet resultSet) throws IOException, SQLException {
+ try (IOStream stream = IOStream.of(format.builder().setHeader(resultSet).get().getHeader())) {
+ stream.forEachOrdered(this::print);
+ }
+ println();
+ }
+
+ /**
+ * Outputs the record separator.
+ *
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ public synchronized void println() throws IOException {
+ format.println(appendable);
+ newRecord = true;
+ }
+
+ /**
+ * Prints the given values as 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
+ */
+ @SuppressWarnings("resource")
+ public synchronized void printRecord(final Iterable> values) throws IOException {
+ IOStream.of(values).forEachOrdered(this::print);
+ endOfRecord();
+ }
+
+ /**
+ * Prints the given values as 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 {
+ printRecord(Arrays.asList(values));
+ }
+
+ /**
+ * Prints the given values as 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
+ * @since 1.10.0
+ */
+ @SuppressWarnings("resource") // caller closes.
+ public synchronized void printRecord(final Stream> values) throws IOException {
+ IOStream.adapt(values).forEachOrdered(this::print);
+ endOfRecord();
+ }
+
+ private void printRecordObject(final Object value) throws IOException {
+ 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 {@link Iterable} handling nested collections/arrays as records.
+ *
+ *
+ * If the given Iterable only contains simple objects, this method will print a single record like
+ * {@link #printRecord(Iterable)}. If the given Iterable contains nested collections/arrays those nested elements
+ * will each be printed as records using {@link #printRecord(Object...)}.
+ *
+ *
+ *
+ * Given the following data structure:
+ *
+ *
+ * {@code
+ * List data = new ArrayList<>();
+ * 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:
+ *
+ *
+ *
+ * {@code
+ * A, B, C
+ * 1, 2, 3
+ * A1, B2, C3
+ * }
+ *
+ *
+ * @param values
+ * the values to print.
+ * @throws IOException
+ * If an I/O error occurs
+ */
+ @SuppressWarnings("resource")
+ public void printRecords(final Iterable> values) throws IOException {
+ IOStream.of(values).forEachOrdered(this::printRecordObject);
+ }
+
+ /**
+ * 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 contain nested collections or arrays, those nested
+ * elements will each be printed as records using {@link #printRecord(Object...)}.
+ *
+ *
+ *
+ * Given the following data structure:
+ *
+ *
+ * {@code
+ * 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:
+ *
+ *
+ * {@code
+ * 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 {
+ printRecords(Arrays.asList(values));
+ }
+
+ /**
+ * Prints all the objects in the given JDBC result set.
+ *
+ * @param resultSet
+ * The values to print.
+ * @throws IOException
+ * If an I/O error occurs.
+ * @throws SQLException
+ * Thrown when 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++) {
+ final Object object = resultSet.getObject(i);
+ if (object instanceof Clob) {
+ try (Reader reader = ((Clob) object).getCharacterStream()) {
+ print(reader);
+ }
+ } else if (object instanceof Blob) {
+ try (InputStream inputStream = ((Blob) object).getBinaryStream()) {
+ print(inputStream);
+ }
+ } else {
+ print(object);
+ }
+ }
+ endOfRecord();
+ }
+ }
+
+ /**
+ * Prints all the objects with metadata in the given JDBC result set based on the header boolean.
+ *
+ * @param resultSet source of row data.
+ * @param printHeader whether to print headers.
+ * @throws IOException If an I/O error occurs
+ * @throws SQLException if a database access error occurs
+ * @since 1.9.0
+ */
+ public void printRecords(final ResultSet resultSet, final boolean printHeader) throws SQLException, IOException {
+ if (printHeader) {
+ printHeaders(resultSet);
+ }
+ printRecords(resultSet);
+ }
+
+ /**
+ * Prints all the objects in the given {@link Stream} handling nested collections/arrays as records.
+ *
+ *
+ * If the given Stream only contains simple objects, this method will print a single record like
+ * {@link #printRecord(Iterable)}. If the given Stream contains nested collections/arrays those nested elements
+ * will each be printed as records using {@link #printRecord(Object...)}.
+ *
+ *
+ *
+ * Given the following data structure:
+ *
+ *
+ * {@code
+ * List data = new ArrayList<>();
+ * data.add(new String[]{ "A", "B", "C" });
+ * data.add(new String[]{ "1", "2", "3" });
+ * data.add(new String[]{ "A1", "B2", "C3" });
+ * Stream stream = data.stream();
+ * }
+ *
+ *
+ *
+ * Calling this method will print:
+ *
+ *
+ *
+ * {@code
+ * A, B, C
+ * 1, 2, 3
+ * A1, B2, C3
+ * }
+ *
+ *
+ * @param values
+ * the values to print.
+ * @throws IOException
+ * If an I/O error occurs
+ * @since 1.10.0
+ */
+ @SuppressWarnings({ "resource" }) // Caller closes.
+ public void printRecords(final Stream> values) throws IOException {
+ IOStream.adapt(values).forEachOrdered(this::printRecordObject);
+ }
+}
diff --git a/src/main/java/org/apache/commons/csv/Constants.java b/src/main/java/org/apache/commons/csv/Constants.java
index 5f8a5cf465..e85578467d 100644
--- a/src/main/java/org/apache/commons/csv/Constants.java
+++ b/src/main/java/org/apache/commons/csv/Constants.java
@@ -1,90 +1,90 @@
-/*
- * 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
- *
- * https://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;
-
-/**
- * Private constants to this package.
- */
-final class Constants {
-
- static final char BACKSLASH = '\\';
-
- static final char BACKSPACE = '\b';
-
- static final String COMMA = ",";
-
- /**
- * Starts a comment, the remainder of the line is the comment.
- */
- static final char COMMENT = '#';
-
- static final char CR = '\r';
-
- /** RFC 4180 defines line breaks as CRLF */
- static final String CRLF = "\r\n";
-
- static final Character DOUBLE_QUOTE_CHAR = Character.valueOf('"'); // N.B. Explicit (un)boxing is intentional
-
- static final String EMPTY = "";
-
- static final String[] EMPTY_STRING_ARRAY = {};
-
- static final char FF = '\f';
-
- static final char LF = '\n';
-
- /**
- * Unicode line separator.
- */
- static final String LINE_SEPARATOR = "\u2028";
-
- /**
- * Unicode next line.
- */
- static final String NEXT_LINE = "\u0085";
-
- /**
- * Unicode paragraph separator.
- */
- static final String PARAGRAPH_SEPARATOR = "\u2029";
-
- static final char PIPE = '|';
-
- /** ASCII record separator */
- static final char RS = 30;
-
- static final char SP = ' ';
-
- static final String SQL_NULL_STRING = "\\N";
-
- static final char TAB = '\t';
-
- /** Undefined state for the lookahead char */
- static final int UNDEFINED = -2;
-
- /** ASCII unit separator */
- static final char US = 31;
-
- /** No instances. */
- private Constants() {
- // noop
- }
-
-}
+/*
+ * 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
+ *
+ * https://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;
+
+/**
+ * Private constants to this package.
+ */
+final class Constants {
+
+ static final char BACKSLASH = '\\';
+
+ static final char BACKSPACE = '\b';
+
+ static final String COMMA = ",";
+
+ /**
+ * Starts a comment, the remainder of the line is the comment.
+ */
+ static final char COMMENT = '#';
+
+ static final char CR = '\r';
+
+ /** RFC 4180 defines line breaks as CRLF */
+ static final String CRLF = "\r\n";
+
+ static final Character DOUBLE_QUOTE_CHAR = Character.valueOf('"'); // N.B. Explicit (un)boxing is intentional
+
+ static final String EMPTY = "";
+
+ static final String[] EMPTY_STRING_ARRAY = {};
+
+ static final char FF = '\f';
+
+ static final char LF = '\n';
+
+ /**
+ * Unicode line separator.
+ */
+ static final String LINE_SEPARATOR = "\u2028";
+
+ /**
+ * Unicode next line.
+ */
+ static final String NEXT_LINE = "\u0085";
+
+ /**
+ * Unicode paragraph separator.
+ */
+ static final String PARAGRAPH_SEPARATOR = "\u2029";
+
+ static final char PIPE = '|';
+
+ /** ASCII record separator */
+ static final char RS = 30;
+
+ static final char SP = ' ';
+
+ static final String SQL_NULL_STRING = "\\N";
+
+ static final char TAB = '\t';
+
+ /** Undefined state for the lookahead char */
+ static final int UNDEFINED = -2;
+
+ /** ASCII unit separator */
+ static final char US = 31;
+
+ /** No instances. */
+ private Constants() {
+ // noop
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java
index 50dfd0f891..9677d8ecc2 100644
--- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java
@@ -1,1533 +1,1533 @@
-/*
- * 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
- *
- * https://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.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNotSame;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Objects;
-
-import org.apache.commons.csv.CSVFormat.Builder;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-/**
- * Tests {@link CSVFormat}.
- */
-public class CSVFormatTest {
-
- public enum EmptyEnum {
- // empty enum.
- }
-
- public enum Header {
- Name, Email, Phone
- }
-
- private static void assertNotEquals(final Object right, final Object left) {
- Assertions.assertNotEquals(right, left);
- Assertions.assertNotEquals(left, right);
- }
-
- private static CSVFormat copy(final CSVFormat format) {
- return format.builder().setDelimiter(format.getDelimiter()).get();
- }
-
- private void assertNotEquals(final String name, final String type, final Object left, final Object right) {
- if (left.equals(right) || right.equals(left)) {
- fail("Objects must not compare equal for " + name + "(" + type + ")");
- }
- if (left.hashCode() == right.hashCode()) {
- fail("Hash code should not be equal for " + name + "(" + type + ")");
- }
- }
-
- @Test
- public void testBuildVsGet() {
- final Builder builder = CSVFormat.DEFAULT.builder();
- assertNotSame(builder.get(), builder.build());
- }
-
- @Test
- public void testDelimiterEmptyStringThrowsException1() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter("").get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testDelimiterSameAsCommentStartThrowsException_Deprecated() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter('!').withCommentMarker('!'));
- }
-
- @Test
- public void testDelimiterSameAsCommentStartThrowsException1() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter('!').setCommentMarker('!').get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testDelimiterSameAsEscapeThrowsException_Deprecated() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter('!').withEscape('!'));
- }
-
- @Test
- public void testDelimiterSameAsEscapeThrowsException1() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter('!').setEscape('!').get());
- }
-
- @Test
- public void testDelimiterSameAsRecordSeparatorThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat(CR));
- }
-
- @Test
- public void testDuplicateHeaderElements() {
- final String[] header = { "A", "A" };
- final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader(header).get();
- assertEquals(2, format.getHeader().length);
- assertArrayEquals(header, format.getHeader());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testDuplicateHeaderElements_Deprecated() {
- final String[] header = { "A", "A" };
- final CSVFormat format = CSVFormat.DEFAULT.withHeader(header);
- assertEquals(2, format.getHeader().length);
- assertArrayEquals(header, format.getHeader());
- }
-
- @Test
- public void testDuplicateHeaderElementsFalse() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setHeader("A", "A").get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testDuplicateHeaderElementsFalse_Deprecated() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withAllowDuplicateHeaderNames(false).withHeader("A", "A"));
- }
-
- @Test
- public void testDuplicateHeaderElementsTrue() {
- CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(true).setHeader("A", "A").get();
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testDuplicateHeaderElementsTrue_Deprecated() {
- CSVFormat.DEFAULT.withAllowDuplicateHeaderNames(true).withHeader("A", "A");
- }
-
- @Test
- public void testDuplicateHeaderElementsTrueContainsEmpty1() {
- CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setHeader("A", "", "B", "").get();
- }
-
- @Test
- public void testDuplicateHeaderElementsTrueContainsEmpty2() {
- CSVFormat.DEFAULT.builder().setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).setHeader("A", "", "B", "").get();
- }
-
- @Test
- public void testDuplicateHeaderElementsTrueContainsEmpty3() {
- CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setAllowMissingColumnNames(true).setHeader("A", "", "B", "").get();
- }
-
- @Test
- public void testEquals() {
- final CSVFormat right = CSVFormat.DEFAULT;
- final CSVFormat left = copy(right);
- Assertions.assertNotEquals(null, right);
- Assertions.assertNotEquals("A String Instance", right);
- 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('\'').builder().setQuote('"').setCommentMarker('#').setQuoteMode(QuoteMode.ALL).get();
- final CSVFormat left = right.builder().setCommentMarker('!').get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsCommentStart_Deprecated() {
- 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('\'').builder().setQuote('"').setCommentMarker('#').setEscape('+').setQuoteMode(QuoteMode.ALL).get();
- final CSVFormat left = right.builder().setEscape('!').get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsEscape_Deprecated() {
- final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withCommentMarker('#').withEscape('+').withQuoteMode(QuoteMode.ALL);
- final CSVFormat left = right.withEscape('!');
-
- assertNotEquals(right, left);
- }
-
- @Test
- public void testEqualsHash() throws Exception {
- final Method[] methods = CSVFormat.class.getDeclaredMethods();
- for (final Method method : methods) {
- if (Modifier.isPublic(method.getModifiers())) {
- final String name = method.getName();
- if (name.startsWith("with")) {
- for (final Class> cls : method.getParameterTypes()) {
- final String type = cls.getCanonicalName();
- switch (type) {
- case "boolean": {
- final Object defTrue = method.invoke(CSVFormat.DEFAULT, Boolean.TRUE);
- final Object defFalse = method.invoke(CSVFormat.DEFAULT, Boolean.FALSE);
- assertNotEquals(name, type, defTrue, defFalse);
- break;
- }
- case "char": {
- final Object a = method.invoke(CSVFormat.DEFAULT, 'a');
- final Object b = method.invoke(CSVFormat.DEFAULT, 'b');
- assertNotEquals(name, type, a, b);
- break;
- }
- case "java.lang.Character": {
- final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { null });
- final Object b = method.invoke(CSVFormat.DEFAULT, Character.valueOf('d'));
- assertNotEquals(name, type, a, b);
- break;
- }
- case "java.lang.String": {
- final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { null });
- final Object b = method.invoke(CSVFormat.DEFAULT, "e");
- assertNotEquals(name, type, a, b);
- break;
- }
- case "java.lang.String[]": {
- final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { new String[] { null, null } });
- final Object b = method.invoke(CSVFormat.DEFAULT, new Object[] { new String[] { "f", "g" } });
- assertNotEquals(name, type, a, b);
- break;
- }
- case "org.apache.commons.csv.QuoteMode": {
- final Object a = method.invoke(CSVFormat.DEFAULT, QuoteMode.MINIMAL);
- final Object b = method.invoke(CSVFormat.DEFAULT, QuoteMode.ALL);
- assertNotEquals(name, type, a, b);
- break;
- }
- case "org.apache.commons.csv.DuplicateHeaderMode": {
- final Object a = method.invoke(CSVFormat.DEFAULT, DuplicateHeaderMode.ALLOW_ALL);
- final Object b = method.invoke(CSVFormat.DEFAULT, DuplicateHeaderMode.DISALLOW);
- assertNotEquals(name, type, a, b);
- break;
- }
- case "java.lang.Object[]": {
- final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { new Object[] { null, null } });
- final Object b = method.invoke(CSVFormat.DEFAULT, new Object[] { new Object[] { new Object(), new Object() } });
- assertNotEquals(name, type, a, b);
- break;
- }
- default:
- if ("withHeader".equals(name)) { // covered above by String[]
- // ignored
- } else {
- fail("Unhandled method: " + name + "(" + type + ")");
- }
- break;
- }
- }
- }
- }
- }
- }
-
- @Test
- public void testEqualsHeader() {
- final CSVFormat right = CSVFormat.newFormat('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setHeader("One", "Two", "Three")
- .setIgnoreEmptyLines(true).setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get();
- final CSVFormat left = right.builder().setHeader("Three", "Two", "One").get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsHeader_Deprecated() {
- 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('\'').builder().setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
- .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get();
- final CSVFormat left = right.builder().setIgnoreEmptyLines(false).get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsIgnoreEmptyLines_Deprecated() {
- 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('\'').builder().setCommentMarker('#').setEscape('+').setIgnoreSurroundingSpaces(true).setQuote('"')
- .setQuoteMode(QuoteMode.ALL).get();
- final CSVFormat left = right.builder().setIgnoreSurroundingSpaces(false).get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsIgnoreSurroundingSpaces_Deprecated() {
- final CSVFormat right = CSVFormat.newFormat('\'').withCommentMarker('#').withEscape('+').withIgnoreSurroundingSpaces().withQuote('"')
- .withQuoteMode(QuoteMode.ALL);
- final CSVFormat left = right.withIgnoreSurroundingSpaces(false);
-
- assertNotEquals(right, left);
- }
-
- @Test
- public void testEqualsLeftNoQuoteRightQuote() {
- final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get();
- final CSVFormat right = left.builder().setQuote('#').get();
-
- assertNotEquals(left, right);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsLeftNoQuoteRightQuote_Deprecated() {
- final CSVFormat left = CSVFormat.newFormat(',').withQuote(null);
- final CSVFormat right = left.withQuote('#');
-
- assertNotEquals(left, right);
- }
-
- @Test
- public void testEqualsNoQuotes() {
- final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get();
- final CSVFormat right = left.builder().setQuote(null).get();
-
- assertEquals(left, right);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsNoQuotes_Deprecated() {
- final CSVFormat left = CSVFormat.newFormat(',').withQuote(null);
- final CSVFormat right = left.withQuote(null);
-
- assertEquals(left, right);
- }
-
- @Test
- public void testEqualsNullString() {
- final CSVFormat right = CSVFormat.newFormat('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
- .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).setNullString("null").get();
- final CSVFormat left = right.builder().setNullString("---").get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsNullString_Deprecated() {
- 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 testEqualsOne() {
-
- final CSVFormat csvFormatOne = CSVFormat.INFORMIX_UNLOAD;
- final CSVFormat csvFormatTwo = CSVFormat.MYSQL;
-
- assertEquals('\\', (char) csvFormatOne.getEscapeCharacter());
- assertEquals('\\', csvFormatOne.getEscapeChar());
- assertNull(csvFormatOne.getQuoteMode());
-
- assertTrue(csvFormatOne.getIgnoreEmptyLines());
- assertFalse(csvFormatOne.getSkipHeaderRecord());
-
- assertFalse(csvFormatOne.getIgnoreHeaderCase());
- assertNull(csvFormatOne.getCommentMarker());
-
- assertFalse(csvFormatOne.isCommentMarkerSet());
- assertTrue(csvFormatOne.isQuoteCharacterSet());
-
- assertEquals('|', csvFormatOne.getDelimiter());
- assertFalse(csvFormatOne.getAllowMissingColumnNames());
-
- assertTrue(csvFormatOne.isEscapeCharacterSet());
- assertEquals("\n", csvFormatOne.getRecordSeparator());
-
- assertEquals('\"', (char) csvFormatOne.getQuoteCharacter());
- assertFalse(csvFormatOne.getTrailingDelimiter());
-
- assertFalse(csvFormatOne.getTrim());
- assertFalse(csvFormatOne.isNullStringSet());
-
- assertNull(csvFormatOne.getNullString());
- assertFalse(csvFormatOne.getIgnoreSurroundingSpaces());
-
- assertTrue(csvFormatTwo.isEscapeCharacterSet());
- assertNull(csvFormatTwo.getQuoteCharacter());
-
- assertFalse(csvFormatTwo.getAllowMissingColumnNames());
- assertEquals(QuoteMode.ALL_NON_NULL, csvFormatTwo.getQuoteMode());
-
- assertEquals('\t', csvFormatTwo.getDelimiter());
- assertArrayEquals(new char[] { '\t' }, csvFormatTwo.getDelimiterCharArray());
- assertEquals("\t", csvFormatTwo.getDelimiterString());
- assertEquals("\n", csvFormatTwo.getRecordSeparator());
-
- assertFalse(csvFormatTwo.isQuoteCharacterSet());
- assertTrue(csvFormatTwo.isNullStringSet());
-
- assertEquals('\\', (char) csvFormatTwo.getEscapeCharacter());
- assertFalse(csvFormatTwo.getIgnoreHeaderCase());
-
- assertFalse(csvFormatTwo.getTrim());
- assertFalse(csvFormatTwo.getIgnoreEmptyLines());
-
- assertEquals("\\N", csvFormatTwo.getNullString());
- assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
-
- assertFalse(csvFormatTwo.getTrailingDelimiter());
- assertFalse(csvFormatTwo.getSkipHeaderRecord());
-
- assertNull(csvFormatTwo.getCommentMarker());
- assertFalse(csvFormatTwo.isCommentMarkerSet());
-
- assertNotSame(csvFormatTwo, csvFormatOne);
- Assertions.assertNotEquals(csvFormatTwo, csvFormatOne);
-
- assertEquals('\\', (char) csvFormatOne.getEscapeCharacter());
- assertNull(csvFormatOne.getQuoteMode());
-
- assertTrue(csvFormatOne.getIgnoreEmptyLines());
- assertFalse(csvFormatOne.getSkipHeaderRecord());
-
- assertFalse(csvFormatOne.getIgnoreHeaderCase());
- assertNull(csvFormatOne.getCommentMarker());
-
- assertFalse(csvFormatOne.isCommentMarkerSet());
- assertTrue(csvFormatOne.isQuoteCharacterSet());
-
- assertEquals('|', csvFormatOne.getDelimiter());
- assertFalse(csvFormatOne.getAllowMissingColumnNames());
-
- assertTrue(csvFormatOne.isEscapeCharacterSet());
- assertEquals("\n", csvFormatOne.getRecordSeparator());
-
- assertEquals('\"', (char) csvFormatOne.getQuoteCharacter());
- assertFalse(csvFormatOne.getTrailingDelimiter());
-
- assertFalse(csvFormatOne.getTrim());
- assertFalse(csvFormatOne.isNullStringSet());
-
- assertNull(csvFormatOne.getNullString());
- assertFalse(csvFormatOne.getIgnoreSurroundingSpaces());
-
- assertTrue(csvFormatTwo.isEscapeCharacterSet());
- assertNull(csvFormatTwo.getQuoteCharacter());
-
- assertFalse(csvFormatTwo.getAllowMissingColumnNames());
- assertEquals(QuoteMode.ALL_NON_NULL, csvFormatTwo.getQuoteMode());
-
- assertEquals('\t', csvFormatTwo.getDelimiter());
- assertEquals("\n", csvFormatTwo.getRecordSeparator());
-
- assertFalse(csvFormatTwo.isQuoteCharacterSet());
- assertTrue(csvFormatTwo.isNullStringSet());
-
- assertEquals('\\', (char) csvFormatTwo.getEscapeCharacter());
- assertFalse(csvFormatTwo.getIgnoreHeaderCase());
-
- assertFalse(csvFormatTwo.getTrim());
- assertFalse(csvFormatTwo.getIgnoreEmptyLines());
-
- assertEquals("\\N", csvFormatTwo.getNullString());
- assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
-
- assertFalse(csvFormatTwo.getTrailingDelimiter());
- assertFalse(csvFormatTwo.getSkipHeaderRecord());
-
- assertNull(csvFormatTwo.getCommentMarker());
- assertFalse(csvFormatTwo.isCommentMarkerSet());
-
- assertNotSame(csvFormatOne, csvFormatTwo);
- assertNotSame(csvFormatTwo, csvFormatOne);
-
- Assertions.assertNotEquals(csvFormatOne, csvFormatTwo);
- Assertions.assertNotEquals(csvFormatTwo, csvFormatOne);
-
- Assertions.assertNotEquals(csvFormatTwo, csvFormatOne);
-
- }
-
- @Test
- public void testEqualsQuoteChar() {
- final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').get();
- final CSVFormat left = right.builder().setQuote('!').get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsQuoteChar_Deprecated() {
- final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"');
- final CSVFormat left = right.withQuote('!');
-
- assertNotEquals(right, left);
- }
-
- @Test
- public void testEqualsQuotePolicy() {
- final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').setQuoteMode(QuoteMode.ALL).get();
- final CSVFormat left = right.builder().setQuoteMode(QuoteMode.MINIMAL).get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsQuotePolicy_Deprecated() {
- 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('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
- .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get();
- final CSVFormat left = right.builder().setRecordSeparator(LF).get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsRecordSeparator_Deprecated() {
- final CSVFormat right = CSVFormat.newFormat('\'').withRecordSeparator(CR).withCommentMarker('#').withEscape('+').withIgnoreEmptyLines()
- .withIgnoreSurroundingSpaces().withQuote('"').withQuoteMode(QuoteMode.ALL);
- final CSVFormat left = right.withRecordSeparator(LF);
-
- assertNotEquals(right, left);
- }
-
- public void testEqualsSkipHeaderRecord() {
- final CSVFormat right = CSVFormat.newFormat('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
- .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).setNullString("null").setSkipHeaderRecord(true).get();
- final CSVFormat left = right.builder().setSkipHeaderRecord(false).get();
-
- assertNotEquals(right, left);
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEqualsSkipHeaderRecord_Deprecated() {
- 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
- public void testEqualsWithNull() {
-
- final CSVFormat csvFormat = CSVFormat.POSTGRESQL_TEXT;
-
- assertEquals('\\', (char) csvFormat.getEscapeCharacter());
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
-
- assertFalse(csvFormat.getTrailingDelimiter());
- assertFalse(csvFormat.getTrim());
-
- assertFalse(csvFormat.isQuoteCharacterSet());
- assertEquals("\\N", csvFormat.getNullString());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertTrue(csvFormat.isEscapeCharacterSet());
-
- assertFalse(csvFormat.isCommentMarkerSet());
- assertNull(csvFormat.getCommentMarker());
-
- assertFalse(csvFormat.getAllowMissingColumnNames());
- assertEquals(QuoteMode.ALL_NON_NULL, csvFormat.getQuoteMode());
-
- assertEquals('\t', csvFormat.getDelimiter());
- assertFalse(csvFormat.getSkipHeaderRecord());
-
- assertEquals("\n", csvFormat.getRecordSeparator());
- assertFalse(csvFormat.getIgnoreEmptyLines());
-
- assertNull(csvFormat.getQuoteCharacter());
- assertTrue(csvFormat.isNullStringSet());
-
- assertEquals('\\', (char) csvFormat.getEscapeCharacter());
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
-
- assertFalse(csvFormat.getTrailingDelimiter());
- assertFalse(csvFormat.getTrim());
-
- assertFalse(csvFormat.isQuoteCharacterSet());
- assertEquals("\\N", csvFormat.getNullString());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertTrue(csvFormat.isEscapeCharacterSet());
-
- assertFalse(csvFormat.isCommentMarkerSet());
- assertNull(csvFormat.getCommentMarker());
-
- assertFalse(csvFormat.getAllowMissingColumnNames());
- assertEquals(QuoteMode.ALL_NON_NULL, csvFormat.getQuoteMode());
-
- assertEquals('\t', csvFormat.getDelimiter());
- assertFalse(csvFormat.getSkipHeaderRecord());
-
- assertEquals("\n", csvFormat.getRecordSeparator());
- assertFalse(csvFormat.getIgnoreEmptyLines());
-
- assertNull(csvFormat.getQuoteCharacter());
- assertTrue(csvFormat.isNullStringSet());
-
- Assertions.assertNotEquals(null, csvFormat);
-
- }
-
- @Test
- public void testEscapeSameAsCommentStartThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setEscape('!').setCommentMarker('!').get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEscapeSameAsCommentStartThrowsException_Deprecated() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape('!').withCommentMarker('!'));
- }
-
- @Test
- public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType() {
- // Cannot assume that callers won't use different Character objects
- assertThrows(IllegalArgumentException.class,
- () -> CSVFormat.DEFAULT.builder().setEscape(Character.valueOf('!')).setCommentMarker(Character.valueOf('!')).get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType_Deprecated() {
- // Cannot assume that callers won't use different Character objects
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape(Character.valueOf('!')).withCommentMarker(Character.valueOf('!')));
- }
-
- @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 // I assume this to be a defect.
- public void testFormatThrowsNullPointerException() {
-
- final CSVFormat csvFormat = CSVFormat.MYSQL;
-
- final NullPointerException e = assertThrows(NullPointerException.class, () -> csvFormat.format((Object[]) null));
- assertEquals(Objects.class.getName(), e.getStackTrace()[0].getClassName());
- }
-
- @Test
- public void testFormatToString() {
- // @formatter:off
- final CSVFormat format = CSVFormat.RFC4180
- .withEscape('?')
- .withDelimiter(',')
- .withQuoteMode(QuoteMode.MINIMAL)
- .withRecordSeparator(CRLF)
- .withQuote('"')
- .withNullString("")
- .withIgnoreHeaderCase(true)
- .withHeaderComments("This is HeaderComments")
- .withHeader("col1", "col2", "col3");
- // @formatter:on
- assertEquals(
- "Delimiter=<,> Escape=> QuoteChar=<\"> QuoteMode= NullString=<> RecordSeparator=<" + CRLF +
- "> IgnoreHeaderCase:ignored SkipHeaderRecord:false HeaderComments:[This is HeaderComments] Header:[col1, col2, col3]",
- format.toString());
- }
-
- @Test
- public void testGetAllowDuplicateHeaderNames() {
- final Builder builder = CSVFormat.DEFAULT.builder();
- assertTrue(builder.get().getAllowDuplicateHeaderNames());
- assertTrue(builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_ALL).get().getAllowDuplicateHeaderNames());
- assertFalse(builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).get().getAllowDuplicateHeaderNames());
- assertFalse(builder.setDuplicateHeaderMode(DuplicateHeaderMode.DISALLOW).get().getAllowDuplicateHeaderNames());
- }
-
- @Test
- public void testGetDuplicateHeaderMode() {
- final Builder builder = CSVFormat.DEFAULT.builder();
-
- assertEquals(DuplicateHeaderMode.ALLOW_ALL, builder.get().getDuplicateHeaderMode());
- assertEquals(DuplicateHeaderMode.ALLOW_ALL, builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_ALL).get().getDuplicateHeaderMode());
- assertEquals(DuplicateHeaderMode.ALLOW_EMPTY, builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).get().getDuplicateHeaderMode());
- assertEquals(DuplicateHeaderMode.DISALLOW, builder.setDuplicateHeaderMode(DuplicateHeaderMode.DISALLOW).get().getDuplicateHeaderMode());
- }
-
- @Test
- public void testGetHeader() {
- final String[] header = { "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 testHashCodeAndWithIgnoreHeaderCase() {
-
- final CSVFormat csvFormat = CSVFormat.INFORMIX_UNLOAD_CSV;
- final CSVFormat csvFormatTwo = csvFormat.withIgnoreHeaderCase();
- csvFormatTwo.hashCode();
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertTrue(csvFormatTwo.getIgnoreHeaderCase()); // now different
- assertFalse(csvFormatTwo.getTrailingDelimiter());
-
- Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal
- assertFalse(csvFormatTwo.getAllowMissingColumnNames());
-
- assertFalse(csvFormatTwo.getTrim());
-
- }
-
- @Test
- public void testJiraCsv236() {
- CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(true).setHeader("CC", "VV", "VV").get();
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testJiraCsv236__Deprecated() {
- CSVFormat.DEFAULT.withAllowDuplicateHeaderNames().withHeader("CC", "VV", "VV");
- }
-
- @Test
- public void testNewFormat() {
-
- final CSVFormat csvFormat = CSVFormat.newFormat('X');
-
- assertFalse(csvFormat.getSkipHeaderRecord());
- assertFalse(csvFormat.isEscapeCharacterSet());
-
- assertNull(csvFormat.getRecordSeparator());
- assertNull(csvFormat.getQuoteMode());
-
- assertNull(csvFormat.getCommentMarker());
- assertFalse(csvFormat.getIgnoreHeaderCase());
-
- assertFalse(csvFormat.getAllowMissingColumnNames());
- assertFalse(csvFormat.getTrim());
-
- assertFalse(csvFormat.isNullStringSet());
- assertNull(csvFormat.getEscapeCharacter());
-
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
- assertFalse(csvFormat.getTrailingDelimiter());
-
- assertEquals('X', csvFormat.getDelimiter());
- assertNull(csvFormat.getNullString());
-
- assertFalse(csvFormat.isQuoteCharacterSet());
- assertFalse(csvFormat.isCommentMarkerSet());
-
- assertNull(csvFormat.getQuoteCharacter());
- assertFalse(csvFormat.getIgnoreEmptyLines());
-
- assertFalse(csvFormat.getSkipHeaderRecord());
- assertFalse(csvFormat.isEscapeCharacterSet());
-
- assertNull(csvFormat.getRecordSeparator());
- assertNull(csvFormat.getQuoteMode());
-
- assertNull(csvFormat.getCommentMarker());
- assertFalse(csvFormat.getIgnoreHeaderCase());
-
- assertFalse(csvFormat.getAllowMissingColumnNames());
- assertFalse(csvFormat.getTrim());
-
- assertFalse(csvFormat.isNullStringSet());
- assertNull(csvFormat.getEscapeCharacter());
-
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
- assertFalse(csvFormat.getTrailingDelimiter());
-
- assertEquals('X', csvFormat.getDelimiter());
- assertNull(csvFormat.getNullString());
-
- assertFalse(csvFormat.isQuoteCharacterSet());
- assertFalse(csvFormat.isCommentMarkerSet());
-
- assertNull(csvFormat.getQuoteCharacter());
- assertFalse(csvFormat.getIgnoreEmptyLines());
-
- }
-
- @Test
- public void testNullRecordSeparatorCsv106() {
- final CSVFormat format = CSVFormat.newFormat(';').builder().setSkipHeaderRecord(true).setHeader("H1", "H2").get();
- final String formatStr = format.format("A", "B");
- assertNotNull(formatStr);
- assertFalse(formatStr.endsWith("null"));
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testNullRecordSeparatorCsv106__Deprecated() {
- final CSVFormat format = CSVFormat.newFormat(';').withSkipHeaderRecord().withHeader("H1", "H2");
- final String formatStr = format.format("A", "B");
- assertNotNull(formatStr);
- assertFalse(formatStr.endsWith("null"));
- }
-
- @Test
- public void testPrintRecord() throws IOException {
- final Appendable out = new StringBuilder();
- final CSVFormat format = CSVFormat.RFC4180;
- format.printRecord(out, "a", "b", "c");
- assertEquals("a,b,c" + format.getRecordSeparator(), out.toString());
- }
-
- @Test
- public void testPrintRecordEmpty() throws IOException {
- final Appendable out = new StringBuilder();
- final CSVFormat format = CSVFormat.RFC4180;
- format.printRecord(out);
- assertEquals(format.getRecordSeparator(), out.toString());
- }
-
- @Test
- public void testPrintWithEscapesEndWithCRLF() throws IOException {
- final Reader in = new StringReader("x,y,x\r\na,?b,c\r\n");
- final Appendable out = new StringBuilder();
- final CSVFormat format = CSVFormat.RFC4180.withEscape('?').withDelimiter(',').withQuote(null).withRecordSeparator(CRLF);
- format.print(in, out, true);
- assertEquals("x?,y?,x?r?na?,??b?,c?r?n", out.toString());
- }
-
- @Test
- public void testPrintWithEscapesEndWithoutCRLF() throws IOException {
- final Reader in = new StringReader("x,y,x");
- final Appendable out = new StringBuilder();
- final CSVFormat format = CSVFormat.RFC4180.withEscape('?').withDelimiter(',').withQuote(null).withRecordSeparator(CRLF);
- format.print(in, out, true);
- assertEquals("x?,y?,x", out.toString());
- }
-
- @Test
- public void testPrintWithoutQuotes() throws IOException {
- final Reader in = new StringReader("");
- final Appendable out = new StringBuilder();
- final CSVFormat format = CSVFormat.RFC4180.withDelimiter(',').withQuote('"').withEscape('?').withQuoteMode(QuoteMode.NON_NUMERIC);
- format.print(in, out, true);
- assertEquals("\"\"", out.toString());
- }
-
- @Test
- public void testPrintWithQuoteModeIsNONE() throws IOException {
- final Reader in = new StringReader("a,b,c");
- final Appendable out = new StringBuilder();
- final CSVFormat format = CSVFormat.RFC4180.withDelimiter(',').withQuote('"').withEscape('?').withQuoteMode(QuoteMode.NONE);
- format.print(in, out, true);
- assertEquals("a?,b?,c", out.toString());
- }
-
- @Test
- public void testPrintWithQuotes() throws IOException {
- final Reader in = new StringReader("\"a,b,c\r\nx,y,z");
- final Appendable out = new StringBuilder();
- final CSVFormat format = CSVFormat.RFC4180.withDelimiter(',').withQuote('"').withEscape('?').withQuoteMode(QuoteMode.NON_NUMERIC);
- format.print(in, out, true);
- assertEquals("\"\"\"a,b,c\r\nx,y,z\"", out.toString());
- }
-
- @Test
- public void testQuoteCharSameAsCommentStartThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setCommentMarker('!').get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testQuoteCharSameAsCommentStartThrowsException_Deprecated() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote('!').withCommentMarker('!'));
- }
-
- @Test
- public void testQuoteCharSameAsCommentStartThrowsExceptionForWrapperType() {
- // Cannot assume that callers won't use different Character objects
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote(Character.valueOf('!')).setCommentMarker('!').get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testQuoteCharSameAsCommentStartThrowsExceptionForWrapperType_Deprecated() {
- // Cannot assume that callers won't use different Character objects
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote(Character.valueOf('!')).withCommentMarker('!'));
- }
-
- @Test
- public void testQuoteCharSameAsDelimiterThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setDelimiter('!').get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testQuoteCharSameAsDelimiterThrowsException_Deprecated() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote('!').withDelimiter('!'));
- }
-
- @Test
- public void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() {
- final Exception exception = assertThrows(IllegalArgumentException.class, () ->
- // @formatter:off
- CSVFormat.DEFAULT.builder()
- .setHeader("Col1", "Col2", "Col3", "Col4")
- .setQuoteMode(QuoteMode.NONE)
- .get()
- // @formatter:on
- );
- final String actualMessage = exception.getMessage();
- final String expectedMessage = "Quote mode set to NONE but no escape character is set";
- assertEquals(expectedMessage, actualMessage);
- }
-
- @Test
- public void testQuotePolicyNoneWithoutEscapeThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat('!').builder().setQuoteMode(QuoteMode.NONE).get());
- }
-
- @SuppressWarnings("deprecation")
- @Test
- public void testQuotePolicyNoneWithoutEscapeThrowsException_Deprecated() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat('!').withQuoteMode(QuoteMode.NONE));
- }
-
- @Test
- public void testRFC4180() {
- assertNull(RFC4180.getCommentMarker());
- assertEquals(',', RFC4180.getDelimiter());
- assertNull(RFC4180.getEscapeCharacter());
- assertFalse(RFC4180.getIgnoreEmptyLines());
- assertEquals(Character.valueOf('"'), RFC4180.getQuoteCharacter());
- assertNull(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();
-
- try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
- oos.writeObject(CSVFormat.DEFAULT);
- oos.flush();
- }
-
- final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
- final CSVFormat format = (CSVFormat) in.readObject();
-
- assertNotNull(format);
- assertEquals(CSVFormat.DEFAULT.getDelimiter(), format.getDelimiter(), "delimiter");
- assertEquals(CSVFormat.DEFAULT.getQuoteCharacter(), format.getQuoteCharacter(), "encapsulator");
- assertEquals(CSVFormat.DEFAULT.getCommentMarker(), format.getCommentMarker(), "comment start");
- assertEquals(CSVFormat.DEFAULT.getRecordSeparator(), format.getRecordSeparator(), "record separator");
- assertEquals(CSVFormat.DEFAULT.getEscapeCharacter(), format.getEscapeCharacter(), "escape");
- assertEquals(CSVFormat.DEFAULT.getIgnoreSurroundingSpaces(), format.getIgnoreSurroundingSpaces(), "trim");
- assertEquals(CSVFormat.DEFAULT.getIgnoreEmptyLines(), format.getIgnoreEmptyLines(), "empty lines");
- }
-
- @Test
- public void testToString() {
-
- final String string = CSVFormat.INFORMIX_UNLOAD.toString();
-
- assertEquals("Delimiter=<|> Escape=<\\> QuoteChar=<\"> RecordSeparator=<\n> EmptyLines:ignored SkipHeaderRecord:false", string);
-
- }
-
- @Test
- public void testToStringAndWithCommentMarkerTakingCharacter() {
-
- final CSVFormat.Predefined csvFormatPredefined = CSVFormat.Predefined.Default;
- final CSVFormat csvFormat = csvFormatPredefined.getFormat();
-
- assertNull(csvFormat.getEscapeCharacter());
- assertTrue(csvFormat.isQuoteCharacterSet());
-
- assertFalse(csvFormat.getTrim());
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
-
- assertFalse(csvFormat.getTrailingDelimiter());
- assertEquals(',', csvFormat.getDelimiter());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertEquals("\r\n", csvFormat.getRecordSeparator());
-
- assertFalse(csvFormat.isCommentMarkerSet());
- assertNull(csvFormat.getCommentMarker());
-
- assertFalse(csvFormat.isNullStringSet());
- assertFalse(csvFormat.getAllowMissingColumnNames());
-
- assertFalse(csvFormat.isEscapeCharacterSet());
- assertFalse(csvFormat.getSkipHeaderRecord());
-
- assertNull(csvFormat.getNullString());
- assertNull(csvFormat.getQuoteMode());
-
- assertTrue(csvFormat.getIgnoreEmptyLines());
- assertEquals('\"', (char) csvFormat.getQuoteCharacter());
-
- final Character character = Character.valueOf('n');
-
- final CSVFormat csvFormatTwo = csvFormat.withCommentMarker(character);
-
- assertNull(csvFormat.getEscapeCharacter());
- assertTrue(csvFormat.isQuoteCharacterSet());
-
- assertFalse(csvFormat.getTrim());
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
-
- assertFalse(csvFormat.getTrailingDelimiter());
- assertEquals(',', csvFormat.getDelimiter());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertEquals("\r\n", csvFormat.getRecordSeparator());
-
- assertFalse(csvFormat.isCommentMarkerSet());
- assertNull(csvFormat.getCommentMarker());
-
- assertFalse(csvFormat.isNullStringSet());
- assertFalse(csvFormat.getAllowMissingColumnNames());
-
- assertFalse(csvFormat.isEscapeCharacterSet());
- assertFalse(csvFormat.getSkipHeaderRecord());
-
- assertNull(csvFormat.getNullString());
- assertNull(csvFormat.getQuoteMode());
-
- assertTrue(csvFormat.getIgnoreEmptyLines());
- assertEquals('\"', (char) csvFormat.getQuoteCharacter());
-
- assertFalse(csvFormatTwo.isNullStringSet());
- assertFalse(csvFormatTwo.getAllowMissingColumnNames());
-
- assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
- assertNull(csvFormatTwo.getNullString());
-
- assertEquals(',', csvFormatTwo.getDelimiter());
- assertFalse(csvFormatTwo.getTrailingDelimiter());
-
- assertTrue(csvFormatTwo.isCommentMarkerSet());
- assertFalse(csvFormatTwo.getIgnoreHeaderCase());
-
- assertFalse(csvFormatTwo.getTrim());
- assertNull(csvFormatTwo.getEscapeCharacter());
-
- assertTrue(csvFormatTwo.isQuoteCharacterSet());
- assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
-
- assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
- assertNull(csvFormatTwo.getQuoteMode());
-
- assertEquals('n', (char) csvFormatTwo.getCommentMarker());
- assertFalse(csvFormatTwo.getSkipHeaderRecord());
-
- assertFalse(csvFormatTwo.isEscapeCharacterSet());
- assertTrue(csvFormatTwo.getIgnoreEmptyLines());
-
- assertNotSame(csvFormat, csvFormatTwo);
- assertNotSame(csvFormatTwo, csvFormat);
-
- Assertions.assertNotEquals(csvFormatTwo, csvFormat);
-
- assertNull(csvFormat.getEscapeCharacter());
- assertTrue(csvFormat.isQuoteCharacterSet());
-
- assertFalse(csvFormat.getTrim());
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
-
- assertFalse(csvFormat.getTrailingDelimiter());
- assertEquals(',', csvFormat.getDelimiter());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertEquals("\r\n", csvFormat.getRecordSeparator());
-
- assertFalse(csvFormat.isCommentMarkerSet());
- assertNull(csvFormat.getCommentMarker());
-
- assertFalse(csvFormat.isNullStringSet());
- assertFalse(csvFormat.getAllowMissingColumnNames());
-
- assertFalse(csvFormat.isEscapeCharacterSet());
- assertFalse(csvFormat.getSkipHeaderRecord());
-
- assertNull(csvFormat.getNullString());
- assertNull(csvFormat.getQuoteMode());
-
- assertTrue(csvFormat.getIgnoreEmptyLines());
- assertEquals('\"', (char) csvFormat.getQuoteCharacter());
-
- assertFalse(csvFormatTwo.isNullStringSet());
- assertFalse(csvFormatTwo.getAllowMissingColumnNames());
-
- assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
- assertNull(csvFormatTwo.getNullString());
-
- assertEquals(',', csvFormatTwo.getDelimiter());
- assertFalse(csvFormatTwo.getTrailingDelimiter());
-
- assertTrue(csvFormatTwo.isCommentMarkerSet());
- assertFalse(csvFormatTwo.getIgnoreHeaderCase());
-
- assertFalse(csvFormatTwo.getTrim());
- assertNull(csvFormatTwo.getEscapeCharacter());
-
- assertTrue(csvFormatTwo.isQuoteCharacterSet());
- assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
-
- assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
- assertNull(csvFormatTwo.getQuoteMode());
-
- assertEquals('n', (char) csvFormatTwo.getCommentMarker());
- assertFalse(csvFormatTwo.getSkipHeaderRecord());
-
- assertFalse(csvFormatTwo.isEscapeCharacterSet());
- assertTrue(csvFormatTwo.getIgnoreEmptyLines());
-
- assertNotSame(csvFormat, csvFormatTwo);
- assertNotSame(csvFormatTwo, csvFormat);
-
- Assertions.assertNotEquals(csvFormat, csvFormatTwo);
-
- Assertions.assertNotEquals(csvFormatTwo, csvFormat);
- assertEquals("Delimiter=<,> QuoteChar=<\"> CommentStart= " + "RecordSeparator=<\r\n> EmptyLines:ignored SkipHeaderRecord:false",
- csvFormatTwo.toString());
-
- }
-
- @Test
- public void testTrim() throws IOException {
- final CSVFormat formatWithTrim = CSVFormat.DEFAULT.withDelimiter(',').withTrim().withQuote(null).withRecordSeparator(CRLF);
-
- CharSequence in = "a,b,c";
- final StringBuilder out = new StringBuilder();
- formatWithTrim.print(in, out, true);
- assertEquals("a,b,c", out.toString());
-
- in = new StringBuilder(" x,y,z");
- out.setLength(0);
- formatWithTrim.print(in, out, true);
- assertEquals("x,y,z", out.toString());
-
- in = new StringBuilder("");
- out.setLength(0);
- formatWithTrim.print(in, out, true);
- assertEquals("", out.toString());
-
- in = new StringBuilder("header\r\n");
- out.setLength(0);
- formatWithTrim.print(in, out, true);
- assertEquals("header", out.toString());
- }
-
- @Test
- public void testWithCommentStart() {
- final CSVFormat formatWithCommentStart = CSVFormat.DEFAULT.withCommentMarker('#');
- assertEquals(Character.valueOf('#'), formatWithCommentStart.getCommentMarker());
- }
-
- @Test
- public void testWithCommentStartCRThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withCommentMarker(CR));
- }
-
- @Test
- public void testWithDelimiter() {
- final CSVFormat formatWithDelimiter = CSVFormat.DEFAULT.withDelimiter('!');
- assertEquals('!', formatWithDelimiter.getDelimiter());
- }
-
- @Test
- public void testWithDelimiterLFThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(LF));
- }
-
- @Test
- public void testWithEmptyDuplicates() {
- final CSVFormat formatWithEmptyDuplicates = CSVFormat.DEFAULT.builder().setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).get();
-
- assertEquals(DuplicateHeaderMode.ALLOW_EMPTY, formatWithEmptyDuplicates.getDuplicateHeaderMode());
- assertFalse(formatWithEmptyDuplicates.getAllowDuplicateHeaderNames());
- }
-
- @Test
- public void testWithEmptyEnum() {
- final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(EmptyEnum.class);
- assertEquals(0, formatWithHeader.getHeader().length);
- }
-
- @Test
- public void testWithEscape() {
- final CSVFormat formatWithEscape = CSVFormat.DEFAULT.withEscape('&');
- assertEquals(Character.valueOf('&'), formatWithEscape.getEscapeCharacter());
- }
-
- @Test
- public void testWithEscapeCRThrowsExceptions() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape(CR));
- }
-
- @Test
- public void testWithFirstRecordAsHeader() {
- final CSVFormat formatWithFirstRecordAsHeader = CSVFormat.DEFAULT.withFirstRecordAsHeader();
- assertTrue(formatWithFirstRecordAsHeader.getSkipHeaderRecord());
- assertEquals(0, formatWithFirstRecordAsHeader.getHeader().length);
- }
-
- @Test
- public void testWithHeader() {
- final String[] header = { "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());
- }
-
- @Test
- public void testWithHeaderComments() {
-
- final CSVFormat csvFormat = CSVFormat.DEFAULT;
-
- assertEquals('\"', (char) csvFormat.getQuoteCharacter());
- assertFalse(csvFormat.isCommentMarkerSet());
-
- assertFalse(csvFormat.isEscapeCharacterSet());
- assertTrue(csvFormat.isQuoteCharacterSet());
-
- assertFalse(csvFormat.getSkipHeaderRecord());
- assertNull(csvFormat.getQuoteMode());
-
- assertEquals(',', csvFormat.getDelimiter());
- assertTrue(csvFormat.getIgnoreEmptyLines());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertNull(csvFormat.getCommentMarker());
-
- assertEquals("\r\n", csvFormat.getRecordSeparator());
- assertFalse(csvFormat.getTrailingDelimiter());
-
- assertFalse(csvFormat.getAllowMissingColumnNames());
- assertFalse(csvFormat.getTrim());
-
- assertFalse(csvFormat.isNullStringSet());
- assertNull(csvFormat.getNullString());
-
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
- assertNull(csvFormat.getEscapeCharacter());
-
- final Object[] objectArray = new Object[8];
- final CSVFormat csvFormatTwo = csvFormat.withHeaderComments(objectArray);
-
- assertEquals('\"', (char) csvFormat.getQuoteCharacter());
- assertFalse(csvFormat.isCommentMarkerSet());
-
- assertFalse(csvFormat.isEscapeCharacterSet());
- assertTrue(csvFormat.isQuoteCharacterSet());
-
- assertFalse(csvFormat.getSkipHeaderRecord());
- assertNull(csvFormat.getQuoteMode());
-
- assertEquals(',', csvFormat.getDelimiter());
- assertTrue(csvFormat.getIgnoreEmptyLines());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertNull(csvFormat.getCommentMarker());
-
- assertEquals("\r\n", csvFormat.getRecordSeparator());
- assertFalse(csvFormat.getTrailingDelimiter());
-
- assertFalse(csvFormat.getAllowMissingColumnNames());
- assertFalse(csvFormat.getTrim());
-
- assertFalse(csvFormat.isNullStringSet());
- assertNull(csvFormat.getNullString());
-
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
- assertNull(csvFormat.getEscapeCharacter());
-
- assertFalse(csvFormatTwo.getIgnoreHeaderCase());
- assertNull(csvFormatTwo.getQuoteMode());
-
- assertTrue(csvFormatTwo.getIgnoreEmptyLines());
- assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
-
- assertNull(csvFormatTwo.getEscapeCharacter());
- assertFalse(csvFormatTwo.getTrim());
-
- assertFalse(csvFormatTwo.isEscapeCharacterSet());
- assertTrue(csvFormatTwo.isQuoteCharacterSet());
-
- assertFalse(csvFormatTwo.getSkipHeaderRecord());
- assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
-
- assertFalse(csvFormatTwo.getAllowMissingColumnNames());
- assertNull(csvFormatTwo.getNullString());
-
- assertFalse(csvFormatTwo.isNullStringSet());
- assertFalse(csvFormatTwo.getTrailingDelimiter());
-
- assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
- assertEquals(',', csvFormatTwo.getDelimiter());
-
- assertNull(csvFormatTwo.getCommentMarker());
- assertFalse(csvFormatTwo.isCommentMarkerSet());
-
- assertNotSame(csvFormat, csvFormatTwo);
- assertNotSame(csvFormatTwo, csvFormat);
-
- Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal
-
- final String string = csvFormatTwo.format(objectArray);
-
- assertEquals('\"', (char) csvFormat.getQuoteCharacter());
- assertFalse(csvFormat.isCommentMarkerSet());
-
- assertFalse(csvFormat.isEscapeCharacterSet());
- assertTrue(csvFormat.isQuoteCharacterSet());
-
- assertFalse(csvFormat.getSkipHeaderRecord());
- assertNull(csvFormat.getQuoteMode());
-
- assertEquals(',', csvFormat.getDelimiter());
- assertTrue(csvFormat.getIgnoreEmptyLines());
-
- assertFalse(csvFormat.getIgnoreHeaderCase());
- assertNull(csvFormat.getCommentMarker());
-
- assertEquals("\r\n", csvFormat.getRecordSeparator());
- assertFalse(csvFormat.getTrailingDelimiter());
-
- assertFalse(csvFormat.getAllowMissingColumnNames());
- assertFalse(csvFormat.getTrim());
-
- assertFalse(csvFormat.isNullStringSet());
- assertNull(csvFormat.getNullString());
-
- assertFalse(csvFormat.getIgnoreSurroundingSpaces());
- assertNull(csvFormat.getEscapeCharacter());
-
- assertFalse(csvFormatTwo.getIgnoreHeaderCase());
- assertNull(csvFormatTwo.getQuoteMode());
-
- assertTrue(csvFormatTwo.getIgnoreEmptyLines());
- assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
-
- assertNull(csvFormatTwo.getEscapeCharacter());
- assertFalse(csvFormatTwo.getTrim());
-
- assertFalse(csvFormatTwo.isEscapeCharacterSet());
- assertTrue(csvFormatTwo.isQuoteCharacterSet());
-
- assertFalse(csvFormatTwo.getSkipHeaderRecord());
- assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
-
- assertFalse(csvFormatTwo.getAllowMissingColumnNames());
- assertNull(csvFormatTwo.getNullString());
-
- assertFalse(csvFormatTwo.isNullStringSet());
- assertFalse(csvFormatTwo.getTrailingDelimiter());
-
- assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
- assertEquals(',', csvFormatTwo.getDelimiter());
-
- assertNull(csvFormatTwo.getCommentMarker());
- assertFalse(csvFormatTwo.isCommentMarkerSet());
-
- assertNotSame(csvFormat, csvFormatTwo);
- assertNotSame(csvFormatTwo, csvFormat);
-
- assertNotNull(string);
- Assertions.assertNotEquals(csvFormat, csvFormatTwo); // CSV-244 - should not be equal
-
- Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal
- assertEquals(",,,,,,,", string);
-
- }
-
- @Test
- public void testWithHeaderEnum() {
- final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(Header.class);
- assertArrayEquals(new String[] { "Name", "Email", "Phone" }, formatWithHeader.getHeader());
- }
-
- @Test
- public void testWithHeaderEnumNull() {
- final CSVFormat format = CSVFormat.DEFAULT;
- final Class> simpleName = null;
- format.withHeader(simpleName);
- }
-
- @Test
- public void testWithHeaderResultSetNull() throws SQLException {
- final CSVFormat format = CSVFormat.DEFAULT;
- final ResultSet resultSet = null;
- format.withHeader(resultSet);
- }
-
- @Test
- public void testWithIgnoreEmptyLines() {
- assertFalse(CSVFormat.DEFAULT.withIgnoreEmptyLines(false).getIgnoreEmptyLines());
- assertTrue(CSVFormat.DEFAULT.withIgnoreEmptyLines().getIgnoreEmptyLines());
- }
-
- @Test
- public void testWithIgnoreSurround() {
- assertFalse(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(false).getIgnoreSurroundingSpaces());
- assertTrue(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces().getIgnoreSurroundingSpaces());
- }
-
- @Test
- public void testWithNullString() {
- final CSVFormat formatWithNullString = CSVFormat.DEFAULT.withNullString("null");
- assertEquals("null", formatWithNullString.getNullString());
- }
-
- @Test
- public void testWithQuoteChar() {
- final CSVFormat formatWithQuoteChar = CSVFormat.DEFAULT.withQuote('"');
- assertEquals(Character.valueOf('"'), formatWithQuoteChar.getQuoteCharacter());
- }
-
- @Test
- public void testWithQuoteLFThrowsException() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote(LF));
- }
-
- @Test
- public void testWithQuotePolicy() {
- final CSVFormat formatWithQuotePolicy = CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL);
- assertEquals(QuoteMode.ALL, formatWithQuotePolicy.getQuoteMode());
- }
-
- @Test
- public void testWithRecordSeparatorCR() {
- final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CR);
- assertEquals(String.valueOf(CR), formatWithRecordSeparator.getRecordSeparator());
- }
-
- @Test
- public void testWithRecordSeparatorCRLF() {
- final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CRLF);
- assertEquals(CRLF, formatWithRecordSeparator.getRecordSeparator());
- }
-
- @Test
- public void testWithRecordSeparatorLF() {
- final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(LF);
- assertEquals(String.valueOf(LF), formatWithRecordSeparator.getRecordSeparator());
- }
-
- @Test
- public void testWithSystemRecordSeparator() {
- final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withSystemRecordSeparator();
- assertEquals(System.lineSeparator(), formatWithRecordSeparator.getRecordSeparator());
- }
-}
+/*
+ * 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
+ *
+ * https://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.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Objects;
+
+import org.apache.commons.csv.CSVFormat.Builder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link CSVFormat}.
+ */
+public class CSVFormatTest {
+
+ public enum EmptyEnum {
+ // empty enum.
+ }
+
+ public enum Header {
+ Name, Email, Phone
+ }
+
+ private static void assertNotEquals(final Object right, final Object left) {
+ Assertions.assertNotEquals(right, left);
+ Assertions.assertNotEquals(left, right);
+ }
+
+ private static CSVFormat copy(final CSVFormat format) {
+ return format.builder().setDelimiter(format.getDelimiter()).get();
+ }
+
+ private void assertNotEquals(final String name, final String type, final Object left, final Object right) {
+ if (left.equals(right) || right.equals(left)) {
+ fail("Objects must not compare equal for " + name + "(" + type + ")");
+ }
+ if (left.hashCode() == right.hashCode()) {
+ fail("Hash code should not be equal for " + name + "(" + type + ")");
+ }
+ }
+
+ @Test
+ public void testBuildVsGet() {
+ final Builder builder = CSVFormat.DEFAULT.builder();
+ assertNotSame(builder.get(), builder.build());
+ }
+
+ @Test
+ public void testDelimiterEmptyStringThrowsException1() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter("").get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testDelimiterSameAsCommentStartThrowsException_Deprecated() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter('!').withCommentMarker('!'));
+ }
+
+ @Test
+ public void testDelimiterSameAsCommentStartThrowsException1() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter('!').setCommentMarker('!').get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testDelimiterSameAsEscapeThrowsException_Deprecated() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter('!').withEscape('!'));
+ }
+
+ @Test
+ public void testDelimiterSameAsEscapeThrowsException1() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter('!').setEscape('!').get());
+ }
+
+ @Test
+ public void testDelimiterSameAsRecordSeparatorThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat(CR));
+ }
+
+ @Test
+ public void testDuplicateHeaderElements() {
+ final String[] header = { "A", "A" };
+ final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader(header).get();
+ assertEquals(2, format.getHeader().length);
+ assertArrayEquals(header, format.getHeader());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testDuplicateHeaderElements_Deprecated() {
+ final String[] header = { "A", "A" };
+ final CSVFormat format = CSVFormat.DEFAULT.withHeader(header);
+ assertEquals(2, format.getHeader().length);
+ assertArrayEquals(header, format.getHeader());
+ }
+
+ @Test
+ public void testDuplicateHeaderElementsFalse() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setHeader("A", "A").get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testDuplicateHeaderElementsFalse_Deprecated() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withAllowDuplicateHeaderNames(false).withHeader("A", "A"));
+ }
+
+ @Test
+ public void testDuplicateHeaderElementsTrue() {
+ CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(true).setHeader("A", "A").get();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testDuplicateHeaderElementsTrue_Deprecated() {
+ CSVFormat.DEFAULT.withAllowDuplicateHeaderNames(true).withHeader("A", "A");
+ }
+
+ @Test
+ public void testDuplicateHeaderElementsTrueContainsEmpty1() {
+ CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setHeader("A", "", "B", "").get();
+ }
+
+ @Test
+ public void testDuplicateHeaderElementsTrueContainsEmpty2() {
+ CSVFormat.DEFAULT.builder().setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).setHeader("A", "", "B", "").get();
+ }
+
+ @Test
+ public void testDuplicateHeaderElementsTrueContainsEmpty3() {
+ CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setAllowMissingColumnNames(true).setHeader("A", "", "B", "").get();
+ }
+
+ @Test
+ public void testEquals() {
+ final CSVFormat right = CSVFormat.DEFAULT;
+ final CSVFormat left = copy(right);
+ Assertions.assertNotEquals(null, right);
+ Assertions.assertNotEquals("A String Instance", right);
+ 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('\'').builder().setQuote('"').setCommentMarker('#').setQuoteMode(QuoteMode.ALL).get();
+ final CSVFormat left = right.builder().setCommentMarker('!').get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsCommentStart_Deprecated() {
+ 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('\'').builder().setQuote('"').setCommentMarker('#').setEscape('+').setQuoteMode(QuoteMode.ALL).get();
+ final CSVFormat left = right.builder().setEscape('!').get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsEscape_Deprecated() {
+ final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withCommentMarker('#').withEscape('+').withQuoteMode(QuoteMode.ALL);
+ final CSVFormat left = right.withEscape('!');
+
+ assertNotEquals(right, left);
+ }
+
+ @Test
+ public void testEqualsHash() throws Exception {
+ final Method[] methods = CSVFormat.class.getDeclaredMethods();
+ for (final Method method : methods) {
+ if (Modifier.isPublic(method.getModifiers())) {
+ final String name = method.getName();
+ if (name.startsWith("with")) {
+ for (final Class> cls : method.getParameterTypes()) {
+ final String type = cls.getCanonicalName();
+ switch (type) {
+ case "boolean": {
+ final Object defTrue = method.invoke(CSVFormat.DEFAULT, Boolean.TRUE);
+ final Object defFalse = method.invoke(CSVFormat.DEFAULT, Boolean.FALSE);
+ assertNotEquals(name, type, defTrue, defFalse);
+ break;
+ }
+ case "char": {
+ final Object a = method.invoke(CSVFormat.DEFAULT, 'a');
+ final Object b = method.invoke(CSVFormat.DEFAULT, 'b');
+ assertNotEquals(name, type, a, b);
+ break;
+ }
+ case "java.lang.Character": {
+ final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { null });
+ final Object b = method.invoke(CSVFormat.DEFAULT, Character.valueOf('d'));
+ assertNotEquals(name, type, a, b);
+ break;
+ }
+ case "java.lang.String": {
+ final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { null });
+ final Object b = method.invoke(CSVFormat.DEFAULT, "e");
+ assertNotEquals(name, type, a, b);
+ break;
+ }
+ case "java.lang.String[]": {
+ final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { new String[] { null, null } });
+ final Object b = method.invoke(CSVFormat.DEFAULT, new Object[] { new String[] { "f", "g" } });
+ assertNotEquals(name, type, a, b);
+ break;
+ }
+ case "org.apache.commons.csv.QuoteMode": {
+ final Object a = method.invoke(CSVFormat.DEFAULT, QuoteMode.MINIMAL);
+ final Object b = method.invoke(CSVFormat.DEFAULT, QuoteMode.ALL);
+ assertNotEquals(name, type, a, b);
+ break;
+ }
+ case "org.apache.commons.csv.DuplicateHeaderMode": {
+ final Object a = method.invoke(CSVFormat.DEFAULT, DuplicateHeaderMode.ALLOW_ALL);
+ final Object b = method.invoke(CSVFormat.DEFAULT, DuplicateHeaderMode.DISALLOW);
+ assertNotEquals(name, type, a, b);
+ break;
+ }
+ case "java.lang.Object[]": {
+ final Object a = method.invoke(CSVFormat.DEFAULT, new Object[] { new Object[] { null, null } });
+ final Object b = method.invoke(CSVFormat.DEFAULT, new Object[] { new Object[] { new Object(), new Object() } });
+ assertNotEquals(name, type, a, b);
+ break;
+ }
+ default:
+ if ("withHeader".equals(name)) { // covered above by String[]
+ // ignored
+ } else {
+ fail("Unhandled method: " + name + "(" + type + ")");
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testEqualsHeader() {
+ final CSVFormat right = CSVFormat.newFormat('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setHeader("One", "Two", "Three")
+ .setIgnoreEmptyLines(true).setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get();
+ final CSVFormat left = right.builder().setHeader("Three", "Two", "One").get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsHeader_Deprecated() {
+ 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('\'').builder().setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
+ .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get();
+ final CSVFormat left = right.builder().setIgnoreEmptyLines(false).get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsIgnoreEmptyLines_Deprecated() {
+ 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('\'').builder().setCommentMarker('#').setEscape('+').setIgnoreSurroundingSpaces(true).setQuote('"')
+ .setQuoteMode(QuoteMode.ALL).get();
+ final CSVFormat left = right.builder().setIgnoreSurroundingSpaces(false).get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsIgnoreSurroundingSpaces_Deprecated() {
+ final CSVFormat right = CSVFormat.newFormat('\'').withCommentMarker('#').withEscape('+').withIgnoreSurroundingSpaces().withQuote('"')
+ .withQuoteMode(QuoteMode.ALL);
+ final CSVFormat left = right.withIgnoreSurroundingSpaces(false);
+
+ assertNotEquals(right, left);
+ }
+
+ @Test
+ public void testEqualsLeftNoQuoteRightQuote() {
+ final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get();
+ final CSVFormat right = left.builder().setQuote('#').get();
+
+ assertNotEquals(left, right);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsLeftNoQuoteRightQuote_Deprecated() {
+ final CSVFormat left = CSVFormat.newFormat(',').withQuote(null);
+ final CSVFormat right = left.withQuote('#');
+
+ assertNotEquals(left, right);
+ }
+
+ @Test
+ public void testEqualsNoQuotes() {
+ final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get();
+ final CSVFormat right = left.builder().setQuote(null).get();
+
+ assertEquals(left, right);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsNoQuotes_Deprecated() {
+ final CSVFormat left = CSVFormat.newFormat(',').withQuote(null);
+ final CSVFormat right = left.withQuote(null);
+
+ assertEquals(left, right);
+ }
+
+ @Test
+ public void testEqualsNullString() {
+ final CSVFormat right = CSVFormat.newFormat('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
+ .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).setNullString("null").get();
+ final CSVFormat left = right.builder().setNullString("---").get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsNullString_Deprecated() {
+ 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 testEqualsOne() {
+
+ final CSVFormat csvFormatOne = CSVFormat.INFORMIX_UNLOAD;
+ final CSVFormat csvFormatTwo = CSVFormat.MYSQL;
+
+ assertEquals('\\', (char) csvFormatOne.getEscapeCharacter());
+ assertEquals('\\', csvFormatOne.getEscapeChar());
+ assertNull(csvFormatOne.getQuoteMode());
+
+ assertTrue(csvFormatOne.getIgnoreEmptyLines());
+ assertFalse(csvFormatOne.getSkipHeaderRecord());
+
+ assertFalse(csvFormatOne.getIgnoreHeaderCase());
+ assertNull(csvFormatOne.getCommentMarker());
+
+ assertFalse(csvFormatOne.isCommentMarkerSet());
+ assertTrue(csvFormatOne.isQuoteCharacterSet());
+
+ assertEquals('|', csvFormatOne.getDelimiter());
+ assertFalse(csvFormatOne.getAllowMissingColumnNames());
+
+ assertTrue(csvFormatOne.isEscapeCharacterSet());
+ assertEquals("\n", csvFormatOne.getRecordSeparator());
+
+ assertEquals('\"', (char) csvFormatOne.getQuoteCharacter());
+ assertFalse(csvFormatOne.getTrailingDelimiter());
+
+ assertFalse(csvFormatOne.getTrim());
+ assertFalse(csvFormatOne.isNullStringSet());
+
+ assertNull(csvFormatOne.getNullString());
+ assertFalse(csvFormatOne.getIgnoreSurroundingSpaces());
+
+ assertTrue(csvFormatTwo.isEscapeCharacterSet());
+ assertNull(csvFormatTwo.getQuoteCharacter());
+
+ assertFalse(csvFormatTwo.getAllowMissingColumnNames());
+ assertEquals(QuoteMode.ALL_NON_NULL, csvFormatTwo.getQuoteMode());
+
+ assertEquals('\t', csvFormatTwo.getDelimiter());
+ assertArrayEquals(new char[] { '\t' }, csvFormatTwo.getDelimiterCharArray());
+ assertEquals("\t", csvFormatTwo.getDelimiterString());
+ assertEquals("\n", csvFormatTwo.getRecordSeparator());
+
+ assertFalse(csvFormatTwo.isQuoteCharacterSet());
+ assertTrue(csvFormatTwo.isNullStringSet());
+
+ assertEquals('\\', (char) csvFormatTwo.getEscapeCharacter());
+ assertFalse(csvFormatTwo.getIgnoreHeaderCase());
+
+ assertFalse(csvFormatTwo.getTrim());
+ assertFalse(csvFormatTwo.getIgnoreEmptyLines());
+
+ assertEquals("\\N", csvFormatTwo.getNullString());
+ assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
+
+ assertFalse(csvFormatTwo.getTrailingDelimiter());
+ assertFalse(csvFormatTwo.getSkipHeaderRecord());
+
+ assertNull(csvFormatTwo.getCommentMarker());
+ assertFalse(csvFormatTwo.isCommentMarkerSet());
+
+ assertNotSame(csvFormatTwo, csvFormatOne);
+ Assertions.assertNotEquals(csvFormatTwo, csvFormatOne);
+
+ assertEquals('\\', (char) csvFormatOne.getEscapeCharacter());
+ assertNull(csvFormatOne.getQuoteMode());
+
+ assertTrue(csvFormatOne.getIgnoreEmptyLines());
+ assertFalse(csvFormatOne.getSkipHeaderRecord());
+
+ assertFalse(csvFormatOne.getIgnoreHeaderCase());
+ assertNull(csvFormatOne.getCommentMarker());
+
+ assertFalse(csvFormatOne.isCommentMarkerSet());
+ assertTrue(csvFormatOne.isQuoteCharacterSet());
+
+ assertEquals('|', csvFormatOne.getDelimiter());
+ assertFalse(csvFormatOne.getAllowMissingColumnNames());
+
+ assertTrue(csvFormatOne.isEscapeCharacterSet());
+ assertEquals("\n", csvFormatOne.getRecordSeparator());
+
+ assertEquals('\"', (char) csvFormatOne.getQuoteCharacter());
+ assertFalse(csvFormatOne.getTrailingDelimiter());
+
+ assertFalse(csvFormatOne.getTrim());
+ assertFalse(csvFormatOne.isNullStringSet());
+
+ assertNull(csvFormatOne.getNullString());
+ assertFalse(csvFormatOne.getIgnoreSurroundingSpaces());
+
+ assertTrue(csvFormatTwo.isEscapeCharacterSet());
+ assertNull(csvFormatTwo.getQuoteCharacter());
+
+ assertFalse(csvFormatTwo.getAllowMissingColumnNames());
+ assertEquals(QuoteMode.ALL_NON_NULL, csvFormatTwo.getQuoteMode());
+
+ assertEquals('\t', csvFormatTwo.getDelimiter());
+ assertEquals("\n", csvFormatTwo.getRecordSeparator());
+
+ assertFalse(csvFormatTwo.isQuoteCharacterSet());
+ assertTrue(csvFormatTwo.isNullStringSet());
+
+ assertEquals('\\', (char) csvFormatTwo.getEscapeCharacter());
+ assertFalse(csvFormatTwo.getIgnoreHeaderCase());
+
+ assertFalse(csvFormatTwo.getTrim());
+ assertFalse(csvFormatTwo.getIgnoreEmptyLines());
+
+ assertEquals("\\N", csvFormatTwo.getNullString());
+ assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
+
+ assertFalse(csvFormatTwo.getTrailingDelimiter());
+ assertFalse(csvFormatTwo.getSkipHeaderRecord());
+
+ assertNull(csvFormatTwo.getCommentMarker());
+ assertFalse(csvFormatTwo.isCommentMarkerSet());
+
+ assertNotSame(csvFormatOne, csvFormatTwo);
+ assertNotSame(csvFormatTwo, csvFormatOne);
+
+ Assertions.assertNotEquals(csvFormatOne, csvFormatTwo);
+ Assertions.assertNotEquals(csvFormatTwo, csvFormatOne);
+
+ Assertions.assertNotEquals(csvFormatTwo, csvFormatOne);
+
+ }
+
+ @Test
+ public void testEqualsQuoteChar() {
+ final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').get();
+ final CSVFormat left = right.builder().setQuote('!').get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsQuoteChar_Deprecated() {
+ final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"');
+ final CSVFormat left = right.withQuote('!');
+
+ assertNotEquals(right, left);
+ }
+
+ @Test
+ public void testEqualsQuotePolicy() {
+ final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').setQuoteMode(QuoteMode.ALL).get();
+ final CSVFormat left = right.builder().setQuoteMode(QuoteMode.MINIMAL).get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsQuotePolicy_Deprecated() {
+ 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('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
+ .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get();
+ final CSVFormat left = right.builder().setRecordSeparator(LF).get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsRecordSeparator_Deprecated() {
+ final CSVFormat right = CSVFormat.newFormat('\'').withRecordSeparator(CR).withCommentMarker('#').withEscape('+').withIgnoreEmptyLines()
+ .withIgnoreSurroundingSpaces().withQuote('"').withQuoteMode(QuoteMode.ALL);
+ final CSVFormat left = right.withRecordSeparator(LF);
+
+ assertNotEquals(right, left);
+ }
+
+ public void testEqualsSkipHeaderRecord() {
+ final CSVFormat right = CSVFormat.newFormat('\'').builder().setRecordSeparator(CR).setCommentMarker('#').setEscape('+').setIgnoreEmptyLines(true)
+ .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).setNullString("null").setSkipHeaderRecord(true).get();
+ final CSVFormat left = right.builder().setSkipHeaderRecord(false).get();
+
+ assertNotEquals(right, left);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEqualsSkipHeaderRecord_Deprecated() {
+ 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
+ public void testEqualsWithNull() {
+
+ final CSVFormat csvFormat = CSVFormat.POSTGRESQL_TEXT;
+
+ assertEquals('\\', (char) csvFormat.getEscapeCharacter());
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+
+ assertFalse(csvFormat.getTrailingDelimiter());
+ assertFalse(csvFormat.getTrim());
+
+ assertFalse(csvFormat.isQuoteCharacterSet());
+ assertEquals("\\N", csvFormat.getNullString());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertTrue(csvFormat.isEscapeCharacterSet());
+
+ assertFalse(csvFormat.isCommentMarkerSet());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+ assertEquals(QuoteMode.ALL_NON_NULL, csvFormat.getQuoteMode());
+
+ assertEquals('\t', csvFormat.getDelimiter());
+ assertFalse(csvFormat.getSkipHeaderRecord());
+
+ assertEquals("\n", csvFormat.getRecordSeparator());
+ assertFalse(csvFormat.getIgnoreEmptyLines());
+
+ assertNull(csvFormat.getQuoteCharacter());
+ assertTrue(csvFormat.isNullStringSet());
+
+ assertEquals('\\', (char) csvFormat.getEscapeCharacter());
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+
+ assertFalse(csvFormat.getTrailingDelimiter());
+ assertFalse(csvFormat.getTrim());
+
+ assertFalse(csvFormat.isQuoteCharacterSet());
+ assertEquals("\\N", csvFormat.getNullString());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertTrue(csvFormat.isEscapeCharacterSet());
+
+ assertFalse(csvFormat.isCommentMarkerSet());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+ assertEquals(QuoteMode.ALL_NON_NULL, csvFormat.getQuoteMode());
+
+ assertEquals('\t', csvFormat.getDelimiter());
+ assertFalse(csvFormat.getSkipHeaderRecord());
+
+ assertEquals("\n", csvFormat.getRecordSeparator());
+ assertFalse(csvFormat.getIgnoreEmptyLines());
+
+ assertNull(csvFormat.getQuoteCharacter());
+ assertTrue(csvFormat.isNullStringSet());
+
+ Assertions.assertNotEquals(null, csvFormat);
+
+ }
+
+ @Test
+ public void testEscapeSameAsCommentStartThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setEscape('!').setCommentMarker('!').get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEscapeSameAsCommentStartThrowsException_Deprecated() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape('!').withCommentMarker('!'));
+ }
+
+ @Test
+ public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType() {
+ // Cannot assume that callers won't use different Character objects
+ assertThrows(IllegalArgumentException.class,
+ () -> CSVFormat.DEFAULT.builder().setEscape(Character.valueOf('!')).setCommentMarker(Character.valueOf('!')).get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType_Deprecated() {
+ // Cannot assume that callers won't use different Character objects
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape(Character.valueOf('!')).withCommentMarker(Character.valueOf('!')));
+ }
+
+ @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 // I assume this to be a defect.
+ public void testFormatThrowsNullPointerException() {
+
+ final CSVFormat csvFormat = CSVFormat.MYSQL;
+
+ final NullPointerException e = assertThrows(NullPointerException.class, () -> csvFormat.format((Object[]) null));
+ assertEquals(Objects.class.getName(), e.getStackTrace()[0].getClassName());
+ }
+
+ @Test
+ public void testFormatToString() {
+ // @formatter:off
+ final CSVFormat format = CSVFormat.RFC4180
+ .withEscape('?')
+ .withDelimiter(',')
+ .withQuoteMode(QuoteMode.MINIMAL)
+ .withRecordSeparator(CRLF)
+ .withQuote('"')
+ .withNullString("")
+ .withIgnoreHeaderCase(true)
+ .withHeaderComments("This is HeaderComments")
+ .withHeader("col1", "col2", "col3");
+ // @formatter:on
+ assertEquals(
+ "Delimiter=<,> Escape=> QuoteChar=<\"> QuoteMode= NullString=<> RecordSeparator=<" + CRLF +
+ "> IgnoreHeaderCase:ignored SkipHeaderRecord:false HeaderComments:[This is HeaderComments] Header:[col1, col2, col3]",
+ format.toString());
+ }
+
+ @Test
+ public void testGetAllowDuplicateHeaderNames() {
+ final Builder builder = CSVFormat.DEFAULT.builder();
+ assertTrue(builder.get().getAllowDuplicateHeaderNames());
+ assertTrue(builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_ALL).get().getAllowDuplicateHeaderNames());
+ assertFalse(builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).get().getAllowDuplicateHeaderNames());
+ assertFalse(builder.setDuplicateHeaderMode(DuplicateHeaderMode.DISALLOW).get().getAllowDuplicateHeaderNames());
+ }
+
+ @Test
+ public void testGetDuplicateHeaderMode() {
+ final Builder builder = CSVFormat.DEFAULT.builder();
+
+ assertEquals(DuplicateHeaderMode.ALLOW_ALL, builder.get().getDuplicateHeaderMode());
+ assertEquals(DuplicateHeaderMode.ALLOW_ALL, builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_ALL).get().getDuplicateHeaderMode());
+ assertEquals(DuplicateHeaderMode.ALLOW_EMPTY, builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).get().getDuplicateHeaderMode());
+ assertEquals(DuplicateHeaderMode.DISALLOW, builder.setDuplicateHeaderMode(DuplicateHeaderMode.DISALLOW).get().getDuplicateHeaderMode());
+ }
+
+ @Test
+ public void testGetHeader() {
+ final String[] header = { "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 testHashCodeAndWithIgnoreHeaderCase() {
+
+ final CSVFormat csvFormat = CSVFormat.INFORMIX_UNLOAD_CSV;
+ final CSVFormat csvFormatTwo = csvFormat.withIgnoreHeaderCase();
+ csvFormatTwo.hashCode();
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertTrue(csvFormatTwo.getIgnoreHeaderCase()); // now different
+ assertFalse(csvFormatTwo.getTrailingDelimiter());
+
+ Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal
+ assertFalse(csvFormatTwo.getAllowMissingColumnNames());
+
+ assertFalse(csvFormatTwo.getTrim());
+
+ }
+
+ @Test
+ public void testJiraCsv236() {
+ CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(true).setHeader("CC", "VV", "VV").get();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testJiraCsv236__Deprecated() {
+ CSVFormat.DEFAULT.withAllowDuplicateHeaderNames().withHeader("CC", "VV", "VV");
+ }
+
+ @Test
+ public void testNewFormat() {
+
+ final CSVFormat csvFormat = CSVFormat.newFormat('X');
+
+ assertFalse(csvFormat.getSkipHeaderRecord());
+ assertFalse(csvFormat.isEscapeCharacterSet());
+
+ assertNull(csvFormat.getRecordSeparator());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertNull(csvFormat.getCommentMarker());
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+ assertFalse(csvFormat.getTrim());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertNull(csvFormat.getEscapeCharacter());
+
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+ assertFalse(csvFormat.getTrailingDelimiter());
+
+ assertEquals('X', csvFormat.getDelimiter());
+ assertNull(csvFormat.getNullString());
+
+ assertFalse(csvFormat.isQuoteCharacterSet());
+ assertFalse(csvFormat.isCommentMarkerSet());
+
+ assertNull(csvFormat.getQuoteCharacter());
+ assertFalse(csvFormat.getIgnoreEmptyLines());
+
+ assertFalse(csvFormat.getSkipHeaderRecord());
+ assertFalse(csvFormat.isEscapeCharacterSet());
+
+ assertNull(csvFormat.getRecordSeparator());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertNull(csvFormat.getCommentMarker());
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+ assertFalse(csvFormat.getTrim());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertNull(csvFormat.getEscapeCharacter());
+
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+ assertFalse(csvFormat.getTrailingDelimiter());
+
+ assertEquals('X', csvFormat.getDelimiter());
+ assertNull(csvFormat.getNullString());
+
+ assertFalse(csvFormat.isQuoteCharacterSet());
+ assertFalse(csvFormat.isCommentMarkerSet());
+
+ assertNull(csvFormat.getQuoteCharacter());
+ assertFalse(csvFormat.getIgnoreEmptyLines());
+
+ }
+
+ @Test
+ public void testNullRecordSeparatorCsv106() {
+ final CSVFormat format = CSVFormat.newFormat(';').builder().setSkipHeaderRecord(true).setHeader("H1", "H2").get();
+ final String formatStr = format.format("A", "B");
+ assertNotNull(formatStr);
+ assertFalse(formatStr.endsWith("null"));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testNullRecordSeparatorCsv106__Deprecated() {
+ final CSVFormat format = CSVFormat.newFormat(';').withSkipHeaderRecord().withHeader("H1", "H2");
+ final String formatStr = format.format("A", "B");
+ assertNotNull(formatStr);
+ assertFalse(formatStr.endsWith("null"));
+ }
+
+ @Test
+ public void testPrintRecord() throws IOException {
+ final Appendable out = new StringBuilder();
+ final CSVFormat format = CSVFormat.RFC4180;
+ format.printRecord(out, "a", "b", "c");
+ assertEquals("a,b,c" + format.getRecordSeparator(), out.toString());
+ }
+
+ @Test
+ public void testPrintRecordEmpty() throws IOException {
+ final Appendable out = new StringBuilder();
+ final CSVFormat format = CSVFormat.RFC4180;
+ format.printRecord(out);
+ assertEquals(format.getRecordSeparator(), out.toString());
+ }
+
+ @Test
+ public void testPrintWithEscapesEndWithCRLF() throws IOException {
+ final Reader in = new StringReader("x,y,x\r\na,?b,c\r\n");
+ final Appendable out = new StringBuilder();
+ final CSVFormat format = CSVFormat.RFC4180.withEscape('?').withDelimiter(',').withQuote(null).withRecordSeparator(CRLF);
+ format.print(in, out, true);
+ assertEquals("x?,y?,x?r?na?,??b?,c?r?n", out.toString());
+ }
+
+ @Test
+ public void testPrintWithEscapesEndWithoutCRLF() throws IOException {
+ final Reader in = new StringReader("x,y,x");
+ final Appendable out = new StringBuilder();
+ final CSVFormat format = CSVFormat.RFC4180.withEscape('?').withDelimiter(',').withQuote(null).withRecordSeparator(CRLF);
+ format.print(in, out, true);
+ assertEquals("x?,y?,x", out.toString());
+ }
+
+ @Test
+ public void testPrintWithoutQuotes() throws IOException {
+ final Reader in = new StringReader("");
+ final Appendable out = new StringBuilder();
+ final CSVFormat format = CSVFormat.RFC4180.withDelimiter(',').withQuote('"').withEscape('?').withQuoteMode(QuoteMode.NON_NUMERIC);
+ format.print(in, out, true);
+ assertEquals("\"\"", out.toString());
+ }
+
+ @Test
+ public void testPrintWithQuoteModeIsNONE() throws IOException {
+ final Reader in = new StringReader("a,b,c");
+ final Appendable out = new StringBuilder();
+ final CSVFormat format = CSVFormat.RFC4180.withDelimiter(',').withQuote('"').withEscape('?').withQuoteMode(QuoteMode.NONE);
+ format.print(in, out, true);
+ assertEquals("a?,b?,c", out.toString());
+ }
+
+ @Test
+ public void testPrintWithQuotes() throws IOException {
+ final Reader in = new StringReader("\"a,b,c\r\nx,y,z");
+ final Appendable out = new StringBuilder();
+ final CSVFormat format = CSVFormat.RFC4180.withDelimiter(',').withQuote('"').withEscape('?').withQuoteMode(QuoteMode.NON_NUMERIC);
+ format.print(in, out, true);
+ assertEquals("\"\"\"a,b,c\r\nx,y,z\"", out.toString());
+ }
+
+ @Test
+ public void testQuoteCharSameAsCommentStartThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setCommentMarker('!').get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testQuoteCharSameAsCommentStartThrowsException_Deprecated() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote('!').withCommentMarker('!'));
+ }
+
+ @Test
+ public void testQuoteCharSameAsCommentStartThrowsExceptionForWrapperType() {
+ // Cannot assume that callers won't use different Character objects
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote(Character.valueOf('!')).setCommentMarker('!').get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testQuoteCharSameAsCommentStartThrowsExceptionForWrapperType_Deprecated() {
+ // Cannot assume that callers won't use different Character objects
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote(Character.valueOf('!')).withCommentMarker('!'));
+ }
+
+ @Test
+ public void testQuoteCharSameAsDelimiterThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setDelimiter('!').get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testQuoteCharSameAsDelimiterThrowsException_Deprecated() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote('!').withDelimiter('!'));
+ }
+
+ @Test
+ public void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() {
+ final Exception exception = assertThrows(IllegalArgumentException.class, () ->
+ // @formatter:off
+ CSVFormat.DEFAULT.builder()
+ .setHeader("Col1", "Col2", "Col3", "Col4")
+ .setQuoteMode(QuoteMode.NONE)
+ .get()
+ // @formatter:on
+ );
+ final String actualMessage = exception.getMessage();
+ final String expectedMessage = "Quote mode set to NONE but no escape character is set";
+ assertEquals(expectedMessage, actualMessage);
+ }
+
+ @Test
+ public void testQuotePolicyNoneWithoutEscapeThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat('!').builder().setQuoteMode(QuoteMode.NONE).get());
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testQuotePolicyNoneWithoutEscapeThrowsException_Deprecated() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat('!').withQuoteMode(QuoteMode.NONE));
+ }
+
+ @Test
+ public void testRFC4180() {
+ assertNull(RFC4180.getCommentMarker());
+ assertEquals(',', RFC4180.getDelimiter());
+ assertNull(RFC4180.getEscapeCharacter());
+ assertFalse(RFC4180.getIgnoreEmptyLines());
+ assertEquals(Character.valueOf('"'), RFC4180.getQuoteCharacter());
+ assertNull(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();
+
+ try (ObjectOutputStream oos = new ObjectOutputStream(out)) {
+ oos.writeObject(CSVFormat.DEFAULT);
+ oos.flush();
+ }
+
+ final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+ final CSVFormat format = (CSVFormat) in.readObject();
+
+ assertNotNull(format);
+ assertEquals(CSVFormat.DEFAULT.getDelimiter(), format.getDelimiter(), "delimiter");
+ assertEquals(CSVFormat.DEFAULT.getQuoteCharacter(), format.getQuoteCharacter(), "encapsulator");
+ assertEquals(CSVFormat.DEFAULT.getCommentMarker(), format.getCommentMarker(), "comment start");
+ assertEquals(CSVFormat.DEFAULT.getRecordSeparator(), format.getRecordSeparator(), "record separator");
+ assertEquals(CSVFormat.DEFAULT.getEscapeCharacter(), format.getEscapeCharacter(), "escape");
+ assertEquals(CSVFormat.DEFAULT.getIgnoreSurroundingSpaces(), format.getIgnoreSurroundingSpaces(), "trim");
+ assertEquals(CSVFormat.DEFAULT.getIgnoreEmptyLines(), format.getIgnoreEmptyLines(), "empty lines");
+ }
+
+ @Test
+ public void testToString() {
+
+ final String string = CSVFormat.INFORMIX_UNLOAD.toString();
+
+ assertEquals("Delimiter=<|> Escape=<\\> QuoteChar=<\"> RecordSeparator=<\n> EmptyLines:ignored SkipHeaderRecord:false", string);
+
+ }
+
+ @Test
+ public void testToStringAndWithCommentMarkerTakingCharacter() {
+
+ final CSVFormat.Predefined csvFormatPredefined = CSVFormat.Predefined.Default;
+ final CSVFormat csvFormat = csvFormatPredefined.getFormat();
+
+ assertNull(csvFormat.getEscapeCharacter());
+ assertTrue(csvFormat.isQuoteCharacterSet());
+
+ assertFalse(csvFormat.getTrim());
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+
+ assertFalse(csvFormat.getTrailingDelimiter());
+ assertEquals(',', csvFormat.getDelimiter());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertEquals("\r\n", csvFormat.getRecordSeparator());
+
+ assertFalse(csvFormat.isCommentMarkerSet());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+
+ assertFalse(csvFormat.isEscapeCharacterSet());
+ assertFalse(csvFormat.getSkipHeaderRecord());
+
+ assertNull(csvFormat.getNullString());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertTrue(csvFormat.getIgnoreEmptyLines());
+ assertEquals('\"', (char) csvFormat.getQuoteCharacter());
+
+ final Character character = Character.valueOf('n');
+
+ final CSVFormat csvFormatTwo = csvFormat.withCommentMarker(character);
+
+ assertNull(csvFormat.getEscapeCharacter());
+ assertTrue(csvFormat.isQuoteCharacterSet());
+
+ assertFalse(csvFormat.getTrim());
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+
+ assertFalse(csvFormat.getTrailingDelimiter());
+ assertEquals(',', csvFormat.getDelimiter());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertEquals("\r\n", csvFormat.getRecordSeparator());
+
+ assertFalse(csvFormat.isCommentMarkerSet());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+
+ assertFalse(csvFormat.isEscapeCharacterSet());
+ assertFalse(csvFormat.getSkipHeaderRecord());
+
+ assertNull(csvFormat.getNullString());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertTrue(csvFormat.getIgnoreEmptyLines());
+ assertEquals('\"', (char) csvFormat.getQuoteCharacter());
+
+ assertFalse(csvFormatTwo.isNullStringSet());
+ assertFalse(csvFormatTwo.getAllowMissingColumnNames());
+
+ assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
+ assertNull(csvFormatTwo.getNullString());
+
+ assertEquals(',', csvFormatTwo.getDelimiter());
+ assertFalse(csvFormatTwo.getTrailingDelimiter());
+
+ assertTrue(csvFormatTwo.isCommentMarkerSet());
+ assertFalse(csvFormatTwo.getIgnoreHeaderCase());
+
+ assertFalse(csvFormatTwo.getTrim());
+ assertNull(csvFormatTwo.getEscapeCharacter());
+
+ assertTrue(csvFormatTwo.isQuoteCharacterSet());
+ assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
+
+ assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
+ assertNull(csvFormatTwo.getQuoteMode());
+
+ assertEquals('n', (char) csvFormatTwo.getCommentMarker());
+ assertFalse(csvFormatTwo.getSkipHeaderRecord());
+
+ assertFalse(csvFormatTwo.isEscapeCharacterSet());
+ assertTrue(csvFormatTwo.getIgnoreEmptyLines());
+
+ assertNotSame(csvFormat, csvFormatTwo);
+ assertNotSame(csvFormatTwo, csvFormat);
+
+ Assertions.assertNotEquals(csvFormatTwo, csvFormat);
+
+ assertNull(csvFormat.getEscapeCharacter());
+ assertTrue(csvFormat.isQuoteCharacterSet());
+
+ assertFalse(csvFormat.getTrim());
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+
+ assertFalse(csvFormat.getTrailingDelimiter());
+ assertEquals(',', csvFormat.getDelimiter());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertEquals("\r\n", csvFormat.getRecordSeparator());
+
+ assertFalse(csvFormat.isCommentMarkerSet());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+
+ assertFalse(csvFormat.isEscapeCharacterSet());
+ assertFalse(csvFormat.getSkipHeaderRecord());
+
+ assertNull(csvFormat.getNullString());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertTrue(csvFormat.getIgnoreEmptyLines());
+ assertEquals('\"', (char) csvFormat.getQuoteCharacter());
+
+ assertFalse(csvFormatTwo.isNullStringSet());
+ assertFalse(csvFormatTwo.getAllowMissingColumnNames());
+
+ assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
+ assertNull(csvFormatTwo.getNullString());
+
+ assertEquals(',', csvFormatTwo.getDelimiter());
+ assertFalse(csvFormatTwo.getTrailingDelimiter());
+
+ assertTrue(csvFormatTwo.isCommentMarkerSet());
+ assertFalse(csvFormatTwo.getIgnoreHeaderCase());
+
+ assertFalse(csvFormatTwo.getTrim());
+ assertNull(csvFormatTwo.getEscapeCharacter());
+
+ assertTrue(csvFormatTwo.isQuoteCharacterSet());
+ assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
+
+ assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
+ assertNull(csvFormatTwo.getQuoteMode());
+
+ assertEquals('n', (char) csvFormatTwo.getCommentMarker());
+ assertFalse(csvFormatTwo.getSkipHeaderRecord());
+
+ assertFalse(csvFormatTwo.isEscapeCharacterSet());
+ assertTrue(csvFormatTwo.getIgnoreEmptyLines());
+
+ assertNotSame(csvFormat, csvFormatTwo);
+ assertNotSame(csvFormatTwo, csvFormat);
+
+ Assertions.assertNotEquals(csvFormat, csvFormatTwo);
+
+ Assertions.assertNotEquals(csvFormatTwo, csvFormat);
+ assertEquals("Delimiter=<,> QuoteChar=<\"> CommentStart= " + "RecordSeparator=<\r\n> EmptyLines:ignored SkipHeaderRecord:false",
+ csvFormatTwo.toString());
+
+ }
+
+ @Test
+ public void testTrim() throws IOException {
+ final CSVFormat formatWithTrim = CSVFormat.DEFAULT.withDelimiter(',').withTrim().withQuote(null).withRecordSeparator(CRLF);
+
+ CharSequence in = "a,b,c";
+ final StringBuilder out = new StringBuilder();
+ formatWithTrim.print(in, out, true);
+ assertEquals("a,b,c", out.toString());
+
+ in = new StringBuilder(" x,y,z");
+ out.setLength(0);
+ formatWithTrim.print(in, out, true);
+ assertEquals("x,y,z", out.toString());
+
+ in = new StringBuilder("");
+ out.setLength(0);
+ formatWithTrim.print(in, out, true);
+ assertEquals("", out.toString());
+
+ in = new StringBuilder("header\r\n");
+ out.setLength(0);
+ formatWithTrim.print(in, out, true);
+ assertEquals("header", out.toString());
+ }
+
+ @Test
+ public void testWithCommentStart() {
+ final CSVFormat formatWithCommentStart = CSVFormat.DEFAULT.withCommentMarker('#');
+ assertEquals(Character.valueOf('#'), formatWithCommentStart.getCommentMarker());
+ }
+
+ @Test
+ public void testWithCommentStartCRThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withCommentMarker(CR));
+ }
+
+ @Test
+ public void testWithDelimiter() {
+ final CSVFormat formatWithDelimiter = CSVFormat.DEFAULT.withDelimiter('!');
+ assertEquals('!', formatWithDelimiter.getDelimiter());
+ }
+
+ @Test
+ public void testWithDelimiterLFThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(LF));
+ }
+
+ @Test
+ public void testWithEmptyDuplicates() {
+ final CSVFormat formatWithEmptyDuplicates = CSVFormat.DEFAULT.builder().setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).get();
+
+ assertEquals(DuplicateHeaderMode.ALLOW_EMPTY, formatWithEmptyDuplicates.getDuplicateHeaderMode());
+ assertFalse(formatWithEmptyDuplicates.getAllowDuplicateHeaderNames());
+ }
+
+ @Test
+ public void testWithEmptyEnum() {
+ final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(EmptyEnum.class);
+ assertEquals(0, formatWithHeader.getHeader().length);
+ }
+
+ @Test
+ public void testWithEscape() {
+ final CSVFormat formatWithEscape = CSVFormat.DEFAULT.withEscape('&');
+ assertEquals(Character.valueOf('&'), formatWithEscape.getEscapeCharacter());
+ }
+
+ @Test
+ public void testWithEscapeCRThrowsExceptions() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape(CR));
+ }
+
+ @Test
+ public void testWithFirstRecordAsHeader() {
+ final CSVFormat formatWithFirstRecordAsHeader = CSVFormat.DEFAULT.withFirstRecordAsHeader();
+ assertTrue(formatWithFirstRecordAsHeader.getSkipHeaderRecord());
+ assertEquals(0, formatWithFirstRecordAsHeader.getHeader().length);
+ }
+
+ @Test
+ public void testWithHeader() {
+ final String[] header = { "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());
+ }
+
+ @Test
+ public void testWithHeaderComments() {
+
+ final CSVFormat csvFormat = CSVFormat.DEFAULT;
+
+ assertEquals('\"', (char) csvFormat.getQuoteCharacter());
+ assertFalse(csvFormat.isCommentMarkerSet());
+
+ assertFalse(csvFormat.isEscapeCharacterSet());
+ assertTrue(csvFormat.isQuoteCharacterSet());
+
+ assertFalse(csvFormat.getSkipHeaderRecord());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertEquals(',', csvFormat.getDelimiter());
+ assertTrue(csvFormat.getIgnoreEmptyLines());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertEquals("\r\n", csvFormat.getRecordSeparator());
+ assertFalse(csvFormat.getTrailingDelimiter());
+
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+ assertFalse(csvFormat.getTrim());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertNull(csvFormat.getNullString());
+
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+ assertNull(csvFormat.getEscapeCharacter());
+
+ final Object[] objectArray = new Object[8];
+ final CSVFormat csvFormatTwo = csvFormat.withHeaderComments(objectArray);
+
+ assertEquals('\"', (char) csvFormat.getQuoteCharacter());
+ assertFalse(csvFormat.isCommentMarkerSet());
+
+ assertFalse(csvFormat.isEscapeCharacterSet());
+ assertTrue(csvFormat.isQuoteCharacterSet());
+
+ assertFalse(csvFormat.getSkipHeaderRecord());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertEquals(',', csvFormat.getDelimiter());
+ assertTrue(csvFormat.getIgnoreEmptyLines());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertEquals("\r\n", csvFormat.getRecordSeparator());
+ assertFalse(csvFormat.getTrailingDelimiter());
+
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+ assertFalse(csvFormat.getTrim());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertNull(csvFormat.getNullString());
+
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+ assertNull(csvFormat.getEscapeCharacter());
+
+ assertFalse(csvFormatTwo.getIgnoreHeaderCase());
+ assertNull(csvFormatTwo.getQuoteMode());
+
+ assertTrue(csvFormatTwo.getIgnoreEmptyLines());
+ assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
+
+ assertNull(csvFormatTwo.getEscapeCharacter());
+ assertFalse(csvFormatTwo.getTrim());
+
+ assertFalse(csvFormatTwo.isEscapeCharacterSet());
+ assertTrue(csvFormatTwo.isQuoteCharacterSet());
+
+ assertFalse(csvFormatTwo.getSkipHeaderRecord());
+ assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
+
+ assertFalse(csvFormatTwo.getAllowMissingColumnNames());
+ assertNull(csvFormatTwo.getNullString());
+
+ assertFalse(csvFormatTwo.isNullStringSet());
+ assertFalse(csvFormatTwo.getTrailingDelimiter());
+
+ assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
+ assertEquals(',', csvFormatTwo.getDelimiter());
+
+ assertNull(csvFormatTwo.getCommentMarker());
+ assertFalse(csvFormatTwo.isCommentMarkerSet());
+
+ assertNotSame(csvFormat, csvFormatTwo);
+ assertNotSame(csvFormatTwo, csvFormat);
+
+ Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal
+
+ final String string = csvFormatTwo.format(objectArray);
+
+ assertEquals('\"', (char) csvFormat.getQuoteCharacter());
+ assertFalse(csvFormat.isCommentMarkerSet());
+
+ assertFalse(csvFormat.isEscapeCharacterSet());
+ assertTrue(csvFormat.isQuoteCharacterSet());
+
+ assertFalse(csvFormat.getSkipHeaderRecord());
+ assertNull(csvFormat.getQuoteMode());
+
+ assertEquals(',', csvFormat.getDelimiter());
+ assertTrue(csvFormat.getIgnoreEmptyLines());
+
+ assertFalse(csvFormat.getIgnoreHeaderCase());
+ assertNull(csvFormat.getCommentMarker());
+
+ assertEquals("\r\n", csvFormat.getRecordSeparator());
+ assertFalse(csvFormat.getTrailingDelimiter());
+
+ assertFalse(csvFormat.getAllowMissingColumnNames());
+ assertFalse(csvFormat.getTrim());
+
+ assertFalse(csvFormat.isNullStringSet());
+ assertNull(csvFormat.getNullString());
+
+ assertFalse(csvFormat.getIgnoreSurroundingSpaces());
+ assertNull(csvFormat.getEscapeCharacter());
+
+ assertFalse(csvFormatTwo.getIgnoreHeaderCase());
+ assertNull(csvFormatTwo.getQuoteMode());
+
+ assertTrue(csvFormatTwo.getIgnoreEmptyLines());
+ assertFalse(csvFormatTwo.getIgnoreSurroundingSpaces());
+
+ assertNull(csvFormatTwo.getEscapeCharacter());
+ assertFalse(csvFormatTwo.getTrim());
+
+ assertFalse(csvFormatTwo.isEscapeCharacterSet());
+ assertTrue(csvFormatTwo.isQuoteCharacterSet());
+
+ assertFalse(csvFormatTwo.getSkipHeaderRecord());
+ assertEquals('\"', (char) csvFormatTwo.getQuoteCharacter());
+
+ assertFalse(csvFormatTwo.getAllowMissingColumnNames());
+ assertNull(csvFormatTwo.getNullString());
+
+ assertFalse(csvFormatTwo.isNullStringSet());
+ assertFalse(csvFormatTwo.getTrailingDelimiter());
+
+ assertEquals("\r\n", csvFormatTwo.getRecordSeparator());
+ assertEquals(',', csvFormatTwo.getDelimiter());
+
+ assertNull(csvFormatTwo.getCommentMarker());
+ assertFalse(csvFormatTwo.isCommentMarkerSet());
+
+ assertNotSame(csvFormat, csvFormatTwo);
+ assertNotSame(csvFormatTwo, csvFormat);
+
+ assertNotNull(string);
+ Assertions.assertNotEquals(csvFormat, csvFormatTwo); // CSV-244 - should not be equal
+
+ Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal
+ assertEquals(",,,,,,,", string);
+
+ }
+
+ @Test
+ public void testWithHeaderEnum() {
+ final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(Header.class);
+ assertArrayEquals(new String[] { "Name", "Email", "Phone" }, formatWithHeader.getHeader());
+ }
+
+ @Test
+ public void testWithHeaderEnumNull() {
+ final CSVFormat format = CSVFormat.DEFAULT;
+ final Class> simpleName = null;
+ format.withHeader(simpleName);
+ }
+
+ @Test
+ public void testWithHeaderResultSetNull() throws SQLException {
+ final CSVFormat format = CSVFormat.DEFAULT;
+ final ResultSet resultSet = null;
+ format.withHeader(resultSet);
+ }
+
+ @Test
+ public void testWithIgnoreEmptyLines() {
+ assertFalse(CSVFormat.DEFAULT.withIgnoreEmptyLines(false).getIgnoreEmptyLines());
+ assertTrue(CSVFormat.DEFAULT.withIgnoreEmptyLines().getIgnoreEmptyLines());
+ }
+
+ @Test
+ public void testWithIgnoreSurround() {
+ assertFalse(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(false).getIgnoreSurroundingSpaces());
+ assertTrue(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces().getIgnoreSurroundingSpaces());
+ }
+
+ @Test
+ public void testWithNullString() {
+ final CSVFormat formatWithNullString = CSVFormat.DEFAULT.withNullString("null");
+ assertEquals("null", formatWithNullString.getNullString());
+ }
+
+ @Test
+ public void testWithQuoteChar() {
+ final CSVFormat formatWithQuoteChar = CSVFormat.DEFAULT.withQuote('"');
+ assertEquals(Character.valueOf('"'), formatWithQuoteChar.getQuoteCharacter());
+ }
+
+ @Test
+ public void testWithQuoteLFThrowsException() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote(LF));
+ }
+
+ @Test
+ public void testWithQuotePolicy() {
+ final CSVFormat formatWithQuotePolicy = CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL);
+ assertEquals(QuoteMode.ALL, formatWithQuotePolicy.getQuoteMode());
+ }
+
+ @Test
+ public void testWithRecordSeparatorCR() {
+ final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CR);
+ assertEquals(String.valueOf(CR), formatWithRecordSeparator.getRecordSeparator());
+ }
+
+ @Test
+ public void testWithRecordSeparatorCRLF() {
+ final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CRLF);
+ assertEquals(CRLF, formatWithRecordSeparator.getRecordSeparator());
+ }
+
+ @Test
+ public void testWithRecordSeparatorLF() {
+ final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(LF);
+ assertEquals(String.valueOf(LF), formatWithRecordSeparator.getRecordSeparator());
+ }
+
+ @Test
+ public void testWithSystemRecordSeparator() {
+ final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withSystemRecordSeparator();
+ assertEquals(System.lineSeparator(), formatWithRecordSeparator.getRecordSeparator());
+ }
+}
diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java
index da49a78cff..38d442e55b 100644
--- a/src/test/java/org/apache/commons/csv/CSVParserTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java
@@ -1,1812 +1,1812 @@
-/*
- * 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
- *
- * https://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.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertInstanceOf;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-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.io.UncheckedIOException;
-import java.net.URL;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.apache.commons.io.input.BOMInputStream;
-import org.apache.commons.io.input.BrokenInputStream;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
-
-/**
- * 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...).
- */
-public class CSVParserTest {
-
- private static final CSVFormat EXCEL_WITH_HEADER = CSVFormat.EXCEL.withHeader();
-
- private static final Charset UTF_8 = StandardCharsets.UTF_8;
-
- private static final String UTF_8_NAME = UTF_8.name();
-
- 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" } };
-
- // CSV with no header comments
- private static final String CSV_INPUT_NO_COMMENT = "A,B" + CRLF + "1,2" + CRLF;
-
- // CSV with a header comment
- private static final String CSV_INPUT_HEADER_COMMENT = "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF;
-
- // CSV with a single line header and trailer comment
- private static final String CSV_INPUT_HEADER_TRAILER_COMMENT = "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF + "# comment";
-
- // CSV with a multi-line header and trailer comment
- private static final String CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT = "# multi-line" + CRLF + "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF +
- "# multi-line" + CRLF + "# comment";
-
- // Format with auto-detected header
- private static final CSVFormat FORMAT_AUTO_HEADER = CSVFormat.Builder.create(CSVFormat.DEFAULT).setCommentMarker('#').setHeader().get();
-
- // Format with explicit header
- // @formatter:off
- private static final CSVFormat FORMAT_EXPLICIT_HEADER = CSVFormat.Builder.create(CSVFormat.DEFAULT)
- .setSkipHeaderRecord(true)
- .setCommentMarker('#')
- .setHeader("A", "B")
- .get();
- // @formatter:on
-
- // Format with explicit header that does not skip the header line
- // @formatter:off
- CSVFormat FORMAT_EXPLICIT_HEADER_NOSKIP = CSVFormat.Builder.create(CSVFormat.DEFAULT)
- .setCommentMarker('#')
- .setHeader("A", "B")
- .get();
- // @formatter:on
-
- @SuppressWarnings("resource") // caller releases
- private BOMInputStream createBOMInputStream(final String resource) throws IOException {
- return new BOMInputStream(ClassLoader.getSystemClassLoader().getResource(resource).openStream());
- }
-
- CSVRecord parse(final CSVParser parser, final int failParseRecordNo) throws IOException {
- if (parser.getRecordNumber() + 1 == failParseRecordNo) {
- assertThrows(IOException.class, () -> parser.nextRecord());
- return null;
- }
- return parser.nextRecord();
- }
-
- private void parseFully(final CSVParser parser) {
- parser.forEach(Assertions::assertNotNull);
- }
-
- @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.
-
- // @formatter:off
- 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 "} };
- // @formatter:on
- final CSVFormat format = CSVFormat.newFormat(',').withQuote('\'').withRecordSeparator(CRLF).withEscape('/').withIgnoreEmptyLines();
- try (CSVParser parser = CSVParser.parse(code, format)) {
- final List records = parser.getRecords();
- assertFalse(records.isEmpty());
- Utils.compare("Records do not match expected result", res, records);
- }
- }
-
- @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.
- // @formatter:off
- final String code = "" + " , , \n" + // 1)
- " \t , , \n" + // 2)
- " // , /, , /,\n" + // 3)
- "";
- final String[][] res = {{" ", " ", " "}, // 1
- {" \t ", " ", " "}, // 2
- {" / ", " , ", " ,"}, // 3
- };
- // @formatter:on
- final CSVFormat format = CSVFormat.newFormat(',').withRecordSeparator(CRLF).withEscape('/').withIgnoreEmptyLines();
- try (CSVParser parser = CSVParser.parse(code, format)) {
- final List records = parser.getRecords();
- assertFalse(records.isEmpty());
- Utils.compare("", res, records);
- }
- }
-
- @Test
- @Disabled
- 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 returned
- { "a\\\\,b" } // backslash in quotes only escapes a delimiter (",")
- };
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
-
- @Test
- @Disabled("CSV-107")
- public void testBOM() throws IOException {
- final URL url = ClassLoader.getSystemClassLoader().getResource("org/apache/commons/csv/CSVFileParser/bom.csv");
- try (CSVParser parser = CSVParser.parse(url, StandardCharsets.UTF_8, EXCEL_WITH_HEADER)) {
- parser.forEach(record -> assertNotNull(record.get("Date")));
- }
- }
-
- @Test
- public void testBOMInputStreamParserWithInputStream() throws IOException {
- try (BOMInputStream inputStream = createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv");
- CSVParser parser = CSVParser.parse(inputStream, UTF_8, EXCEL_WITH_HEADER)) {
- parser.forEach(record -> assertNotNull(record.get("Date")));
- }
- }
-
- @Test
- public void testBOMInputStreamParserWithReader() throws IOException {
- try (Reader reader = new InputStreamReader(createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv"), UTF_8_NAME);
- CSVParser parser = CSVParser.builder()
- .setReader(reader)
- .setFormat(EXCEL_WITH_HEADER)
- .get()) {
- parser.forEach(record -> assertNotNull(record.get("Date")));
- }
- }
-
- @Test
- public void testBOMInputStreamParseWithReader() throws IOException {
- try (Reader reader = new InputStreamReader(createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv"), UTF_8_NAME);
- CSVParser parser = CSVParser.builder()
- .setReader(reader)
- .setFormat(EXCEL_WITH_HEADER)
- .get()) {
- parser.forEach(record -> assertNotNull(record.get("Date")));
- }
- }
-
- @Test
- public void testCarriageReturnEndings() throws IOException {
- final String string = "foo\rbaar,\rhello,world\r,kanu";
- try (CSVParser parser = CSVParser.builder().setCharSequence(string).get()) {
- final List records = parser.getRecords();
- assertEquals(4, records.size());
- }
- }
-
- @Test
- public void testCarriageReturnLineFeedEndings() throws IOException {
- final String string = "foo\r\nbaar,\r\nhello,world\r\n,kanu";
- try (CSVParser parser = CSVParser.builder().setCharSequence(string).get()) {
- final List records = parser.getRecords();
- assertEquals(4, records.size());
- }
- }
-
- @Test
- public void testClose() throws Exception {
- final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z");
- final Iterator records;
- try (CSVParser parser = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in)) {
- records = parser.iterator();
- assertTrue(records.hasNext());
- }
- assertFalse(records.hasNext());
- assertThrows(NoSuchElementException.class, records::next);
- }
-
- @Test
- public void testCSV141CSVFormat_DEFAULT() throws Exception {
- testCSV141Failure(CSVFormat.DEFAULT, 3);
- }
-
- @Test
- public void testCSV141CSVFormat_INFORMIX_UNLOAD() throws Exception {
- testCSV141Failure(CSVFormat.INFORMIX_UNLOAD, 1);
- }
-
- @Test
- public void testCSV141CSVFormat_INFORMIX_UNLOAD_CSV() throws Exception {
- testCSV141Failure(CSVFormat.INFORMIX_UNLOAD_CSV, 3);
- }
-
- @Test
- public void testCSV141CSVFormat_ORACLE() throws Exception {
- testCSV141Failure(CSVFormat.ORACLE, 2);
- }
-
- @Test
- public void testCSV141CSVFormat_POSTGRESQL_CSV() throws Exception {
- testCSV141Failure(CSVFormat.POSTGRESQL_CSV, 3);
- }
-
- @Test
- public void testCSV141Excel() throws Exception {
- testCSV141Ok(CSVFormat.EXCEL);
- }
-
- private void testCSV141Failure(final CSVFormat format, final int failParseRecordNo) throws IOException {
- final Path path = Paths.get("src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv");
- try (CSVParser parser = CSVParser.parse(path, StandardCharsets.UTF_8, format)) {
- // row 1
- CSVRecord record = parse(parser, failParseRecordNo);
- if (record == null) {
- return; // expected failure
- }
- assertEquals("1414770317901", record.get(0));
- assertEquals("android.widget.EditText", record.get(1));
- assertEquals("pass sem1 _84*|*", record.get(2));
- assertEquals("0", record.get(3));
- assertEquals("pass sem1 _8", record.get(4));
- assertEquals(5, record.size());
- // row 2
- record = parse(parser, failParseRecordNo);
- if (record == null) {
- return; // expected failure
- }
- assertEquals("1414770318470", record.get(0));
- assertEquals("android.widget.EditText", record.get(1));
- assertEquals("pass sem1 _84:|", record.get(2));
- assertEquals("0", record.get(3));
- assertEquals("pass sem1 _84:\\", record.get(4));
- assertEquals(5, record.size());
- // row 3: Fail for certain
- assertThrows(IOException.class, () -> parser.nextRecord());
- }
- }
-
- private void testCSV141Ok(final CSVFormat format) throws IOException {
- final Path path = Paths.get("src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv");
- try (CSVParser parser = CSVParser.parse(path, StandardCharsets.UTF_8, format)) {
- // row 1
- CSVRecord record = parser.nextRecord();
- assertEquals("1414770317901", record.get(0));
- assertEquals("android.widget.EditText", record.get(1));
- assertEquals("pass sem1 _84*|*", record.get(2));
- assertEquals("0", record.get(3));
- assertEquals("pass sem1 _8", record.get(4));
- assertEquals(5, record.size());
- // row 2
- record = parser.nextRecord();
- assertEquals("1414770318470", record.get(0));
- assertEquals("android.widget.EditText", record.get(1));
- assertEquals("pass sem1 _84:|", record.get(2));
- assertEquals("0", record.get(3));
- assertEquals("pass sem1 _84:\\", record.get(4));
- assertEquals(5, record.size());
- // row 3
- record = parser.nextRecord();
- assertEquals("1414770318327", record.get(0));
- assertEquals("android.widget.EditText", record.get(1));
- assertEquals("pass sem1\n1414770318628\"", record.get(2));
- assertEquals("android.widget.EditText", record.get(3));
- assertEquals("pass sem1 _84*|*", record.get(4));
- assertEquals("0", record.get(5));
- assertEquals("pass sem1\n", record.get(6));
- assertEquals(7, record.size());
- // EOF
- record = parser.nextRecord();
- assertNull(record);
- }
- }
-
- @Test
- public void testCSV141RFC4180() throws Exception {
- testCSV141Failure(CSVFormat.RFC4180, 3);
- }
-
- @Test
- public void testCSV235() throws IOException {
- final String dqString = "\"aaa\",\"b\"\"bb\",\"ccc\""; // "aaa","b""bb","ccc"
- try (CSVParser parser = CSVFormat.RFC4180.parse(new StringReader(dqString))) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertFalse(records.hasNext());
- assertEquals(3, record.size());
- assertEquals("aaa", record.get(0));
- assertEquals("b\"bb", record.get(1));
- assertEquals("ccc", record.get(2));
- }
- }
-
- @Test
- public void testCSV57() throws Exception {
- try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) {
- final List list = parser.getRecords();
- assertNotNull(list);
- assertEquals(0, list.size());
- }
- }
-
- @Test
- public void testDefaultFormat() throws IOException {
- // @formatter:off
- final String code = "" + "a,b#\n" + // 1)
- "\"\n\",\" \",#\n" + // 2)
- "#,\"\"\n" + // 3)
- "# Final comment\n" // 4)
- ;
- // @formatter:on
- final String[][] res = { { "a", "b#" }, { "\n", " ", "#" }, { "#", "" }, { "# Final comment" } };
- CSVFormat format = CSVFormat.DEFAULT;
- assertFalse(format.isCommentMarkerSet());
- final String[][] resComments = { { "a", "b#" }, { "\n", " ", "#" } };
- try (CSVParser parser = CSVParser.parse(code, format)) {
- final List records = parser.getRecords();
- assertFalse(records.isEmpty());
- Utils.compare("Failed to parse without comments", res, records);
- format = CSVFormat.DEFAULT.withCommentMarker('#');
- }
- try (CSVParser parser = CSVParser.parse(code, format)) {
- final List records = parser.getRecords();
- Utils.compare("Failed to parse with comments", resComments, records);
- }
- }
-
- @Test
- public void testDuplicateHeadersAllowedByDefault() throws Exception {
- try (CSVParser parser = CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader())) {
- // noop
- }
- }
-
- @Test
- public void testDuplicateHeadersNotAllowed() {
- assertThrows(IllegalArgumentException.class,
- () -> CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader().withAllowDuplicateHeaderNames(false)));
- }
-
- @Test
- public void testEmptyFile() throws Exception {
- try (CSVParser parser = CSVParser.parse(Paths.get("src/test/resources/org/apache/commons/csv/empty.txt"), StandardCharsets.UTF_8,
- CSVFormat.DEFAULT)) {
- assertNull(parser.nextRecord());
- }
- }
-
- @Test
- public void testEmptyFileHeaderParsing() throws Exception {
- try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT.withFirstRecordAsHeader())) {
- assertNull(parser.nextRecord());
- assertTrue(parser.getHeaderNames().isEmpty());
- }
- }
-
- @Test
- public void testEmptyLineBehaviorCSV() 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) {
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
- }
-
- @Test
- public void testEmptyLineBehaviorExcel() 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) {
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
- }
-
- @Test
- public void testEmptyString() throws Exception {
- try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) {
- assertNull(parser.nextRecord());
- }
- }
-
- @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) {
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
- }
-
- @Test
- public void testEndOfFileBehaviorExcel() 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) {
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
- }
-
- @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", "" } };
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
-
- @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", "" } };
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
-
- /**
- * 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";
- try (CSVParser parser = CSVParser.parse(code, EXCEL_WITH_HEADER)) {
- parser.getRecords().forEach(record -> {
- assertEquals("a", record.get("A"));
- assertEquals("b", record.get("B"));
- assertEquals("c", record.get("C"));
- });
- }
- }
-
- @Test
- public void testFirstEndOfLineCr() throws IOException {
- final String data = "foo\rbaar,\rhello,world\r,kanu";
- try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(4, records.size());
- assertEquals("\r", parser.getFirstEndOfLine());
- }
- }
-
- @Test
- public void testFirstEndOfLineCrLf() throws IOException {
- final String data = "foo\r\nbaar,\r\nhello,world\r\n,kanu";
- try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(4, records.size());
- assertEquals("\r\n", parser.getFirstEndOfLine());
- }
- }
-
- @Test
- public void testFirstEndOfLineLf() throws IOException {
- final String data = "foo\nbaar,\nhello,world\n,kanu";
- try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(4, records.size());
- assertEquals("\n", parser.getFirstEndOfLine());
- }
- }
-
- @Test
- public void testForEach() throws Exception {
- try (Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
- CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
- final List records = new ArrayList<>();
- for (final CSVRecord record : parser) {
- 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 testGetHeaderComment_HeaderComment1() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) {
- parser.getRecords();
- // Expect a header comment
- assertTrue(parser.hasHeaderComment());
- assertEquals("header comment", parser.getHeaderComment());
- }
- }
-
- @Test
- public void testGetHeaderComment_HeaderComment2() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
- parser.getRecords();
- // Expect a header comment
- assertTrue(parser.hasHeaderComment());
- assertEquals("header comment", parser.getHeaderComment());
- }
- }
-
- @Test
- public void testGetHeaderComment_HeaderComment3() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
- parser.getRecords();
- // Expect no header comment - the text "comment" is attached to the first record
- assertFalse(parser.hasHeaderComment());
- assertNull(parser.getHeaderComment());
- }
- }
-
- @Test
- public void testGetHeaderComment_HeaderTrailerComment() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
- parser.getRecords();
- // Expect a header comment
- assertTrue(parser.hasHeaderComment());
- assertEquals("multi-line" + LF + "header comment", parser.getHeaderComment());
- }
- }
-
- @Test
- public void testGetHeaderComment_NoComment1() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_AUTO_HEADER)) {
- parser.getRecords();
- // Expect no header comment
- assertFalse(parser.hasHeaderComment());
- assertNull(parser.getHeaderComment());
- }
- }
-
- @Test
- public void testGetHeaderComment_NoComment2() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER)) {
- parser.getRecords();
- // Expect no header comment
- assertFalse(parser.hasHeaderComment());
- assertNull(parser.getHeaderComment());
- }
- }
-
- @Test
- public void testGetHeaderComment_NoComment3() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
- parser.getRecords();
- // Expect no header comment
- assertFalse(parser.hasHeaderComment());
- assertNull(parser.getHeaderComment());
- }
- }
-
- @Test
- public void testGetHeaderMap() throws Exception {
- try (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.
- assertEquals("A", columnNames.next());
- assertEquals("B", columnNames.next());
- 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());
- }
- }
-
- @Test
- public void testGetHeaderNames() throws IOException {
- try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
- final Map nameIndexMap = parser.getHeaderMap();
- final List headerNames = parser.getHeaderNames();
- assertNotNull(headerNames);
- assertEquals(nameIndexMap.size(), headerNames.size());
- for (int i = 0; i < headerNames.size(); i++) {
- final String name = headerNames.get(i);
- assertEquals(i, nameIndexMap.get(name).intValue());
- }
- }
- }
-
- @Test
- public void testGetHeaderNamesReadOnly() throws IOException {
- try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
- final List headerNames = parser.getHeaderNames();
- assertNotNull(headerNames);
- assertThrows(UnsupportedOperationException.class, () -> headerNames.add("This is a read-only list."));
- }
- }
-
- @Test
- public void testGetLine() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) {
- for (final String[] re : RESULT) {
- assertArrayEquals(re, parser.nextRecord().values());
- }
-
- assertNull(parser.nextRecord());
- }
- }
-
- @Test
- public void testGetLineNumberWithCR() throws Exception {
- validateLineNumbers(String.valueOf(CR));
- }
-
- @Test
- public void testGetLineNumberWithCRLF() throws Exception {
- validateLineNumbers(CRLF);
- }
-
- @Test
- public void testGetLineNumberWithLF() throws Exception {
- validateLineNumbers(String.valueOf(LF));
- }
-
- @Test
- public void testGetOneLine() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_1, CSVFormat.DEFAULT)) {
- final CSVRecord record = parser.getRecords().get(0);
- assertArrayEquals(RESULT[0], record.values());
- }
- }
-
- /**
- * Tests reusing a parser to process new string records one at a time as they are being discovered. See [CSV-110].
- *
- * @throws IOException when an I/O error occurs.
- */
- @Test
- public void testGetOneLineOneParser() throws IOException {
- final CSVFormat format = CSVFormat.DEFAULT;
- try (PipedWriter writer = new PipedWriter();
- CSVParser parser = CSVParser.builder()
- .setReader(new PipedReader(writer))
- .setFormat(format)
- .get()) {
- 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());
- }
- }
-
- @Test
- public void testGetRecordFourBytesRead() throws Exception {
- final String code = "id,a,b,c\n" +
- "1,😊,🤔,😂\n" +
- "2,😊,🤔,😂\n" +
- "3,😊,🤔,😂\n";
- final CSVFormat format = CSVFormat.Builder.create()
- .setDelimiter(',')
- .setQuote('\'')
- .get();
- try (CSVParser parser = CSVParser.builder().setReader(new StringReader(code)).setFormat(format).setCharset(UTF_8).setTrackBytes(true).get()) {
- CSVRecord record = new CSVRecord(parser, null, null, 1L, 0L, 0L);
-
- assertEquals(0, parser.getRecordNumber());
- assertNotNull(record = parser.nextRecord());
- assertEquals(1, record.getRecordNumber());
- assertEquals(code.indexOf('i'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), record.getCharacterPosition());
-
- assertNotNull(record = parser.nextRecord());
- assertEquals(2, record.getRecordNumber());
- assertEquals(code.indexOf('1'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), record.getCharacterPosition());
- assertNotNull(record = parser.nextRecord());
- assertEquals(3, record.getRecordNumber());
- assertEquals(code.indexOf('2'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), 26);
- assertNotNull(record = parser.nextRecord());
- assertEquals(4, record.getRecordNumber());
- assertEquals(code.indexOf('3'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), 43);
- }
- }
-
- @Test
- public void testGetRecordNumberWithCR() throws Exception {
- validateRecordNumbers(String.valueOf(CR));
- }
-
- @Test
- public void testGetRecordNumberWithCRLF() throws Exception {
- validateRecordNumbers(CRLF);
- }
-
- @Test
- public void testGetRecordNumberWithLF() throws Exception {
- validateRecordNumbers(String.valueOf(LF));
- }
-
- @Test
- public void testGetRecordPositionWithCRLF() throws Exception {
- validateRecordPosition(CRLF);
- }
-
- @Test
- public void testGetRecordPositionWithLF() throws Exception {
- validateRecordPosition(String.valueOf(LF));
- }
-
- @Test
- public void testGetRecords() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) {
- final List records = parser.getRecords();
- assertEquals(RESULT.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < RESULT.length; i++) {
- assertArrayEquals(RESULT[i], records.get(i).values());
- }
- }
- }
-
- @Test
- public void testGetRecordsFromBrokenInputStream() throws IOException {
- @SuppressWarnings("resource") // We also get an exception on close, which is OK but can't assert in a try.
- final CSVParser parser = CSVParser.parse(new BrokenInputStream(), UTF_8, CSVFormat.DEFAULT);
- assertThrows(UncheckedIOException.class, parser::getRecords);
-
- }
-
- @Test
- public void testGetRecordThreeBytesRead() throws Exception {
- final String code = "id,date,val5,val4\n" +
- "11111111111111,'4017-09-01',きちんと節分近くには咲いてる~,v4\n" +
- "22222222222222,'4017-01-01',おはよう私の友人~,v4\n" +
- "33333333333333,'4017-01-01',きる自然の力ってすごいな~,v4\n";
- final CSVFormat format = CSVFormat.Builder.create()
- .setDelimiter(',')
- .setQuote('\'')
- .get();
- try (CSVParser parser = CSVParser.builder().setReader(new StringReader(code)).setFormat(format).setCharset(UTF_8).setTrackBytes(true).get()) {
- CSVRecord record = new CSVRecord(parser, null, null, 1L, 0L, 0L);
-
- assertEquals(0, parser.getRecordNumber());
- assertNotNull(record = parser.nextRecord());
- assertEquals(1, record.getRecordNumber());
- assertEquals(code.indexOf('i'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), record.getCharacterPosition());
-
- assertNotNull(record = parser.nextRecord());
- assertEquals(2, record.getRecordNumber());
- assertEquals(code.indexOf('1'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), record.getCharacterPosition());
-
- assertNotNull(record = parser.nextRecord());
- assertEquals(3, record.getRecordNumber());
- assertEquals(code.indexOf('2'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), 95);
-
- assertNotNull(record = parser.nextRecord());
- assertEquals(4, record.getRecordNumber());
- assertEquals(code.indexOf('3'), record.getCharacterPosition());
- assertEquals(record.getBytePosition(), 154);
- }
- }
-
- @Test
- public void testGetRecordWithMultiLineValues() throws Exception {
- try (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(9, parser.getCurrentLineNumber());
- assertEquals(3, record.getRecordNumber());
- assertEquals(3, parser.getRecordNumber());
- assertNull(record = parser.nextRecord());
- assertEquals(9, parser.getCurrentLineNumber());
- assertEquals(3, parser.getRecordNumber());
- }
- }
-
- @Test
- public void testGetTrailerComment_HeaderComment1() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) {
- parser.getRecords();
- assertFalse(parser.hasTrailerComment());
- assertNull(parser.getTrailerComment());
- }
- }
-
- @Test
- public void testGetTrailerComment_HeaderComment2() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
- parser.getRecords();
- assertFalse(parser.hasTrailerComment());
- assertNull(parser.getTrailerComment());
- }
- }
-
- @Test
- public void testGetTrailerComment_HeaderComment3() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
- parser.getRecords();
- assertFalse(parser.hasTrailerComment());
- assertNull(parser.getTrailerComment());
- }
- }
-
- @Test
- public void testGetTrailerComment_HeaderTrailerComment1() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
- parser.getRecords();
- assertTrue(parser.hasTrailerComment());
- assertEquals("comment", parser.getTrailerComment());
- }
- }
-
- @Test
- public void testGetTrailerComment_HeaderTrailerComment2() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
- parser.getRecords();
- assertTrue(parser.hasTrailerComment());
- assertEquals("comment", parser.getTrailerComment());
- }
- }
-
- @Test
- public void testGetTrailerComment_HeaderTrailerComment3() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
- parser.getRecords();
- assertTrue(parser.hasTrailerComment());
- assertEquals("comment", parser.getTrailerComment());
- }
- }
-
- @Test
- public void testGetTrailerComment_MultilineComment() throws IOException {
- try (CSVParser parser = CSVParser.parse(CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
- parser.getRecords();
- assertTrue(parser.hasTrailerComment());
- assertEquals("multi-line" + LF + "comment", parser.getTrailerComment());
- }
- }
-
- @Test
- public void testHeader() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
-
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
- final Iterator records = parser.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 testHeaderComment() throws Exception {
- final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in)) {
- final Iterator records = parser.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");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withAllowMissingColumnNames().parse(in)) {
- final Iterator records = parser.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
- public void testHeaderMissingWithNull() throws Exception {
- final Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withNullString("").withAllowMissingColumnNames().parse(in)) {
- parser.iterator();
- }
- }
-
- @Test
- public void testHeadersMissing() throws Exception {
- try (Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
- CSVParser parser = CSVFormat.DEFAULT.withHeader().withAllowMissingColumnNames().parse(in)) {
- parser.iterator();
- }
- }
-
- @Test
- public void testHeadersMissingException() {
- final Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withHeader().parse(in).iterator());
- }
-
- @Test
- public void testHeadersMissingOneColumnException() {
- final Reader in = new StringReader("a,,c,d,e\n1,2,3,4,5\nv,w,x,y,z");
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withHeader().parse(in).iterator());
- }
-
- @Test
- public void testHeadersWithNullColumnName() throws IOException {
- final Reader in = new StringReader("header1,null,header3\n1,2,3\n4,5,6");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withNullString("null").withAllowMissingColumnNames().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- // Expect the null header to be missing
- @SuppressWarnings("resource")
- final CSVParser recordParser = record.getParser();
- assertEquals(Arrays.asList("header1", "header3"), recordParser.getHeaderNames());
- assertEquals(2, recordParser.getHeaderMap().size());
- }
- }
-
- @Test
- public void testIgnoreCaseHeaderMapping() throws Exception {
- final Reader reader = new StringReader("1,2,3");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("One", "TWO", "three").withIgnoreHeaderCase().parse(reader)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertEquals("1", record.get("one"));
- assertEquals("2", record.get("two"));
- assertEquals("3", record.get("THREE"));
- }
- }
-
- @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";
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(3, records.size());
- }
- }
-
- @Test
- public void testInvalidFormat() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR));
- }
-
- @Test
- public void testIterator() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
- final Iterator iterator = parser.iterator();
- assertTrue(iterator.hasNext());
- assertThrows(UnsupportedOperationException.class, iterator::remove);
- 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());
- assertThrows(NoSuchElementException.class, iterator::next);
- }
- }
-
- @Test
- public void testIteratorSequenceBreaking() throws IOException {
- final String fiveRows = "1\n2\n3\n4\n5\n";
- // Iterator hasNext() shouldn't break sequence
- try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
- final Iterator iter = parser.iterator();
- int recordNumber = 0;
- while (iter.hasNext()) {
- final CSVRecord record = iter.next();
- recordNumber++;
- assertEquals(String.valueOf(recordNumber), record.get(0));
- if (recordNumber >= 2) {
- break;
- }
- }
- iter.hasNext();
- while (iter.hasNext()) {
- final CSVRecord record = iter.next();
- recordNumber++;
- assertEquals(String.valueOf(recordNumber), record.get(0));
- }
- }
- // Consecutive enhanced for loops shouldn't break sequence
- try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
- int recordNumber = 0;
- for (final CSVRecord record : parser) {
- recordNumber++;
- assertEquals(String.valueOf(recordNumber), record.get(0));
- if (recordNumber >= 2) {
- break;
- }
- }
- for (final CSVRecord record : parser) {
- recordNumber++;
- assertEquals(String.valueOf(recordNumber), record.get(0));
- }
- }
- // Consecutive enhanced for loops with hasNext() peeking shouldn't break sequence
- try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
- int recordNumber = 0;
- for (final CSVRecord record : parser) {
- recordNumber++;
- assertEquals(String.valueOf(recordNumber), record.get(0));
- if (recordNumber >= 2) {
- break;
- }
- }
- parser.iterator().hasNext();
- for (final CSVRecord record : parser) {
- recordNumber++;
- assertEquals(String.valueOf(recordNumber), record.get(0));
- }
- }
- }
-
- @Test
- public void testLineFeedEndings() throws IOException {
- final String code = "foo\nbaar,\nhello,world\n,kanu";
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
- final List records = parser.getRecords();
- assertEquals(4, records.size());
- }
- }
-
- @Test
- public void testMappedButNotSetAsOutlook2007ContactExport() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("A", "B", "C").withSkipHeaderRecord().parse(in)) {
- final Iterator records = parser.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());
- // end
- assertFalse(records.hasNext());
- }
- }
-
- @Test
- @Disabled
- public void testMongoDbCsv() throws Exception {
- try (CSVParser parser = CSVParser.parse("\"a a\",b,c" + LF + "d,e,f", CSVFormat.MONGODB_CSV)) {
- final Iterator itr1 = parser.iterator();
- final Iterator itr2 = parser.iterator();
-
- final CSVRecord first = itr1.next();
- assertEquals("a 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));
- }
- }
-
- @Test
- // TODO this may lead to strange behavior, throw an exception if iterator() has already been called?
- public void testMultipleIterators() throws Exception {
- try (CSVParser parser = CSVParser.parse("a,b,c" + CRLF + "d,e,f", CSVFormat.DEFAULT)) {
- final Iterator itr1 = 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 = itr1.next();
- assertEquals("d", second.get(0));
- assertEquals("e", second.get(1));
- assertEquals("f", second.get(2));
- }
- }
-
- @Test
- public void testNewCSVParserNullReaderFormat() {
- assertThrows(NullPointerException.class, () -> new CSVParser(null, CSVFormat.DEFAULT));
- }
-
- @Test
- public void testNewCSVParserReaderNullFormat() {
- assertThrows(NullPointerException.class, () -> new CSVParser(new StringReader(""), null));
- }
-
- @Test
- public void testNoHeaderMap() throws Exception {
- try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT)) {
- assertNull(parser.getHeaderMap());
- }
- }
-
- @Test
- public void testNotValueCSV() throws IOException {
- final String source = "#";
- final CSVFormat csvFormat = CSVFormat.DEFAULT.withCommentMarker('#');
- try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
- final CSVRecord csvRecord = csvParser.nextRecord();
- assertNull(csvRecord);
- }
- }
-
- @Test
- public void testParse() throws Exception {
- final ClassLoader loader = ClassLoader.getSystemClassLoader();
- final URL url = loader.getResource("org/apache/commons/csv/CSVFileParser/test.csv");
- final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader("A", "B", "C", "D").get();
- final Charset charset = StandardCharsets.UTF_8;
- // Reader
- try (CSVParser parser = CSVParser.parse(new InputStreamReader(url.openStream(), charset), format)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).get()) {
- parseFully(parser);
- }
- // String
- final Path path = Paths.get(url.toURI());
- final String string = new String(Files.readAllBytes(path), charset);
- try (CSVParser parser = CSVParser.parse(string, format)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setCharSequence(string).setFormat(format).get()) {
- parseFully(parser);
- }
- // File
- final File file = new File(url.toURI());
- try (CSVParser parser = CSVParser.parse(file, charset, format)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setFile(file).setCharset(charset).setFormat(format).get()) {
- parseFully(parser);
- }
- // InputStream
- try (CSVParser parser = CSVParser.parse(url.openStream(), charset, format)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setInputStream(url.openStream()).setCharset(charset).setFormat(format).get()) {
- parseFully(parser);
- }
- // Path
- try (CSVParser parser = CSVParser.parse(path, charset, format)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setPath(path).setCharset(charset).setFormat(format).get()) {
- parseFully(parser);
- }
- // URL
- try (CSVParser parser = CSVParser.parse(url, charset, format)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setURI(url.toURI()).setCharset(charset).setFormat(format).get()) {
- parseFully(parser);
- }
- // InputStreamReader
- try (CSVParser parser = new CSVParser(new InputStreamReader(url.openStream(), charset), format)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).get()) {
- parseFully(parser);
- }
- // InputStreamReader with longs
- try (CSVParser parser = new CSVParser(new InputStreamReader(url.openStream(), charset), format, /* characterOffset= */0, /* recordNumber= */1)) {
- parseFully(parser);
- }
- try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).setCharacterOffset(0)
- .setRecordNumber(0).get()) {
- parseFully(parser);
- }
- }
-
- @Test
- public void testParseFileNullFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse(new File("CSVFileParser/test.csv"), Charset.defaultCharset(), null));
- }
-
- @Test
- public void testParseNullFileFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse((File) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
- }
-
- @Test
- public void testParseNullPathFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse((Path) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
- }
-
- @Test
- public void testParseNullStringFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse((String) null, CSVFormat.DEFAULT));
- }
-
- @Test
- public void testParseNullUrlCharsetFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse((URL) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
- }
-
- @Test
- public void testParserUrlNullCharsetFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse(new URL("https://commons.apache.org"), null, CSVFormat.DEFAULT));
- }
-
- @Test
- public void testParseStringNullFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse("csv data", (CSVFormat) null));
- }
-
- @Test
- public void testParseUrlCharsetNullFormat() {
- assertThrows(NullPointerException.class, () -> CSVParser.parse(new URL("https://commons.apache.org"), Charset.defaultCharset(), null));
- }
-
- @Test
- public void testParseWithDelimiterStringWithEscape() throws IOException {
- final String source = "a![!|!]b![|]c[|]xyz\r\nabc[abc][|]xyz";
- final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').get();
- try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
- CSVRecord csvRecord = csvParser.nextRecord();
- assertEquals("a[|]b![|]c", csvRecord.get(0));
- assertEquals("xyz", csvRecord.get(1));
- csvRecord = csvParser.nextRecord();
- assertEquals("abc[abc]", csvRecord.get(0));
- assertEquals("xyz", csvRecord.get(1));
- }
- }
-
- @Test
- public void testParseWithDelimiterStringWithQuote() throws IOException {
- final String source = "'a[|]b[|]c'[|]xyz\r\nabc[abc][|]xyz";
- final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').get();
- try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
- CSVRecord csvRecord = csvParser.nextRecord();
- assertEquals("a[|]b[|]c", csvRecord.get(0));
- assertEquals("xyz", csvRecord.get(1));
- csvRecord = csvParser.nextRecord();
- assertEquals("abc[abc]", csvRecord.get(0));
- assertEquals("xyz", csvRecord.get(1));
- }
- }
-
- @Test
- public void testParseWithDelimiterWithEscape() throws IOException {
- final String source = "a!,b!,c,xyz";
- final CSVFormat csvFormat = CSVFormat.DEFAULT.withEscape('!');
- try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
- final CSVRecord csvRecord = csvParser.nextRecord();
- assertEquals("a,b,c", csvRecord.get(0));
- assertEquals("xyz", csvRecord.get(1));
- }
- }
-
- @Test
- public void testParseWithDelimiterWithQuote() throws IOException {
- final String source = "'a,b,c',xyz";
- final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'');
- try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
- final CSVRecord csvRecord = csvParser.nextRecord();
- assertEquals("a,b,c", csvRecord.get(0));
- assertEquals("xyz", csvRecord.get(1));
- }
- }
-
- @Test
- public void testParseWithQuoteThrowsException() {
- final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'');
- assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c','")).nextRecord());
- assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c'abc,xyz")).nextRecord());
- assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'abc'a,b,c',xyz")).nextRecord());
- }
-
- @Test
- public void testParseWithQuoteWithEscape() throws IOException {
- final String source = "'a?,b?,c?d',xyz";
- final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'').withEscape('?');
- try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
- final CSVRecord csvRecord = csvParser.nextRecord();
- assertEquals("a,b,c?d", csvRecord.get(0));
- assertEquals("xyz", csvRecord.get(1));
- }
- }
-
- @ParameterizedTest
- @EnumSource(CSVFormat.Predefined.class)
- public void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format) throws Exception {
- final String[][] lines = { { "a", "b" }, { "", "x" } };
- final StringWriter buf = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(buf, format.getFormat())) {
- printer.printRecords(Stream.of(lines));
- }
- try (CSVParser csvRecords = CSVParser.builder()
- .setReader(new StringReader(buf.toString()))
- .setFormat(format.getFormat())
- .get()) {
- for (final String[] line : lines) {
- assertArrayEquals(line, csvRecords.nextRecord().values());
- }
- assertNull(csvRecords.nextRecord());
- }
- }
-
- @Test
- public void testProvidedHeader() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
-
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("A", "B", "C").parse(in)) {
- final Iterator records = parser.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");
-
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
- final Iterator records = parser.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 testRepeatedHeadersAreReturnedInCSVRecordHeaderNames() throws IOException {
- final Reader in = new StringReader("header1,header2,header1\n1,2,3\n4,5,6");
- try (CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().withTrim().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- @SuppressWarnings("resource")
- final CSVParser recordParser = record.getParser();
- assertEquals(Arrays.asList("header1", "header2", "header1"), recordParser.getHeaderNames());
- }
- }
-
- @Test
- public void testRoundtrip() throws Exception {
- final StringWriter out = new StringWriter();
- final String data = "a,b,c\r\n1,2,3\r\nx,y,z\r\n";
- try (CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT);
- CSVParser parse = CSVParser.parse(data, CSVFormat.DEFAULT)) {
- for (final CSVRecord record : parse) {
- printer.printRecord(record);
- }
- assertEquals(data, out.toString());
- }
- }
-
- @Test
- public void testSkipAutoHeader() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertEquals("1", record.get("a"));
- assertEquals("2", record.get("b"));
- assertEquals("3", record.get("c"));
- }
- }
-
- @Test
- public void testSkipHeaderOverrideDuplicateHeaders() throws Exception {
- final Reader in = new StringReader("a,a,a\n1,2,3\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertEquals("1", record.get("X"));
- assertEquals("2", record.get("Y"));
- assertEquals("3", record.get("Z"));
- }
- }
-
- @Test
- public void testSkipSetAltHeaders() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertEquals("1", record.get("X"));
- assertEquals("2", record.get("Y"));
- assertEquals("3", record.get("Z"));
- }
- }
-
- @Test
- public void testSkipSetHeader() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("a", "b", "c").withSkipHeaderRecord().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertEquals("1", record.get("a"));
- assertEquals("2", record.get("b"));
- assertEquals("3", record.get("c"));
- }
- }
-
- @Test
- @Disabled
- 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) {
- try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
- final List records = parser.getRecords();
- assertEquals(res.length, records.size());
- assertFalse(records.isEmpty());
- for (int i = 0; i < res.length; i++) {
- assertArrayEquals(res[i], records.get(i).values());
- }
- }
- }
- }
-
- @Test
- public void testStream() throws Exception {
- final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
- final List list = parser.stream().collect(Collectors.toList());
- assertFalse(list.isEmpty());
- assertArrayEquals(new String[] { "a", "b", "c" }, list.get(0).values());
- assertArrayEquals(new String[] { "1", "2", "3" }, list.get(1).values());
- assertArrayEquals(new String[] { "x", "y", "z" }, list.get(2).values());
- }
- }
-
- @Test
- public void testThrowExceptionWithLineAndPosition() throws IOException {
- final String csvContent = "col1,col2,col3,col4,col5,col6,col7,col8,col9,col10\nrec1,rec2,rec3,rec4,rec5,rec6,rec7,rec8,\"\"rec9\"\",rec10";
- final StringReader stringReader = new StringReader(csvContent);
- // @formatter:off
- final CSVFormat csvFormat = CSVFormat.DEFAULT.builder()
- .setHeader()
- .setSkipHeaderRecord(true)
- .get();
- // @formatter:on
- try (CSVParser csvParser = csvFormat.parse(stringReader)) {
- final UncheckedIOException exception = assertThrows(UncheckedIOException.class, csvParser::getRecords);
- assertInstanceOf(CSVException.class, exception.getCause());
- assertTrue(exception.getMessage().contains("Invalid character between encapsulated token and delimiter at line: 2, position: 94"),
- exception::getMessage);
- }
- }
-
- @Test
- public void testTrailingDelimiter() throws Exception {
- final Reader in = new StringReader("a,a,a,\n\"1\",\"2\",\"3\",\nx,y,z,");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().withTrailingDelimiter().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertEquals("1", record.get("X"));
- assertEquals("2", record.get("Y"));
- assertEquals("3", record.get("Z"));
- assertEquals(3, record.size());
- }
- }
-
- @Test
- public void testTrim() throws Exception {
- final Reader in = new StringReader("a,a,a\n\" 1 \",\" 2 \",\" 3 \"\nx,y,z");
- try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().withTrim().parse(in)) {
- final Iterator records = parser.iterator();
- final CSVRecord record = records.next();
- assertEquals("1", record.get("X"));
- assertEquals("2", record.get("Y"));
- assertEquals("3", record.get("Z"));
- assertEquals(3, record.size());
- }
- }
-
- private void validateLineNumbers(final String lineSeparator) throws IOException {
- try (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());
- // Read EOF without EOL should 3
- assertEquals(3, parser.getCurrentLineNumber());
- assertNull(parser.nextRecord());
- // Read EOF without EOL should 3
- assertEquals(3, parser.getCurrentLineNumber());
- }
- }
-
- private void validateRecordNumbers(final String lineSeparator) throws IOException {
- try (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());
- }
- }
-
- 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);
- final long positionRecord3;
- try (CSVParser parser = CSVParser.parse(code, format)) {
- CSVRecord record;
- assertEquals(0, parser.getRecordNumber());
- // nextRecord
- assertNotNull(record = parser.nextRecord());
- assertEquals(1, record.getRecordNumber());
- assertEquals(code.indexOf('a'), record.getCharacterPosition());
- // nextRecord
- assertNotNull(record = parser.nextRecord());
- assertEquals(2, record.getRecordNumber());
- assertEquals(code.indexOf('1'), record.getCharacterPosition());
- // nextRecord
- assertNotNull(record = parser.nextRecord());
- 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));
- // nextRecord
- assertNotNull(record = parser.nextRecord());
- assertEquals(4, record.getRecordNumber());
- assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
- // nextRecord
- assertNotNull(record = parser.nextRecord());
- assertEquals(5, record.getRecordNumber());
- assertEquals(code.indexOf("EOF"), record.getCharacterPosition());
- }
- // now try to read starting at record 3
- try (CSVParser parser = CSVParser.builder()
- .setReader(new StringReader(code.substring((int) positionRecord3)))
- .setFormat(format)
- .setCharacterOffset(positionRecord3)
- .setRecordNumber(3)
- .get()) {
- CSVRecord record;
- // nextRecord
- 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));
- // nextRecord
- assertNotNull(record = parser.nextRecord());
- assertEquals(4, record.getRecordNumber());
- assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
- assertEquals("\u00c4", record.get(0));
- } // again with ctor
- try (CSVParser parser = new CSVParser(new StringReader(code.substring((int) positionRecord3)), format, positionRecord3, 3)) {
- CSVRecord record;
- // nextRecord
- 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));
- // nextRecord
- assertNotNull(record = parser.nextRecord());
- assertEquals(4, record.getRecordNumber());
- assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
- assertEquals("\u00c4", record.get(0));
- }
- }
-}
+/*
+ * 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
+ *
+ * https://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.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+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.io.UncheckedIOException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.commons.io.input.BOMInputStream;
+import org.apache.commons.io.input.BrokenInputStream;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.EnumSource;
+
+/**
+ * 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...).
+ */
+public class CSVParserTest {
+
+ private static final CSVFormat EXCEL_WITH_HEADER = CSVFormat.EXCEL.withHeader();
+
+ private static final Charset UTF_8 = StandardCharsets.UTF_8;
+
+ private static final String UTF_8_NAME = UTF_8.name();
+
+ 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" } };
+
+ // CSV with no header comments
+ private static final String CSV_INPUT_NO_COMMENT = "A,B" + CRLF + "1,2" + CRLF;
+
+ // CSV with a header comment
+ private static final String CSV_INPUT_HEADER_COMMENT = "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF;
+
+ // CSV with a single line header and trailer comment
+ private static final String CSV_INPUT_HEADER_TRAILER_COMMENT = "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF + "# comment";
+
+ // CSV with a multi-line header and trailer comment
+ private static final String CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT = "# multi-line" + CRLF + "# header comment" + CRLF + "A,B" + CRLF + "1,2" + CRLF +
+ "# multi-line" + CRLF + "# comment";
+
+ // Format with auto-detected header
+ private static final CSVFormat FORMAT_AUTO_HEADER = CSVFormat.Builder.create(CSVFormat.DEFAULT).setCommentMarker('#').setHeader().get();
+
+ // Format with explicit header
+ // @formatter:off
+ private static final CSVFormat FORMAT_EXPLICIT_HEADER = CSVFormat.Builder.create(CSVFormat.DEFAULT)
+ .setSkipHeaderRecord(true)
+ .setCommentMarker('#')
+ .setHeader("A", "B")
+ .get();
+ // @formatter:on
+
+ // Format with explicit header that does not skip the header line
+ // @formatter:off
+ CSVFormat FORMAT_EXPLICIT_HEADER_NOSKIP = CSVFormat.Builder.create(CSVFormat.DEFAULT)
+ .setCommentMarker('#')
+ .setHeader("A", "B")
+ .get();
+ // @formatter:on
+
+ @SuppressWarnings("resource") // caller releases
+ private BOMInputStream createBOMInputStream(final String resource) throws IOException {
+ return new BOMInputStream(ClassLoader.getSystemClassLoader().getResource(resource).openStream());
+ }
+
+ CSVRecord parse(final CSVParser parser, final int failParseRecordNo) throws IOException {
+ if (parser.getRecordNumber() + 1 == failParseRecordNo) {
+ assertThrows(IOException.class, () -> parser.nextRecord());
+ return null;
+ }
+ return parser.nextRecord();
+ }
+
+ private void parseFully(final CSVParser parser) {
+ parser.forEach(Assertions::assertNotNull);
+ }
+
+ @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.
+
+ // @formatter:off
+ 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 "} };
+ // @formatter:on
+ final CSVFormat format = CSVFormat.newFormat(',').withQuote('\'').withRecordSeparator(CRLF).withEscape('/').withIgnoreEmptyLines();
+ try (CSVParser parser = CSVParser.parse(code, format)) {
+ final List records = parser.getRecords();
+ assertFalse(records.isEmpty());
+ Utils.compare("Records do not match expected result", res, records);
+ }
+ }
+
+ @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.
+ // @formatter:off
+ final String code = "" + " , , \n" + // 1)
+ " \t , , \n" + // 2)
+ " // , /, , /,\n" + // 3)
+ "";
+ final String[][] res = {{" ", " ", " "}, // 1
+ {" \t ", " ", " "}, // 2
+ {" / ", " , ", " ,"}, // 3
+ };
+ // @formatter:on
+ final CSVFormat format = CSVFormat.newFormat(',').withRecordSeparator(CRLF).withEscape('/').withIgnoreEmptyLines();
+ try (CSVParser parser = CSVParser.parse(code, format)) {
+ final List records = parser.getRecords();
+ assertFalse(records.isEmpty());
+ Utils.compare("", res, records);
+ }
+ }
+
+ @Test
+ @Disabled
+ 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 returned
+ { "a\\\\,b" } // backslash in quotes only escapes a delimiter (",")
+ };
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+
+ @Test
+ @Disabled("CSV-107")
+ public void testBOM() throws IOException {
+ final URL url = ClassLoader.getSystemClassLoader().getResource("org/apache/commons/csv/CSVFileParser/bom.csv");
+ try (CSVParser parser = CSVParser.parse(url, StandardCharsets.UTF_8, EXCEL_WITH_HEADER)) {
+ parser.forEach(record -> assertNotNull(record.get("Date")));
+ }
+ }
+
+ @Test
+ public void testBOMInputStreamParserWithInputStream() throws IOException {
+ try (BOMInputStream inputStream = createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv");
+ CSVParser parser = CSVParser.parse(inputStream, UTF_8, EXCEL_WITH_HEADER)) {
+ parser.forEach(record -> assertNotNull(record.get("Date")));
+ }
+ }
+
+ @Test
+ public void testBOMInputStreamParserWithReader() throws IOException {
+ try (Reader reader = new InputStreamReader(createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv"), UTF_8_NAME);
+ CSVParser parser = CSVParser.builder()
+ .setReader(reader)
+ .setFormat(EXCEL_WITH_HEADER)
+ .get()) {
+ parser.forEach(record -> assertNotNull(record.get("Date")));
+ }
+ }
+
+ @Test
+ public void testBOMInputStreamParseWithReader() throws IOException {
+ try (Reader reader = new InputStreamReader(createBOMInputStream("org/apache/commons/csv/CSVFileParser/bom.csv"), UTF_8_NAME);
+ CSVParser parser = CSVParser.builder()
+ .setReader(reader)
+ .setFormat(EXCEL_WITH_HEADER)
+ .get()) {
+ parser.forEach(record -> assertNotNull(record.get("Date")));
+ }
+ }
+
+ @Test
+ public void testCarriageReturnEndings() throws IOException {
+ final String string = "foo\rbaar,\rhello,world\r,kanu";
+ try (CSVParser parser = CSVParser.builder().setCharSequence(string).get()) {
+ final List records = parser.getRecords();
+ assertEquals(4, records.size());
+ }
+ }
+
+ @Test
+ public void testCarriageReturnLineFeedEndings() throws IOException {
+ final String string = "foo\r\nbaar,\r\nhello,world\r\n,kanu";
+ try (CSVParser parser = CSVParser.builder().setCharSequence(string).get()) {
+ final List records = parser.getRecords();
+ assertEquals(4, records.size());
+ }
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z");
+ final Iterator records;
+ try (CSVParser parser = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in)) {
+ records = parser.iterator();
+ assertTrue(records.hasNext());
+ }
+ assertFalse(records.hasNext());
+ assertThrows(NoSuchElementException.class, records::next);
+ }
+
+ @Test
+ public void testCSV141CSVFormat_DEFAULT() throws Exception {
+ testCSV141Failure(CSVFormat.DEFAULT, 3);
+ }
+
+ @Test
+ public void testCSV141CSVFormat_INFORMIX_UNLOAD() throws Exception {
+ testCSV141Failure(CSVFormat.INFORMIX_UNLOAD, 1);
+ }
+
+ @Test
+ public void testCSV141CSVFormat_INFORMIX_UNLOAD_CSV() throws Exception {
+ testCSV141Failure(CSVFormat.INFORMIX_UNLOAD_CSV, 3);
+ }
+
+ @Test
+ public void testCSV141CSVFormat_ORACLE() throws Exception {
+ testCSV141Failure(CSVFormat.ORACLE, 2);
+ }
+
+ @Test
+ public void testCSV141CSVFormat_POSTGRESQL_CSV() throws Exception {
+ testCSV141Failure(CSVFormat.POSTGRESQL_CSV, 3);
+ }
+
+ @Test
+ public void testCSV141Excel() throws Exception {
+ testCSV141Ok(CSVFormat.EXCEL);
+ }
+
+ private void testCSV141Failure(final CSVFormat format, final int failParseRecordNo) throws IOException {
+ final Path path = Paths.get("src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv");
+ try (CSVParser parser = CSVParser.parse(path, StandardCharsets.UTF_8, format)) {
+ // row 1
+ CSVRecord record = parse(parser, failParseRecordNo);
+ if (record == null) {
+ return; // expected failure
+ }
+ assertEquals("1414770317901", record.get(0));
+ assertEquals("android.widget.EditText", record.get(1));
+ assertEquals("pass sem1 _84*|*", record.get(2));
+ assertEquals("0", record.get(3));
+ assertEquals("pass sem1 _8", record.get(4));
+ assertEquals(5, record.size());
+ // row 2
+ record = parse(parser, failParseRecordNo);
+ if (record == null) {
+ return; // expected failure
+ }
+ assertEquals("1414770318470", record.get(0));
+ assertEquals("android.widget.EditText", record.get(1));
+ assertEquals("pass sem1 _84:|", record.get(2));
+ assertEquals("0", record.get(3));
+ assertEquals("pass sem1 _84:\\", record.get(4));
+ assertEquals(5, record.size());
+ // row 3: Fail for certain
+ assertThrows(IOException.class, () -> parser.nextRecord());
+ }
+ }
+
+ private void testCSV141Ok(final CSVFormat format) throws IOException {
+ final Path path = Paths.get("src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv");
+ try (CSVParser parser = CSVParser.parse(path, StandardCharsets.UTF_8, format)) {
+ // row 1
+ CSVRecord record = parser.nextRecord();
+ assertEquals("1414770317901", record.get(0));
+ assertEquals("android.widget.EditText", record.get(1));
+ assertEquals("pass sem1 _84*|*", record.get(2));
+ assertEquals("0", record.get(3));
+ assertEquals("pass sem1 _8", record.get(4));
+ assertEquals(5, record.size());
+ // row 2
+ record = parser.nextRecord();
+ assertEquals("1414770318470", record.get(0));
+ assertEquals("android.widget.EditText", record.get(1));
+ assertEquals("pass sem1 _84:|", record.get(2));
+ assertEquals("0", record.get(3));
+ assertEquals("pass sem1 _84:\\", record.get(4));
+ assertEquals(5, record.size());
+ // row 3
+ record = parser.nextRecord();
+ assertEquals("1414770318327", record.get(0));
+ assertEquals("android.widget.EditText", record.get(1));
+ assertEquals("pass sem1\n1414770318628\"", record.get(2));
+ assertEquals("android.widget.EditText", record.get(3));
+ assertEquals("pass sem1 _84*|*", record.get(4));
+ assertEquals("0", record.get(5));
+ assertEquals("pass sem1\n", record.get(6));
+ assertEquals(7, record.size());
+ // EOF
+ record = parser.nextRecord();
+ assertNull(record);
+ }
+ }
+
+ @Test
+ public void testCSV141RFC4180() throws Exception {
+ testCSV141Failure(CSVFormat.RFC4180, 3);
+ }
+
+ @Test
+ public void testCSV235() throws IOException {
+ final String dqString = "\"aaa\",\"b\"\"bb\",\"ccc\""; // "aaa","b""bb","ccc"
+ try (CSVParser parser = CSVFormat.RFC4180.parse(new StringReader(dqString))) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertFalse(records.hasNext());
+ assertEquals(3, record.size());
+ assertEquals("aaa", record.get(0));
+ assertEquals("b\"bb", record.get(1));
+ assertEquals("ccc", record.get(2));
+ }
+ }
+
+ @Test
+ public void testCSV57() throws Exception {
+ try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) {
+ final List list = parser.getRecords();
+ assertNotNull(list);
+ assertEquals(0, list.size());
+ }
+ }
+
+ @Test
+ public void testDefaultFormat() throws IOException {
+ // @formatter:off
+ final String code = "" + "a,b#\n" + // 1)
+ "\"\n\",\" \",#\n" + // 2)
+ "#,\"\"\n" + // 3)
+ "# Final comment\n" // 4)
+ ;
+ // @formatter:on
+ final String[][] res = { { "a", "b#" }, { "\n", " ", "#" }, { "#", "" }, { "# Final comment" } };
+ CSVFormat format = CSVFormat.DEFAULT;
+ assertFalse(format.isCommentMarkerSet());
+ final String[][] resComments = { { "a", "b#" }, { "\n", " ", "#" } };
+ try (CSVParser parser = CSVParser.parse(code, format)) {
+ final List records = parser.getRecords();
+ assertFalse(records.isEmpty());
+ Utils.compare("Failed to parse without comments", res, records);
+ format = CSVFormat.DEFAULT.withCommentMarker('#');
+ }
+ try (CSVParser parser = CSVParser.parse(code, format)) {
+ final List records = parser.getRecords();
+ Utils.compare("Failed to parse with comments", resComments, records);
+ }
+ }
+
+ @Test
+ public void testDuplicateHeadersAllowedByDefault() throws Exception {
+ try (CSVParser parser = CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader())) {
+ // noop
+ }
+ }
+
+ @Test
+ public void testDuplicateHeadersNotAllowed() {
+ assertThrows(IllegalArgumentException.class,
+ () -> CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader().withAllowDuplicateHeaderNames(false)));
+ }
+
+ @Test
+ public void testEmptyFile() throws Exception {
+ try (CSVParser parser = CSVParser.parse(Paths.get("src/test/resources/org/apache/commons/csv/empty.txt"), StandardCharsets.UTF_8,
+ CSVFormat.DEFAULT)) {
+ assertNull(parser.nextRecord());
+ }
+ }
+
+ @Test
+ public void testEmptyFileHeaderParsing() throws Exception {
+ try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT.withFirstRecordAsHeader())) {
+ assertNull(parser.nextRecord());
+ assertTrue(parser.getHeaderNames().isEmpty());
+ }
+ }
+
+ @Test
+ public void testEmptyLineBehaviorCSV() 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) {
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testEmptyLineBehaviorExcel() 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) {
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testEmptyString() throws Exception {
+ try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) {
+ assertNull(parser.nextRecord());
+ }
+ }
+
+ @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) {
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testEndOfFileBehaviorExcel() 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) {
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+ }
+
+ @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", "" } };
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+
+ @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", "" } };
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+
+ /**
+ * 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";
+ try (CSVParser parser = CSVParser.parse(code, EXCEL_WITH_HEADER)) {
+ parser.getRecords().forEach(record -> {
+ assertEquals("a", record.get("A"));
+ assertEquals("b", record.get("B"));
+ assertEquals("c", record.get("C"));
+ });
+ }
+ }
+
+ @Test
+ public void testFirstEndOfLineCr() throws IOException {
+ final String data = "foo\rbaar,\rhello,world\r,kanu";
+ try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(4, records.size());
+ assertEquals("\r", parser.getFirstEndOfLine());
+ }
+ }
+
+ @Test
+ public void testFirstEndOfLineCrLf() throws IOException {
+ final String data = "foo\r\nbaar,\r\nhello,world\r\n,kanu";
+ try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(4, records.size());
+ assertEquals("\r\n", parser.getFirstEndOfLine());
+ }
+ }
+
+ @Test
+ public void testFirstEndOfLineLf() throws IOException {
+ final String data = "foo\nbaar,\nhello,world\n,kanu";
+ try (CSVParser parser = CSVParser.parse(data, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(4, records.size());
+ assertEquals("\n", parser.getFirstEndOfLine());
+ }
+ }
+
+ @Test
+ public void testForEach() throws Exception {
+ try (Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+ CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
+ final List records = new ArrayList<>();
+ for (final CSVRecord record : parser) {
+ 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 testGetHeaderComment_HeaderComment1() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) {
+ parser.getRecords();
+ // Expect a header comment
+ assertTrue(parser.hasHeaderComment());
+ assertEquals("header comment", parser.getHeaderComment());
+ }
+ }
+
+ @Test
+ public void testGetHeaderComment_HeaderComment2() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
+ parser.getRecords();
+ // Expect a header comment
+ assertTrue(parser.hasHeaderComment());
+ assertEquals("header comment", parser.getHeaderComment());
+ }
+ }
+
+ @Test
+ public void testGetHeaderComment_HeaderComment3() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
+ parser.getRecords();
+ // Expect no header comment - the text "comment" is attached to the first record
+ assertFalse(parser.hasHeaderComment());
+ assertNull(parser.getHeaderComment());
+ }
+ }
+
+ @Test
+ public void testGetHeaderComment_HeaderTrailerComment() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
+ parser.getRecords();
+ // Expect a header comment
+ assertTrue(parser.hasHeaderComment());
+ assertEquals("multi-line" + LF + "header comment", parser.getHeaderComment());
+ }
+ }
+
+ @Test
+ public void testGetHeaderComment_NoComment1() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_AUTO_HEADER)) {
+ parser.getRecords();
+ // Expect no header comment
+ assertFalse(parser.hasHeaderComment());
+ assertNull(parser.getHeaderComment());
+ }
+ }
+
+ @Test
+ public void testGetHeaderComment_NoComment2() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER)) {
+ parser.getRecords();
+ // Expect no header comment
+ assertFalse(parser.hasHeaderComment());
+ assertNull(parser.getHeaderComment());
+ }
+ }
+
+ @Test
+ public void testGetHeaderComment_NoComment3() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
+ parser.getRecords();
+ // Expect no header comment
+ assertFalse(parser.hasHeaderComment());
+ assertNull(parser.getHeaderComment());
+ }
+ }
+
+ @Test
+ public void testGetHeaderMap() throws Exception {
+ try (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.
+ assertEquals("A", columnNames.next());
+ assertEquals("B", columnNames.next());
+ 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());
+ }
+ }
+
+ @Test
+ public void testGetHeaderNames() throws IOException {
+ try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
+ final Map nameIndexMap = parser.getHeaderMap();
+ final List headerNames = parser.getHeaderNames();
+ assertNotNull(headerNames);
+ assertEquals(nameIndexMap.size(), headerNames.size());
+ for (int i = 0; i < headerNames.size(); i++) {
+ final String name = headerNames.get(i);
+ assertEquals(i, nameIndexMap.get(name).intValue());
+ }
+ }
+ }
+
+ @Test
+ public void testGetHeaderNamesReadOnly() throws IOException {
+ try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) {
+ final List headerNames = parser.getHeaderNames();
+ assertNotNull(headerNames);
+ assertThrows(UnsupportedOperationException.class, () -> headerNames.add("This is a read-only list."));
+ }
+ }
+
+ @Test
+ public void testGetLine() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) {
+ for (final String[] re : RESULT) {
+ assertArrayEquals(re, parser.nextRecord().values());
+ }
+
+ assertNull(parser.nextRecord());
+ }
+ }
+
+ @Test
+ public void testGetLineNumberWithCR() throws Exception {
+ validateLineNumbers(String.valueOf(CR));
+ }
+
+ @Test
+ public void testGetLineNumberWithCRLF() throws Exception {
+ validateLineNumbers(CRLF);
+ }
+
+ @Test
+ public void testGetLineNumberWithLF() throws Exception {
+ validateLineNumbers(String.valueOf(LF));
+ }
+
+ @Test
+ public void testGetOneLine() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_1, CSVFormat.DEFAULT)) {
+ final CSVRecord record = parser.getRecords().get(0);
+ assertArrayEquals(RESULT[0], record.values());
+ }
+ }
+
+ /**
+ * Tests reusing a parser to process new string records one at a time as they are being discovered. See [CSV-110].
+ *
+ * @throws IOException when an I/O error occurs.
+ */
+ @Test
+ public void testGetOneLineOneParser() throws IOException {
+ final CSVFormat format = CSVFormat.DEFAULT;
+ try (PipedWriter writer = new PipedWriter();
+ CSVParser parser = CSVParser.builder()
+ .setReader(new PipedReader(writer))
+ .setFormat(format)
+ .get()) {
+ 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());
+ }
+ }
+
+ @Test
+ public void testGetRecordFourBytesRead() throws Exception {
+ final String code = "id,a,b,c\n" +
+ "1,😊,🤔,😂\n" +
+ "2,😊,🤔,😂\n" +
+ "3,😊,🤔,😂\n";
+ final CSVFormat format = CSVFormat.Builder.create()
+ .setDelimiter(',')
+ .setQuote('\'')
+ .get();
+ try (CSVParser parser = CSVParser.builder().setReader(new StringReader(code)).setFormat(format).setCharset(UTF_8).setTrackBytes(true).get()) {
+ CSVRecord record = new CSVRecord(parser, null, null, 1L, 0L, 0L);
+
+ assertEquals(0, parser.getRecordNumber());
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(1, record.getRecordNumber());
+ assertEquals(code.indexOf('i'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), record.getCharacterPosition());
+
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(2, record.getRecordNumber());
+ assertEquals(code.indexOf('1'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), record.getCharacterPosition());
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(3, record.getRecordNumber());
+ assertEquals(code.indexOf('2'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), 26);
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(4, record.getRecordNumber());
+ assertEquals(code.indexOf('3'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), 43);
+ }
+ }
+
+ @Test
+ public void testGetRecordNumberWithCR() throws Exception {
+ validateRecordNumbers(String.valueOf(CR));
+ }
+
+ @Test
+ public void testGetRecordNumberWithCRLF() throws Exception {
+ validateRecordNumbers(CRLF);
+ }
+
+ @Test
+ public void testGetRecordNumberWithLF() throws Exception {
+ validateRecordNumbers(String.valueOf(LF));
+ }
+
+ @Test
+ public void testGetRecordPositionWithCRLF() throws Exception {
+ validateRecordPosition(CRLF);
+ }
+
+ @Test
+ public void testGetRecordPositionWithLF() throws Exception {
+ validateRecordPosition(String.valueOf(LF));
+ }
+
+ @Test
+ public void testGetRecords() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) {
+ final List records = parser.getRecords();
+ assertEquals(RESULT.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < RESULT.length; i++) {
+ assertArrayEquals(RESULT[i], records.get(i).values());
+ }
+ }
+ }
+
+ @Test
+ public void testGetRecordsFromBrokenInputStream() throws IOException {
+ @SuppressWarnings("resource") // We also get an exception on close, which is OK but can't assert in a try.
+ final CSVParser parser = CSVParser.parse(new BrokenInputStream(), UTF_8, CSVFormat.DEFAULT);
+ assertThrows(UncheckedIOException.class, parser::getRecords);
+
+ }
+
+ @Test
+ public void testGetRecordThreeBytesRead() throws Exception {
+ final String code = "id,date,val5,val4\n" +
+ "11111111111111,'4017-09-01',きちんと節分近くには咲いてる~,v4\n" +
+ "22222222222222,'4017-01-01',おはよう私の友人~,v4\n" +
+ "33333333333333,'4017-01-01',きる自然の力ってすごいな~,v4\n";
+ final CSVFormat format = CSVFormat.Builder.create()
+ .setDelimiter(',')
+ .setQuote('\'')
+ .get();
+ try (CSVParser parser = CSVParser.builder().setReader(new StringReader(code)).setFormat(format).setCharset(UTF_8).setTrackBytes(true).get()) {
+ CSVRecord record = new CSVRecord(parser, null, null, 1L, 0L, 0L);
+
+ assertEquals(0, parser.getRecordNumber());
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(1, record.getRecordNumber());
+ assertEquals(code.indexOf('i'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), record.getCharacterPosition());
+
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(2, record.getRecordNumber());
+ assertEquals(code.indexOf('1'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), record.getCharacterPosition());
+
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(3, record.getRecordNumber());
+ assertEquals(code.indexOf('2'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), 95);
+
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(4, record.getRecordNumber());
+ assertEquals(code.indexOf('3'), record.getCharacterPosition());
+ assertEquals(record.getBytePosition(), 154);
+ }
+ }
+
+ @Test
+ public void testGetRecordWithMultiLineValues() throws Exception {
+ try (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(9, parser.getCurrentLineNumber());
+ assertEquals(3, record.getRecordNumber());
+ assertEquals(3, parser.getRecordNumber());
+ assertNull(record = parser.nextRecord());
+ assertEquals(9, parser.getCurrentLineNumber());
+ assertEquals(3, parser.getRecordNumber());
+ }
+ }
+
+ @Test
+ public void testGetTrailerComment_HeaderComment1() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) {
+ parser.getRecords();
+ assertFalse(parser.hasTrailerComment());
+ assertNull(parser.getTrailerComment());
+ }
+ }
+
+ @Test
+ public void testGetTrailerComment_HeaderComment2() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
+ parser.getRecords();
+ assertFalse(parser.hasTrailerComment());
+ assertNull(parser.getTrailerComment());
+ }
+ }
+
+ @Test
+ public void testGetTrailerComment_HeaderComment3() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
+ parser.getRecords();
+ assertFalse(parser.hasTrailerComment());
+ assertNull(parser.getTrailerComment());
+ }
+ }
+
+ @Test
+ public void testGetTrailerComment_HeaderTrailerComment1() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
+ parser.getRecords();
+ assertTrue(parser.hasTrailerComment());
+ assertEquals("comment", parser.getTrailerComment());
+ }
+ }
+
+ @Test
+ public void testGetTrailerComment_HeaderTrailerComment2() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER)) {
+ parser.getRecords();
+ assertTrue(parser.hasTrailerComment());
+ assertEquals("comment", parser.getTrailerComment());
+ }
+ }
+
+ @Test
+ public void testGetTrailerComment_HeaderTrailerComment3() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) {
+ parser.getRecords();
+ assertTrue(parser.hasTrailerComment());
+ assertEquals("comment", parser.getTrailerComment());
+ }
+ }
+
+ @Test
+ public void testGetTrailerComment_MultilineComment() throws IOException {
+ try (CSVParser parser = CSVParser.parse(CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) {
+ parser.getRecords();
+ assertTrue(parser.hasTrailerComment());
+ assertEquals("multi-line" + LF + "comment", parser.getTrailerComment());
+ }
+ }
+
+ @Test
+ public void testHeader() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
+ final Iterator records = parser.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 testHeaderComment() throws Exception {
+ final Reader in = new StringReader("# comment\na,b,c\n1,2,3\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withCommentMarker('#').withHeader().parse(in)) {
+ final Iterator records = parser.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");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withAllowMissingColumnNames().parse(in)) {
+ final Iterator records = parser.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
+ public void testHeaderMissingWithNull() throws Exception {
+ final Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withNullString("").withAllowMissingColumnNames().parse(in)) {
+ parser.iterator();
+ }
+ }
+
+ @Test
+ public void testHeadersMissing() throws Exception {
+ try (Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
+ CSVParser parser = CSVFormat.DEFAULT.withHeader().withAllowMissingColumnNames().parse(in)) {
+ parser.iterator();
+ }
+ }
+
+ @Test
+ public void testHeadersMissingException() {
+ final Reader in = new StringReader("a,,c,,e\n1,2,3,4,5\nv,w,x,y,z");
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withHeader().parse(in).iterator());
+ }
+
+ @Test
+ public void testHeadersMissingOneColumnException() {
+ final Reader in = new StringReader("a,,c,d,e\n1,2,3,4,5\nv,w,x,y,z");
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withHeader().parse(in).iterator());
+ }
+
+ @Test
+ public void testHeadersWithNullColumnName() throws IOException {
+ final Reader in = new StringReader("header1,null,header3\n1,2,3\n4,5,6");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader().withNullString("null").withAllowMissingColumnNames().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ // Expect the null header to be missing
+ @SuppressWarnings("resource")
+ final CSVParser recordParser = record.getParser();
+ assertEquals(Arrays.asList("header1", "header3"), recordParser.getHeaderNames());
+ assertEquals(2, recordParser.getHeaderMap().size());
+ }
+ }
+
+ @Test
+ public void testIgnoreCaseHeaderMapping() throws Exception {
+ final Reader reader = new StringReader("1,2,3");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("One", "TWO", "three").withIgnoreHeaderCase().parse(reader)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertEquals("1", record.get("one"));
+ assertEquals("2", record.get("two"));
+ assertEquals("3", record.get("THREE"));
+ }
+ }
+
+ @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";
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(3, records.size());
+ }
+ }
+
+ @Test
+ public void testInvalidFormat() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR));
+ }
+
+ @Test
+ public void testIterator() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
+ final Iterator iterator = parser.iterator();
+ assertTrue(iterator.hasNext());
+ assertThrows(UnsupportedOperationException.class, iterator::remove);
+ 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());
+ assertThrows(NoSuchElementException.class, iterator::next);
+ }
+ }
+
+ @Test
+ public void testIteratorSequenceBreaking() throws IOException {
+ final String fiveRows = "1\n2\n3\n4\n5\n";
+ // Iterator hasNext() shouldn't break sequence
+ try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
+ final Iterator iter = parser.iterator();
+ int recordNumber = 0;
+ while (iter.hasNext()) {
+ final CSVRecord record = iter.next();
+ recordNumber++;
+ assertEquals(String.valueOf(recordNumber), record.get(0));
+ if (recordNumber >= 2) {
+ break;
+ }
+ }
+ iter.hasNext();
+ while (iter.hasNext()) {
+ final CSVRecord record = iter.next();
+ recordNumber++;
+ assertEquals(String.valueOf(recordNumber), record.get(0));
+ }
+ }
+ // Consecutive enhanced for loops shouldn't break sequence
+ try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
+ int recordNumber = 0;
+ for (final CSVRecord record : parser) {
+ recordNumber++;
+ assertEquals(String.valueOf(recordNumber), record.get(0));
+ if (recordNumber >= 2) {
+ break;
+ }
+ }
+ for (final CSVRecord record : parser) {
+ recordNumber++;
+ assertEquals(String.valueOf(recordNumber), record.get(0));
+ }
+ }
+ // Consecutive enhanced for loops with hasNext() peeking shouldn't break sequence
+ try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(fiveRows))) {
+ int recordNumber = 0;
+ for (final CSVRecord record : parser) {
+ recordNumber++;
+ assertEquals(String.valueOf(recordNumber), record.get(0));
+ if (recordNumber >= 2) {
+ break;
+ }
+ }
+ parser.iterator().hasNext();
+ for (final CSVRecord record : parser) {
+ recordNumber++;
+ assertEquals(String.valueOf(recordNumber), record.get(0));
+ }
+ }
+ }
+
+ @Test
+ public void testLineFeedEndings() throws IOException {
+ final String code = "foo\nbaar,\nhello,world\n,kanu";
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.DEFAULT)) {
+ final List records = parser.getRecords();
+ assertEquals(4, records.size());
+ }
+ }
+
+ @Test
+ public void testMappedButNotSetAsOutlook2007ContactExport() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("A", "B", "C").withSkipHeaderRecord().parse(in)) {
+ final Iterator records = parser.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());
+ // end
+ assertFalse(records.hasNext());
+ }
+ }
+
+ @Test
+ @Disabled
+ public void testMongoDbCsv() throws Exception {
+ try (CSVParser parser = CSVParser.parse("\"a a\",b,c" + LF + "d,e,f", CSVFormat.MONGODB_CSV)) {
+ final Iterator itr1 = parser.iterator();
+ final Iterator itr2 = parser.iterator();
+
+ final CSVRecord first = itr1.next();
+ assertEquals("a 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));
+ }
+ }
+
+ @Test
+ // TODO this may lead to strange behavior, throw an exception if iterator() has already been called?
+ public void testMultipleIterators() throws Exception {
+ try (CSVParser parser = CSVParser.parse("a,b,c" + CRLF + "d,e,f", CSVFormat.DEFAULT)) {
+ final Iterator itr1 = 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 = itr1.next();
+ assertEquals("d", second.get(0));
+ assertEquals("e", second.get(1));
+ assertEquals("f", second.get(2));
+ }
+ }
+
+ @Test
+ public void testNewCSVParserNullReaderFormat() {
+ assertThrows(NullPointerException.class, () -> new CSVParser(null, CSVFormat.DEFAULT));
+ }
+
+ @Test
+ public void testNewCSVParserReaderNullFormat() {
+ assertThrows(NullPointerException.class, () -> new CSVParser(new StringReader(""), null));
+ }
+
+ @Test
+ public void testNoHeaderMap() throws Exception {
+ try (CSVParser parser = CSVParser.parse("a,b,c\n1,2,3\nx,y,z", CSVFormat.DEFAULT)) {
+ assertNull(parser.getHeaderMap());
+ }
+ }
+
+ @Test
+ public void testNotValueCSV() throws IOException {
+ final String source = "#";
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.withCommentMarker('#');
+ try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
+ final CSVRecord csvRecord = csvParser.nextRecord();
+ assertNull(csvRecord);
+ }
+ }
+
+ @Test
+ public void testParse() throws Exception {
+ final ClassLoader loader = ClassLoader.getSystemClassLoader();
+ final URL url = loader.getResource("org/apache/commons/csv/CSVFileParser/test.csv");
+ final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader("A", "B", "C", "D").get();
+ final Charset charset = StandardCharsets.UTF_8;
+ // Reader
+ try (CSVParser parser = CSVParser.parse(new InputStreamReader(url.openStream(), charset), format)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).get()) {
+ parseFully(parser);
+ }
+ // String
+ final Path path = Paths.get(url.toURI());
+ final String string = new String(Files.readAllBytes(path), charset);
+ try (CSVParser parser = CSVParser.parse(string, format)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setCharSequence(string).setFormat(format).get()) {
+ parseFully(parser);
+ }
+ // File
+ final File file = new File(url.toURI());
+ try (CSVParser parser = CSVParser.parse(file, charset, format)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setFile(file).setCharset(charset).setFormat(format).get()) {
+ parseFully(parser);
+ }
+ // InputStream
+ try (CSVParser parser = CSVParser.parse(url.openStream(), charset, format)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setInputStream(url.openStream()).setCharset(charset).setFormat(format).get()) {
+ parseFully(parser);
+ }
+ // Path
+ try (CSVParser parser = CSVParser.parse(path, charset, format)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setPath(path).setCharset(charset).setFormat(format).get()) {
+ parseFully(parser);
+ }
+ // URL
+ try (CSVParser parser = CSVParser.parse(url, charset, format)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setURI(url.toURI()).setCharset(charset).setFormat(format).get()) {
+ parseFully(parser);
+ }
+ // InputStreamReader
+ try (CSVParser parser = new CSVParser(new InputStreamReader(url.openStream(), charset), format)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).get()) {
+ parseFully(parser);
+ }
+ // InputStreamReader with longs
+ try (CSVParser parser = new CSVParser(new InputStreamReader(url.openStream(), charset), format, /* characterOffset= */0, /* recordNumber= */1)) {
+ parseFully(parser);
+ }
+ try (CSVParser parser = CSVParser.builder().setReader(new InputStreamReader(url.openStream(), charset)).setFormat(format).setCharacterOffset(0)
+ .setRecordNumber(0).get()) {
+ parseFully(parser);
+ }
+ }
+
+ @Test
+ public void testParseFileNullFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse(new File("CSVFileParser/test.csv"), Charset.defaultCharset(), null));
+ }
+
+ @Test
+ public void testParseNullFileFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse((File) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
+ }
+
+ @Test
+ public void testParseNullPathFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse((Path) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
+ }
+
+ @Test
+ public void testParseNullStringFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse((String) null, CSVFormat.DEFAULT));
+ }
+
+ @Test
+ public void testParseNullUrlCharsetFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse((URL) null, Charset.defaultCharset(), CSVFormat.DEFAULT));
+ }
+
+ @Test
+ public void testParserUrlNullCharsetFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse(new URL("https://commons.apache.org"), null, CSVFormat.DEFAULT));
+ }
+
+ @Test
+ public void testParseStringNullFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse("csv data", (CSVFormat) null));
+ }
+
+ @Test
+ public void testParseUrlCharsetNullFormat() {
+ assertThrows(NullPointerException.class, () -> CSVParser.parse(new URL("https://commons.apache.org"), Charset.defaultCharset(), null));
+ }
+
+ @Test
+ public void testParseWithDelimiterStringWithEscape() throws IOException {
+ final String source = "a![!|!]b![|]c[|]xyz\r\nabc[abc][|]xyz";
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').get();
+ try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
+ CSVRecord csvRecord = csvParser.nextRecord();
+ assertEquals("a[|]b![|]c", csvRecord.get(0));
+ assertEquals("xyz", csvRecord.get(1));
+ csvRecord = csvParser.nextRecord();
+ assertEquals("abc[abc]", csvRecord.get(0));
+ assertEquals("xyz", csvRecord.get(1));
+ }
+ }
+
+ @Test
+ public void testParseWithDelimiterStringWithQuote() throws IOException {
+ final String source = "'a[|]b[|]c'[|]xyz\r\nabc[abc][|]xyz";
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').get();
+ try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
+ CSVRecord csvRecord = csvParser.nextRecord();
+ assertEquals("a[|]b[|]c", csvRecord.get(0));
+ assertEquals("xyz", csvRecord.get(1));
+ csvRecord = csvParser.nextRecord();
+ assertEquals("abc[abc]", csvRecord.get(0));
+ assertEquals("xyz", csvRecord.get(1));
+ }
+ }
+
+ @Test
+ public void testParseWithDelimiterWithEscape() throws IOException {
+ final String source = "a!,b!,c,xyz";
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.withEscape('!');
+ try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
+ final CSVRecord csvRecord = csvParser.nextRecord();
+ assertEquals("a,b,c", csvRecord.get(0));
+ assertEquals("xyz", csvRecord.get(1));
+ }
+ }
+
+ @Test
+ public void testParseWithDelimiterWithQuote() throws IOException {
+ final String source = "'a,b,c',xyz";
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'');
+ try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
+ final CSVRecord csvRecord = csvParser.nextRecord();
+ assertEquals("a,b,c", csvRecord.get(0));
+ assertEquals("xyz", csvRecord.get(1));
+ }
+ }
+
+ @Test
+ public void testParseWithQuoteThrowsException() {
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'');
+ assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c','")).nextRecord());
+ assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'a,b,c'abc,xyz")).nextRecord());
+ assertThrows(IOException.class, () -> csvFormat.parse(new StringReader("'abc'a,b,c',xyz")).nextRecord());
+ }
+
+ @Test
+ public void testParseWithQuoteWithEscape() throws IOException {
+ final String source = "'a?,b?,c?d',xyz";
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.withQuote('\'').withEscape('?');
+ try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) {
+ final CSVRecord csvRecord = csvParser.nextRecord();
+ assertEquals("a,b,c?d", csvRecord.get(0));
+ assertEquals("xyz", csvRecord.get(1));
+ }
+ }
+
+ @ParameterizedTest
+ @EnumSource(CSVFormat.Predefined.class)
+ public void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format) throws Exception {
+ final String[][] lines = { { "a", "b" }, { "", "x" } };
+ final StringWriter buf = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(buf, format.getFormat())) {
+ printer.printRecords(Stream.of(lines));
+ }
+ try (CSVParser csvRecords = CSVParser.builder()
+ .setReader(new StringReader(buf.toString()))
+ .setFormat(format.getFormat())
+ .get()) {
+ for (final String[] line : lines) {
+ assertArrayEquals(line, csvRecords.nextRecord().values());
+ }
+ assertNull(csvRecords.nextRecord());
+ }
+ }
+
+ @Test
+ public void testProvidedHeader() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("A", "B", "C").parse(in)) {
+ final Iterator records = parser.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");
+
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
+ final Iterator records = parser.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 testRepeatedHeadersAreReturnedInCSVRecordHeaderNames() throws IOException {
+ final Reader in = new StringReader("header1,header2,header1\n1,2,3\n4,5,6");
+ try (CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().withTrim().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ @SuppressWarnings("resource")
+ final CSVParser recordParser = record.getParser();
+ assertEquals(Arrays.asList("header1", "header2", "header1"), recordParser.getHeaderNames());
+ }
+ }
+
+ @Test
+ public void testRoundtrip() throws Exception {
+ final StringWriter out = new StringWriter();
+ final String data = "a,b,c\r\n1,2,3\r\nx,y,z\r\n";
+ try (CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT);
+ CSVParser parse = CSVParser.parse(data, CSVFormat.DEFAULT)) {
+ for (final CSVRecord record : parse) {
+ printer.printRecord(record);
+ }
+ assertEquals(data, out.toString());
+ }
+ }
+
+ @Test
+ public void testSkipAutoHeader() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertEquals("1", record.get("a"));
+ assertEquals("2", record.get("b"));
+ assertEquals("3", record.get("c"));
+ }
+ }
+
+ @Test
+ public void testSkipHeaderOverrideDuplicateHeaders() throws Exception {
+ final Reader in = new StringReader("a,a,a\n1,2,3\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertEquals("1", record.get("X"));
+ assertEquals("2", record.get("Y"));
+ assertEquals("3", record.get("Z"));
+ }
+ }
+
+ @Test
+ public void testSkipSetAltHeaders() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertEquals("1", record.get("X"));
+ assertEquals("2", record.get("Y"));
+ assertEquals("3", record.get("Z"));
+ }
+ }
+
+ @Test
+ public void testSkipSetHeader() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("a", "b", "c").withSkipHeaderRecord().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertEquals("1", record.get("a"));
+ assertEquals("2", record.get("b"));
+ assertEquals("3", record.get("c"));
+ }
+ }
+
+ @Test
+ @Disabled
+ 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) {
+ try (CSVParser parser = CSVParser.parse(code, CSVFormat.EXCEL)) {
+ final List records = parser.getRecords();
+ assertEquals(res.length, records.size());
+ assertFalse(records.isEmpty());
+ for (int i = 0; i < res.length; i++) {
+ assertArrayEquals(res[i], records.get(i).values());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testStream() throws Exception {
+ final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.parse(in)) {
+ final List list = parser.stream().collect(Collectors.toList());
+ assertFalse(list.isEmpty());
+ assertArrayEquals(new String[] { "a", "b", "c" }, list.get(0).values());
+ assertArrayEquals(new String[] { "1", "2", "3" }, list.get(1).values());
+ assertArrayEquals(new String[] { "x", "y", "z" }, list.get(2).values());
+ }
+ }
+
+ @Test
+ public void testThrowExceptionWithLineAndPosition() throws IOException {
+ final String csvContent = "col1,col2,col3,col4,col5,col6,col7,col8,col9,col10\nrec1,rec2,rec3,rec4,rec5,rec6,rec7,rec8,\"\"rec9\"\",rec10";
+ final StringReader stringReader = new StringReader(csvContent);
+ // @formatter:off
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.builder()
+ .setHeader()
+ .setSkipHeaderRecord(true)
+ .get();
+ // @formatter:on
+ try (CSVParser csvParser = csvFormat.parse(stringReader)) {
+ final UncheckedIOException exception = assertThrows(UncheckedIOException.class, csvParser::getRecords);
+ assertInstanceOf(CSVException.class, exception.getCause());
+ assertTrue(exception.getMessage().contains("Invalid character between encapsulated token and delimiter at line: 2, position: 94"),
+ exception::getMessage);
+ }
+ }
+
+ @Test
+ public void testTrailingDelimiter() throws Exception {
+ final Reader in = new StringReader("a,a,a,\n\"1\",\"2\",\"3\",\nx,y,z,");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().withTrailingDelimiter().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertEquals("1", record.get("X"));
+ assertEquals("2", record.get("Y"));
+ assertEquals("3", record.get("Z"));
+ assertEquals(3, record.size());
+ }
+ }
+
+ @Test
+ public void testTrim() throws Exception {
+ final Reader in = new StringReader("a,a,a\n\" 1 \",\" 2 \",\" 3 \"\nx,y,z");
+ try (CSVParser parser = CSVFormat.DEFAULT.withHeader("X", "Y", "Z").withSkipHeaderRecord().withTrim().parse(in)) {
+ final Iterator records = parser.iterator();
+ final CSVRecord record = records.next();
+ assertEquals("1", record.get("X"));
+ assertEquals("2", record.get("Y"));
+ assertEquals("3", record.get("Z"));
+ assertEquals(3, record.size());
+ }
+ }
+
+ private void validateLineNumbers(final String lineSeparator) throws IOException {
+ try (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());
+ // Read EOF without EOL should 3
+ assertEquals(3, parser.getCurrentLineNumber());
+ assertNull(parser.nextRecord());
+ // Read EOF without EOL should 3
+ assertEquals(3, parser.getCurrentLineNumber());
+ }
+ }
+
+ private void validateRecordNumbers(final String lineSeparator) throws IOException {
+ try (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());
+ }
+ }
+
+ 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);
+ final long positionRecord3;
+ try (CSVParser parser = CSVParser.parse(code, format)) {
+ CSVRecord record;
+ assertEquals(0, parser.getRecordNumber());
+ // nextRecord
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(1, record.getRecordNumber());
+ assertEquals(code.indexOf('a'), record.getCharacterPosition());
+ // nextRecord
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(2, record.getRecordNumber());
+ assertEquals(code.indexOf('1'), record.getCharacterPosition());
+ // nextRecord
+ assertNotNull(record = parser.nextRecord());
+ 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));
+ // nextRecord
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(4, record.getRecordNumber());
+ assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
+ // nextRecord
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(5, record.getRecordNumber());
+ assertEquals(code.indexOf("EOF"), record.getCharacterPosition());
+ }
+ // now try to read starting at record 3
+ try (CSVParser parser = CSVParser.builder()
+ .setReader(new StringReader(code.substring((int) positionRecord3)))
+ .setFormat(format)
+ .setCharacterOffset(positionRecord3)
+ .setRecordNumber(3)
+ .get()) {
+ CSVRecord record;
+ // nextRecord
+ 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));
+ // nextRecord
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(4, record.getRecordNumber());
+ assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
+ assertEquals("\u00c4", record.get(0));
+ } // again with ctor
+ try (CSVParser parser = new CSVParser(new StringReader(code.substring((int) positionRecord3)), format, positionRecord3, 3)) {
+ CSVRecord record;
+ // nextRecord
+ 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));
+ // nextRecord
+ assertNotNull(record = parser.nextRecord());
+ assertEquals(4, record.getRecordNumber());
+ assertEquals(code.indexOf('\u00c4'), record.getCharacterPosition());
+ assertEquals("\u00c4", record.get(0));
+ }
+ }
+}
diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
index b4b560a1d8..f457460c9b 100644
--- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
@@ -1,1926 +1,1926 @@
-/*
- * 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
- *
- * https://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.CR;
-import static org.junit.jupiter.api.Assertions.assertArrayEquals;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNotEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import java.io.CharArrayWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.Reader;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.sql.BatchUpdateException;
-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.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Random;
-import java.util.Vector;
-import java.util.stream.Stream;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.NullOutputStream;
-import org.apache.commons.lang3.StringUtils;
-import org.h2.tools.SimpleResultSet;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.Test;
-
-/**
- * Tests {@link CSVPrinter}.
- */
-public class CSVPrinterTest {
-
- private static final int TABLE_RECORD_COUNT = 2;
- private static final char DQUOTE_CHAR = '"';
- private static final char EURO_CH = '\u20AC';
- private static final int ITERATIONS_FOR_RANDOM_TEST = 50000;
- private static final char QUOTE_CH = '\'';
-
- 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 String longText2;
-
- private final String recordSeparator = CSVFormat.DEFAULT.getRecordSeparator();
-
- private void assertInitialState(final CSVPrinter printer) {
- assertEquals(0, printer.getRecordCount());
- }
-
- private File createTempFile() throws IOException {
- return createTempPath().toFile();
- }
-
- private Path createTempPath() throws IOException {
- return Files.createTempFile(getClass().getName(), ".csv");
- }
-
- 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 = generateLines(nLines, nCol);
-
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
-
- for (int i = 0; i < nLines; i++) {
- // for (int j=0; j parseResult = parser.getRecords();
-
- final String[][] expected = lines.clone();
- for (int i = 0; i < expected.length; i++) {
- expected[i] = expectNulls(expected[i], format);
- }
- Utils.compare("Printer output :" + printable(result), expected, parseResult);
- }
- }
-
- private void doRandom(final CSVFormat format, final int iter) throws Exception {
- for (int i = 0; i < iter; i++) {
- doOneRandom(format);
- }
- }
-
- /**
- * Converts an input CSV array into expected output values WRT NULLs. NULL strings are converted to null values because the parser will convert these
- * strings to null.
- */
- private T[] expectNulls(final T[] original, final CSVFormat csvFormat) {
- final T[] fixed = original.clone();
- for (int i = 0; i < fixed.length; i++) {
- if (Objects.equals(csvFormat.getNullString(), fixed[i])) {
- fixed[i] = null;
- }
- }
- return fixed;
- }
-
- private String[][] generateLines(final int nLines, final int nCol) {
- 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();
- }
- }
- return lines;
- }
-
- private Connection getH2Connection() throws SQLException, ClassNotFoundException {
- Class.forName("org.h2.Driver");
- return DriverManager.getConnection("jdbc:h2:mem:my_test;", "sa", "");
- }
-
- private CSVPrinter printWithHeaderComments(final StringWriter sw, final Date now, final CSVFormat baseFormat) throws IOException {
- // Use withHeaderComments first to test CSV-145
- // @formatter:off
- final CSVFormat format = baseFormat.builder()
- .setHeaderComments((String[]) null) // don't blow up
- .setHeaderComments((Object[]) null) // don't blow up
- .setHeaderComments("Generated by Apache Commons CSV 1.1", now)
- .setCommentMarker('#')
- .setHeader("Col1", "Col2")
- .get();
- // @formatter:on
- final CSVPrinter printer = format.print(sw);
- printer.printRecord("A", "B");
- printer.printRecord("C", "D");
- printer.close();
- return printer;
- }
-
- 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
- final 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 = DQUOTE_CHAR;
- break;
- case 7:
- ch = '\'';
- break;
- case 8:
- ch = BACKSLASH;
- break;
- default:
- ch = (char) r.nextInt(300);
- break;
- // default: ch = 'a'; break;
- }
- buf[i] = ch;
- }
- return new String(buf);
- }
-
- private void setUpTable(final Connection connection) throws SQLException {
- try (Statement statement = connection.createStatement()) {
- statement.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), TEXT CLOB, BIN_DATA BLOB)");
- statement.execute("insert into TEST values(1, 'r1', 'long text 1', 'binary data 1')");
- longText2 = StringUtils.repeat('a', IOUtils.DEFAULT_BUFFER_SIZE - 4);
- longText2 += "\"\r\n\"b\"";
- longText2 += StringUtils.repeat('c', IOUtils.DEFAULT_BUFFER_SIZE - 1);
- statement.execute("insert into TEST values(2, 'r2', '" + longText2 + "', 'binary data 2')");
- longText2 = longText2.replace("\"", "\"\"");
- }
- }
-
- @Test
- public void testCloseBackwardCompatibility() throws IOException {
- try (Writer writer = mock(Writer.class)) {
- final CSVFormat csvFormat = CSVFormat.DEFAULT;
- try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) {
- assertInitialState(printer);
- }
- verify(writer, never()).flush();
- verify(writer, times(1)).close();
- }
- }
-
- @Test
- public void testCloseWithCsvFormatAutoFlushOff() throws IOException {
- try (Writer writer = mock(Writer.class)) {
- final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(false);
- try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) {
- assertInitialState(printer);
- }
- verify(writer, never()).flush();
- verify(writer, times(1)).close();
- }
- }
-
- @Test
- public void testCloseWithCsvFormatAutoFlushOn() throws IOException {
- // System.out.println("start method");
- try (Writer writer = mock(Writer.class)) {
- final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(true);
- try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) {
- assertInitialState(printer);
- }
- verify(writer, times(1)).flush();
- verify(writer, times(1)).close();
- }
- }
-
- @Test
- public void testCloseWithFlushOff() throws IOException {
- try (Writer writer = mock(Writer.class)) {
- final CSVFormat csvFormat = CSVFormat.DEFAULT;
- @SuppressWarnings("resource")
- final CSVPrinter printer = new CSVPrinter(writer, csvFormat);
- assertInitialState(printer);
- printer.close(false);
- assertEquals(0, printer.getRecordCount());
- verify(writer, never()).flush();
- verify(writer, times(1)).close();
- }
- }
-
- @Test
- public void testCloseWithFlushOn() throws IOException {
- try (Writer writer = mock(Writer.class)) {
- @SuppressWarnings("resource")
- final CSVPrinter printer = new CSVPrinter(writer, CSVFormat.DEFAULT);
- assertInitialState(printer);
- printer.close(true);
- assertEquals(0, printer.getRecordCount());
- verify(writer, times(1)).flush();
- }
- }
-
- @Test
- public void testCRComment() throws IOException {
- final StringWriter sw = new StringWriter();
- final Object value = "abc";
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) {
- assertInitialState(printer);
- printer.print(value);
- assertEquals(0, printer.getRecordCount());
- printer.printComment("This is a comment\r\non multiple lines\rthis is next comment\r");
- assertEquals("abc" + recordSeparator + "# This is a comment" + recordSeparator + "# on multiple lines" + recordSeparator +
- "# this is next comment" + recordSeparator + "# " + recordSeparator, sw.toString());
- assertEquals(0, printer.getRecordCount());
- }
- }
-
- @Test
- public void testCSV135() throws IOException {
- final List list = new LinkedList<>();
- list.add("\"\""); // ""
- list.add("\\\\"); // \\
- list.add("\\\"\\"); // \"\
- //
- // "",\\,\"\ (unchanged)
- tryFormat(list, null, null, "\"\",\\\\,\\\"\\");
- //
- // """""",\\,"\""\" (quoted, and embedded DQ doubled)
- tryFormat(list, '"', null, "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
- //
- // "",\\\\,\\"\\ (escapes escaped, not quoted)
- tryFormat(list, null, '\\', "\"\",\\\\\\\\,\\\\\"\\\\");
- //
- // "\"\"","\\\\","\\\"\\" (quoted, and embedded DQ & escape escaped)
- tryFormat(list, '"', '\\', "\"\\\"\\\"\",\"\\\\\\\\\",\"\\\\\\\"\\\\\"");
- //
- // """""",\\,"\""\" (quoted, embedded DQ escaped)
- tryFormat(list, '"', '"', "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
- }
-
- @Test
- public void testCSV259() throws IOException {
- final StringWriter sw = new StringWriter();
- try (Reader reader = new FileReader("src/test/resources/org/apache/commons/csv/CSV-259/sample.txt");
- CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null))) {
- assertInitialState(printer);
- printer.print(reader);
- assertEquals("x!,y!,z", sw.toString());
- }
- }
-
- @Test
- public void testDelimeterQuoted() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
- assertInitialState(printer);
- printer.print("a,b,c");
- printer.print("xyz");
- assertEquals("'a,b,c',xyz", sw.toString());
- }
- }
-
- @Test
- public void testDelimeterQuoteNone() throws IOException {
- final StringWriter sw = new StringWriter();
- final CSVFormat format = CSVFormat.DEFAULT.withEscape('!').withQuoteMode(QuoteMode.NONE);
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
- assertInitialState(printer);
- printer.print("a,b,c");
- printer.print("xyz");
- assertEquals("a!,b!,c,xyz", sw.toString());
- }
- }
-
- @Test
- public void testDelimeterStringQuoted() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').get())) {
- assertInitialState(printer);
- printer.print("a[|]b[|]c");
- printer.print("xyz");
- assertEquals("'a[|]b[|]c'[|]xyz", sw.toString());
- }
- }
-
- @Test
- public void testDelimeterStringQuoteNone() throws IOException {
- final StringWriter sw = new StringWriter();
- final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').setQuoteMode(QuoteMode.NONE).get();
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
- assertInitialState(printer);
- printer.print("a[|]b[|]c");
- printer.print("xyz");
- printer.print("a[xy]bc[]");
- assertEquals("a![!|!]b![!|!]c[|]xyz[|]a[xy]bc[]", sw.toString());
- }
- }
-
- @Test
- public void testDelimiterEscaped() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null))) {
- assertInitialState(printer);
- printer.print("a,b,c");
- printer.print("xyz");
- assertEquals("a!,b!,c,xyz", sw.toString());
- }
- }
-
- @Test
- public void testDelimiterPlain() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
- assertInitialState(printer);
- printer.print("a,b,c");
- printer.print("xyz");
- assertEquals("a,b,c,xyz", sw.toString());
- }
- }
-
- @Test
- public void testDelimiterStringEscaped() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.builder().setDelimiter("|||").setEscape('!').setQuote(null).get())) {
- assertInitialState(printer);
- printer.print("a|||b|||c");
- printer.print("xyz");
- assertEquals("a!|!|!|b!|!|!|c|||xyz", sw.toString());
- }
- }
-
- @Test
- public void testDisabledComment() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printComment("This is a comment");
- assertEquals("", sw.toString());
- assertEquals(0, printer.getRecordCount());
- }
- }
-
- @Test
- public void testDontQuoteEuroFirstChar() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) {
- assertInitialState(printer);
- printer.printRecord(EURO_CH, "Deux");
- assertEquals(EURO_CH + ",Deux" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testEolEscaped() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) {
- assertInitialState(printer);
- printer.print("a\rb\nc");
- printer.print("x\fy\bz");
- assertEquals("a!rb!nc,x\fy\bz", sw.toString());
- }
- }
-
- @Test
- public void testEolPlain() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
- assertInitialState(printer);
- printer.print("a\rb\nc");
- printer.print("x\fy\bz");
- assertEquals("a\rb\nc,x\fy\bz", sw.toString());
- }
- }
-
- @Test
- public void testEolQuoted() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
- assertInitialState(printer);
- printer.print("a\rb\nc");
- printer.print("x\by\fz");
- assertEquals("'a\rb\nc',x\by\fz", sw.toString());
- }
- }
-
- @SuppressWarnings("unlikely-arg-type")
- @Test
- public void testEquals() throws IOException {
- // Don't use assertNotEquals here
- assertFalse(CSVFormat.DEFAULT.equals(null));
- // Don't use assertNotEquals here
- assertFalse(CSVFormat.DEFAULT.equals(""));
- }
-
- @Test
- public void testEscapeBackslash1() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
- assertInitialState(printer);
- printer.print("\\");
- }
- assertEquals("\\", sw.toString());
- }
-
- @Test
- public void testEscapeBackslash2() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
- assertInitialState(printer);
- printer.print("\\\r");
- }
- assertEquals("'\\\r'", sw.toString());
- }
-
- @Test
- public void testEscapeBackslash3() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
- assertInitialState(printer);
- printer.print("X\\\r");
- }
- assertEquals("'X\\\r'", sw.toString());
- }
-
- @Test
- public void testEscapeBackslash4() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
- assertInitialState(printer);
- printer.print("\\\\");
- }
- assertEquals("\\\\", sw.toString());
- }
-
- @Test
- public void testEscapeBackslash5() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
- assertInitialState(printer);
- printer.print("\\\\");
- }
- assertEquals("\\\\", sw.toString());
- }
-
- @Test
- public void testEscapeNull1() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
- assertInitialState(printer);
- printer.print("\\");
- }
- assertEquals("\\", sw.toString());
- }
-
- @Test
- public void testEscapeNull2() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
- assertInitialState(printer);
- printer.print("\\\r");
- }
- assertEquals("\"\\\r\"", sw.toString());
- }
-
- @Test
- public void testEscapeNull3() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
- assertInitialState(printer);
- printer.print("X\\\r");
- }
- assertEquals("\"X\\\r\"", sw.toString());
- }
-
- @Test
- public void testEscapeNull4() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
- assertInitialState(printer);
- printer.print("\\\\");
- }
- assertEquals("\\\\", sw.toString());
- }
-
- @Test
- public void testEscapeNull5() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
- assertInitialState(printer);
- printer.print("\\\\");
- }
- assertEquals("\\\\", sw.toString());
- }
-
- @Test
- public void testExcelPrintAllArrayOfArrays() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords((Object[]) new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } });
- assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllArrayOfArraysWithFirstEmptyValue2() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords((Object[]) new String[][] { { "" } });
- assertEquals("\"\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllArrayOfArraysWithFirstSpaceValue1() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords((Object[]) new String[][] { { " ", "r1c2" } });
- assertEquals("\" \",r1c2" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllArrayOfArraysWithFirstTabValue1() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords((Object[]) new String[][] { { "\t", "r1c2" } });
- assertEquals("\"\t\",r1c2" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllArrayOfLists() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords((Object[]) new List[] { Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2") });
- assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllArrayOfListsWithFirstEmptyValue2() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords((Object[]) new List[] { Arrays.asList("") });
- assertEquals("\"\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllIterableOfArrays() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords(Arrays.asList(new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } }));
- assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllIterableOfArraysWithFirstEmptyValue2() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords(Arrays.asList(new String[][] { { "" } }));
- assertEquals("\"\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllIterableOfLists() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords(Arrays.asList(Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2")));
- assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrintAllStreamOfArrays() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecords(Stream.of(new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } }));
- assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrinter1() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecord("a", "b");
- assertEquals("a,b" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testExcelPrinter2() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
- assertInitialState(printer);
- printer.printRecord("a,b", "b");
- assertEquals("\"a,b\",b" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testHeader() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3"))) {
- assertEquals(1, printer.getRecordCount());
- 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());
- }
- }
-
- @Test
- public void testHeaderCommentExcel() throws IOException {
- final StringWriter sw = new StringWriter();
- final Date now = new Date();
- final CSVFormat format = CSVFormat.EXCEL;
- try (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());
- }
- }
-
- @Test
- public void testHeaderCommentTdf() throws IOException {
- final StringWriter sw = new StringWriter();
- final Date now = new Date();
- final CSVFormat format = CSVFormat.TDF;
- try (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());
- }
- }
-
- @Test
- public void testHeaderNotSet() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
- assertInitialState(printer);
- printer.printRecord("a", "b", "c");
- printer.printRecord("x", "y", "z");
- assertEquals("a,b,c\r\nx,y,z\r\n", sw.toString());
- }
- }
-
- @Test
- public void testInvalidFormat() {
- assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR));
- }
-
- @Test
- public void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException {
- final StringWriter sw = new StringWriter();
- final CSVFormat csvFormat = CSVFormat.DEFAULT;
- try (Connection connection = getH2Connection()) {
- setUpTable(connection);
- try (Statement stmt = connection.createStatement();
- CSVPrinter printer = new CSVPrinter(sw, csvFormat);
- ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT, BIN_DATA from TEST")) {
- assertInitialState(printer);
- printer.printRecords(resultSet);
- assertEquals(TABLE_RECORD_COUNT, printer.getRecordCount());
- }
- }
- final String csv = sw.toString();
- assertEquals("1,r1,\"long text 1\",\"YmluYXJ5IGRhdGEgMQ==\r\n\"" + recordSeparator + "2,r2,\"" + longText2 + "\",\"YmluYXJ5IGRhdGEgMg==\r\n\"" +
- recordSeparator, csv);
- // Round trip the data
- try (StringReader reader = new StringReader(csv);
- CSVParser csvParser = csvFormat.parse(reader)) {
- // Row 1
- CSVRecord record = csvParser.nextRecord();
- assertEquals("1", record.get(0));
- assertEquals("r1", record.get(1));
- assertEquals("long text 1", record.get(2));
- assertEquals("YmluYXJ5IGRhdGEgMQ==\r\n", record.get(3));
- // Row 2
- record = csvParser.nextRecord();
- assertEquals("2", record.get(0));
- assertEquals("r2", record.get(1));
- assertEquals("YmluYXJ5IGRhdGEgMg==\r\n", record.get(3));
- }
- }
-
- @Test
- public void testJdbcPrinterWithFirstEmptyValue2() throws IOException, ClassNotFoundException, SQLException {
- final StringWriter sw = new StringWriter();
- try (Connection connection = getH2Connection()) {
- try (Statement stmt = connection.createStatement();
- ResultSet resultSet = stmt.executeQuery("select '' AS EMPTYVALUE from DUAL");
- CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet).print(sw)) {
- printer.printRecords(resultSet);
- }
- }
- assertEquals("EMPTYVALUE" + recordSeparator + "\"\"" + recordSeparator, sw.toString());
- }
-
- @Test
- public void testJdbcPrinterWithResultSet() throws IOException, ClassNotFoundException, SQLException {
- final StringWriter sw = new StringWriter();
- try (Connection connection = getH2Connection()) {
- setUpTable(connection);
- try (Statement stmt = connection.createStatement();
- ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT from TEST");
- CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet).print(sw)) {
- printer.printRecords(resultSet);
- }
- }
- assertEquals("ID,NAME,TEXT" + recordSeparator + "1,r1,\"long text 1\"" + recordSeparator + "2,r2,\"" + longText2 + "\"" + recordSeparator,
- sw.toString());
- }
-
- @Test
- public void testJdbcPrinterWithResultSetHeader() throws IOException, ClassNotFoundException, SQLException {
- final StringWriter sw = new StringWriter();
- try (Connection connection = getH2Connection()) {
- setUpTable(connection);
- try (Statement stmt = connection.createStatement();
- CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- try (ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST")) {
- printer.printRecords(resultSet, true);
- assertEquals(TABLE_RECORD_COUNT, printer.getRecordCount());
- assertEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator, sw.toString());
- }
- try (ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST")) {
- printer.printRecords(resultSet, false);
- assertEquals(TABLE_RECORD_COUNT * 2, printer.getRecordCount());
- assertNotEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator, sw.toString());
- }
- }
- }
- }
-
- @Test
- public void testJdbcPrinterWithResultSetMetaData() throws IOException, ClassNotFoundException, SQLException {
- final StringWriter sw = new StringWriter();
- try (Connection connection = getH2Connection()) {
- setUpTable(connection);
- try (Statement stmt = connection.createStatement();
- ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT from TEST");
- CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet.getMetaData()).print(sw)) {
- // The header is the first record.
- assertEquals(1, printer.getRecordCount());
- printer.printRecords(resultSet);
- assertEquals(3, printer.getRecordCount());
- assertEquals("ID,NAME,TEXT" + recordSeparator + "1,r1,\"long text 1\"" + recordSeparator + "2,r2,\"" + longText2 + "\"" + recordSeparator,
- sw.toString());
- }
- }
- }
-
- @Test
- public void testJira135_part1() throws IOException {
- final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
- final StringWriter sw = new StringWriter();
- final List list = new LinkedList<>();
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
- list.add("\"");
- printer.printRecord(list);
- }
- final String expected = "\"\\\"\"" + format.getRecordSeparator();
- assertEquals(expected, sw.toString());
- final String[] record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(list.toArray(), format), record0);
- }
-
- @Test
- @Disabled
- public void testJira135_part2() throws IOException {
- final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
- final StringWriter sw = new StringWriter();
- final List list = new LinkedList<>();
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
- list.add("\n");
- printer.printRecord(list);
- }
- final String expected = "\"\\n\"" + format.getRecordSeparator();
- assertEquals(expected, sw.toString());
- final String[] record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(list.toArray(), format), record0);
- }
-
- @Test
- public void testJira135_part3() throws IOException {
- final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
- final StringWriter sw = new StringWriter();
- final List list = new LinkedList<>();
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
- list.add("\\");
- printer.printRecord(list);
- }
- final String expected = "\"\\\\\"" + format.getRecordSeparator();
- assertEquals(expected, sw.toString());
- final String[] record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(list.toArray(), format), record0);
- }
-
- @Test
- @Disabled
- public void testJira135All() throws IOException {
- final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
- final StringWriter sw = new StringWriter();
- final List list = new LinkedList<>();
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
- list.add("\"");
- list.add("\n");
- list.add("\\");
- printer.printRecord(list);
- }
- final String expected = "\"\\\"\",\"\\n\",\"\\\"" + format.getRecordSeparator();
- assertEquals(expected, sw.toString());
- final String[] record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(list.toArray(), format), record0);
- }
-
- @Test
- public void testMongoDbCsvBasic() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
- printer.printRecord("a", "b");
- assertEquals("a,b" + recordSeparator, sw.toString());
- assertEquals(1, printer.getRecordCount());
- }
- }
-
- @Test
- public void testMongoDbCsvCommaInValue() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
- printer.printRecord("a,b", "c");
- assertEquals("\"a,b\",c" + recordSeparator, sw.toString());
- assertEquals(1, printer.getRecordCount());
- }
- }
-
- @Test
- public void testMongoDbCsvDoubleQuoteInValue() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
- printer.printRecord("a \"c\" b", "d");
- assertEquals("\"a \"\"c\"\" b\",d" + recordSeparator, sw.toString());
- assertEquals(1, printer.getRecordCount());
- }
- }
-
- @Test
- public void testMongoDbCsvTabInValue() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
- printer.printRecord("a\tb", "c");
- assertEquals("a\tb,c" + recordSeparator, sw.toString());
- assertEquals(1, printer.getRecordCount());
- }
- }
-
- @Test
- public void testMongoDbTsvBasic() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
- printer.printRecord("a", "b");
- assertEquals("a\tb" + recordSeparator, sw.toString());
- assertEquals(1, printer.getRecordCount());
- }
- }
-
- @Test
- public void testMongoDbTsvCommaInValue() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
- printer.printRecord("a,b", "c");
- assertEquals("a,b\tc" + recordSeparator, sw.toString());
- assertEquals(1, printer.getRecordCount());
- }
- }
-
- @Test
- public void testMongoDbTsvTabInValue() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
- printer.printRecord("a\tb", "c");
- assertEquals("\"a\tb\"\tc" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testMultiLineComment() throws IOException {
- final StringWriter sw = new StringWriter();
- try (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());
- assertEquals(0, printer.getRecordCount());
- }
- }
-
- @Test
- public void testMySqlNullOutput() throws IOException {
- Object[] s = new String[] { "NULL", null };
- CSVFormat format = CSVFormat.MYSQL.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.NON_NUMERIC);
- StringWriter writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- String expected = "\"NULL\"\tNULL\n";
- assertEquals(expected, writer.toString());
- String[] record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(s, record0);
-
- s = new String[] { "\\N", null };
- format = CSVFormat.MYSQL.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\t\\N\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\N", "A" };
- format = CSVFormat.MYSQL.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\tA\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\n", "A" };
- format = CSVFormat.MYSQL.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\n\tA\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "", null };
- format = CSVFormat.MYSQL.withNullString("NULL");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\tNULL\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "", null };
- format = CSVFormat.MYSQL;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\t\\N\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\N", "", "\u000e,\\\r" };
- format = CSVFormat.MYSQL;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\t\t\u000e,\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "NULL", "\\\r" };
- format = CSVFormat.MYSQL;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "NULL\t\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\\r" };
- format = CSVFormat.MYSQL;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
- }
-
- @Test
- public void testMySqlNullStringDefault() {
- assertEquals("\\N", CSVFormat.MYSQL.getNullString());
- }
-
- @Test
- public void testNewCsvPrinterAppendableNullFormat() {
- assertThrows(NullPointerException.class, () -> new CSVPrinter(new StringWriter(), null));
- }
-
- @Test
- public void testNewCsvPrinterNullAppendableFormat() {
- assertThrows(NullPointerException.class, () -> new CSVPrinter(null, CSVFormat.DEFAULT));
- }
-
- @Test
- public void testNotFlushable() throws IOException {
- final Appendable out = new StringBuilder();
- try (CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT)) {
- printer.printRecord("a", "b", "c");
- assertEquals("a,b,c" + recordSeparator, out.toString());
- printer.flush();
- }
- }
-
- @Test
- public void testParseCustomNullValues() throws IOException {
- final StringWriter sw = new StringWriter();
- final CSVFormat format = CSVFormat.DEFAULT.withNullString("NULL");
- try (CSVPrinter printer = new CSVPrinter(sw, format)) {
- printer.printRecord("a", null, "b");
- }
- final String csvString = sw.toString();
- assertEquals("a,NULL,b" + recordSeparator, csvString);
- try (CSVParser iterable = format.parse(new StringReader(csvString))) {
- final Iterator iterator = iterable.iterator();
- final CSVRecord record = iterator.next();
- assertEquals("a", record.get(0));
- assertNull(record.get(1));
- assertEquals("b", record.get(2));
- assertFalse(iterator.hasNext());
- }
- }
-
- @Test
- public void testPlainEscaped() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) {
- printer.print("abc");
- printer.print("xyz");
- assertEquals("abc,xyz", sw.toString());
- }
- }
-
- @Test
- public void testPlainPlain() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
- printer.print("abc");
- printer.print("xyz");
- assertEquals("abc,xyz", sw.toString());
- }
- }
-
- @Test
- public void testPlainQuoted() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
- printer.print("abc");
- assertEquals("abc", sw.toString());
- }
- }
-
- @Test
- @Disabled
- public void testPostgreSqlCsvNullOutput() throws IOException {
- Object[] s = new String[] { "NULL", null };
- CSVFormat format = CSVFormat.POSTGRESQL_CSV.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.ALL_NON_NULL);
- StringWriter writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- String expected = "\"NULL\",NULL\n";
- assertEquals(expected, writer.toString());
- String[] record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(new Object[2], record0);
-
- s = new String[] { "\\N", null };
- format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\t\\N\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\N", "A" };
- format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\tA\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\n", "A" };
- format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\n\tA\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "", null };
- format = CSVFormat.POSTGRESQL_CSV.withNullString("NULL");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\tNULL\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "", null };
- format = CSVFormat.POSTGRESQL_CSV;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\t\\N\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\N", "", "\u000e,\\\r" };
- format = CSVFormat.POSTGRESQL_CSV;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\t\t\u000e,\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "NULL", "\\\r" };
- format = CSVFormat.POSTGRESQL_CSV;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "NULL\t\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\\r" };
- format = CSVFormat.POSTGRESQL_CSV;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
- }
-
- @Test
- @Disabled
- public void testPostgreSqlCsvTextOutput() throws IOException {
- Object[] s = new String[] { "NULL", null };
- CSVFormat format = CSVFormat.POSTGRESQL_TEXT.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.ALL_NON_NULL);
- StringWriter writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- String expected = "\"NULL\"\tNULL\n";
- assertEquals(expected, writer.toString());
- String[] record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(new Object[2], record0);
-
- s = new String[] { "\\N", null };
- format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\t\\N\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\N", "A" };
- format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\tA\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\n", "A" };
- format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\n\tA\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "", null };
- format = CSVFormat.POSTGRESQL_TEXT.withNullString("NULL");
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\tNULL\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "", null };
- format = CSVFormat.POSTGRESQL_TEXT;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\t\\N\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\N", "", "\u000e,\\\r" };
- format = CSVFormat.POSTGRESQL_TEXT;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\N\t\t\u000e,\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "NULL", "\\\r" };
- format = CSVFormat.POSTGRESQL_TEXT;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "NULL\t\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
-
- s = new String[] { "\\\r" };
- format = CSVFormat.POSTGRESQL_TEXT;
- writer = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(writer, format)) {
- printer.printRecord(s);
- }
- expected = "\\\\\\r\n";
- assertEquals(expected, writer.toString());
- record0 = toFirstRecordValues(expected, format);
- assertArrayEquals(expectNulls(s, format), record0);
- }
-
- @Test
- public void testPostgreSqlNullStringDefaultCsv() {
- assertEquals("", CSVFormat.POSTGRESQL_CSV.getNullString());
- }
-
- @Test
- public void testPostgreSqlNullStringDefaultText() {
- assertEquals("\\N", CSVFormat.POSTGRESQL_TEXT.getNullString());
- }
-
- @Test
- public void testPrint() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = CSVFormat.DEFAULT.print(sw)) {
- assertInitialState(printer);
- printer.printRecord("a", "b\\c");
- assertEquals("a,b\\c" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrintCSVParser() throws IOException {
- // @formatter:off
- final String code = "a1,b1\n" + // 1)
- "a2,b2\n" + // 2)
- "a3,b3\n" + // 3)
- "a4,b4\n"; // 4)
- // @formatter:on
- final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
- final CSVFormat format = CSVFormat.DEFAULT;
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = format.print(sw);
- CSVParser parser = CSVParser.parse(code, format)) {
- assertInitialState(printer);
- printer.printRecords(parser);
- }
- try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
- final List records = parser.getRecords();
- assertFalse(records.isEmpty());
- Utils.compare("Fail", res, records);
- }
- }
-
- @Test
- public void testPrintCSVRecord() throws IOException {
- // @formatter:off
- final String code = "a1,b1\n" + // 1)
- "a2,b2\n" + // 2)
- "a3,b3\n" + // 3)
- "a4,b4\n"; // 4)
- // @formatter:on
- final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
- final CSVFormat format = CSVFormat.DEFAULT;
- final StringWriter sw = new StringWriter();
- int row = 0;
- try (CSVPrinter printer = format.print(sw);
- CSVParser parser = CSVParser.parse(code, format)) {
- assertInitialState(printer);
- for (final CSVRecord record : parser) {
- printer.printRecord(record);
- assertEquals(++row, printer.getRecordCount());
- }
- assertEquals(row, printer.getRecordCount());
- }
- try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
- final List records = parser.getRecords();
- assertFalse(records.isEmpty());
- Utils.compare("Fail", res, records);
- }
- }
-
- @Test
- public void testPrintCSVRecords() throws IOException {
- // @formatter:off
- final String code = "a1,b1\n" + // 1)
- "a2,b2\n" + // 2)
- "a3,b3\n" + // 3)
- "a4,b4\n"; // 4)
- // @formatter:on
- final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
- final CSVFormat format = CSVFormat.DEFAULT;
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = format.print(sw);
- CSVParser parser = CSVParser.parse(code, format)) {
- assertInitialState(printer);
- printer.printRecords(parser.getRecords());
- }
- try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
- final List records = parser.getRecords();
- assertFalse(records.isEmpty());
- Utils.compare("Fail", res, records);
- }
- }
-
- @Test
- public void testPrintCustomNullValues() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withNullString("NULL"))) {
- assertInitialState(printer);
- printer.printRecord("a", null, "b");
- assertEquals("a,NULL,b" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrinter1() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a", "b");
- assertEquals(1, printer.getRecordCount());
- assertEquals("a,b" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrinter2() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a,b", "b");
- assertEquals("\"a,b\",b" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrinter3() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a, b", "b ");
- assertEquals("\"a, b\",\"b \"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrinter4() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a", "b\"c");
- assertEquals("a,\"b\"\"c\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrinter5() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a", "b\nc");
- assertEquals("a,\"b\nc\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrinter6() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a", "b\r\nc");
- assertEquals("a,\"b\r\nc\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrinter7() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a", "b\\c");
- assertEquals("a,b\\c" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrintNullValues() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
- assertInitialState(printer);
- printer.printRecord("a", null, "b");
- assertEquals("a,,b" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testPrintOnePositiveInteger() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.MINIMAL))) {
- assertInitialState(printer);
- printer.print(Integer.MAX_VALUE);
- assertEquals(String.valueOf(Integer.MAX_VALUE), sw.toString());
- }
- }
-
- /**
- * Test to target the use of {@link IOUtils#copy(java.io.Reader, Appendable)} which directly buffers the value from the Reader to the Appendable.
- *
- *
- * Requires the format to have no quote or escape character, value to be a {@link Reader Reader} and the output MUST NOT be a {@link Writer Writer}
- * but some other Appendable.
- *
- *
- * @throws IOException Not expected to happen
- */
- @Test
- public void testPrintReaderWithoutQuoteToAppendable() throws IOException {
- final StringBuilder sb = new StringBuilder();
- final String content = "testValue";
- try (CSVPrinter printer = new CSVPrinter(sb, CSVFormat.DEFAULT.withQuote(null))) {
- assertInitialState(printer);
- final StringReader value = new StringReader(content);
- printer.print(value);
- }
- assertEquals(content, sb.toString());
- }
-
- /**
- * Test to target the use of {@link IOUtils#copyLarge(java.io.Reader, Writer)} which directly buffers the value from the Reader to the Writer.
- *
- *
- * Requires the format to have no quote or escape character, value to be a {@link Reader Reader} and the output MUST be a {@link Writer Writer}.
- *
- *
- * @throws IOException Not expected to happen
- */
- @Test
- public void testPrintReaderWithoutQuoteToWriter() throws IOException {
- final StringWriter sw = new StringWriter();
- final String content = "testValue";
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
- final StringReader value = new StringReader(content);
- printer.print(value);
- }
- assertEquals(content, sw.toString());
- }
-
- @Test
- public void testPrintRecordStream() throws IOException {
- // @formatter:off
- final String code = "a1,b1\n" + // 1)
- "a2,b2\n" + // 2)
- "a3,b3\n" + // 3)
- "a4,b4\n"; // 4)
- // @formatter:on
- final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
- final CSVFormat format = CSVFormat.DEFAULT;
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = format.print(sw);
- CSVParser parser = CSVParser.parse(code, format)) {
- long count = 0;
- for (final CSVRecord record : parser) {
- printer.printRecord(record.stream());
- assertEquals(++count, printer.getRecordCount());
- }
- }
- try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
- final List records = parser.getRecords();
- assertFalse(records.isEmpty());
- Utils.compare("Fail", res, records);
- }
- }
-
- @Test
- public void testPrintRecordsWithCSVRecord() throws IOException {
- final String[] values = { "A", "B", "C" };
- final String rowData = StringUtils.join(values, ',');
- final CharArrayWriter charArrayWriter = new CharArrayWriter(0);
- try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(rowData));
- CSVPrinter printer = CSVFormat.INFORMIX_UNLOAD.print(charArrayWriter)) {
- long count = 0;
- for (final CSVRecord record : parser) {
- printer.printRecord(record);
- assertEquals(++count, printer.getRecordCount());
- }
- }
- assertEquals(6, charArrayWriter.size());
- assertEquals("A|B|C" + CSVFormat.INFORMIX_UNLOAD.getRecordSeparator(), charArrayWriter.toString());
- }
-
- @Test
- public void testPrintRecordsWithEmptyVector() throws IOException {
- final PrintStream out = System.out;
- try {
- System.setOut(new PrintStream(NullOutputStream.INSTANCE));
- try (CSVPrinter printer = CSVFormat.POSTGRESQL_TEXT.printer()) {
- final Vector vector = new Vector<>();
- final int expectedCapacity = 23;
- vector.setSize(expectedCapacity);
- printer.printRecords(vector);
- assertEquals(expectedCapacity, vector.capacity());
- assertEquals(expectedCapacity, printer.getRecordCount());
- }
- } finally {
- System.setOut(out);
- }
- }
-
- @Test
- public void testPrintRecordsWithObjectArray() throws IOException {
- final CharArrayWriter charArrayWriter = new CharArrayWriter(0);
- final Object[] objectArray = new Object[6];
- try (CSVPrinter printer = CSVFormat.INFORMIX_UNLOAD.print(charArrayWriter)) {
- final HashSet hashSet = new HashSet<>();
- objectArray[3] = hashSet;
- printer.printRecords(objectArray);
- assertEquals(objectArray.length, printer.getRecordCount());
- }
- assertEquals(6, charArrayWriter.size());
- assertEquals("\n\n\n\n\n\n", charArrayWriter.toString());
- }
-
- @Test
- public void testPrintRecordsWithResultSetOneRow() throws IOException, SQLException {
- try (CSVPrinter printer = CSVFormat.MYSQL.printer()) {
- try (ResultSet resultSet = new SimpleResultSet()) {
- assertInitialState(printer);
- printer.printRecords(resultSet);
- assertInitialState(printer);
- assertEquals(0, resultSet.getRow());
- }
- }
- }
-
- @Test
- public void testPrintToFileWithCharsetUtf16Be() throws IOException {
- final File file = createTempFile();
- try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, StandardCharsets.UTF_16BE)) {
- printer.printRecord("a", "b\\c");
- }
- assertEquals("a,b\\c" + recordSeparator, FileUtils.readFileToString(file, StandardCharsets.UTF_16BE));
- }
-
- @Test
- public void testPrintToFileWithDefaultCharset() throws IOException {
- final File file = createTempFile();
- try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, Charset.defaultCharset())) {
- printer.printRecord("a", "b\\c");
- }
- assertEquals("a,b\\c" + recordSeparator, FileUtils.readFileToString(file, Charset.defaultCharset()));
- }
-
- @Test
- public void testPrintToPathWithDefaultCharset() throws IOException {
- final Path file = createTempPath();
- try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, Charset.defaultCharset())) {
- printer.printRecord("a", "b\\c");
- }
- assertEquals("a,b\\c" + recordSeparator, new String(Files.readAllBytes(file), Charset.defaultCharset()));
- }
-
- @Test
- public void testQuoteAll() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL))) {
- printer.printRecord("a", "b\nc", "d");
- assertEquals("\"a\",\"b\nc\",\"d\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testQuoteCommaFirstChar() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) {
- printer.printRecord(",");
- assertEquals("\",\"" + recordSeparator, sw.toString());
- }
- }
-
- @Test
- public void testQuoteNonNumeric() throws IOException {
- final StringWriter sw = new StringWriter();
- try (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());
- }
- }
-
- @Test
- public void testRandomDefault() throws Exception {
- doRandom(CSVFormat.DEFAULT, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- public void testRandomExcel() throws Exception {
- doRandom(CSVFormat.EXCEL, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- @Disabled
- public void testRandomMongoDbCsv() throws Exception {
- doRandom(CSVFormat.MONGODB_CSV, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- public void testRandomMySql() throws Exception {
- doRandom(CSVFormat.MYSQL, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- @Disabled
- public void testRandomOracle() throws Exception {
- doRandom(CSVFormat.ORACLE, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- @Disabled
- public void testRandomPostgreSqlCsv() throws Exception {
- doRandom(CSVFormat.POSTGRESQL_CSV, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- public void testRandomPostgreSqlText() throws Exception {
- doRandom(CSVFormat.POSTGRESQL_TEXT, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- public void testRandomRfc4180() throws Exception {
- doRandom(CSVFormat.RFC4180, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- public void testRandomTdf() throws Exception {
- doRandom(CSVFormat.TDF, ITERATIONS_FOR_RANDOM_TEST);
- }
-
- @Test
- public void testSingleLineComment() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) {
- printer.printComment("This is a comment");
- assertEquals("# This is a comment" + recordSeparator, sw.toString());
- assertEquals(0, printer.getRecordCount());
- }
- }
-
- @Test
- public void testSingleQuoteQuoted() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
- printer.print("a'b'c");
- printer.print("xyz");
- assertEquals("'a''b''c',xyz", sw.toString());
- }
- }
-
- @Test
- public void testSkipHeaderRecordFalse() throws IOException {
- // functionally identical to testHeader, used to test CSV-153
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3").withSkipHeaderRecord(false))) {
- 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());
- }
- }
-
- @Test
- public void testSkipHeaderRecordTrue() throws IOException {
- // functionally identical to testHeaderNotSet, used to test CSV-153
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3").withSkipHeaderRecord(true))) {
- printer.printRecord("a", "b", "c");
- printer.printRecord("x", "y", "z");
- assertEquals("a,b,c\r\nx,y,z\r\n", sw.toString());
- }
- }
-
- @Test
- public void testTrailingDelimiterOnTwoColumns() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrailingDelimiter())) {
- printer.printRecord("A", "B");
- assertEquals("A,B,\r\n", sw.toString());
- }
- }
-
- @Test
- public void testTrimOffOneColumn() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim(false))) {
- printer.print(" A ");
- assertEquals("\" A \"", sw.toString());
- }
- }
-
- @Test
- public void testTrimOnOneColumn() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) {
- printer.print(" A ");
- assertEquals("A", sw.toString());
- }
- }
-
- @Test
- public void testTrimOnTwoColumns() throws IOException {
- final StringWriter sw = new StringWriter();
- try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) {
- printer.print(" A ");
- printer.print(" B ");
- assertEquals("A,B", sw.toString());
- }
- }
-
- private String[] toFirstRecordValues(final String expected, final CSVFormat format) throws IOException {
- try (CSVParser parser = CSVParser.parse(expected, format)) {
- return parser.getRecords().get(0).values();
- }
- }
-
- private void tryFormat(final List list, final Character quote, final Character escape, final String expected) throws IOException {
- final CSVFormat format = CSVFormat.DEFAULT.withQuote(quote).withEscape(escape).withRecordSeparator(null);
- final Appendable out = new StringBuilder();
- try (CSVPrinter printer = new CSVPrinter(out, format)) {
- printer.printRecord(list);
- }
- assertEquals(expected, out.toString());
- }
-
-}
+/*
+ * 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
+ *
+ * https://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.CR;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.io.CharArrayWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.sql.BatchUpdateException;
+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.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Random;
+import java.util.Vector;
+import java.util.stream.Stream;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.output.NullOutputStream;
+import org.apache.commons.lang3.StringUtils;
+import org.h2.tools.SimpleResultSet;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link CSVPrinter}.
+ */
+public class CSVPrinterTest {
+
+ private static final int TABLE_RECORD_COUNT = 2;
+ private static final char DQUOTE_CHAR = '"';
+ private static final char EURO_CH = '\u20AC';
+ private static final int ITERATIONS_FOR_RANDOM_TEST = 50000;
+ private static final char QUOTE_CH = '\'';
+
+ 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 String longText2;
+
+ private final String recordSeparator = CSVFormat.DEFAULT.getRecordSeparator();
+
+ private void assertInitialState(final CSVPrinter printer) {
+ assertEquals(0, printer.getRecordCount());
+ }
+
+ private File createTempFile() throws IOException {
+ return createTempPath().toFile();
+ }
+
+ private Path createTempPath() throws IOException {
+ return Files.createTempFile(getClass().getName(), ".csv");
+ }
+
+ 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 = generateLines(nLines, nCol);
+
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+
+ for (int i = 0; i < nLines; i++) {
+ // for (int j=0; j parseResult = parser.getRecords();
+
+ final String[][] expected = lines.clone();
+ for (int i = 0; i < expected.length; i++) {
+ expected[i] = expectNulls(expected[i], format);
+ }
+ Utils.compare("Printer output :" + printable(result), expected, parseResult);
+ }
+ }
+
+ private void doRandom(final CSVFormat format, final int iter) throws Exception {
+ for (int i = 0; i < iter; i++) {
+ doOneRandom(format);
+ }
+ }
+
+ /**
+ * Converts an input CSV array into expected output values WRT NULLs. NULL strings are converted to null values because the parser will convert these
+ * strings to null.
+ */
+ private T[] expectNulls(final T[] original, final CSVFormat csvFormat) {
+ final T[] fixed = original.clone();
+ for (int i = 0; i < fixed.length; i++) {
+ if (Objects.equals(csvFormat.getNullString(), fixed[i])) {
+ fixed[i] = null;
+ }
+ }
+ return fixed;
+ }
+
+ private String[][] generateLines(final int nLines, final int nCol) {
+ 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();
+ }
+ }
+ return lines;
+ }
+
+ private Connection getH2Connection() throws SQLException, ClassNotFoundException {
+ Class.forName("org.h2.Driver");
+ return DriverManager.getConnection("jdbc:h2:mem:my_test;", "sa", "");
+ }
+
+ private CSVPrinter printWithHeaderComments(final StringWriter sw, final Date now, final CSVFormat baseFormat) throws IOException {
+ // Use withHeaderComments first to test CSV-145
+ // @formatter:off
+ final CSVFormat format = baseFormat.builder()
+ .setHeaderComments((String[]) null) // don't blow up
+ .setHeaderComments((Object[]) null) // don't blow up
+ .setHeaderComments("Generated by Apache Commons CSV 1.1", now)
+ .setCommentMarker('#')
+ .setHeader("Col1", "Col2")
+ .get();
+ // @formatter:on
+ final CSVPrinter printer = format.print(sw);
+ printer.printRecord("A", "B");
+ printer.printRecord("C", "D");
+ printer.close();
+ return printer;
+ }
+
+ 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
+ final 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 = DQUOTE_CHAR;
+ break;
+ case 7:
+ ch = '\'';
+ break;
+ case 8:
+ ch = BACKSLASH;
+ break;
+ default:
+ ch = (char) r.nextInt(300);
+ break;
+ // default: ch = 'a'; break;
+ }
+ buf[i] = ch;
+ }
+ return new String(buf);
+ }
+
+ private void setUpTable(final Connection connection) throws SQLException {
+ try (Statement statement = connection.createStatement()) {
+ statement.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), TEXT CLOB, BIN_DATA BLOB)");
+ statement.execute("insert into TEST values(1, 'r1', 'long text 1', 'binary data 1')");
+ longText2 = StringUtils.repeat('a', IOUtils.DEFAULT_BUFFER_SIZE - 4);
+ longText2 += "\"\r\n\"b\"";
+ longText2 += StringUtils.repeat('c', IOUtils.DEFAULT_BUFFER_SIZE - 1);
+ statement.execute("insert into TEST values(2, 'r2', '" + longText2 + "', 'binary data 2')");
+ longText2 = longText2.replace("\"", "\"\"");
+ }
+ }
+
+ @Test
+ public void testCloseBackwardCompatibility() throws IOException {
+ try (Writer writer = mock(Writer.class)) {
+ final CSVFormat csvFormat = CSVFormat.DEFAULT;
+ try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) {
+ assertInitialState(printer);
+ }
+ verify(writer, never()).flush();
+ verify(writer, times(1)).close();
+ }
+ }
+
+ @Test
+ public void testCloseWithCsvFormatAutoFlushOff() throws IOException {
+ try (Writer writer = mock(Writer.class)) {
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(false);
+ try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) {
+ assertInitialState(printer);
+ }
+ verify(writer, never()).flush();
+ verify(writer, times(1)).close();
+ }
+ }
+
+ @Test
+ public void testCloseWithCsvFormatAutoFlushOn() throws IOException {
+ // System.out.println("start method");
+ try (Writer writer = mock(Writer.class)) {
+ final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(true);
+ try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) {
+ assertInitialState(printer);
+ }
+ verify(writer, times(1)).flush();
+ verify(writer, times(1)).close();
+ }
+ }
+
+ @Test
+ public void testCloseWithFlushOff() throws IOException {
+ try (Writer writer = mock(Writer.class)) {
+ final CSVFormat csvFormat = CSVFormat.DEFAULT;
+ @SuppressWarnings("resource")
+ final CSVPrinter printer = new CSVPrinter(writer, csvFormat);
+ assertInitialState(printer);
+ printer.close(false);
+ assertEquals(0, printer.getRecordCount());
+ verify(writer, never()).flush();
+ verify(writer, times(1)).close();
+ }
+ }
+
+ @Test
+ public void testCloseWithFlushOn() throws IOException {
+ try (Writer writer = mock(Writer.class)) {
+ @SuppressWarnings("resource")
+ final CSVPrinter printer = new CSVPrinter(writer, CSVFormat.DEFAULT);
+ assertInitialState(printer);
+ printer.close(true);
+ assertEquals(0, printer.getRecordCount());
+ verify(writer, times(1)).flush();
+ }
+ }
+
+ @Test
+ public void testCRComment() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final Object value = "abc";
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) {
+ assertInitialState(printer);
+ printer.print(value);
+ assertEquals(0, printer.getRecordCount());
+ printer.printComment("This is a comment\r\non multiple lines\rthis is next comment\r");
+ assertEquals("abc" + recordSeparator + "# This is a comment" + recordSeparator + "# on multiple lines" + recordSeparator +
+ "# this is next comment" + recordSeparator + "# " + recordSeparator, sw.toString());
+ assertEquals(0, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testCSV135() throws IOException {
+ final List list = new LinkedList<>();
+ list.add("\"\""); // ""
+ list.add("\\\\"); // \\
+ list.add("\\\"\\"); // \"\
+ //
+ // "",\\,\"\ (unchanged)
+ tryFormat(list, null, null, "\"\",\\\\,\\\"\\");
+ //
+ // """""",\\,"\""\" (quoted, and embedded DQ doubled)
+ tryFormat(list, '"', null, "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
+ //
+ // "",\\\\,\\"\\ (escapes escaped, not quoted)
+ tryFormat(list, null, '\\', "\"\",\\\\\\\\,\\\\\"\\\\");
+ //
+ // "\"\"","\\\\","\\\"\\" (quoted, and embedded DQ & escape escaped)
+ tryFormat(list, '"', '\\', "\"\\\"\\\"\",\"\\\\\\\\\",\"\\\\\\\"\\\\\"");
+ //
+ // """""",\\,"\""\" (quoted, embedded DQ escaped)
+ tryFormat(list, '"', '"', "\"\"\"\"\"\",\\\\,\"\\\"\"\\\"");
+ }
+
+ @Test
+ public void testCSV259() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (Reader reader = new FileReader("src/test/resources/org/apache/commons/csv/CSV-259/sample.txt");
+ CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null))) {
+ assertInitialState(printer);
+ printer.print(reader);
+ assertEquals("x!,y!,z", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDelimeterQuoted() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
+ assertInitialState(printer);
+ printer.print("a,b,c");
+ printer.print("xyz");
+ assertEquals("'a,b,c',xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDelimeterQuoteNone() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final CSVFormat format = CSVFormat.DEFAULT.withEscape('!').withQuoteMode(QuoteMode.NONE);
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+ assertInitialState(printer);
+ printer.print("a,b,c");
+ printer.print("xyz");
+ assertEquals("a!,b!,c,xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDelimeterStringQuoted() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').get())) {
+ assertInitialState(printer);
+ printer.print("a[|]b[|]c");
+ printer.print("xyz");
+ assertEquals("'a[|]b[|]c'[|]xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDelimeterStringQuoteNone() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').setQuoteMode(QuoteMode.NONE).get();
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+ assertInitialState(printer);
+ printer.print("a[|]b[|]c");
+ printer.print("xyz");
+ printer.print("a[xy]bc[]");
+ assertEquals("a![!|!]b![!|!]c[|]xyz[|]a[xy]bc[]", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDelimiterEscaped() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null))) {
+ assertInitialState(printer);
+ printer.print("a,b,c");
+ printer.print("xyz");
+ assertEquals("a!,b!,c,xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDelimiterPlain() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
+ assertInitialState(printer);
+ printer.print("a,b,c");
+ printer.print("xyz");
+ assertEquals("a,b,c,xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDelimiterStringEscaped() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.builder().setDelimiter("|||").setEscape('!').setQuote(null).get())) {
+ assertInitialState(printer);
+ printer.print("a|||b|||c");
+ printer.print("xyz");
+ assertEquals("a!|!|!|b!|!|!|c|||xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testDisabledComment() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printComment("This is a comment");
+ assertEquals("", sw.toString());
+ assertEquals(0, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testDontQuoteEuroFirstChar() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) {
+ assertInitialState(printer);
+ printer.printRecord(EURO_CH, "Deux");
+ assertEquals(EURO_CH + ",Deux" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testEolEscaped() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) {
+ assertInitialState(printer);
+ printer.print("a\rb\nc");
+ printer.print("x\fy\bz");
+ assertEquals("a!rb!nc,x\fy\bz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testEolPlain() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
+ assertInitialState(printer);
+ printer.print("a\rb\nc");
+ printer.print("x\fy\bz");
+ assertEquals("a\rb\nc,x\fy\bz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testEolQuoted() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
+ assertInitialState(printer);
+ printer.print("a\rb\nc");
+ printer.print("x\by\fz");
+ assertEquals("'a\rb\nc',x\by\fz", sw.toString());
+ }
+ }
+
+ @SuppressWarnings("unlikely-arg-type")
+ @Test
+ public void testEquals() throws IOException {
+ // Don't use assertNotEquals here
+ assertFalse(CSVFormat.DEFAULT.equals(null));
+ // Don't use assertNotEquals here
+ assertFalse(CSVFormat.DEFAULT.equals(""));
+ }
+
+ @Test
+ public void testEscapeBackslash1() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
+ assertInitialState(printer);
+ printer.print("\\");
+ }
+ assertEquals("\\", sw.toString());
+ }
+
+ @Test
+ public void testEscapeBackslash2() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
+ assertInitialState(printer);
+ printer.print("\\\r");
+ }
+ assertEquals("'\\\r'", sw.toString());
+ }
+
+ @Test
+ public void testEscapeBackslash3() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
+ assertInitialState(printer);
+ printer.print("X\\\r");
+ }
+ assertEquals("'X\\\r'", sw.toString());
+ }
+
+ @Test
+ public void testEscapeBackslash4() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
+ assertInitialState(printer);
+ printer.print("\\\\");
+ }
+ assertEquals("\\\\", sw.toString());
+ }
+
+ @Test
+ public void testEscapeBackslash5() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) {
+ assertInitialState(printer);
+ printer.print("\\\\");
+ }
+ assertEquals("\\\\", sw.toString());
+ }
+
+ @Test
+ public void testEscapeNull1() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
+ assertInitialState(printer);
+ printer.print("\\");
+ }
+ assertEquals("\\", sw.toString());
+ }
+
+ @Test
+ public void testEscapeNull2() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
+ assertInitialState(printer);
+ printer.print("\\\r");
+ }
+ assertEquals("\"\\\r\"", sw.toString());
+ }
+
+ @Test
+ public void testEscapeNull3() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
+ assertInitialState(printer);
+ printer.print("X\\\r");
+ }
+ assertEquals("\"X\\\r\"", sw.toString());
+ }
+
+ @Test
+ public void testEscapeNull4() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
+ assertInitialState(printer);
+ printer.print("\\\\");
+ }
+ assertEquals("\\\\", sw.toString());
+ }
+
+ @Test
+ public void testEscapeNull5() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) {
+ assertInitialState(printer);
+ printer.print("\\\\");
+ }
+ assertEquals("\\\\", sw.toString());
+ }
+
+ @Test
+ public void testExcelPrintAllArrayOfArrays() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords((Object[]) new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } });
+ assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllArrayOfArraysWithFirstEmptyValue2() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords((Object[]) new String[][] { { "" } });
+ assertEquals("\"\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllArrayOfArraysWithFirstSpaceValue1() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords((Object[]) new String[][] { { " ", "r1c2" } });
+ assertEquals("\" \",r1c2" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllArrayOfArraysWithFirstTabValue1() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords((Object[]) new String[][] { { "\t", "r1c2" } });
+ assertEquals("\"\t\",r1c2" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllArrayOfLists() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords((Object[]) new List[] { Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2") });
+ assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllArrayOfListsWithFirstEmptyValue2() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords((Object[]) new List[] { Arrays.asList("") });
+ assertEquals("\"\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllIterableOfArrays() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords(Arrays.asList(new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } }));
+ assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllIterableOfArraysWithFirstEmptyValue2() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords(Arrays.asList(new String[][] { { "" } }));
+ assertEquals("\"\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllIterableOfLists() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords(Arrays.asList(Arrays.asList("r1c1", "r1c2"), Arrays.asList("r2c1", "r2c2")));
+ assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrintAllStreamOfArrays() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecords(Stream.of(new String[][] { { "r1c1", "r1c2" }, { "r2c1", "r2c2" } }));
+ assertEquals("r1c1,r1c2" + recordSeparator + "r2c1,r2c2" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrinter1() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b");
+ assertEquals("a,b" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testExcelPrinter2() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) {
+ assertInitialState(printer);
+ printer.printRecord("a,b", "b");
+ assertEquals("\"a,b\",b" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testHeader() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3"))) {
+ assertEquals(1, printer.getRecordCount());
+ 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());
+ }
+ }
+
+ @Test
+ public void testHeaderCommentExcel() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final Date now = new Date();
+ final CSVFormat format = CSVFormat.EXCEL;
+ try (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());
+ }
+ }
+
+ @Test
+ public void testHeaderCommentTdf() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final Date now = new Date();
+ final CSVFormat format = CSVFormat.TDF;
+ try (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());
+ }
+ }
+
+ @Test
+ public void testHeaderNotSet() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b", "c");
+ printer.printRecord("x", "y", "z");
+ assertEquals("a,b,c\r\nx,y,z\r\n", sw.toString());
+ }
+ }
+
+ @Test
+ public void testInvalidFormat() {
+ assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR));
+ }
+
+ @Test
+ public void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException {
+ final StringWriter sw = new StringWriter();
+ final CSVFormat csvFormat = CSVFormat.DEFAULT;
+ try (Connection connection = getH2Connection()) {
+ setUpTable(connection);
+ try (Statement stmt = connection.createStatement();
+ CSVPrinter printer = new CSVPrinter(sw, csvFormat);
+ ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT, BIN_DATA from TEST")) {
+ assertInitialState(printer);
+ printer.printRecords(resultSet);
+ assertEquals(TABLE_RECORD_COUNT, printer.getRecordCount());
+ }
+ }
+ final String csv = sw.toString();
+ assertEquals("1,r1,\"long text 1\",\"YmluYXJ5IGRhdGEgMQ==\r\n\"" + recordSeparator + "2,r2,\"" + longText2 + "\",\"YmluYXJ5IGRhdGEgMg==\r\n\"" +
+ recordSeparator, csv);
+ // Round trip the data
+ try (StringReader reader = new StringReader(csv);
+ CSVParser csvParser = csvFormat.parse(reader)) {
+ // Row 1
+ CSVRecord record = csvParser.nextRecord();
+ assertEquals("1", record.get(0));
+ assertEquals("r1", record.get(1));
+ assertEquals("long text 1", record.get(2));
+ assertEquals("YmluYXJ5IGRhdGEgMQ==\r\n", record.get(3));
+ // Row 2
+ record = csvParser.nextRecord();
+ assertEquals("2", record.get(0));
+ assertEquals("r2", record.get(1));
+ assertEquals("YmluYXJ5IGRhdGEgMg==\r\n", record.get(3));
+ }
+ }
+
+ @Test
+ public void testJdbcPrinterWithFirstEmptyValue2() throws IOException, ClassNotFoundException, SQLException {
+ final StringWriter sw = new StringWriter();
+ try (Connection connection = getH2Connection()) {
+ try (Statement stmt = connection.createStatement();
+ ResultSet resultSet = stmt.executeQuery("select '' AS EMPTYVALUE from DUAL");
+ CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet).print(sw)) {
+ printer.printRecords(resultSet);
+ }
+ }
+ assertEquals("EMPTYVALUE" + recordSeparator + "\"\"" + recordSeparator, sw.toString());
+ }
+
+ @Test
+ public void testJdbcPrinterWithResultSet() throws IOException, ClassNotFoundException, SQLException {
+ final StringWriter sw = new StringWriter();
+ try (Connection connection = getH2Connection()) {
+ setUpTable(connection);
+ try (Statement stmt = connection.createStatement();
+ ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT from TEST");
+ CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet).print(sw)) {
+ printer.printRecords(resultSet);
+ }
+ }
+ assertEquals("ID,NAME,TEXT" + recordSeparator + "1,r1,\"long text 1\"" + recordSeparator + "2,r2,\"" + longText2 + "\"" + recordSeparator,
+ sw.toString());
+ }
+
+ @Test
+ public void testJdbcPrinterWithResultSetHeader() throws IOException, ClassNotFoundException, SQLException {
+ final StringWriter sw = new StringWriter();
+ try (Connection connection = getH2Connection()) {
+ setUpTable(connection);
+ try (Statement stmt = connection.createStatement();
+ CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ try (ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST")) {
+ printer.printRecords(resultSet, true);
+ assertEquals(TABLE_RECORD_COUNT, printer.getRecordCount());
+ assertEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator, sw.toString());
+ }
+ try (ResultSet resultSet = stmt.executeQuery("select ID, NAME from TEST")) {
+ printer.printRecords(resultSet, false);
+ assertEquals(TABLE_RECORD_COUNT * 2, printer.getRecordCount());
+ assertNotEquals("ID,NAME" + recordSeparator + "1,r1" + recordSeparator + "2,r2" + recordSeparator, sw.toString());
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testJdbcPrinterWithResultSetMetaData() throws IOException, ClassNotFoundException, SQLException {
+ final StringWriter sw = new StringWriter();
+ try (Connection connection = getH2Connection()) {
+ setUpTable(connection);
+ try (Statement stmt = connection.createStatement();
+ ResultSet resultSet = stmt.executeQuery("select ID, NAME, TEXT from TEST");
+ CSVPrinter printer = CSVFormat.DEFAULT.withHeader(resultSet.getMetaData()).print(sw)) {
+ // The header is the first record.
+ assertEquals(1, printer.getRecordCount());
+ printer.printRecords(resultSet);
+ assertEquals(3, printer.getRecordCount());
+ assertEquals("ID,NAME,TEXT" + recordSeparator + "1,r1,\"long text 1\"" + recordSeparator + "2,r2,\"" + longText2 + "\"" + recordSeparator,
+ sw.toString());
+ }
+ }
+ }
+
+ @Test
+ public void testJira135_part1() throws IOException {
+ final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
+ final StringWriter sw = new StringWriter();
+ final List list = new LinkedList<>();
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+ list.add("\"");
+ printer.printRecord(list);
+ }
+ final String expected = "\"\\\"\"" + format.getRecordSeparator();
+ assertEquals(expected, sw.toString());
+ final String[] record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(list.toArray(), format), record0);
+ }
+
+ @Test
+ @Disabled
+ public void testJira135_part2() throws IOException {
+ final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
+ final StringWriter sw = new StringWriter();
+ final List list = new LinkedList<>();
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+ list.add("\n");
+ printer.printRecord(list);
+ }
+ final String expected = "\"\\n\"" + format.getRecordSeparator();
+ assertEquals(expected, sw.toString());
+ final String[] record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(list.toArray(), format), record0);
+ }
+
+ @Test
+ public void testJira135_part3() throws IOException {
+ final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
+ final StringWriter sw = new StringWriter();
+ final List list = new LinkedList<>();
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+ list.add("\\");
+ printer.printRecord(list);
+ }
+ final String expected = "\"\\\\\"" + format.getRecordSeparator();
+ assertEquals(expected, sw.toString());
+ final String[] record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(list.toArray(), format), record0);
+ }
+
+ @Test
+ @Disabled
+ public void testJira135All() throws IOException {
+ final CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator('\n').withQuote(DQUOTE_CHAR).withEscape(BACKSLASH);
+ final StringWriter sw = new StringWriter();
+ final List list = new LinkedList<>();
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+ list.add("\"");
+ list.add("\n");
+ list.add("\\");
+ printer.printRecord(list);
+ }
+ final String expected = "\"\\\"\",\"\\n\",\"\\\"" + format.getRecordSeparator();
+ assertEquals(expected, sw.toString());
+ final String[] record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(list.toArray(), format), record0);
+ }
+
+ @Test
+ public void testMongoDbCsvBasic() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
+ printer.printRecord("a", "b");
+ assertEquals("a,b" + recordSeparator, sw.toString());
+ assertEquals(1, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testMongoDbCsvCommaInValue() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
+ printer.printRecord("a,b", "c");
+ assertEquals("\"a,b\",c" + recordSeparator, sw.toString());
+ assertEquals(1, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testMongoDbCsvDoubleQuoteInValue() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
+ printer.printRecord("a \"c\" b", "d");
+ assertEquals("\"a \"\"c\"\" b\",d" + recordSeparator, sw.toString());
+ assertEquals(1, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testMongoDbCsvTabInValue() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) {
+ printer.printRecord("a\tb", "c");
+ assertEquals("a\tb,c" + recordSeparator, sw.toString());
+ assertEquals(1, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testMongoDbTsvBasic() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
+ printer.printRecord("a", "b");
+ assertEquals("a\tb" + recordSeparator, sw.toString());
+ assertEquals(1, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testMongoDbTsvCommaInValue() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
+ printer.printRecord("a,b", "c");
+ assertEquals("a,b\tc" + recordSeparator, sw.toString());
+ assertEquals(1, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testMongoDbTsvTabInValue() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) {
+ printer.printRecord("a\tb", "c");
+ assertEquals("\"a\tb\"\tc" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testMultiLineComment() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (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());
+ assertEquals(0, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testMySqlNullOutput() throws IOException {
+ Object[] s = new String[] { "NULL", null };
+ CSVFormat format = CSVFormat.MYSQL.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.NON_NUMERIC);
+ StringWriter writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ String expected = "\"NULL\"\tNULL\n";
+ assertEquals(expected, writer.toString());
+ String[] record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(s, record0);
+
+ s = new String[] { "\\N", null };
+ format = CSVFormat.MYSQL.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\t\\N\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\N", "A" };
+ format = CSVFormat.MYSQL.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\tA\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\n", "A" };
+ format = CSVFormat.MYSQL.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\n\tA\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "", null };
+ format = CSVFormat.MYSQL.withNullString("NULL");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\tNULL\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "", null };
+ format = CSVFormat.MYSQL;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\t\\N\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\N", "", "\u000e,\\\r" };
+ format = CSVFormat.MYSQL;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\t\t\u000e,\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "NULL", "\\\r" };
+ format = CSVFormat.MYSQL;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "NULL\t\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\\r" };
+ format = CSVFormat.MYSQL;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+ }
+
+ @Test
+ public void testMySqlNullStringDefault() {
+ assertEquals("\\N", CSVFormat.MYSQL.getNullString());
+ }
+
+ @Test
+ public void testNewCsvPrinterAppendableNullFormat() {
+ assertThrows(NullPointerException.class, () -> new CSVPrinter(new StringWriter(), null));
+ }
+
+ @Test
+ public void testNewCsvPrinterNullAppendableFormat() {
+ assertThrows(NullPointerException.class, () -> new CSVPrinter(null, CSVFormat.DEFAULT));
+ }
+
+ @Test
+ public void testNotFlushable() throws IOException {
+ final Appendable out = new StringBuilder();
+ try (CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT)) {
+ printer.printRecord("a", "b", "c");
+ assertEquals("a,b,c" + recordSeparator, out.toString());
+ printer.flush();
+ }
+ }
+
+ @Test
+ public void testParseCustomNullValues() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final CSVFormat format = CSVFormat.DEFAULT.withNullString("NULL");
+ try (CSVPrinter printer = new CSVPrinter(sw, format)) {
+ printer.printRecord("a", null, "b");
+ }
+ final String csvString = sw.toString();
+ assertEquals("a,NULL,b" + recordSeparator, csvString);
+ try (CSVParser iterable = format.parse(new StringReader(csvString))) {
+ final Iterator iterator = iterable.iterator();
+ final CSVRecord record = iterator.next();
+ assertEquals("a", record.get(0));
+ assertNull(record.get(1));
+ assertEquals("b", record.get(2));
+ assertFalse(iterator.hasNext());
+ }
+ }
+
+ @Test
+ public void testPlainEscaped() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) {
+ printer.print("abc");
+ printer.print("xyz");
+ assertEquals("abc,xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testPlainPlain() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
+ printer.print("abc");
+ printer.print("xyz");
+ assertEquals("abc,xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testPlainQuoted() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
+ printer.print("abc");
+ assertEquals("abc", sw.toString());
+ }
+ }
+
+ @Test
+ @Disabled
+ public void testPostgreSqlCsvNullOutput() throws IOException {
+ Object[] s = new String[] { "NULL", null };
+ CSVFormat format = CSVFormat.POSTGRESQL_CSV.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.ALL_NON_NULL);
+ StringWriter writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ String expected = "\"NULL\",NULL\n";
+ assertEquals(expected, writer.toString());
+ String[] record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(new Object[2], record0);
+
+ s = new String[] { "\\N", null };
+ format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\t\\N\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\N", "A" };
+ format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\tA\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\n", "A" };
+ format = CSVFormat.POSTGRESQL_CSV.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\n\tA\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "", null };
+ format = CSVFormat.POSTGRESQL_CSV.withNullString("NULL");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\tNULL\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "", null };
+ format = CSVFormat.POSTGRESQL_CSV;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\t\\N\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\N", "", "\u000e,\\\r" };
+ format = CSVFormat.POSTGRESQL_CSV;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\t\t\u000e,\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "NULL", "\\\r" };
+ format = CSVFormat.POSTGRESQL_CSV;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "NULL\t\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\\r" };
+ format = CSVFormat.POSTGRESQL_CSV;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+ }
+
+ @Test
+ @Disabled
+ public void testPostgreSqlCsvTextOutput() throws IOException {
+ Object[] s = new String[] { "NULL", null };
+ CSVFormat format = CSVFormat.POSTGRESQL_TEXT.withQuote(DQUOTE_CHAR).withNullString("NULL").withQuoteMode(QuoteMode.ALL_NON_NULL);
+ StringWriter writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ String expected = "\"NULL\"\tNULL\n";
+ assertEquals(expected, writer.toString());
+ String[] record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(new Object[2], record0);
+
+ s = new String[] { "\\N", null };
+ format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\t\\N\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\N", "A" };
+ format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\tA\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\n", "A" };
+ format = CSVFormat.POSTGRESQL_TEXT.withNullString("\\N");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\n\tA\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "", null };
+ format = CSVFormat.POSTGRESQL_TEXT.withNullString("NULL");
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\tNULL\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "", null };
+ format = CSVFormat.POSTGRESQL_TEXT;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\t\\N\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\N", "", "\u000e,\\\r" };
+ format = CSVFormat.POSTGRESQL_TEXT;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\N\t\t\u000e,\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "NULL", "\\\r" };
+ format = CSVFormat.POSTGRESQL_TEXT;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "NULL\t\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+
+ s = new String[] { "\\\r" };
+ format = CSVFormat.POSTGRESQL_TEXT;
+ writer = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(writer, format)) {
+ printer.printRecord(s);
+ }
+ expected = "\\\\\\r\n";
+ assertEquals(expected, writer.toString());
+ record0 = toFirstRecordValues(expected, format);
+ assertArrayEquals(expectNulls(s, format), record0);
+ }
+
+ @Test
+ public void testPostgreSqlNullStringDefaultCsv() {
+ assertEquals("", CSVFormat.POSTGRESQL_CSV.getNullString());
+ }
+
+ @Test
+ public void testPostgreSqlNullStringDefaultText() {
+ assertEquals("\\N", CSVFormat.POSTGRESQL_TEXT.getNullString());
+ }
+
+ @Test
+ public void testPrint() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = CSVFormat.DEFAULT.print(sw)) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b\\c");
+ assertEquals("a,b\\c" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrintCSVParser() throws IOException {
+ // @formatter:off
+ final String code = "a1,b1\n" + // 1)
+ "a2,b2\n" + // 2)
+ "a3,b3\n" + // 3)
+ "a4,b4\n"; // 4)
+ // @formatter:on
+ final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
+ final CSVFormat format = CSVFormat.DEFAULT;
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = format.print(sw);
+ CSVParser parser = CSVParser.parse(code, format)) {
+ assertInitialState(printer);
+ printer.printRecords(parser);
+ }
+ try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
+ final List records = parser.getRecords();
+ assertFalse(records.isEmpty());
+ Utils.compare("Fail", res, records);
+ }
+ }
+
+ @Test
+ public void testPrintCSVRecord() throws IOException {
+ // @formatter:off
+ final String code = "a1,b1\n" + // 1)
+ "a2,b2\n" + // 2)
+ "a3,b3\n" + // 3)
+ "a4,b4\n"; // 4)
+ // @formatter:on
+ final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
+ final CSVFormat format = CSVFormat.DEFAULT;
+ final StringWriter sw = new StringWriter();
+ int row = 0;
+ try (CSVPrinter printer = format.print(sw);
+ CSVParser parser = CSVParser.parse(code, format)) {
+ assertInitialState(printer);
+ for (final CSVRecord record : parser) {
+ printer.printRecord(record);
+ assertEquals(++row, printer.getRecordCount());
+ }
+ assertEquals(row, printer.getRecordCount());
+ }
+ try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
+ final List records = parser.getRecords();
+ assertFalse(records.isEmpty());
+ Utils.compare("Fail", res, records);
+ }
+ }
+
+ @Test
+ public void testPrintCSVRecords() throws IOException {
+ // @formatter:off
+ final String code = "a1,b1\n" + // 1)
+ "a2,b2\n" + // 2)
+ "a3,b3\n" + // 3)
+ "a4,b4\n"; // 4)
+ // @formatter:on
+ final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
+ final CSVFormat format = CSVFormat.DEFAULT;
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = format.print(sw);
+ CSVParser parser = CSVParser.parse(code, format)) {
+ assertInitialState(printer);
+ printer.printRecords(parser.getRecords());
+ }
+ try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
+ final List records = parser.getRecords();
+ assertFalse(records.isEmpty());
+ Utils.compare("Fail", res, records);
+ }
+ }
+
+ @Test
+ public void testPrintCustomNullValues() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withNullString("NULL"))) {
+ assertInitialState(printer);
+ printer.printRecord("a", null, "b");
+ assertEquals("a,NULL,b" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrinter1() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b");
+ assertEquals(1, printer.getRecordCount());
+ assertEquals("a,b" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrinter2() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a,b", "b");
+ assertEquals("\"a,b\",b" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrinter3() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a, b", "b ");
+ assertEquals("\"a, b\",\"b \"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrinter4() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b\"c");
+ assertEquals("a,\"b\"\"c\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrinter5() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b\nc");
+ assertEquals("a,\"b\nc\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrinter6() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b\r\nc");
+ assertEquals("a,\"b\r\nc\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrinter7() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a", "b\\c");
+ assertEquals("a,b\\c" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrintNullValues() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) {
+ assertInitialState(printer);
+ printer.printRecord("a", null, "b");
+ assertEquals("a,,b" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testPrintOnePositiveInteger() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.MINIMAL))) {
+ assertInitialState(printer);
+ printer.print(Integer.MAX_VALUE);
+ assertEquals(String.valueOf(Integer.MAX_VALUE), sw.toString());
+ }
+ }
+
+ /**
+ * Test to target the use of {@link IOUtils#copy(java.io.Reader, Appendable)} which directly buffers the value from the Reader to the Appendable.
+ *
+ *
+ * Requires the format to have no quote or escape character, value to be a {@link Reader Reader} and the output MUST NOT be a {@link Writer Writer}
+ * but some other Appendable.
+ *
+ *
+ * @throws IOException Not expected to happen
+ */
+ @Test
+ public void testPrintReaderWithoutQuoteToAppendable() throws IOException {
+ final StringBuilder sb = new StringBuilder();
+ final String content = "testValue";
+ try (CSVPrinter printer = new CSVPrinter(sb, CSVFormat.DEFAULT.withQuote(null))) {
+ assertInitialState(printer);
+ final StringReader value = new StringReader(content);
+ printer.print(value);
+ }
+ assertEquals(content, sb.toString());
+ }
+
+ /**
+ * Test to target the use of {@link IOUtils#copyLarge(java.io.Reader, Writer)} which directly buffers the value from the Reader to the Writer.
+ *
+ *
+ * Requires the format to have no quote or escape character, value to be a {@link Reader Reader} and the output MUST be a {@link Writer Writer}.
+ *
+ *
+ * @throws IOException Not expected to happen
+ */
+ @Test
+ public void testPrintReaderWithoutQuoteToWriter() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final String content = "testValue";
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) {
+ final StringReader value = new StringReader(content);
+ printer.print(value);
+ }
+ assertEquals(content, sw.toString());
+ }
+
+ @Test
+ public void testPrintRecordStream() throws IOException {
+ // @formatter:off
+ final String code = "a1,b1\n" + // 1)
+ "a2,b2\n" + // 2)
+ "a3,b3\n" + // 3)
+ "a4,b4\n"; // 4)
+ // @formatter:on
+ final String[][] res = { { "a1", "b1" }, { "a2", "b2" }, { "a3", "b3" }, { "a4", "b4" } };
+ final CSVFormat format = CSVFormat.DEFAULT;
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = format.print(sw);
+ CSVParser parser = CSVParser.parse(code, format)) {
+ long count = 0;
+ for (final CSVRecord record : parser) {
+ printer.printRecord(record.stream());
+ assertEquals(++count, printer.getRecordCount());
+ }
+ }
+ try (CSVParser parser = CSVParser.parse(sw.toString(), format)) {
+ final List records = parser.getRecords();
+ assertFalse(records.isEmpty());
+ Utils.compare("Fail", res, records);
+ }
+ }
+
+ @Test
+ public void testPrintRecordsWithCSVRecord() throws IOException {
+ final String[] values = { "A", "B", "C" };
+ final String rowData = StringUtils.join(values, ',');
+ final CharArrayWriter charArrayWriter = new CharArrayWriter(0);
+ try (CSVParser parser = CSVFormat.DEFAULT.parse(new StringReader(rowData));
+ CSVPrinter printer = CSVFormat.INFORMIX_UNLOAD.print(charArrayWriter)) {
+ long count = 0;
+ for (final CSVRecord record : parser) {
+ printer.printRecord(record);
+ assertEquals(++count, printer.getRecordCount());
+ }
+ }
+ assertEquals(6, charArrayWriter.size());
+ assertEquals("A|B|C" + CSVFormat.INFORMIX_UNLOAD.getRecordSeparator(), charArrayWriter.toString());
+ }
+
+ @Test
+ public void testPrintRecordsWithEmptyVector() throws IOException {
+ final PrintStream out = System.out;
+ try {
+ System.setOut(new PrintStream(NullOutputStream.INSTANCE));
+ try (CSVPrinter printer = CSVFormat.POSTGRESQL_TEXT.printer()) {
+ final Vector vector = new Vector<>();
+ final int expectedCapacity = 23;
+ vector.setSize(expectedCapacity);
+ printer.printRecords(vector);
+ assertEquals(expectedCapacity, vector.capacity());
+ assertEquals(expectedCapacity, printer.getRecordCount());
+ }
+ } finally {
+ System.setOut(out);
+ }
+ }
+
+ @Test
+ public void testPrintRecordsWithObjectArray() throws IOException {
+ final CharArrayWriter charArrayWriter = new CharArrayWriter(0);
+ final Object[] objectArray = new Object[6];
+ try (CSVPrinter printer = CSVFormat.INFORMIX_UNLOAD.print(charArrayWriter)) {
+ final HashSet hashSet = new HashSet<>();
+ objectArray[3] = hashSet;
+ printer.printRecords(objectArray);
+ assertEquals(objectArray.length, printer.getRecordCount());
+ }
+ assertEquals(6, charArrayWriter.size());
+ assertEquals("\n\n\n\n\n\n", charArrayWriter.toString());
+ }
+
+ @Test
+ public void testPrintRecordsWithResultSetOneRow() throws IOException, SQLException {
+ try (CSVPrinter printer = CSVFormat.MYSQL.printer()) {
+ try (ResultSet resultSet = new SimpleResultSet()) {
+ assertInitialState(printer);
+ printer.printRecords(resultSet);
+ assertInitialState(printer);
+ assertEquals(0, resultSet.getRow());
+ }
+ }
+ }
+
+ @Test
+ public void testPrintToFileWithCharsetUtf16Be() throws IOException {
+ final File file = createTempFile();
+ try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, StandardCharsets.UTF_16BE)) {
+ printer.printRecord("a", "b\\c");
+ }
+ assertEquals("a,b\\c" + recordSeparator, FileUtils.readFileToString(file, StandardCharsets.UTF_16BE));
+ }
+
+ @Test
+ public void testPrintToFileWithDefaultCharset() throws IOException {
+ final File file = createTempFile();
+ try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, Charset.defaultCharset())) {
+ printer.printRecord("a", "b\\c");
+ }
+ assertEquals("a,b\\c" + recordSeparator, FileUtils.readFileToString(file, Charset.defaultCharset()));
+ }
+
+ @Test
+ public void testPrintToPathWithDefaultCharset() throws IOException {
+ final Path file = createTempPath();
+ try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, Charset.defaultCharset())) {
+ printer.printRecord("a", "b\\c");
+ }
+ assertEquals("a,b\\c" + recordSeparator, new String(Files.readAllBytes(file), Charset.defaultCharset()));
+ }
+
+ @Test
+ public void testQuoteAll() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL))) {
+ printer.printRecord("a", "b\nc", "d");
+ assertEquals("\"a\",\"b\nc\",\"d\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testQuoteCommaFirstChar() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) {
+ printer.printRecord(",");
+ assertEquals("\",\"" + recordSeparator, sw.toString());
+ }
+ }
+
+ @Test
+ public void testQuoteNonNumeric() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (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());
+ }
+ }
+
+ @Test
+ public void testRandomDefault() throws Exception {
+ doRandom(CSVFormat.DEFAULT, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ public void testRandomExcel() throws Exception {
+ doRandom(CSVFormat.EXCEL, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ @Disabled
+ public void testRandomMongoDbCsv() throws Exception {
+ doRandom(CSVFormat.MONGODB_CSV, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ public void testRandomMySql() throws Exception {
+ doRandom(CSVFormat.MYSQL, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ @Disabled
+ public void testRandomOracle() throws Exception {
+ doRandom(CSVFormat.ORACLE, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ @Disabled
+ public void testRandomPostgreSqlCsv() throws Exception {
+ doRandom(CSVFormat.POSTGRESQL_CSV, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ public void testRandomPostgreSqlText() throws Exception {
+ doRandom(CSVFormat.POSTGRESQL_TEXT, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ public void testRandomRfc4180() throws Exception {
+ doRandom(CSVFormat.RFC4180, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ public void testRandomTdf() throws Exception {
+ doRandom(CSVFormat.TDF, ITERATIONS_FOR_RANDOM_TEST);
+ }
+
+ @Test
+ public void testSingleLineComment() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) {
+ printer.printComment("This is a comment");
+ assertEquals("# This is a comment" + recordSeparator, sw.toString());
+ assertEquals(0, printer.getRecordCount());
+ }
+ }
+
+ @Test
+ public void testSingleQuoteQuoted() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) {
+ printer.print("a'b'c");
+ printer.print("xyz");
+ assertEquals("'a''b''c',xyz", sw.toString());
+ }
+ }
+
+ @Test
+ public void testSkipHeaderRecordFalse() throws IOException {
+ // functionally identical to testHeader, used to test CSV-153
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3").withSkipHeaderRecord(false))) {
+ 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());
+ }
+ }
+
+ @Test
+ public void testSkipHeaderRecordTrue() throws IOException {
+ // functionally identical to testHeaderNotSet, used to test CSV-153
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withHeader("C1", "C2", "C3").withSkipHeaderRecord(true))) {
+ printer.printRecord("a", "b", "c");
+ printer.printRecord("x", "y", "z");
+ assertEquals("a,b,c\r\nx,y,z\r\n", sw.toString());
+ }
+ }
+
+ @Test
+ public void testTrailingDelimiterOnTwoColumns() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrailingDelimiter())) {
+ printer.printRecord("A", "B");
+ assertEquals("A,B,\r\n", sw.toString());
+ }
+ }
+
+ @Test
+ public void testTrimOffOneColumn() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim(false))) {
+ printer.print(" A ");
+ assertEquals("\" A \"", sw.toString());
+ }
+ }
+
+ @Test
+ public void testTrimOnOneColumn() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) {
+ printer.print(" A ");
+ assertEquals("A", sw.toString());
+ }
+ }
+
+ @Test
+ public void testTrimOnTwoColumns() throws IOException {
+ final StringWriter sw = new StringWriter();
+ try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) {
+ printer.print(" A ");
+ printer.print(" B ");
+ assertEquals("A,B", sw.toString());
+ }
+ }
+
+ private String[] toFirstRecordValues(final String expected, final CSVFormat format) throws IOException {
+ try (CSVParser parser = CSVParser.parse(expected, format)) {
+ return parser.getRecords().get(0).values();
+ }
+ }
+
+ private void tryFormat(final List list, final Character quote, final Character escape, final String expected) throws IOException {
+ final CSVFormat format = CSVFormat.DEFAULT.withQuote(quote).withEscape(escape).withRecordSeparator(null);
+ final Appendable out = new StringBuilder();
+ try (CSVPrinter printer = new CSVPrinter(out, format)) {
+ printer.printRecord(list);
+ }
+ assertEquals(expected, out.toString());
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/csv/PerformanceTest.java b/src/test/java/org/apache/commons/csv/PerformanceTest.java
index f692ae8e8d..bf0d483897 100644
--- a/src/test/java/org/apache/commons/csv/PerformanceTest.java
+++ b/src/test/java/org/apache/commons/csv/PerformanceTest.java
@@ -1,345 +1,345 @@
-/*
- * 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
- *
- * https://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.io.IOUtils.EOF;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.zip.GZIPInputStream;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-
-/**
- * Basic test harness.
- */
-@SuppressWarnings("boxing")
-public class PerformanceTest {
-
- @FunctionalInterface
- private interface CSVParserFactory {
- CSVParser createParser() throws IOException;
- }
-
- // Container for basic statistics
- private static final class Stats {
- final int count;
- final int fields;
-
- Stats(final int c, final int f) {
- count = c;
- fields = f;
- }
- }
-
- private static final String[] PROPERTY_NAMES = { "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 = 11; // skip first test
-
- private static int num; // number of elapsed times recorded
-
- private static final long[] ELAPSED_TIMES = new long[max];
- private static final CSVFormat format = CSVFormat.EXCEL;
-
- private static final String TEST_RESRC = "org/apache/commons/csv/perf/worldcitiespop.txt.gz";
-
- private static final File BIG_FILE = new File(FileUtils.getTempDirectoryPath(), "worldcitiespop.txt");
-
- private static Reader createReader() throws IOException {
- return new InputStreamReader(new FileInputStream(BIG_FILE), StandardCharsets.ISO_8859_1);
- }
-
- private static Lexer createTestCSVLexer(final String test, final ExtendedBufferedReader input)
- throws InstantiationException, IllegalAccessException, InvocationTargetException, Exception {
- return test.startsWith("CSVLexer") ? getLexerCtor(test).newInstance(format, input) : new Lexer(format, input);
- }
-
- 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(CSVFormat.class, ExtendedBufferedReader.class);
- }
-
- private static Stats iterate(final Iterable iterable) {
- int count = 0;
- int fields = 0;
- for (final CSVRecord record : iterable) {
- count++;
- fields += record.size();
- }
- return new Stats(count, fields);
- }
-
- public static void main(final String[] args) throws Exception {
- if (BIG_FILE.exists()) {
- System.out.printf("Found test fixture %s: %,d bytes.%n", BIG_FILE, BIG_FILE.length());
- } else {
- System.out.println("Decompressing test fixture to: " + BIG_FILE + "...");
- try (InputStream input = new GZIPInputStream(PerformanceTest.class.getClassLoader().getResourceAsStream(TEST_RESRC));
- 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()));
- }
- }
- final int argc = args.length;
- if (argc > 0) {
- max = Integer.parseInt(args[0]);
- }
-
- final String[] tests;
- if (argc > 1) {
- tests = new String[argc - 1];
- System.arraycopy(args, 1, tests, 0, argc - 1);
- } else {
- tests = new String[] { "file", "split", "extb", "exts", "csv", "csv-path", "csv-path-db", "csv-url", "lexreset", "lexnew" };
- }
- for (final String p : PROPERTY_NAMES) {
- System.out.printf("%s=%s%n", p, System.getProperty(p));
- }
- System.out.printf("Max count: %d%n%n", max);
-
- for (final String test : tests) {
- switch (test) {
- case "file":
- testReadBigFile(false);
- break;
- case "split":
- testReadBigFile(true);
- break;
- case "csv":
- testParseCommonsCSV();
- break;
- case "csv-path":
- testParsePath();
- break;
- case "csv-path-db":
- testParsePathDoubleBuffering();
- break;
- case "csv-url":
- testParseURL();
- break;
- case "lexreset":
- testCSVLexer(false, test);
- break;
- case "lexnew":
- testCSVLexer(true, test);
- break;
- default:
- if (test.startsWith("CSVLexer")) {
- testCSVLexer(false, test);
- } else if ("extb".equals(test)) {
- testExtendedBuffer(false);
- } else if ("exts".equals(test)) {
- testExtendedBuffer(true);
- } else {
- System.out.printf("Invalid test name: %s%n", test);
- }
- break;
- }
- }
- }
-
- 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);
- }
-
- // calculate and show average
- private static void show() {
- if (num > 1) {
- long tot = 0;
- for (int i = 1; i < num; i++) { // skip first test
- tot += ELAPSED_TIMES[i];
- }
- System.out.printf("%-20s: %5dms%n%n", "Average(not first)", tot / (num - 1));
- }
- num = 0; // ready for next set
- }
-
- // 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 %d lines %d fields%n", msg, elapsed, s.count, s.fields);
- ELAPSED_TIMES[num] = elapsed;
- num++;
- }
-
- 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 String simpleName;
- final Stats stats;
- final long startMillis;
- try (ExtendedBufferedReader input = new ExtendedBufferedReader(createReader());
- Lexer lexer = createTestCSVLexer(test, input)) {
- if (test.startsWith("CSVLexer")) {
- dynamic = "!";
- }
- simpleName = lexer.getClass().getSimpleName();
- int count = 0;
- int fields = 0;
- startMillis = 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));
- stats = new Stats(count, fields);
- }
- show(simpleName + dynamic + " " + (newToken ? "new" : "reset"), stats, startMillis);
- }
- show();
- }
-
- private static void testExtendedBuffer(final boolean makeString) throws Exception {
- for (int i = 0; i < max; i++) {
- int fields = 0;
- int lines = 0;
- final long startMillis;
- try (ExtendedBufferedReader in = new ExtendedBufferedReader(createReader())) {
- startMillis = System.currentTimeMillis();
- int read;
- if (makeString) {
- StringBuilder sb = new StringBuilder();
- while ((read = in.read()) != EOF) {
- 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()) != EOF) {
- if (read == ',') { // count delimiters
- fields++;
- } else if (read == '\n') {
- lines++;
- }
- }
- }
- fields += lines; // EOL is a delimiter too
- }
- show("Extended" + (makeString ? " toString" : ""), new Stats(lines, fields), startMillis);
- }
- show();
- }
-
- private static void testParseCommonsCSV() throws Exception {
- testParser("CSV", () -> CSVParser.builder().setReader(createReader()).setFormat(format).get());
- }
-
- private static void testParsePath() throws Exception {
- testParser("CSV-PATH", () -> CSVParser.parse(Files.newInputStream(Paths.get(BIG_FILE.toURI())), StandardCharsets.ISO_8859_1, format));
- }
-
- private static void testParsePathDoubleBuffering() throws Exception {
- testParser("CSV-PATH-DB", () -> CSVParser.parse(Files.newBufferedReader(Paths.get(BIG_FILE.toURI()), StandardCharsets.ISO_8859_1), format));
- }
-
- private static void testParser(final String msg, final CSVParserFactory fac) throws Exception {
- for (int i = 0; i < max; i++) {
- final long startMillis;
- final Stats stats;
- try (CSVParser parser = fac.createParser()) {
- startMillis = System.currentTimeMillis();
- stats = iterate(parser);
- }
- show(msg, stats, startMillis);
- }
- show();
- }
-
- private static void testParseURL() throws Exception {
- testParser("CSV-URL", () -> CSVParser.parse(BIG_FILE.toURI().toURL(), StandardCharsets.ISO_8859_1, format));
- }
-
- private static void testReadBigFile(final boolean split) throws Exception {
- for (int i = 0; i < max; i++) {
- final long startMillis;
- final Stats stats;
- try (BufferedReader in = new BufferedReader(createReader())) {
- startMillis = System.currentTimeMillis();
- stats = readAll(in, split);
- }
- show(split ? "file+split" : "file", stats, startMillis);
- }
- show();
- }
-}
-
+/*
+ * 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
+ *
+ * https://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.io.IOUtils.EOF;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+
+/**
+ * Basic test harness.
+ */
+@SuppressWarnings("boxing")
+public class PerformanceTest {
+
+ @FunctionalInterface
+ private interface CSVParserFactory {
+ CSVParser createParser() throws IOException;
+ }
+
+ // Container for basic statistics
+ private static final class Stats {
+ final int count;
+ final int fields;
+
+ Stats(final int c, final int f) {
+ count = c;
+ fields = f;
+ }
+ }
+
+ private static final String[] PROPERTY_NAMES = { "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 = 11; // skip first test
+
+ private static int num; // number of elapsed times recorded
+
+ private static final long[] ELAPSED_TIMES = new long[max];
+ private static final CSVFormat format = CSVFormat.EXCEL;
+
+ private static final String TEST_RESRC = "org/apache/commons/csv/perf/worldcitiespop.txt.gz";
+
+ private static final File BIG_FILE = new File(FileUtils.getTempDirectoryPath(), "worldcitiespop.txt");
+
+ private static Reader createReader() throws IOException {
+ return new InputStreamReader(new FileInputStream(BIG_FILE), StandardCharsets.ISO_8859_1);
+ }
+
+ private static Lexer createTestCSVLexer(final String test, final ExtendedBufferedReader input)
+ throws InstantiationException, IllegalAccessException, InvocationTargetException, Exception {
+ return test.startsWith("CSVLexer") ? getLexerCtor(test).newInstance(format, input) : new Lexer(format, input);
+ }
+
+ 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(CSVFormat.class, ExtendedBufferedReader.class);
+ }
+
+ private static Stats iterate(final Iterable iterable) {
+ int count = 0;
+ int fields = 0;
+ for (final CSVRecord record : iterable) {
+ count++;
+ fields += record.size();
+ }
+ return new Stats(count, fields);
+ }
+
+ public static void main(final String[] args) throws Exception {
+ if (BIG_FILE.exists()) {
+ System.out.printf("Found test fixture %s: %,d bytes.%n", BIG_FILE, BIG_FILE.length());
+ } else {
+ System.out.println("Decompressing test fixture to: " + BIG_FILE + "...");
+ try (InputStream input = new GZIPInputStream(PerformanceTest.class.getClassLoader().getResourceAsStream(TEST_RESRC));
+ 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()));
+ }
+ }
+ final int argc = args.length;
+ if (argc > 0) {
+ max = Integer.parseInt(args[0]);
+ }
+
+ final String[] tests;
+ if (argc > 1) {
+ tests = new String[argc - 1];
+ System.arraycopy(args, 1, tests, 0, argc - 1);
+ } else {
+ tests = new String[] { "file", "split", "extb", "exts", "csv", "csv-path", "csv-path-db", "csv-url", "lexreset", "lexnew" };
+ }
+ for (final String p : PROPERTY_NAMES) {
+ System.out.printf("%s=%s%n", p, System.getProperty(p));
+ }
+ System.out.printf("Max count: %d%n%n", max);
+
+ for (final String test : tests) {
+ switch (test) {
+ case "file":
+ testReadBigFile(false);
+ break;
+ case "split":
+ testReadBigFile(true);
+ break;
+ case "csv":
+ testParseCommonsCSV();
+ break;
+ case "csv-path":
+ testParsePath();
+ break;
+ case "csv-path-db":
+ testParsePathDoubleBuffering();
+ break;
+ case "csv-url":
+ testParseURL();
+ break;
+ case "lexreset":
+ testCSVLexer(false, test);
+ break;
+ case "lexnew":
+ testCSVLexer(true, test);
+ break;
+ default:
+ if (test.startsWith("CSVLexer")) {
+ testCSVLexer(false, test);
+ } else if ("extb".equals(test)) {
+ testExtendedBuffer(false);
+ } else if ("exts".equals(test)) {
+ testExtendedBuffer(true);
+ } else {
+ System.out.printf("Invalid test name: %s%n", test);
+ }
+ break;
+ }
+ }
+ }
+
+ 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);
+ }
+
+ // calculate and show average
+ private static void show() {
+ if (num > 1) {
+ long tot = 0;
+ for (int i = 1; i < num; i++) { // skip first test
+ tot += ELAPSED_TIMES[i];
+ }
+ System.out.printf("%-20s: %5dms%n%n", "Average(not first)", tot / (num - 1));
+ }
+ num = 0; // ready for next set
+ }
+
+ // 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 %d lines %d fields%n", msg, elapsed, s.count, s.fields);
+ ELAPSED_TIMES[num] = elapsed;
+ num++;
+ }
+
+ 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 String simpleName;
+ final Stats stats;
+ final long startMillis;
+ try (ExtendedBufferedReader input = new ExtendedBufferedReader(createReader());
+ Lexer lexer = createTestCSVLexer(test, input)) {
+ if (test.startsWith("CSVLexer")) {
+ dynamic = "!";
+ }
+ simpleName = lexer.getClass().getSimpleName();
+ int count = 0;
+ int fields = 0;
+ startMillis = 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));
+ stats = new Stats(count, fields);
+ }
+ show(simpleName + dynamic + " " + (newToken ? "new" : "reset"), stats, startMillis);
+ }
+ show();
+ }
+
+ private static void testExtendedBuffer(final boolean makeString) throws Exception {
+ for (int i = 0; i < max; i++) {
+ int fields = 0;
+ int lines = 0;
+ final long startMillis;
+ try (ExtendedBufferedReader in = new ExtendedBufferedReader(createReader())) {
+ startMillis = System.currentTimeMillis();
+ int read;
+ if (makeString) {
+ StringBuilder sb = new StringBuilder();
+ while ((read = in.read()) != EOF) {
+ 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()) != EOF) {
+ if (read == ',') { // count delimiters
+ fields++;
+ } else if (read == '\n') {
+ lines++;
+ }
+ }
+ }
+ fields += lines; // EOL is a delimiter too
+ }
+ show("Extended" + (makeString ? " toString" : ""), new Stats(lines, fields), startMillis);
+ }
+ show();
+ }
+
+ private static void testParseCommonsCSV() throws Exception {
+ testParser("CSV", () -> CSVParser.builder().setReader(createReader()).setFormat(format).get());
+ }
+
+ private static void testParsePath() throws Exception {
+ testParser("CSV-PATH", () -> CSVParser.parse(Files.newInputStream(Paths.get(BIG_FILE.toURI())), StandardCharsets.ISO_8859_1, format));
+ }
+
+ private static void testParsePathDoubleBuffering() throws Exception {
+ testParser("CSV-PATH-DB", () -> CSVParser.parse(Files.newBufferedReader(Paths.get(BIG_FILE.toURI()), StandardCharsets.ISO_8859_1), format));
+ }
+
+ private static void testParser(final String msg, final CSVParserFactory fac) throws Exception {
+ for (int i = 0; i < max; i++) {
+ final long startMillis;
+ final Stats stats;
+ try (CSVParser parser = fac.createParser()) {
+ startMillis = System.currentTimeMillis();
+ stats = iterate(parser);
+ }
+ show(msg, stats, startMillis);
+ }
+ show();
+ }
+
+ private static void testParseURL() throws Exception {
+ testParser("CSV-URL", () -> CSVParser.parse(BIG_FILE.toURI().toURL(), StandardCharsets.ISO_8859_1, format));
+ }
+
+ private static void testReadBigFile(final boolean split) throws Exception {
+ for (int i = 0; i < max; i++) {
+ final long startMillis;
+ final Stats stats;
+ try (BufferedReader in = new BufferedReader(createReader())) {
+ startMillis = System.currentTimeMillis();
+ stats = readAll(in, split);
+ }
+ show(split ? "file+split" : "file", stats, startMillis);
+ }
+ show();
+ }
+}
+
diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java
index cee88f15e0..641797fe88 100644
--- a/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java
+++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java
@@ -1,54 +1,54 @@
-/*
- * 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
- *
- * https://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.issues;
-
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.StandardCharsets;
-
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.junit.jupiter.api.Test;
-
-public class JiraCsv198Test {
-
- // @formatter:off
- private static final CSVFormat CSV_FORMAT = CSVFormat.EXCEL.builder()
- .setDelimiter('^')
- .setHeader()
- .setSkipHeaderRecord(true)
- .get();
- // @formatter:on
-
- @Test
- public void test() throws UnsupportedEncodingException, IOException {
- final InputStream pointsOfReference = getClass().getResourceAsStream("/org/apache/commons/csv/CSV-198/optd_por_public.csv");
- assertNotNull(pointsOfReference);
- try (@SuppressWarnings("resource")
- CSVParser parser = CSV_FORMAT.parse(new InputStreamReader(pointsOfReference, StandardCharsets.UTF_8))) {
- parser.forEach(record -> assertNotNull(record.get("location_type")));
- }
- }
-
-}
+/*
+ * 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
+ *
+ * https://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.issues;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVParser;
+import org.junit.jupiter.api.Test;
+
+public class JiraCsv198Test {
+
+ // @formatter:off
+ private static final CSVFormat CSV_FORMAT = CSVFormat.EXCEL.builder()
+ .setDelimiter('^')
+ .setHeader()
+ .setSkipHeaderRecord(true)
+ .get();
+ // @formatter:on
+
+ @Test
+ public void test() throws UnsupportedEncodingException, IOException {
+ final InputStream pointsOfReference = getClass().getResourceAsStream("/org/apache/commons/csv/CSV-198/optd_por_public.csv");
+ assertNotNull(pointsOfReference);
+ try (@SuppressWarnings("resource")
+ CSVParser parser = CSV_FORMAT.parse(new InputStreamReader(pointsOfReference, StandardCharsets.UTF_8))) {
+ parser.forEach(record -> assertNotNull(record.get("location_type")));
+ }
+ }
+
+}
diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java
index 9da17465cb..a4e3960c96 100644
--- a/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java
+++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java
@@ -1,54 +1,54 @@
-/*
- * 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
- *
- * https://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.issues;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.junit.jupiter.api.Test;
-
-public class JiraCsv211Test {
-
- @Test
- public void testJiraCsv211Format() throws IOException {
- // @formatter:off
- final CSVFormat printFormat = CSVFormat.DEFAULT.builder()
- .setDelimiter('\t')
- .setHeader("ID", "Name", "Country", "Age")
- .get();
- // @formatter:on
- final String formatted = printFormat.format("1", "Jane Doe", "USA", "");
- assertEquals("ID\tName\tCountry\tAge\r\n1\tJane Doe\tUSA\t", formatted);
-
- final CSVFormat parseFormat = CSVFormat.DEFAULT.builder().setDelimiter('\t').setHeader().setSkipHeaderRecord(true).get();
- try (CSVParser parser = parseFormat.parse(new StringReader(formatted))) {
- parser.forEach(record -> {
- assertEquals("1", record.get(0));
- assertEquals("Jane Doe", record.get(1));
- assertEquals("USA", record.get(2));
- assertEquals("", record.get(3));
- });
- }
- }
-}
+/*
+ * 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
+ *
+ * https://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.issues;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVParser;
+import org.junit.jupiter.api.Test;
+
+public class JiraCsv211Test {
+
+ @Test
+ public void testJiraCsv211Format() throws IOException {
+ // @formatter:off
+ final CSVFormat printFormat = CSVFormat.DEFAULT.builder()
+ .setDelimiter('\t')
+ .setHeader("ID", "Name", "Country", "Age")
+ .get();
+ // @formatter:on
+ final String formatted = printFormat.format("1", "Jane Doe", "USA", "");
+ assertEquals("ID\tName\tCountry\tAge\r\n1\tJane Doe\tUSA\t", formatted);
+
+ final CSVFormat parseFormat = CSVFormat.DEFAULT.builder().setDelimiter('\t').setHeader().setSkipHeaderRecord(true).get();
+ try (CSVParser parser = parseFormat.parse(new StringReader(formatted))) {
+ parser.forEach(record -> {
+ assertEquals("1", record.get(0));
+ assertEquals("Jane Doe", record.get(1));
+ assertEquals("USA", record.get(2));
+ assertEquals("", record.get(3));
+ });
+ }
+ }
+}
diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java
index 4e614816a1..0be6a52f81 100644
--- a/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java
+++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java
@@ -1,216 +1,216 @@
-/*
- * 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
- *
- * https://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.issues;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
-
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.apache.commons.csv.CSVPrinter;
-import org.apache.commons.csv.CSVRecord;
-import org.junit.jupiter.api.Test;
-
-public class JiraCsv288Test {
-
- private void print(final CSVRecord csvRecord, final CSVPrinter csvPrinter) throws IOException {
- for (final String value : csvRecord) {
- csvPrinter.print(value);
- }
- }
-
- @Test
- // Before fix:
- // expected: but was:
- public void testParseWithABADelimiter() throws Exception {
- final Reader in = new StringReader("a|~|b|~|c|~|d|~||~|f");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser parser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("|~|").get())) {
- for (final CSVRecord csvRecord : parser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Before fix:
- // expected: but was:
- public void testParseWithDoublePipeDelimiter() throws Exception {
- final Reader in = new StringReader("a||b||c||d||||f");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Regression, already passed before fix
-
- public void testParseWithDoublePipeDelimiterDoubleCharValue() throws Exception {
- final Reader in = new StringReader("a||bb||cc||dd||f");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,bb,cc,dd,f", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Before fix:
- // expected: but was:
- public void testParseWithDoublePipeDelimiterEndsWithDelimiter() throws Exception {
- final Reader in = new StringReader("a||b||c||d||||f||");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f,", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Before fix:
- // expected: but was:
- public void testParseWithDoublePipeDelimiterQuoted() throws Exception {
- final Reader in = new StringReader("a||\"b||c\"||d||||f");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b||c,d,,f", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Regression, already passed before fix
- public void testParseWithSinglePipeDelimiterEndsWithDelimiter() throws Exception {
- final Reader in = new StringReader("a|b|c|d||f|");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("|").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f,", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Before fix:
- // expected: but was:
- public void testParseWithTriplePipeDelimiter() throws Exception {
- final Reader in = new StringReader("a|||b|||c|||d||||||f");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("|||").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Regression, already passed before fix
- public void testParseWithTwoCharDelimiter1() throws Exception {
- final Reader in = new StringReader("a~|b~|c~|d~|~|f");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Regression, already passed before fix
- public void testParseWithTwoCharDelimiter2() throws Exception {
- final Reader in = new StringReader("a~|b~|c~|d~|~|f~");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f~", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Regression, already passed before fix
- public void testParseWithTwoCharDelimiter3() throws Exception {
- final Reader in = new StringReader("a~|b~|c~|d~|~|f|");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f|", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Regression, already passed before fix
- public void testParseWithTwoCharDelimiter4() throws Exception {
- final Reader in = new StringReader("a~|b~|c~|d~|~|f~~||g");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f~,|g", stringBuilder.toString());
- }
- }
- }
-
- @Test
- // Before fix:
- // expected: but was:
- public void testParseWithTwoCharDelimiterEndsWithDelimiter() throws Exception {
- final Reader in = new StringReader("a~|b~|c~|d~|~|f~|");
- final StringBuilder stringBuilder = new StringBuilder();
- try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
- CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
- for (final CSVRecord csvRecord : csvParser) {
- print(csvRecord, csvPrinter);
- assertEquals("a,b,c,d,,f,", stringBuilder.toString());
- }
- }
- }
-}
+/*
+ * 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
+ *
+ * https://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.issues;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.apache.commons.csv.CSVFormat;
+import org.apache.commons.csv.CSVParser;
+import org.apache.commons.csv.CSVPrinter;
+import org.apache.commons.csv.CSVRecord;
+import org.junit.jupiter.api.Test;
+
+public class JiraCsv288Test {
+
+ private void print(final CSVRecord csvRecord, final CSVPrinter csvPrinter) throws IOException {
+ for (final String value : csvRecord) {
+ csvPrinter.print(value);
+ }
+ }
+
+ @Test
+ // Before fix:
+ // expected: but was:
+ public void testParseWithABADelimiter() throws Exception {
+ final Reader in = new StringReader("a|~|b|~|c|~|d|~||~|f");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser parser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("|~|").get())) {
+ for (final CSVRecord csvRecord : parser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Before fix:
+ // expected: but was:
+ public void testParseWithDoublePipeDelimiter() throws Exception {
+ final Reader in = new StringReader("a||b||c||d||||f");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Regression, already passed before fix
+
+ public void testParseWithDoublePipeDelimiterDoubleCharValue() throws Exception {
+ final Reader in = new StringReader("a||bb||cc||dd||f");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,bb,cc,dd,f", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Before fix:
+ // expected: but was:
+ public void testParseWithDoublePipeDelimiterEndsWithDelimiter() throws Exception {
+ final Reader in = new StringReader("a||b||c||d||||f||");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f,", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Before fix:
+ // expected: but was:
+ public void testParseWithDoublePipeDelimiterQuoted() throws Exception {
+ final Reader in = new StringReader("a||\"b||c\"||d||||f");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("||").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b||c,d,,f", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Regression, already passed before fix
+ public void testParseWithSinglePipeDelimiterEndsWithDelimiter() throws Exception {
+ final Reader in = new StringReader("a|b|c|d||f|");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("|").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f,", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Before fix:
+ // expected: but was:
+ public void testParseWithTriplePipeDelimiter() throws Exception {
+ final Reader in = new StringReader("a|||b|||c|||d||||||f");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("|||").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Regression, already passed before fix
+ public void testParseWithTwoCharDelimiter1() throws Exception {
+ final Reader in = new StringReader("a~|b~|c~|d~|~|f");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Regression, already passed before fix
+ public void testParseWithTwoCharDelimiter2() throws Exception {
+ final Reader in = new StringReader("a~|b~|c~|d~|~|f~");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f~", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Regression, already passed before fix
+ public void testParseWithTwoCharDelimiter3() throws Exception {
+ final Reader in = new StringReader("a~|b~|c~|d~|~|f|");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f|", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Regression, already passed before fix
+ public void testParseWithTwoCharDelimiter4() throws Exception {
+ final Reader in = new StringReader("a~|b~|c~|d~|~|f~~||g");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f~,|g", stringBuilder.toString());
+ }
+ }
+ }
+
+ @Test
+ // Before fix:
+ // expected: but was:
+ public void testParseWithTwoCharDelimiterEndsWithDelimiter() throws Exception {
+ final Reader in = new StringReader("a~|b~|c~|d~|~|f~|");
+ final StringBuilder stringBuilder = new StringBuilder();
+ try (CSVPrinter csvPrinter = new CSVPrinter(stringBuilder, CSVFormat.EXCEL);
+ CSVParser csvParser = CSVParser.parse(in, CSVFormat.Builder.create().setDelimiter("~|").get())) {
+ for (final CSVRecord csvRecord : csvParser) {
+ print(csvRecord, csvPrinter);
+ assertEquals("a,b,c,d,,f,", stringBuilder.toString());
+ }
+ }
+ }
+}