From 38ada7d7143940114bca939c760eae271000f9b5 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 20 May 2025 08:13:29 -0400 Subject: [PATCH 001/245] Bump org.apache.commons:commons-parent from 83 to 84 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index df1462775..8fb451f41 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 83 + 84 commons-csv 1.14.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3cb97f78c..4d23e65d2 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ Bump commons-io:commons-io from 2.18.0 to 2.19.0. - Bump org.apache.commons:commons-parent from 81 to 83 #542. + Bump org.apache.commons:commons-parent from 81 to 84 #542. Bump com.opencsv:opencsv from 5.10 to 5.11 #545. From 3cbc2913701f4612d7c30ddf4fd736acda6711ad Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 20 May 2025 16:35:38 -0400 Subject: [PATCH 002/245] Update Apache License URL to HTTPS See https://www.apache.org/legal/src-headers.html --- .asf.yaml | 2 +- .gitattributes | 2 +- .github/GH-ROBOTS.txt | 2 +- .github/dependabot.yml | 2 +- .github/pull_request_template.md | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- .github/workflows/scorecards-analysis.yml | 2 +- BENCHMARK.md | 2 +- CODE_OF_CONDUCT.md | 2 +- LICENSE.txt | 2 +- SECURITY.md | 2 +- benchmark-prereq.sh | 2 +- pom.xml | 2 +- src/assembly/bin.xml | 2 +- src/assembly/src.xml | 2 +- src/changes/changes.xml | 2 +- src/changes/release-notes.vm | 2 +- src/conf/checkstyle/checkstyle-suppressions.xml | 2 +- src/conf/checkstyle/checkstyle.xml | 2 +- src/site/resources/pmd/pmd-ruleset.xml | 2 +- src/site/resources/spotbugs/spotbugs-exclude-filter.xml | 2 +- src/site/site.xml | 2 +- src/site/xdoc/index.xml | 2 +- src/site/xdoc/user-guide.xml | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index c56b33138..a2dc85766 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -5,7 +5,7 @@ # (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 +# 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, diff --git a/.gitattributes b/.gitattributes index bec231c19..f42866e4b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,7 +5,7 @@ # (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 +# 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, diff --git a/.github/GH-ROBOTS.txt b/.github/GH-ROBOTS.txt index e3329e55f..64a88674f 100644 --- a/.github/GH-ROBOTS.txt +++ b/.github/GH-ROBOTS.txt @@ -5,7 +5,7 @@ # (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 +# 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, diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9ebcd0ebb..00079caf1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ # (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 +# 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, diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d126a970c..e17973cb0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,7 +7,7 @@ "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 + 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 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 84d9df4ce..e7c680d2f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,7 +5,7 @@ # (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 +# 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, diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 9d226a458..33573cf94 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -6,7 +6,7 @@ # "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 +# 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 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 02b3996bd..4b4bf2e01 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -5,7 +5,7 @@ # (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 +# 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, diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 802675206..8f044bb21 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -5,7 +5,7 @@ # (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 +# 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, diff --git a/BENCHMARK.md b/BENCHMARK.md index e8b579b2e..c45918a28 100644 --- a/BENCHMARK.md +++ b/BENCHMARK.md @@ -6,7 +6,7 @@ (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 + 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, diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 3ed501501..b4342f33c 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -6,7 +6,7 @@ (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 + 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, diff --git a/LICENSE.txt b/LICENSE.txt index d64569567..ff9ad4530 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -193,7 +193,7 @@ 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 + 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, diff --git a/SECURITY.md b/SECURITY.md index 51943ba7b..744d4cddb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,7 @@ (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 + 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, diff --git a/benchmark-prereq.sh b/benchmark-prereq.sh index 1d03f6773..bd1db9182 100755 --- a/benchmark-prereq.sh +++ b/benchmark-prereq.sh @@ -8,7 +8,7 @@ # "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 +# 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, diff --git a/pom.xml b/pom.xml index 8fb451f41..5ac78ed95 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ (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 + 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, diff --git a/src/assembly/bin.xml b/src/assembly/bin.xml index f73d62f6d..3526ca9e9 100644 --- a/src/assembly/bin.xml +++ b/src/assembly/bin.xml @@ -6,7 +6,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more (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 + 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, diff --git a/src/assembly/src.xml b/src/assembly/src.xml index 9f33f58f2..1330db01f 100644 --- a/src/assembly/src.xml +++ b/src/assembly/src.xml @@ -6,7 +6,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more (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 + 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, diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4d23e65d2..d9b0fd2a3 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -7,7 +7,7 @@ (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 + 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, diff --git a/src/changes/release-notes.vm b/src/changes/release-notes.vm index 5f5501269..576982955 100644 --- a/src/changes/release-notes.vm +++ b/src/changes/release-notes.vm @@ -6,7 +6,7 @@ ## "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 +## 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 diff --git a/src/conf/checkstyle/checkstyle-suppressions.xml b/src/conf/checkstyle/checkstyle-suppressions.xml index e1a4807cc..f1eab03c4 100644 --- a/src/conf/checkstyle/checkstyle-suppressions.xml +++ b/src/conf/checkstyle/checkstyle-suppressions.xml @@ -7,7 +7,7 @@ (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 + 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, diff --git a/src/conf/checkstyle/checkstyle.xml b/src/conf/checkstyle/checkstyle.xml index 1010cb262..4e8691243 100644 --- a/src/conf/checkstyle/checkstyle.xml +++ b/src/conf/checkstyle/checkstyle.xml @@ -7,7 +7,7 @@ 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 + 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, diff --git a/src/site/resources/pmd/pmd-ruleset.xml b/src/site/resources/pmd/pmd-ruleset.xml index 5acc76402..a7ccc9216 100644 --- a/src/site/resources/pmd/pmd-ruleset.xml +++ b/src/site/resources/pmd/pmd-ruleset.xml @@ -7,7 +7,7 @@ (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 + 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, diff --git a/src/site/resources/spotbugs/spotbugs-exclude-filter.xml b/src/site/resources/spotbugs/spotbugs-exclude-filter.xml index a7364d40d..a58e09e24 100644 --- a/src/site/resources/spotbugs/spotbugs-exclude-filter.xml +++ b/src/site/resources/spotbugs/spotbugs-exclude-filter.xml @@ -6,7 +6,7 @@ (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 + 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, diff --git a/src/site/site.xml b/src/site/site.xml index 86c1afa1e..232c2056c 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -7,7 +7,7 @@ (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 + 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, diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index 491a384b4..a133db619 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -7,7 +7,7 @@ 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 + 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, diff --git a/src/site/xdoc/user-guide.xml b/src/site/xdoc/user-guide.xml index 64d9a4039..d5a1f2685 100644 --- a/src/site/xdoc/user-guide.xml +++ b/src/site/xdoc/user-guide.xml @@ -7,7 +7,7 @@ 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 + 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, From 9e9e26557355e4977712e3144b677131521cdf12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:16:37 +0000 Subject: [PATCH 003/245] Bump ossf/scorecard-action from 2.4.1 to 2.4.2 Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.1 to 2.4.2. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/f49aabe0b5af0936a0987cfb85d86b75731b0186...05b42c624433fc40578a4040d5cf5e36ddca8cde) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 8f044bb21..3edd29d96 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -45,7 +45,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # 2.4.1 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # 2.4.2 with: results_file: results.sarif results_format: sarif From 28ab1635bedaf55b1743ef8f4577c840cd4009fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:16:47 +0000 Subject: [PATCH 004/245] Bump github/codeql-action from 3.28.18 to 3.28.19 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.18 to 3.28.19. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ff0a06e83cb2de871e5a09832bc6a81e7276941f...fca7ace96b7d713c7035871441bd52efbe39e27e) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.28.19 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e7c680d2f..3f2fc9e55 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # 3.28.18 + uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@ff0a06e83cb2de871e5a09832bc6a81e7276941f # 3.28.18 + uses: github/codeql-action/autobuild@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # 3.28.18 + uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 8f044bb21..411032144 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # 3.28.18 + uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 with: sarif_file: results.sarif From f364373e4bf52b831420aea5f2131d40ee04e497 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:33:25 +0000 Subject: [PATCH 005/245] Bump com.opencsv:opencsv from 5.11 to 5.11.1 Bumps com.opencsv:opencsv from 5.11 to 5.11.1. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-version: 5.11.1 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5ac78ed95..ec93a5b3b 100644 --- a/pom.xml +++ b/pom.xml @@ -386,7 +386,7 @@ com.opencsv opencsv - 5.11 + 5.11.1 test From 2bb942380769d525d588efea88b2407e2db7a021 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:03:18 -0400 Subject: [PATCH 006/245] Bump com.opencsv:opencsv from 5.11 to 5.11.1 #551 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index d9b0fd2a3..c86f459da 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,7 @@ Bump commons-io:commons-io from 2.18.0 to 2.19.0. Bump org.apache.commons:commons-parent from 81 to 84 #542. - Bump com.opencsv:opencsv from 5.10 to 5.11 #545. + Bump com.opencsv:opencsv from 5.10 to 5.11.1 #545, #551. From e5c8f49d3cd60c6147a87df69a2e7ed1f6162bc2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:12:52 -0400 Subject: [PATCH 007/245] Inline single use local variable --- src/main/java/org/apache/commons/csv/CSVParser.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 33ae78567..4d74bc96f 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -886,7 +886,7 @@ CSVRecord nextRecord() throws IOException { recordList.clear(); StringBuilder sb = null; final long startCharPosition = lexer.getCharacterPosition() + characterOffset; - final long startBytePosition = lexer.getBytesRead() + this.characterOffset; + final long startBytePosition = lexer.getBytesRead() + characterOffset; do { reusableToken.reset(); lexer.nextToken(reusableToken); @@ -919,12 +919,10 @@ CSVRecord nextRecord() throws IOException { throw new CSVException("Unexpected Token type: %s", reusableToken.type); } } while (reusableToken.type == TOKEN); - if (!recordList.isEmpty()) { recordNumber++; - final String comment = Objects.toString(sb, null); - result = new CSVRecord(this, recordList.toArray(Constants.EMPTY_STRING_ARRAY), comment, - recordNumber, startCharPosition, startBytePosition); + result = new CSVRecord(this, recordList.toArray(Constants.EMPTY_STRING_ARRAY), Objects.toString(sb, null), recordNumber, startCharPosition, + startBytePosition); } return result; } From 1054469e9959d2fc8b3ac6db0167871e13d5d686 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:15:16 -0400 Subject: [PATCH 008/245] Javadoc --- src/main/java/org/apache/commons/csv/CSVRecord.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVRecord.java b/src/main/java/org/apache/commons/csv/CSVRecord.java index c04725af7..4fcd6362c 100644 --- a/src/main/java/org/apache/commons/csv/CSVRecord.java +++ b/src/main/java/org/apache/commons/csv/CSVRecord.java @@ -359,9 +359,9 @@ public String toString() { } /** - * Gets the values for this record. This is not a copy. + * Gets the values for this record. This is not a copy. * - * @return the values for this record. + * @return the values for this record, never null. * @since 1.10.0 */ public String[] values() { From f64cbff689c93b0edba6670b639c7e354b555edb Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:17:53 -0400 Subject: [PATCH 009/245] Javadoc --- .../org/apache/commons/csv/CSVRecord.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVRecord.java b/src/main/java/org/apache/commons/csv/CSVRecord.java index 4fcd6362c..148c76ca8 100644 --- a/src/main/java/org/apache/commons/csv/CSVRecord.java +++ b/src/main/java/org/apache/commons/csv/CSVRecord.java @@ -55,13 +55,13 @@ public final class CSVRecord implements Serializable, Iterable { */ private final long bytePosition; - /** The accumulated comments (if any) */ + /** The accumulated comments (if any). */ private final String comment; /** The record number. */ private final long recordNumber; - /** The values of the record */ + /** The values of the record. */ private final String[] values; /** The parser that originates this record. This is not serialized. */ @@ -114,9 +114,9 @@ public String get(final int i) { * the name of the column to be retrieved. * @return the column value, maybe null depending on {@link CSVFormat#getNullString()}. * @throws IllegalStateException - * if no header mapping was provided + * if no header mapping was provided. * @throws IllegalArgumentException - * if {@code name} is not mapped or if the record is inconsistent + * if {@code name} is not mapped or if the record is inconsistent. * @see #isMapped(String) * @see #isConsistent() * @see #getParser() @@ -214,7 +214,7 @@ public long getRecordNumber() { * If there is no following record (that is, the comment is at EOF), * then the comment will be ignored. * - * @return true if this record has a comment, false otherwise + * @return true if this record has a comment, false otherwise. * @since 1.3 */ public boolean hasComment() { @@ -229,7 +229,7 @@ public boolean hasComment() { * test but still produce parsable files. *

* - * @return true of this record is valid, false if not + * @return true of this record is valid, false if not. */ public boolean isConsistent() { final Map headerMap = getHeaderMapRaw(); @@ -252,8 +252,8 @@ public boolean isMapped(final String name) { * Checks whether a column with a given index has a value. * * @param index - * a column index (0-based) - * @return whether a column with a given index has a value + * a column index (0-based). + * @return whether a column with a given index has a value. */ public boolean isSet(final int index) { return 0 <= index && index < values.length; @@ -264,7 +264,7 @@ public boolean isSet(final int index) { * * @param name * the name of the column to be retrieved. - * @return whether a given column is mapped and has a value + * @return whether a given column is mapped and has a value. */ public boolean isSet(final String name) { return isMapped(name) && getHeaderMapRaw().get(name).intValue() < values.length; // Explicit (un)boxing is intentional @@ -283,7 +283,7 @@ public Iterator iterator() { /** * Puts all values of this record into the given Map. * - * @param the map type + * @param the map type. * @param map The Map to populate. * @return the given map. * @since 1.9.0 From 7a264a24fc6ee4b3f717d0e799b893b7f7f30fbd Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:22:34 -0400 Subject: [PATCH 010/245] Use final Format --- .../apache/commons/csv/JiraCsv196Test.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java index cff3a7729..3b6c74011 100644 --- a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java +++ b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ + package org.apache.commons.csv; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -36,11 +37,16 @@ private Reader getTestInput(final String path) { @Test public void testParseFourBytes() throws IOException { final CSVFormat format = CSVFormat.Builder.create().setDelimiter(',').setQuote('\'').get(); - try (CSVParser parser = new CSVParser.Builder().setFormat(format).setReader(getTestInput("org/apache/commons/csv/CSV-196/emoji.csv")) - .setCharset(StandardCharsets.UTF_8).setTrackBytes(true).get()) { + // @formatter:off + try (CSVParser parser = new CSVParser.Builder() + .setFormat(format) + .setReader(getTestInput("org/apache/commons/csv/CSV-196/emoji.csv")) + .setCharset(StandardCharsets.UTF_8) + .setTrackBytes(true).get()) { + // @formatter:on final long[] charByteKey = { 0, 84, 701, 1318, 1935 }; int idx = 0; - for (CSVRecord record : parser) { + for (final CSVRecord record : parser) { assertEquals(charByteKey[idx++], record.getBytePosition(), "index " + idx); } } @@ -49,11 +55,16 @@ public void testParseFourBytes() throws IOException { @Test public void testParseThreeBytes() throws IOException { final CSVFormat format = CSVFormat.Builder.create().setDelimiter(',').setQuote('\'').get(); - try (CSVParser parser = new CSVParser.Builder().setFormat(format).setReader(getTestInput("org/apache/commons/csv/CSV-196/japanese.csv")) - .setCharset(StandardCharsets.UTF_8).setTrackBytes(true).get()) { + // @formatter:off + try (CSVParser parser = new CSVParser.Builder() + .setFormat(format) + .setReader(getTestInput("org/apache/commons/csv/CSV-196/japanese.csv")) + .setCharset(StandardCharsets.UTF_8) + .setTrackBytes(true).get()) { + // @formatter:on final long[] charByteKey = { 0, 89, 242, 395 }; int idx = 0; - for (CSVRecord record : parser) { + for (final CSVRecord record : parser) { assertEquals(charByteKey[idx++], record.getBytePosition(), "index " + idx); } } From 0cf4f113265a30feeaad98bb98ee6abc5181ee97 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:22:58 -0400 Subject: [PATCH 011/245] Sort members --- .../org/apache/commons/csv/CSVPrinter.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVPrinter.java b/src/main/java/org/apache/commons/csv/CSVPrinter.java index 68d8d40ef..59948557e 100644 --- a/src/main/java/org/apache/commons/csv/CSVPrinter.java +++ b/src/main/java/org/apache/commons/csv/CSVPrinter.java @@ -208,19 +208,6 @@ public void print(final Object value) throws IOException { } } - /** - * 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 - */ - private void printRaw(final Object value) throws IOException { - format.print(value, appendable, newRecord); - newRecord = false; - } - /** * Prints a comment on a new line among the delimiter-separated values. * @@ -313,6 +300,19 @@ public void println() throws IOException { } } + /** + * 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 + */ + private void printRaw(final Object value) throws IOException { + format.print(value, appendable, newRecord); + newRecord = false; + } + /** * Prints the given values as a single record of delimiter-separated values followed by the record separator. * From 8c75343539f42812acca7e21b9b4d55180d1b8c7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:24:03 -0400 Subject: [PATCH 012/245] No need to nest elses --- .../java/org/apache/commons/csv/ExtendedBufferedReader.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java index 8c0a034a2..75748d812 100644 --- a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java +++ b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java @@ -140,11 +140,11 @@ private int getEncodedCharLength(final int current) throws CharacterCodingExcept if (Character.isHighSurrogate(cChar)) { // Move on to the next char (low surrogate) return 0; - } else if (Character.isSurrogatePair(lChar, cChar)) { + } + if (Character.isSurrogatePair(lChar, cChar)) { return encoder.encode(CharBuffer.wrap(new char[] { lChar, cChar })).limit(); - } else { - throw new CharacterCodingException(); } + throw new CharacterCodingException(); } /** From cefed9b924a577ccfc2bbd26217250ef10b5c5bc Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:24:13 -0400 Subject: [PATCH 013/245] Use final --- src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java index b7e3bae85..5caeecd6d 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java @@ -77,7 +77,7 @@ public void testParse() throws IOException { int comments = 0; int records = 0; try (Reader reader = getTestReader(); CSVParser parser = format.parse(reader)) { - for (CSVRecord csvRecord : parser) { + for (final CSVRecord csvRecord : parser) { records++; if (csvRecord.hasComment()) { comments++; From 08e842c8b6c5860b47a6c4efdce8e1e79d430035 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:28:44 -0400 Subject: [PATCH 014/245] Run CI on Linux and macOS --- .github/workflows/maven.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 4b4bf2e01..630852b56 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -23,15 +23,19 @@ permissions: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.experimental }} strategy: + fail-fast: false matrix: + os: [ubuntu-latest, macos-13] java: [ 8, 11, 17, 21, 24 ] experimental: [false] + # Keep the same parameter order as the matrix above include: - - java: 25-ea - experimental: true + - os: ubuntu-latest + java: 25-ea + experimental: true steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 From 32bc94743541234e70f7287a5a3c450d796d9d0b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:35:03 -0400 Subject: [PATCH 015/245] Add @SuppressWarnings and comments Format --- src/main/java/org/apache/commons/csv/CSVParser.java | 6 +++--- .../java/org/apache/commons/csv/JiraCsv196Test.java | 12 ++++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 4d74bc96f..9b96f7c7f 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -552,9 +552,9 @@ public CSVParser(final Reader reader, final CSVFormat format, final long charact * If there is a problem reading the header or skipping the first record. * @throws CSVException Thrown on invalid CSV input data. */ - private CSVParser(final Reader reader, final CSVFormat format, final long characterOffset, final long recordNumber, - final Charset charset, final boolean trackBytes) - throws IOException { + @SuppressWarnings("resource") // reader is managed by lexer. + private CSVParser(final Reader reader, final CSVFormat format, final long characterOffset, final long recordNumber, final Charset charset, + final boolean trackBytes) throws IOException { Objects.requireNonNull(reader, "reader"); Objects.requireNonNull(format, "format"); this.format = format.copy(); diff --git a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java index 3b6c74011..90261f2bd 100644 --- a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java +++ b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java @@ -38,11 +38,13 @@ private Reader getTestInput(final String path) { public void testParseFourBytes() throws IOException { final CSVFormat format = CSVFormat.Builder.create().setDelimiter(',').setQuote('\'').get(); // @formatter:off - try (CSVParser parser = new CSVParser.Builder() + try (@SuppressWarnings("resource") // parser closes the reader. + CSVParser parser = new CSVParser.Builder() .setFormat(format) .setReader(getTestInput("org/apache/commons/csv/CSV-196/emoji.csv")) .setCharset(StandardCharsets.UTF_8) - .setTrackBytes(true).get()) { + .setTrackBytes(true) + .get()) { // @formatter:on final long[] charByteKey = { 0, 84, 701, 1318, 1935 }; int idx = 0; @@ -56,11 +58,13 @@ public void testParseFourBytes() throws IOException { public void testParseThreeBytes() throws IOException { final CSVFormat format = CSVFormat.Builder.create().setDelimiter(',').setQuote('\'').get(); // @formatter:off - try (CSVParser parser = new CSVParser.Builder() + try (@SuppressWarnings("resource") // parser closes the reader. + CSVParser parser = new CSVParser.Builder() .setFormat(format) .setReader(getTestInput("org/apache/commons/csv/CSV-196/japanese.csv")) .setCharset(StandardCharsets.UTF_8) - .setTrackBytes(true).get()) { + .setTrackBytes(true) + .get()) { // @formatter:on final long[] charByteKey = { 0, 89, 242, 395 }; int idx = 0; From cff3260114fa419a185191c4440df4db102d993e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Jun 2025 09:40:09 -0400 Subject: [PATCH 016/245] Better assertion failure message --- src/test/java/org/apache/commons/csv/JiraCsv196Test.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java index 90261f2bd..ef94efe0f 100644 --- a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java +++ b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java @@ -49,7 +49,7 @@ public void testParseFourBytes() throws IOException { final long[] charByteKey = { 0, 84, 701, 1318, 1935 }; int idx = 0; for (final CSVRecord record : parser) { - assertEquals(charByteKey[idx++], record.getBytePosition(), "index " + idx); + assertEquals(charByteKey[idx++], record.getBytePosition(), "At index " + idx); } } } @@ -69,7 +69,7 @@ public void testParseThreeBytes() throws IOException { final long[] charByteKey = { 0, 89, 242, 395 }; int idx = 0; for (final CSVRecord record : parser) { - assertEquals(charByteKey[idx++], record.getBytePosition(), "index " + idx); + assertEquals(charByteKey[idx++], record.getBytePosition(), "At index " + idx); } } } From f97c172162256366058f23b8e13a1ccb3b129d82 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 7 Jun 2025 14:42:56 -0400 Subject: [PATCH 017/245] Use JUnit 5 convention for test method visibility --- .../commons/csv/CSVDuplicateHeaderTest.java | 4 +- .../apache/commons/csv/CSVFileParserTest.java | 4 +- .../commons/csv/CSVFormatPredefinedTest.java | 20 +- .../org/apache/commons/csv/CSVFormatTest.java | 220 ++++++++-------- .../org/apache/commons/csv/CSVParserTest.java | 248 +++++++++--------- .../apache/commons/csv/CSVPrinterTest.java | 244 ++++++++--------- .../org/apache/commons/csv/CSVRecordTest.java | 62 ++--- .../csv/ExtendedBufferedReaderTest.java | 12 +- .../apache/commons/csv/JiraCsv196Test.java | 4 +- .../org/apache/commons/csv/LexerTest.java | 66 ++--- .../org/apache/commons/csv/TokenTest.java | 2 +- .../org/apache/commons/csv/UserGuideTest.java | 4 +- .../commons/csv/issues/JiraCsv148Test.java | 4 +- .../commons/csv/issues/JiraCsv149Test.java | 4 +- .../commons/csv/issues/JiraCsv150Test.java | 6 +- .../commons/csv/issues/JiraCsv154Test.java | 4 +- .../commons/csv/issues/JiraCsv167Test.java | 2 +- .../commons/csv/issues/JiraCsv198Test.java | 2 +- .../commons/csv/issues/JiraCsv203Test.java | 14 +- .../commons/csv/issues/JiraCsv206Test.java | 2 +- .../commons/csv/issues/JiraCsv211Test.java | 2 +- .../commons/csv/issues/JiraCsv213Test.java | 2 +- .../commons/csv/issues/JiraCsv247Test.java | 4 +- .../commons/csv/issues/JiraCsv248Test.java | 2 +- .../commons/csv/issues/JiraCsv249Test.java | 2 +- .../commons/csv/issues/JiraCsv253Test.java | 2 +- .../commons/csv/issues/JiraCsv263Test.java | 2 +- .../commons/csv/issues/JiraCsv264Test.java | 6 +- .../commons/csv/issues/JiraCsv265Test.java | 4 +- .../commons/csv/issues/JiraCsv271Test.java | 4 +- .../commons/csv/issues/JiraCsv288Test.java | 24 +- .../commons/csv/issues/JiraCsv290Test.java | 6 +- .../commons/csv/issues/JiraCsv294Test.java | 8 +- .../commons/csv/issues/JiraCsv93Test.java | 6 +- .../commons/csv/perf/PerformanceTest.java | 4 +- 35 files changed, 503 insertions(+), 503 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java b/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java index 124e9efce..c5705e28e 100644 --- a/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java +++ b/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java @@ -272,7 +272,7 @@ static Stream duplicateHeaderData() { */ @ParameterizedTest @MethodSource(value = {"duplicateHeaderAllowsMissingColumnsNamesData"}) - public void testCSVFormat(final DuplicateHeaderMode duplicateHeaderMode, + void testCSVFormat(final DuplicateHeaderMode duplicateHeaderMode, final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final String[] headers, @@ -305,7 +305,7 @@ public void testCSVFormat(final DuplicateHeaderMode duplicateHeaderMode, */ @ParameterizedTest @MethodSource(value = {"duplicateHeaderData"}) - public void testCSVParser(final DuplicateHeaderMode duplicateHeaderMode, + void testCSVParser(final DuplicateHeaderMode duplicateHeaderMode, final boolean allowMissingColumnNames, final boolean ignoreHeaderCase, final String[] headers, diff --git a/src/test/java/org/apache/commons/csv/CSVFileParserTest.java b/src/test/java/org/apache/commons/csv/CSVFileParserTest.java index fd989779d..cb01de376 100644 --- a/src/test/java/org/apache/commons/csv/CSVFileParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFileParserTest.java @@ -59,7 +59,7 @@ private String readTestData(final BufferedReader reader) throws IOException { @ParameterizedTest @MethodSource("generateData") - public void testCSVFile(final File testFile) throws Exception { + void testCSVFile(final File testFile) throws Exception { try (FileReader fr = new FileReader(testFile); BufferedReader testDataReader = new BufferedReader(fr)) { String line = readTestData(testDataReader); assertNotNull("file must contain config line", line); @@ -104,7 +104,7 @@ public void testCSVFile(final File testFile) throws Exception { @ParameterizedTest @MethodSource("generateData") - public void testCSVUrl(final File testFile) throws Exception { + void testCSVUrl(final File testFile) throws Exception { try (FileReader fr = new FileReader(testFile); BufferedReader testData = new BufferedReader(fr)) { String line = readTestData(testData); assertNotNull("file must contain config line", line); diff --git a/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java b/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java index e907d4f17..8ff96e968 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java @@ -34,52 +34,52 @@ private void test(final CSVFormat format, final String enumName) { } @Test - public void testDefault() { + void testDefault() { test(CSVFormat.DEFAULT, "Default"); } @Test - public void testExcel() { + void testExcel() { test(CSVFormat.EXCEL, "Excel"); } @Test - public void testMongoDbCsv() { + void testMongoDbCsv() { test(CSVFormat.MONGODB_CSV, "MongoDBCsv"); } @Test - public void testMongoDbTsv() { + void testMongoDbTsv() { test(CSVFormat.MONGODB_TSV, "MongoDBTsv"); } @Test - public void testMySQL() { + void testMySQL() { test(CSVFormat.MYSQL, "MySQL"); } @Test - public void testOracle() { + void testOracle() { test(CSVFormat.ORACLE, "Oracle"); } @Test - public void testPostgreSqlCsv() { + void testPostgreSqlCsv() { test(CSVFormat.POSTGRESQL_CSV, "PostgreSQLCsv"); } @Test - public void testPostgreSqlText() { + void testPostgreSqlText() { test(CSVFormat.POSTGRESQL_TEXT, "PostgreSQLText"); } @Test - public void testRFC4180() { + void testRFC4180() { test(CSVFormat.RFC4180, "RFC4180"); } @Test - public void testTDF() { + void testTDF() { test(CSVFormat.TDF, "TDF"); } } diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index 0c7e763e5..31ad476e7 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -83,65 +83,65 @@ private void assertNotEquals(final String name, final String type, final Object } @Test - public void testBuildVsGet() { + void testBuildVsGet() { final Builder builder = CSVFormat.DEFAULT.builder(); assertNotSame(builder.get(), builder.build()); } @Test - public void testDelimiterCharLineBreakCrThrowsException1() { + void testDelimiterCharLineBreakCrThrowsException1() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter(Constants.CR).get()); } @Test - public void testDelimiterCharLineBreakLfThrowsException1() { + void testDelimiterCharLineBreakLfThrowsException1() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter(Constants.LF).get()); } @Test - public void testDelimiterEmptyStringThrowsException1() { + void testDelimiterEmptyStringThrowsException1() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter("").get()); } @SuppressWarnings("deprecation") @Test - public void testDelimiterSameAsCommentStartThrowsException_Deprecated() { + void testDelimiterSameAsCommentStartThrowsException_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter('!').withCommentMarker('!')); } @Test - public void testDelimiterSameAsCommentStartThrowsException1() { + void testDelimiterSameAsCommentStartThrowsException1() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter('!').setCommentMarker('!').get()); } @SuppressWarnings("deprecation") @Test - public void testDelimiterSameAsEscapeThrowsException_Deprecated() { + void testDelimiterSameAsEscapeThrowsException_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter('!').withEscape('!')); } @Test - public void testDelimiterSameAsEscapeThrowsException1() { + void testDelimiterSameAsEscapeThrowsException1() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter('!').setEscape('!').get()); } @Test - public void testDelimiterSameAsRecordSeparatorThrowsException() { + void testDelimiterSameAsRecordSeparatorThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat(CR)); } @Test - public void testDelimiterStringLineBreakCrThrowsException1() { + void testDelimiterStringLineBreakCrThrowsException1() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter(String.valueOf(Constants.CR)).get()); } @Test - public void testDelimiterStringLineBreakLfThrowsException1() { + void testDelimiterStringLineBreakLfThrowsException1() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setDelimiter(String.valueOf(Constants.LF)).get()); } @Test - public void testDuplicateHeaderElements() { + void testDuplicateHeaderElements() { final String[] header = { "A", "A" }; final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader(header).get(); assertEquals(2, format.getHeader().length); @@ -150,7 +150,7 @@ public void testDuplicateHeaderElements() { @SuppressWarnings("deprecation") @Test - public void testDuplicateHeaderElements_Deprecated() { + void testDuplicateHeaderElements_Deprecated() { final String[] header = { "A", "A" }; final CSVFormat format = CSVFormat.DEFAULT.withHeader(header); assertEquals(2, format.getHeader().length); @@ -158,44 +158,44 @@ public void testDuplicateHeaderElements_Deprecated() { } @Test - public void testDuplicateHeaderElementsFalse() { + void testDuplicateHeaderElementsFalse() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setHeader("A", "A").get()); } @SuppressWarnings("deprecation") @Test - public void testDuplicateHeaderElementsFalse_Deprecated() { + void testDuplicateHeaderElementsFalse_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withAllowDuplicateHeaderNames(false).withHeader("A", "A")); } @Test - public void testDuplicateHeaderElementsTrue() { + void testDuplicateHeaderElementsTrue() { CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(true).setHeader("A", "A").get(); } @SuppressWarnings("deprecation") @Test - public void testDuplicateHeaderElementsTrue_Deprecated() { + void testDuplicateHeaderElementsTrue_Deprecated() { CSVFormat.DEFAULT.withAllowDuplicateHeaderNames(true).withHeader("A", "A"); } @Test - public void testDuplicateHeaderElementsTrueContainsEmpty1() { + void testDuplicateHeaderElementsTrueContainsEmpty1() { CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setHeader("A", "", "B", "").get(); } @Test - public void testDuplicateHeaderElementsTrueContainsEmpty2() { + void testDuplicateHeaderElementsTrueContainsEmpty2() { CSVFormat.DEFAULT.builder().setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).setHeader("A", "", "B", "").get(); } @Test - public void testDuplicateHeaderElementsTrueContainsEmpty3() { + void testDuplicateHeaderElementsTrueContainsEmpty3() { CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(false).setAllowMissingColumnNames(true).setHeader("A", "", "B", "").get(); } @Test - public void testEquals() { + void testEquals() { final CSVFormat right = CSVFormat.DEFAULT; final CSVFormat left = copy(right); Assertions.assertNotEquals(null, right); @@ -208,7 +208,7 @@ public void testEquals() { } @Test - public void testEqualsCommentStart() { + void testEqualsCommentStart() { final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').setCommentMarker('#').setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setCommentMarker('!').get(); @@ -217,7 +217,7 @@ public void testEqualsCommentStart() { @SuppressWarnings("deprecation") @Test - public void testEqualsCommentStart_Deprecated() { + void testEqualsCommentStart_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withCommentMarker('#').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withCommentMarker('!'); @@ -225,7 +225,7 @@ public void testEqualsCommentStart_Deprecated() { } @Test - public void testEqualsDelimiter() { + void testEqualsDelimiter() { final CSVFormat right = CSVFormat.newFormat('!'); final CSVFormat left = CSVFormat.newFormat('?'); @@ -233,7 +233,7 @@ public void testEqualsDelimiter() { } @Test - public void testEqualsEscape() { + void testEqualsEscape() { final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').setCommentMarker('#').setEscape('+').setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setEscape('!').get(); @@ -242,7 +242,7 @@ public void testEqualsEscape() { @SuppressWarnings("deprecation") @Test - public void testEqualsEscape_Deprecated() { + void testEqualsEscape_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withCommentMarker('#').withEscape('+').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withEscape('!'); @@ -250,7 +250,7 @@ public void testEqualsEscape_Deprecated() { } @Test - public void testEqualsHash() throws Exception { + void testEqualsHash() throws Exception { final Method[] methods = CSVFormat.class.getDeclaredMethods(); for (final Method method : methods) { if (Modifier.isPublic(method.getModifiers())) { @@ -322,7 +322,7 @@ public void testEqualsHash() throws Exception { } @Test - public void testEqualsHeader() { + 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(); @@ -332,7 +332,7 @@ public void testEqualsHeader() { @SuppressWarnings("deprecation") @Test - public void testEqualsHeader_Deprecated() { + 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"); @@ -341,7 +341,7 @@ public void testEqualsHeader_Deprecated() { } @Test - public void testEqualsIgnoreEmptyLines() { + 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(); @@ -351,7 +351,7 @@ public void testEqualsIgnoreEmptyLines() { @SuppressWarnings("deprecation") @Test - public void testEqualsIgnoreEmptyLines_Deprecated() { + void testEqualsIgnoreEmptyLines_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withCommentMarker('#').withEscape('+').withIgnoreEmptyLines().withIgnoreSurroundingSpaces() .withQuote('"').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withIgnoreEmptyLines(false); @@ -360,7 +360,7 @@ public void testEqualsIgnoreEmptyLines_Deprecated() { } @Test - public void testEqualsIgnoreSurroundingSpaces() { + 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(); @@ -370,7 +370,7 @@ public void testEqualsIgnoreSurroundingSpaces() { @SuppressWarnings("deprecation") @Test - public void testEqualsIgnoreSurroundingSpaces_Deprecated() { + void testEqualsIgnoreSurroundingSpaces_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withCommentMarker('#').withEscape('+').withIgnoreSurroundingSpaces().withQuote('"') .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withIgnoreSurroundingSpaces(false); @@ -379,7 +379,7 @@ public void testEqualsIgnoreSurroundingSpaces_Deprecated() { } @Test - public void testEqualsLeftNoQuoteRightQuote() { + void testEqualsLeftNoQuoteRightQuote() { final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get(); final CSVFormat right = left.builder().setQuote('#').get(); @@ -388,7 +388,7 @@ public void testEqualsLeftNoQuoteRightQuote() { @SuppressWarnings("deprecation") @Test - public void testEqualsLeftNoQuoteRightQuote_Deprecated() { + void testEqualsLeftNoQuoteRightQuote_Deprecated() { final CSVFormat left = CSVFormat.newFormat(',').withQuote(null); final CSVFormat right = left.withQuote('#'); @@ -396,7 +396,7 @@ public void testEqualsLeftNoQuoteRightQuote_Deprecated() { } @Test - public void testEqualsNoQuotes() { + void testEqualsNoQuotes() { final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get(); final CSVFormat right = left.builder().setQuote(null).get(); @@ -405,7 +405,7 @@ public void testEqualsNoQuotes() { @SuppressWarnings("deprecation") @Test - public void testEqualsNoQuotes_Deprecated() { + void testEqualsNoQuotes_Deprecated() { final CSVFormat left = CSVFormat.newFormat(',').withQuote(null); final CSVFormat right = left.withQuote(null); @@ -413,7 +413,7 @@ public void testEqualsNoQuotes_Deprecated() { } @Test - public void testEqualsNullString() { + 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(); @@ -423,7 +423,7 @@ public void testEqualsNullString() { @SuppressWarnings("deprecation") @Test - public void testEqualsNullString_Deprecated() { + 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("---"); @@ -432,7 +432,7 @@ public void testEqualsNullString_Deprecated() { } @Test - public void testEqualsOne() { + void testEqualsOne() { final CSVFormat csvFormatOne = CSVFormat.INFORMIX_UNLOAD; final CSVFormat csvFormatTwo = CSVFormat.MYSQL; @@ -562,7 +562,7 @@ public void testEqualsOne() { } @Test - public void testEqualsQuoteChar() { + void testEqualsQuoteChar() { final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').get(); final CSVFormat left = right.builder().setQuote('!').get(); @@ -571,7 +571,7 @@ public void testEqualsQuoteChar() { @SuppressWarnings("deprecation") @Test - public void testEqualsQuoteChar_Deprecated() { + void testEqualsQuoteChar_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"'); final CSVFormat left = right.withQuote('!'); @@ -579,7 +579,7 @@ public void testEqualsQuoteChar_Deprecated() { } @Test - public void testEqualsQuotePolicy() { + void testEqualsQuotePolicy() { final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setQuoteMode(QuoteMode.MINIMAL).get(); @@ -588,7 +588,7 @@ public void testEqualsQuotePolicy() { @SuppressWarnings("deprecation") @Test - public void testEqualsQuotePolicy_Deprecated() { + void testEqualsQuotePolicy_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withQuoteMode(QuoteMode.MINIMAL); @@ -596,7 +596,7 @@ public void testEqualsQuotePolicy_Deprecated() { } @Test - public void testEqualsRecordSeparator() { + 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(); @@ -606,7 +606,7 @@ public void testEqualsRecordSeparator() { @SuppressWarnings("deprecation") @Test - public void testEqualsRecordSeparator_Deprecated() { + void testEqualsRecordSeparator_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withRecordSeparator(CR).withCommentMarker('#').withEscape('+').withIgnoreEmptyLines() .withIgnoreSurroundingSpaces().withQuote('"').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withRecordSeparator(LF); @@ -614,7 +614,7 @@ public void testEqualsRecordSeparator_Deprecated() { assertNotEquals(right, left); } - public void testEqualsSkipHeaderRecord() { + 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(); @@ -624,7 +624,7 @@ public void testEqualsSkipHeaderRecord() { @SuppressWarnings("deprecation") @Test - public void testEqualsSkipHeaderRecord_Deprecated() { + 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); @@ -633,7 +633,7 @@ public void testEqualsSkipHeaderRecord_Deprecated() { } @Test - public void testEqualsWithNull() { + void testEqualsWithNull() { final CSVFormat csvFormat = CSVFormat.POSTGRESQL_TEXT; @@ -696,18 +696,18 @@ public void testEqualsWithNull() { } @Test - public void testEscapeSameAsCommentStartThrowsException() { + void testEscapeSameAsCommentStartThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setEscape('!').setCommentMarker('!').get()); } @SuppressWarnings("deprecation") @Test - public void testEscapeSameAsCommentStartThrowsException_Deprecated() { + void testEscapeSameAsCommentStartThrowsException_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape('!').withCommentMarker('!')); } @Test - public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType() { + 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()); @@ -715,13 +715,13 @@ public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType() { @SuppressWarnings("deprecation") @Test - public void testEscapeSameAsCommentStartThrowsExceptionForWrapperType_Deprecated() { + 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() { + void testFormat() { final CSVFormat format = CSVFormat.DEFAULT; assertEquals("", format.format()); @@ -730,7 +730,7 @@ public void testFormat() { } @Test // I assume this to be a defect. - public void testFormatThrowsNullPointerException() { + void testFormatThrowsNullPointerException() { final CSVFormat csvFormat = CSVFormat.MYSQL; @@ -739,7 +739,7 @@ public void testFormatThrowsNullPointerException() { } @Test - public void testFormatToString() { + void testFormatToString() { // @formatter:off final CSVFormat format = CSVFormat.RFC4180 .withEscape('?') @@ -759,7 +759,7 @@ public void testFormatToString() { } @Test - public void testGetAllowDuplicateHeaderNames() { + void testGetAllowDuplicateHeaderNames() { final Builder builder = CSVFormat.DEFAULT.builder(); assertTrue(builder.get().getAllowDuplicateHeaderNames()); assertTrue(builder.setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_ALL).get().getAllowDuplicateHeaderNames()); @@ -768,7 +768,7 @@ public void testGetAllowDuplicateHeaderNames() { } @Test - public void testGetDuplicateHeaderMode() { + void testGetDuplicateHeaderMode() { final Builder builder = CSVFormat.DEFAULT.builder(); assertEquals(DuplicateHeaderMode.ALLOW_ALL, builder.get().getDuplicateHeaderMode()); @@ -778,7 +778,7 @@ public void testGetDuplicateHeaderMode() { } @Test - public void testGetHeader() { + void testGetHeader() { final String[] header = { "one", "two", "three" }; final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(header); // getHeader() makes a copy of the header array. @@ -791,7 +791,7 @@ public void testGetHeader() { } @Test - public void testHashCodeAndWithIgnoreHeaderCase() { + void testHashCodeAndWithIgnoreHeaderCase() { final CSVFormat csvFormat = CSVFormat.INFORMIX_UNLOAD_CSV; final CSVFormat csvFormatTwo = csvFormat.withIgnoreHeaderCase(); @@ -809,18 +809,18 @@ public void testHashCodeAndWithIgnoreHeaderCase() { } @Test - public void testJiraCsv236() { + void testJiraCsv236() { CSVFormat.DEFAULT.builder().setAllowDuplicateHeaderNames(true).setHeader("CC", "VV", "VV").get(); } @SuppressWarnings("deprecation") @Test - public void testJiraCsv236__Deprecated() { + void testJiraCsv236__Deprecated() { CSVFormat.DEFAULT.withAllowDuplicateHeaderNames().withHeader("CC", "VV", "VV"); } @Test - public void testNewFormat() { + void testNewFormat() { final CSVFormat csvFormat = CSVFormat.newFormat('X'); @@ -881,7 +881,7 @@ public void testNewFormat() { } @Test - public void testNullRecordSeparatorCsv106() { + void testNullRecordSeparatorCsv106() { final CSVFormat format = CSVFormat.newFormat(';').builder().setSkipHeaderRecord(true).setHeader("H1", "H2").get(); final String formatStr = format.format("A", "B"); assertNotNull(formatStr); @@ -890,7 +890,7 @@ public void testNullRecordSeparatorCsv106() { @SuppressWarnings("deprecation") @Test - public void testNullRecordSeparatorCsv106__Deprecated() { + void testNullRecordSeparatorCsv106__Deprecated() { final CSVFormat format = CSVFormat.newFormat(';').withSkipHeaderRecord().withHeader("H1", "H2"); final String formatStr = format.format("A", "B"); assertNotNull(formatStr); @@ -898,7 +898,7 @@ public void testNullRecordSeparatorCsv106__Deprecated() { } @Test - public void testPrintRecord() throws IOException { + void testPrintRecord() throws IOException { final Appendable out = new StringBuilder(); final CSVFormat format = CSVFormat.RFC4180; format.printRecord(out, "a", "b", "c"); @@ -906,7 +906,7 @@ public void testPrintRecord() throws IOException { } @Test - public void testPrintRecordEmpty() throws IOException { + void testPrintRecordEmpty() throws IOException { final Appendable out = new StringBuilder(); final CSVFormat format = CSVFormat.RFC4180; format.printRecord(out); @@ -914,7 +914,7 @@ public void testPrintRecordEmpty() throws IOException { } @Test - public void testPrintWithEscapesEndWithCRLF() throws IOException { + 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); @@ -923,7 +923,7 @@ public void testPrintWithEscapesEndWithCRLF() throws IOException { } @Test - public void testPrintWithEscapesEndWithoutCRLF() throws IOException { + 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); @@ -932,7 +932,7 @@ public void testPrintWithEscapesEndWithoutCRLF() throws IOException { } @Test - public void testPrintWithoutQuotes() throws IOException { + 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); @@ -941,7 +941,7 @@ public void testPrintWithoutQuotes() throws IOException { } @Test - public void testPrintWithQuoteModeIsNONE() throws IOException { + 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); @@ -950,7 +950,7 @@ public void testPrintWithQuoteModeIsNONE() throws IOException { } @Test - public void testPrintWithQuotes() throws IOException { + 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); @@ -959,42 +959,42 @@ public void testPrintWithQuotes() throws IOException { } @Test - public void testQuoteCharSameAsCommentStartThrowsException() { + void testQuoteCharSameAsCommentStartThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setCommentMarker('!').get()); } @SuppressWarnings("deprecation") @Test - public void testQuoteCharSameAsCommentStartThrowsException_Deprecated() { + void testQuoteCharSameAsCommentStartThrowsException_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote('!').withCommentMarker('!')); } @Test - public void testQuoteCharSameAsCommentStartThrowsExceptionForWrapperType() { + 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() { + 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() { + void testQuoteCharSameAsDelimiterThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setDelimiter('!').get()); } @SuppressWarnings("deprecation") @Test - public void testQuoteCharSameAsDelimiterThrowsException_Deprecated() { + void testQuoteCharSameAsDelimiterThrowsException_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote('!').withDelimiter('!')); } @Test - public void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() { + void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() { final Exception exception = assertThrows(IllegalArgumentException.class, () -> // @formatter:off CSVFormat.DEFAULT.builder() @@ -1009,18 +1009,18 @@ public void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() { } @Test - public void testQuotePolicyNoneWithoutEscapeThrowsException() { + void testQuotePolicyNoneWithoutEscapeThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat('!').builder().setQuoteMode(QuoteMode.NONE).get()); } @SuppressWarnings("deprecation") @Test - public void testQuotePolicyNoneWithoutEscapeThrowsException_Deprecated() { + void testQuotePolicyNoneWithoutEscapeThrowsException_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.newFormat('!').withQuoteMode(QuoteMode.NONE)); } @Test - public void testRFC4180() { + void testRFC4180() { assertNull(RFC4180.getCommentMarker()); assertEquals(',', RFC4180.getDelimiter()); assertNull(RFC4180.getEscapeCharacter()); @@ -1032,7 +1032,7 @@ public void testRFC4180() { @SuppressWarnings("boxing") // no need to worry about boxing here @Test - public void testSerialization() throws Exception { + void testSerialization() throws Exception { final ByteArrayOutputStream out = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(out)) { @@ -1054,7 +1054,7 @@ public void testSerialization() throws Exception { } @Test - public void testToString() { + void testToString() { final String string = CSVFormat.INFORMIX_UNLOAD.toString(); @@ -1063,7 +1063,7 @@ public void testToString() { } @Test - public void testToStringAndWithCommentMarkerTakingCharacter() { + void testToStringAndWithCommentMarkerTakingCharacter() { final CSVFormat.Predefined csvFormatPredefined = CSVFormat.Predefined.Default; final CSVFormat csvFormat = csvFormatPredefined.getFormat(); @@ -1224,7 +1224,7 @@ public void testToStringAndWithCommentMarkerTakingCharacter() { } @Test - public void testTrim() throws IOException { + void testTrim() throws IOException { final CSVFormat formatWithTrim = CSVFormat.DEFAULT.withDelimiter(',').withTrim().withQuote(null).withRecordSeparator(CRLF); CharSequence in = "a,b,c"; @@ -1249,29 +1249,29 @@ public void testTrim() throws IOException { } @Test - public void testWithCommentStart() { + void testWithCommentStart() { final CSVFormat formatWithCommentStart = CSVFormat.DEFAULT.withCommentMarker('#'); assertEquals(Character.valueOf('#'), formatWithCommentStart.getCommentMarker()); } @Test - public void testWithCommentStartCRThrowsException() { + void testWithCommentStartCRThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withCommentMarker(CR)); } @Test - public void testWithDelimiter() { + void testWithDelimiter() { final CSVFormat formatWithDelimiter = CSVFormat.DEFAULT.withDelimiter('!'); assertEquals('!', formatWithDelimiter.getDelimiter()); } @Test - public void testWithDelimiterLFThrowsException() { + void testWithDelimiterLFThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(LF)); } @Test - public void testWithEmptyDuplicates() { + void testWithEmptyDuplicates() { final CSVFormat formatWithEmptyDuplicates = CSVFormat.DEFAULT.builder().setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_EMPTY).get(); assertEquals(DuplicateHeaderMode.ALLOW_EMPTY, formatWithEmptyDuplicates.getDuplicateHeaderMode()); @@ -1279,31 +1279,31 @@ public void testWithEmptyDuplicates() { } @Test - public void testWithEmptyEnum() { + void testWithEmptyEnum() { final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(EmptyEnum.class); assertEquals(0, formatWithHeader.getHeader().length); } @Test - public void testWithEscape() { + void testWithEscape() { final CSVFormat formatWithEscape = CSVFormat.DEFAULT.withEscape('&'); assertEquals(Character.valueOf('&'), formatWithEscape.getEscapeCharacter()); } @Test - public void testWithEscapeCRThrowsExceptions() { + void testWithEscapeCRThrowsExceptions() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withEscape(CR)); } @Test - public void testWithFirstRecordAsHeader() { + void testWithFirstRecordAsHeader() { final CSVFormat formatWithFirstRecordAsHeader = CSVFormat.DEFAULT.withFirstRecordAsHeader(); assertTrue(formatWithFirstRecordAsHeader.getSkipHeaderRecord()); assertEquals(0, formatWithFirstRecordAsHeader.getHeader().length); } @Test - public void testWithHeader() { + void testWithHeader() { final String[] header = { "one", "two", "three" }; // withHeader() makes a copy of the header array. final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(header); @@ -1312,7 +1312,7 @@ public void testWithHeader() { } @Test - public void testWithHeaderComments() { + void testWithHeaderComments() { final CSVFormat csvFormat = CSVFormat.DEFAULT; @@ -1473,80 +1473,80 @@ public void testWithHeaderComments() { } @Test - public void testWithHeaderEnum() { + void testWithHeaderEnum() { final CSVFormat formatWithHeader = CSVFormat.DEFAULT.withHeader(Header.class); assertArrayEquals(new String[] { "Name", "Email", "Phone" }, formatWithHeader.getHeader()); } @Test - public void testWithHeaderEnumNull() { + void testWithHeaderEnumNull() { final CSVFormat format = CSVFormat.DEFAULT; final Class> simpleName = null; format.withHeader(simpleName); } @Test - public void testWithHeaderResultSetNull() throws SQLException { + void testWithHeaderResultSetNull() throws SQLException { final CSVFormat format = CSVFormat.DEFAULT; final ResultSet resultSet = null; format.withHeader(resultSet); } @Test - public void testWithIgnoreEmptyLines() { + void testWithIgnoreEmptyLines() { assertFalse(CSVFormat.DEFAULT.withIgnoreEmptyLines(false).getIgnoreEmptyLines()); assertTrue(CSVFormat.DEFAULT.withIgnoreEmptyLines().getIgnoreEmptyLines()); } @Test - public void testWithIgnoreSurround() { + void testWithIgnoreSurround() { assertFalse(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces(false).getIgnoreSurroundingSpaces()); assertTrue(CSVFormat.DEFAULT.withIgnoreSurroundingSpaces().getIgnoreSurroundingSpaces()); } @Test - public void testWithNullString() { + void testWithNullString() { final CSVFormat formatWithNullString = CSVFormat.DEFAULT.withNullString("null"); assertEquals("null", formatWithNullString.getNullString()); } @Test - public void testWithQuoteChar() { + void testWithQuoteChar() { final CSVFormat formatWithQuoteChar = CSVFormat.DEFAULT.withQuote('"'); assertEquals(Character.valueOf('"'), formatWithQuoteChar.getQuoteCharacter()); } @Test - public void testWithQuoteLFThrowsException() { + void testWithQuoteLFThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote(LF)); } @Test - public void testWithQuotePolicy() { + void testWithQuotePolicy() { final CSVFormat formatWithQuotePolicy = CSVFormat.DEFAULT.withQuoteMode(QuoteMode.ALL); assertEquals(QuoteMode.ALL, formatWithQuotePolicy.getQuoteMode()); } @Test - public void testWithRecordSeparatorCR() { + void testWithRecordSeparatorCR() { final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CR); assertEquals(String.valueOf(CR), formatWithRecordSeparator.getRecordSeparator()); } @Test - public void testWithRecordSeparatorCRLF() { + void testWithRecordSeparatorCRLF() { final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(CRLF); assertEquals(CRLF, formatWithRecordSeparator.getRecordSeparator()); } @Test - public void testWithRecordSeparatorLF() { + void testWithRecordSeparatorLF() { final CSVFormat formatWithRecordSeparator = CSVFormat.DEFAULT.withRecordSeparator(LF); assertEquals(String.valueOf(LF), formatWithRecordSeparator.getRecordSeparator()); } @Test - public void testWithSystemRecordSeparator() { + 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 20ab9b658..8304a568c 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -140,7 +140,7 @@ private void parseFully(final CSVParser parser) { } @Test - public void testBackslashEscaping() throws IOException { + 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. @@ -176,7 +176,7 @@ public void testBackslashEscaping() throws IOException { } @Test - public void testBackslashEscaping2() throws IOException { + 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. @@ -200,7 +200,7 @@ public void testBackslashEscaping2() throws IOException { @Test @Disabled - public void testBackslashEscapingOld() throws IOException { + 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 @@ -224,7 +224,7 @@ public void testBackslashEscapingOld() throws IOException { @Test @Disabled("CSV-107") - public void testBOM() throws IOException { + 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"))); @@ -232,7 +232,7 @@ public void testBOM() throws IOException { } @Test - public void testBOMInputStreamParserWithInputStream() throws IOException { + 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"))); @@ -240,7 +240,7 @@ public void testBOMInputStreamParserWithInputStream() throws IOException { } @Test - public void testBOMInputStreamParserWithReader() throws IOException { + 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) @@ -251,7 +251,7 @@ public void testBOMInputStreamParserWithReader() throws IOException { } @Test - public void testBOMInputStreamParseWithReader() throws IOException { + 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) @@ -262,7 +262,7 @@ public void testBOMInputStreamParseWithReader() throws IOException { } @Test - public void testCarriageReturnEndings() throws IOException { + 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(); @@ -271,7 +271,7 @@ public void testCarriageReturnEndings() throws IOException { } @Test - public void testCarriageReturnLineFeedEndings() throws IOException { + 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(); @@ -280,7 +280,7 @@ public void testCarriageReturnLineFeedEndings() throws IOException { } @Test - public void testClose() throws Exception { + 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)) { @@ -292,32 +292,32 @@ public void testClose() throws Exception { } @Test - public void testCSV141CSVFormat_DEFAULT() throws Exception { + void testCSV141CSVFormat_DEFAULT() throws Exception { testCSV141Failure(CSVFormat.DEFAULT, 3); } @Test - public void testCSV141CSVFormat_INFORMIX_UNLOAD() throws Exception { + void testCSV141CSVFormat_INFORMIX_UNLOAD() throws Exception { testCSV141Failure(CSVFormat.INFORMIX_UNLOAD, 1); } @Test - public void testCSV141CSVFormat_INFORMIX_UNLOAD_CSV() throws Exception { + void testCSV141CSVFormat_INFORMIX_UNLOAD_CSV() throws Exception { testCSV141Failure(CSVFormat.INFORMIX_UNLOAD_CSV, 3); } @Test - public void testCSV141CSVFormat_ORACLE() throws Exception { + void testCSV141CSVFormat_ORACLE() throws Exception { testCSV141Failure(CSVFormat.ORACLE, 2); } @Test - public void testCSV141CSVFormat_POSTGRESQL_CSV() throws Exception { + void testCSV141CSVFormat_POSTGRESQL_CSV() throws Exception { testCSV141Failure(CSVFormat.POSTGRESQL_CSV, 3); } @Test - public void testCSV141Excel() throws Exception { + void testCSV141Excel() throws Exception { testCSV141Ok(CSVFormat.EXCEL); } @@ -387,12 +387,12 @@ record = parser.nextRecord(); } @Test - public void testCSV141RFC4180() throws Exception { + void testCSV141RFC4180() throws Exception { testCSV141Failure(CSVFormat.RFC4180, 3); } @Test - public void testCSV235() throws IOException { + 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(); @@ -406,7 +406,7 @@ public void testCSV235() throws IOException { } @Test - public void testCSV57() throws Exception { + void testCSV57() throws Exception { try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) { final List list = parser.getRecords(); assertNotNull(list); @@ -415,7 +415,7 @@ public void testCSV57() throws Exception { } @Test - public void testDefaultFormat() throws IOException { + void testDefaultFormat() throws IOException { // @formatter:off final String code = "" + "a,b#\n" + // 1) "\"\n\",\" \",#\n" + // 2) @@ -440,20 +440,20 @@ public void testDefaultFormat() throws IOException { } @Test - public void testDuplicateHeadersAllowedByDefault() throws Exception { + 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() { + 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 { + 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()); @@ -461,7 +461,7 @@ public void testEmptyFile() throws Exception { } @Test - public void testEmptyFileHeaderParsing() throws Exception { + void testEmptyFileHeaderParsing() throws Exception { try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT.withFirstRecordAsHeader())) { assertNull(parser.nextRecord()); assertTrue(parser.getHeaderNames().isEmpty()); @@ -469,7 +469,7 @@ public void testEmptyFileHeaderParsing() throws Exception { } @Test - public void testEmptyLineBehaviorCSV() throws Exception { + 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 }; @@ -486,7 +486,7 @@ public void testEmptyLineBehaviorCSV() throws Exception { } @Test - public void testEmptyLineBehaviorExcel() throws Exception { + 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 { "" } }; @@ -503,14 +503,14 @@ public void testEmptyLineBehaviorExcel() throws Exception { } @Test - public void testEmptyString() throws Exception { + void testEmptyString() throws Exception { try (CSVParser parser = CSVParser.parse("", CSVFormat.DEFAULT)) { assertNull(parser.nextRecord()); } } @Test - public void testEndOfFileBehaviorCSV() throws Exception { + 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 @@ -528,7 +528,7 @@ public void testEndOfFileBehaviorCSV() throws Exception { } @Test - public void testEndOfFileBehaviorExcel() throws Exception { + 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 @@ -547,7 +547,7 @@ public void testEndOfFileBehaviorExcel() throws Exception { } @Test - public void testExcelFormat1() throws IOException { + 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", "" } }; @@ -562,7 +562,7 @@ public void testExcelFormat1() throws IOException { } @Test - public void testExcelFormat2() throws Exception { + 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)) { @@ -579,7 +579,7 @@ public void testExcelFormat2() throws Exception { * Tests an exported Excel worksheet with a header row and rows that have more columns than the headers */ @Test - public void testExcelHeaderCountLessThanData() throws Exception { + 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 -> { @@ -591,7 +591,7 @@ public void testExcelHeaderCountLessThanData() throws Exception { } @Test - public void testFirstEndOfLineCr() throws IOException { + 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(); @@ -601,7 +601,7 @@ public void testFirstEndOfLineCr() throws IOException { } @Test - public void testFirstEndOfLineCrLf() throws IOException { + 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(); @@ -611,7 +611,7 @@ public void testFirstEndOfLineCrLf() throws IOException { } @Test - public void testFirstEndOfLineLf() throws IOException { + 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(); @@ -621,7 +621,7 @@ public void testFirstEndOfLineLf() throws IOException { } @Test - public void testForEach() throws Exception { + 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<>(); @@ -636,7 +636,7 @@ public void testForEach() throws Exception { } @Test - public void testGetHeaderComment_HeaderComment1() throws IOException { + void testGetHeaderComment_HeaderComment1() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) { parser.getRecords(); // Expect a header comment @@ -646,7 +646,7 @@ public void testGetHeaderComment_HeaderComment1() throws IOException { } @Test - public void testGetHeaderComment_HeaderComment2() throws IOException { + void testGetHeaderComment_HeaderComment2() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) { parser.getRecords(); // Expect a header comment @@ -656,7 +656,7 @@ public void testGetHeaderComment_HeaderComment2() throws IOException { } @Test - public void testGetHeaderComment_HeaderComment3() throws IOException { + 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 @@ -666,7 +666,7 @@ public void testGetHeaderComment_HeaderComment3() throws IOException { } @Test - public void testGetHeaderComment_HeaderTrailerComment() throws IOException { + 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 @@ -676,7 +676,7 @@ public void testGetHeaderComment_HeaderTrailerComment() throws IOException { } @Test - public void testGetHeaderComment_NoComment1() throws IOException { + void testGetHeaderComment_NoComment1() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_AUTO_HEADER)) { parser.getRecords(); // Expect no header comment @@ -686,7 +686,7 @@ public void testGetHeaderComment_NoComment1() throws IOException { } @Test - public void testGetHeaderComment_NoComment2() throws IOException { + void testGetHeaderComment_NoComment2() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER)) { parser.getRecords(); // Expect no header comment @@ -696,7 +696,7 @@ public void testGetHeaderComment_NoComment2() throws IOException { } @Test - public void testGetHeaderComment_NoComment3() throws IOException { + void testGetHeaderComment_NoComment3() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_NO_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) { parser.getRecords(); // Expect no header comment @@ -706,7 +706,7 @@ public void testGetHeaderComment_NoComment3() throws IOException { } @Test - public void testGetHeaderMap() throws Exception { + 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(); @@ -730,7 +730,7 @@ public void testGetHeaderMap() throws Exception { } @Test - public void testGetHeaderNames() throws IOException { + 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(); @@ -744,7 +744,7 @@ public void testGetHeaderNames() throws IOException { } @Test - public void testGetHeaderNamesReadOnly() throws IOException { + 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); @@ -753,7 +753,7 @@ public void testGetHeaderNamesReadOnly() throws IOException { } @Test - public void testGetLine() throws IOException { + void testGetLine() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) { for (final String[] re : RESULT) { assertArrayEquals(re, parser.nextRecord().values()); @@ -764,22 +764,22 @@ public void testGetLine() throws IOException { } @Test - public void testGetLineNumberWithCR() throws Exception { + void testGetLineNumberWithCR() throws Exception { validateLineNumbers(String.valueOf(CR)); } @Test - public void testGetLineNumberWithCRLF() throws Exception { + void testGetLineNumberWithCRLF() throws Exception { validateLineNumbers(CRLF); } @Test - public void testGetLineNumberWithLF() throws Exception { + void testGetLineNumberWithLF() throws Exception { validateLineNumbers(String.valueOf(LF)); } @Test - public void testGetOneLine() throws IOException { + 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()); @@ -792,7 +792,7 @@ public void testGetOneLine() throws IOException { * @throws IOException when an I/O error occurs. */ @Test - public void testGetOneLineOneParser() throws IOException { + void testGetOneLineOneParser() throws IOException { final CSVFormat format = CSVFormat.DEFAULT; try (PipedWriter writer = new PipedWriter(); PipedReader origin = new PipedReader(writer); @@ -812,7 +812,7 @@ public void testGetOneLineOneParser() throws IOException { } @Test - public void testGetRecordFourBytesRead() throws Exception { + void testGetRecordFourBytesRead() throws Exception { final String code = "id,a,b,c\n" + "1,😊,🤔,😂\n" + "2,😊,🤔,😂\n" + @@ -846,32 +846,32 @@ public void testGetRecordFourBytesRead() throws Exception { } @Test - public void testGetRecordNumberWithCR() throws Exception { + void testGetRecordNumberWithCR() throws Exception { validateRecordNumbers(String.valueOf(CR)); } @Test - public void testGetRecordNumberWithCRLF() throws Exception { + void testGetRecordNumberWithCRLF() throws Exception { validateRecordNumbers(CRLF); } @Test - public void testGetRecordNumberWithLF() throws Exception { + void testGetRecordNumberWithLF() throws Exception { validateRecordNumbers(String.valueOf(LF)); } @Test - public void testGetRecordPositionWithCRLF() throws Exception { + void testGetRecordPositionWithCRLF() throws Exception { validateRecordPosition(CRLF); } @Test - public void testGetRecordPositionWithLF() throws Exception { + void testGetRecordPositionWithLF() throws Exception { validateRecordPosition(String.valueOf(LF)); } @Test - public void testGetRecords() throws IOException { + void testGetRecords() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) { final List records = parser.getRecords(); assertEquals(RESULT.length, records.size()); @@ -883,7 +883,7 @@ public void testGetRecords() throws IOException { } @Test - public void testGetRecordsFromBrokenInputStream() throws IOException { + 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); @@ -892,7 +892,7 @@ public void testGetRecordsFromBrokenInputStream() throws IOException { @ParameterizedTest @ValueSource(longs = { -1, 0, 1, 2, 3, 4, Long.MAX_VALUE }) - public void testGetRecordsMaxRows(final long maxRows) throws IOException { + void testGetRecordsMaxRows(final long maxRows) throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.builder().setIgnoreSurroundingSpaces(true).setMaxRows(maxRows).get())) { final List records = parser.getRecords(); final long expectedLength = maxRows <= 0 || maxRows > RESULT.length ? RESULT.length : maxRows; @@ -905,7 +905,7 @@ public void testGetRecordsMaxRows(final long maxRows) throws IOException { } @Test - public void testGetRecordThreeBytesRead() throws Exception { + void testGetRecordThreeBytesRead() throws Exception { final String code = "id,date,val5,val4\n" + "11111111111111,'4017-09-01',きちんと節分近くには咲いてる~,v4\n" + "22222222222222,'4017-01-01',おはよう私の友人~,v4\n" + @@ -941,7 +941,7 @@ public void testGetRecordThreeBytesRead() throws Exception { } @Test - public void testGetRecordWithMultiLineValues() throws Exception { + 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; @@ -966,7 +966,7 @@ public void testGetRecordWithMultiLineValues() throws Exception { } @Test - public void testGetTrailerComment_HeaderComment1() throws IOException { + void testGetTrailerComment_HeaderComment1() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) { parser.getRecords(); assertFalse(parser.hasTrailerComment()); @@ -975,7 +975,7 @@ public void testGetTrailerComment_HeaderComment1() throws IOException { } @Test - public void testGetTrailerComment_HeaderComment2() throws IOException { + void testGetTrailerComment_HeaderComment2() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER)) { parser.getRecords(); assertFalse(parser.hasTrailerComment()); @@ -984,7 +984,7 @@ public void testGetTrailerComment_HeaderComment2() throws IOException { } @Test - public void testGetTrailerComment_HeaderComment3() throws IOException { + void testGetTrailerComment_HeaderComment3() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) { parser.getRecords(); assertFalse(parser.hasTrailerComment()); @@ -993,7 +993,7 @@ public void testGetTrailerComment_HeaderComment3() throws IOException { } @Test - public void testGetTrailerComment_HeaderTrailerComment1() throws IOException { + void testGetTrailerComment_HeaderTrailerComment1() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) { parser.getRecords(); assertTrue(parser.hasTrailerComment()); @@ -1002,7 +1002,7 @@ public void testGetTrailerComment_HeaderTrailerComment1() throws IOException { } @Test - public void testGetTrailerComment_HeaderTrailerComment2() throws IOException { + void testGetTrailerComment_HeaderTrailerComment2() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER)) { parser.getRecords(); assertTrue(parser.hasTrailerComment()); @@ -1011,7 +1011,7 @@ public void testGetTrailerComment_HeaderTrailerComment2() throws IOException { } @Test - public void testGetTrailerComment_HeaderTrailerComment3() throws IOException { + void testGetTrailerComment_HeaderTrailerComment3() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_TRAILER_COMMENT, FORMAT_EXPLICIT_HEADER_NOSKIP)) { parser.getRecords(); assertTrue(parser.hasTrailerComment()); @@ -1020,7 +1020,7 @@ public void testGetTrailerComment_HeaderTrailerComment3() throws IOException { } @Test - public void testGetTrailerComment_MultilineComment() throws IOException { + void testGetTrailerComment_MultilineComment() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_MULTILINE_HEADER_TRAILER_COMMENT, FORMAT_AUTO_HEADER)) { parser.getRecords(); assertTrue(parser.hasTrailerComment()); @@ -1029,7 +1029,7 @@ public void testGetTrailerComment_MultilineComment() throws IOException { } @Test - public void testHeader() throws Exception { + 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)) { @@ -1048,7 +1048,7 @@ public void testHeader() throws Exception { } @Test - public void testHeaderComment() throws Exception { + 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(); @@ -1064,7 +1064,7 @@ public void testHeaderComment() throws Exception { } @Test - public void testHeaderMissing() throws Exception { + 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(); @@ -1079,7 +1079,7 @@ public void testHeaderMissing() throws Exception { } @Test - public void testHeaderMissingWithNull() throws Exception { + 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(); @@ -1087,7 +1087,7 @@ public void testHeaderMissingWithNull() throws Exception { } @Test - public void testHeadersMissing() throws Exception { + 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(); @@ -1095,19 +1095,19 @@ public void testHeadersMissing() throws Exception { } @Test - public void testHeadersMissingException() { + 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() { + 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 { + 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(); @@ -1121,7 +1121,7 @@ public void testHeadersWithNullColumnName() throws IOException { } @Test - public void testIgnoreCaseHeaderMapping() throws Exception { + 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(); @@ -1133,7 +1133,7 @@ public void testIgnoreCaseHeaderMapping() throws Exception { } @Test - public void testIgnoreEmptyLines() throws IOException { + 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"; @@ -1144,12 +1144,12 @@ public void testIgnoreEmptyLines() throws IOException { } @Test - public void testInvalidFormat() { + void testInvalidFormat() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR)); } @Test - public void testIterator() throws Exception { + 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(); @@ -1168,7 +1168,7 @@ public void testIterator() throws Exception { @ParameterizedTest @ValueSource(longs = { -1, 0, 1, 2, 3, 4, 5, Long.MAX_VALUE }) - public void testIteratorMaxRows(final long maxRows) throws Exception { + void testIteratorMaxRows(final long maxRows) throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); try (CSVParser parser = CSVFormat.DEFAULT.builder().setMaxRows(maxRows).get().parse(in)) { final Iterator iterator = parser.iterator(); @@ -1195,7 +1195,7 @@ public void testIteratorMaxRows(final long maxRows) throws Exception { } @Test - public void testIteratorSequenceBreaking() throws IOException { + 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))) { @@ -1250,7 +1250,7 @@ public void testIteratorSequenceBreaking() throws IOException { } @Test - public void testLineFeedEndings() throws IOException { + 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(); @@ -1259,7 +1259,7 @@ public void testLineFeedEndings() throws IOException { } @Test - public void testMappedButNotSetAsOutlook2007ContactExport() throws Exception { + 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(); @@ -1294,7 +1294,7 @@ record = records.next(); @Test @Disabled - public void testMongoDbCsv() throws Exception { + 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(); @@ -1313,7 +1313,7 @@ public void testMongoDbCsv() throws Exception { @Test // TODO this may lead to strange behavior, throw an exception if iterator() has already been called? - public void testMultipleIterators() throws Exception { + void testMultipleIterators() throws Exception { try (CSVParser parser = CSVParser.parse("a,b,c" + CRLF + "d,e,f", CSVFormat.DEFAULT)) { final Iterator itr1 = parser.iterator(); @@ -1330,24 +1330,24 @@ public void testMultipleIterators() throws Exception { } @Test - public void testNewCSVParserNullReaderFormat() { + void testNewCSVParserNullReaderFormat() { assertThrows(NullPointerException.class, () -> new CSVParser(null, CSVFormat.DEFAULT)); } @Test - public void testNewCSVParserReaderNullFormat() { + void testNewCSVParserReaderNullFormat() { assertThrows(NullPointerException.class, () -> new CSVParser(new StringReader(""), null)); } @Test - public void testNoHeaderMap() throws Exception { + 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 { + void testNotValueCSV() throws IOException { final String source = "#"; final CSVFormat csvFormat = CSVFormat.DEFAULT.withCommentMarker('#'); try (CSVParser csvParser = csvFormat.parse(new StringReader(source))) { @@ -1357,7 +1357,7 @@ public void testNotValueCSV() throws IOException { } @Test - public void testParse() throws Exception { + void testParse() throws Exception { final URL url = ClassLoader.getSystemClassLoader().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; @@ -1424,7 +1424,7 @@ public void testParse() throws Exception { } @Test - public void testParseFileCharsetNullFormat() throws IOException { + void testParseFileCharsetNullFormat() throws IOException { final File file = new File("src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv"); try (CSVParser parser = CSVParser.parse(file, Charset.defaultCharset(), null)) { // null maps to DEFAULT. @@ -1433,7 +1433,7 @@ public void testParseFileCharsetNullFormat() throws IOException { } @Test - public void testParseInputStreamCharsetNullFormat() throws IOException { + void testParseInputStreamCharsetNullFormat() throws IOException { try (InputStream in = Files.newInputStream(Paths.get("src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv")); CSVParser parser = CSVParser.parse(in, Charset.defaultCharset(), null)) { // null maps to DEFAULT. @@ -1442,27 +1442,27 @@ public void testParseInputStreamCharsetNullFormat() throws IOException { } @Test - public void testParseNullFileFormat() { + void testParseNullFileFormat() { assertThrows(NullPointerException.class, () -> CSVParser.parse((File) null, Charset.defaultCharset(), CSVFormat.DEFAULT)); } @Test - public void testParseNullPathFormat() { + void testParseNullPathFormat() { assertThrows(NullPointerException.class, () -> CSVParser.parse((Path) null, Charset.defaultCharset(), CSVFormat.DEFAULT)); } @Test - public void testParseNullStringFormat() { + void testParseNullStringFormat() { assertThrows(NullPointerException.class, () -> CSVParser.parse((String) null, CSVFormat.DEFAULT)); } @Test - public void testParseNullUrlCharsetFormat() { + void testParseNullUrlCharsetFormat() { assertThrows(NullPointerException.class, () -> CSVParser.parse((URL) null, Charset.defaultCharset(), CSVFormat.DEFAULT)); } @Test - public void testParsePathCharsetNullFormat() throws IOException { + void testParsePathCharsetNullFormat() throws IOException { final Path path = Paths.get("src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv"); try (CSVParser parser = CSVParser.parse(path, Charset.defaultCharset(), null)) { // null maps to DEFAULT. @@ -1471,7 +1471,7 @@ public void testParsePathCharsetNullFormat() throws IOException { } @Test - public void testParserUrlNullCharsetFormat() throws IOException { + void testParserUrlNullCharsetFormat() throws IOException { final URL url = ClassLoader.getSystemClassLoader().getResource("org/apache/commons/csv/CSVFileParser/test.csv"); try (CSVParser parser = CSVParser.parse(url, null, CSVFormat.DEFAULT)) { // null maps to DEFAULT. @@ -1480,7 +1480,7 @@ public void testParserUrlNullCharsetFormat() throws IOException { } @Test - public void testParseStringNullFormat() throws IOException { + void testParseStringNullFormat() throws IOException { try (CSVParser parser = CSVParser.parse("1,2,3", null)) { // null maps to DEFAULT. final List records = parser.getRecords(); @@ -1494,7 +1494,7 @@ public void testParseStringNullFormat() throws IOException { } @Test - public void testParseUrlCharsetNullFormat() throws IOException { + void testParseUrlCharsetNullFormat() throws IOException { final URL url = ClassLoader.getSystemClassLoader().getResource("org/apache/commons/csv/CSVFileParser/test.csv"); try (CSVParser parser = CSVParser.parse(url, Charset.defaultCharset(), null)) { // null maps to DEFAULT. @@ -1503,7 +1503,7 @@ public void testParseUrlCharsetNullFormat() throws IOException { } @Test - public void testParseWithDelimiterStringWithEscape() throws IOException { + 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))) { @@ -1517,7 +1517,7 @@ public void testParseWithDelimiterStringWithEscape() throws IOException { } @Test - public void testParseWithDelimiterStringWithQuote() throws IOException { + 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))) { @@ -1531,7 +1531,7 @@ public void testParseWithDelimiterStringWithQuote() throws IOException { } @Test - public void testParseWithDelimiterWithEscape() throws IOException { + 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))) { @@ -1542,7 +1542,7 @@ public void testParseWithDelimiterWithEscape() throws IOException { } @Test - public void testParseWithDelimiterWithQuote() throws IOException { + 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))) { @@ -1553,7 +1553,7 @@ public void testParseWithDelimiterWithQuote() throws IOException { } @Test - public void testParseWithQuoteThrowsException() { + 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()); @@ -1561,7 +1561,7 @@ public void testParseWithQuoteThrowsException() { } @Test - public void testParseWithQuoteWithEscape() throws IOException { + 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))) { @@ -1573,7 +1573,7 @@ public void testParseWithQuoteWithEscape() throws IOException { @ParameterizedTest @EnumSource(CSVFormat.Predefined.class) - public void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format) throws Exception { + 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())) { @@ -1591,7 +1591,7 @@ public void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format } @Test - public void testProvidedHeader() throws Exception { + 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(); @@ -1611,7 +1611,7 @@ public void testProvidedHeader() throws Exception { } @Test - public void testProvidedHeaderAuto() throws Exception { + 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(); @@ -1631,7 +1631,7 @@ public void testProvidedHeaderAuto() throws Exception { } @Test - public void testRepeatedHeadersAreReturnedInCSVRecordHeaderNames() throws IOException { + 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(); @@ -1643,7 +1643,7 @@ public void testRepeatedHeadersAreReturnedInCSVRecordHeaderNames() throws IOExce } @Test - public void testRoundtrip() throws Exception { + 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); @@ -1656,7 +1656,7 @@ public void testRoundtrip() throws Exception { } @Test - public void testSkipAutoHeader() throws Exception { + 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(); @@ -1668,7 +1668,7 @@ public void testSkipAutoHeader() throws Exception { } @Test - public void testSkipHeaderOverrideDuplicateHeaders() throws Exception { + 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(); @@ -1680,7 +1680,7 @@ public void testSkipHeaderOverrideDuplicateHeaders() throws Exception { } @Test - public void testSkipSetAltHeaders() throws Exception { + 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(); @@ -1692,7 +1692,7 @@ public void testSkipSetAltHeaders() throws Exception { } @Test - public void testSkipSetHeader() throws Exception { + 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(); @@ -1705,7 +1705,7 @@ public void testSkipSetHeader() throws Exception { @Test @Disabled - public void testStartWithEmptyLinesThenHeaders() throws Exception { + 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 { "" } }; @@ -1722,7 +1722,7 @@ public void testStartWithEmptyLinesThenHeaders() throws Exception { } @Test - public void testStream() throws Exception { + 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()); @@ -1735,7 +1735,7 @@ public void testStream() throws Exception { @ParameterizedTest @ValueSource(longs = { -1, 0, 1, 2, 3, 4, Long.MAX_VALUE }) - public void testStreamMaxRows(final long maxRows) throws Exception { + void testStreamMaxRows(final long maxRows) throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); try (CSVParser parser = CSVFormat.DEFAULT.builder().setMaxRows(maxRows).get().parse(in)) { final List list = parser.stream().collect(Collectors.toList()); @@ -1751,7 +1751,7 @@ public void testStreamMaxRows(final long maxRows) throws Exception { } @Test - public void testThrowExceptionWithLineAndPosition() throws IOException { + 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 @@ -1769,7 +1769,7 @@ public void testThrowExceptionWithLineAndPosition() throws IOException { } @Test - public void testTrailingDelimiter() throws Exception { + 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(); @@ -1782,7 +1782,7 @@ public void testTrailingDelimiter() throws Exception { } @Test - public void testTrim() throws Exception { + 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(); diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index a1a59cf4f..d9d751987 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -265,7 +265,7 @@ private void setUpTable(final Connection connection) throws SQLException { } @Test - public void testCloseBackwardCompatibility() throws IOException { + void testCloseBackwardCompatibility() throws IOException { try (Writer writer = mock(Writer.class)) { final CSVFormat csvFormat = CSVFormat.DEFAULT; try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) { @@ -277,7 +277,7 @@ public void testCloseBackwardCompatibility() throws IOException { } @Test - public void testCloseWithCsvFormatAutoFlushOff() throws IOException { + void testCloseWithCsvFormatAutoFlushOff() throws IOException { try (Writer writer = mock(Writer.class)) { final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(false); try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) { @@ -289,7 +289,7 @@ public void testCloseWithCsvFormatAutoFlushOff() throws IOException { } @Test - public void testCloseWithCsvFormatAutoFlushOn() throws IOException { + void testCloseWithCsvFormatAutoFlushOn() throws IOException { // System.out.println("start method"); try (Writer writer = mock(Writer.class)) { final CSVFormat csvFormat = CSVFormat.DEFAULT.withAutoFlush(true); @@ -302,7 +302,7 @@ public void testCloseWithCsvFormatAutoFlushOn() throws IOException { } @Test - public void testCloseWithFlushOff() throws IOException { + void testCloseWithFlushOff() throws IOException { try (Writer writer = mock(Writer.class)) { final CSVFormat csvFormat = CSVFormat.DEFAULT; @SuppressWarnings("resource") @@ -316,7 +316,7 @@ public void testCloseWithFlushOff() throws IOException { } @Test - public void testCloseWithFlushOn() throws IOException { + void testCloseWithFlushOn() throws IOException { try (Writer writer = mock(Writer.class)) { @SuppressWarnings("resource") final CSVPrinter printer = new CSVPrinter(writer, CSVFormat.DEFAULT); @@ -328,7 +328,7 @@ public void testCloseWithFlushOn() throws IOException { } @Test - public void testCRComment() throws IOException { + void testCRComment() throws IOException { final StringWriter sw = new StringWriter(); final Object value = "abc"; try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) { @@ -343,7 +343,7 @@ public void testCRComment() throws IOException { } @Test - public void testCSV135() throws IOException { + void testCSV135() throws IOException { final List list = new LinkedList<>(); list.add("\"\""); // "" list.add("\\\\"); // \\ @@ -366,7 +366,7 @@ public void testCSV135() throws IOException { } @Test - public void testCSV259() throws IOException { + 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))) { @@ -377,7 +377,7 @@ public void testCSV259() throws IOException { } @Test - public void testDelimeterQuoted() throws IOException { + void testDelimeterQuoted() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) { assertInitialState(printer); @@ -388,7 +388,7 @@ public void testDelimeterQuoted() throws IOException { } @Test - public void testDelimeterQuoteNone() throws IOException { + 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)) { @@ -400,7 +400,7 @@ public void testDelimeterQuoteNone() throws IOException { } @Test - public void testDelimeterStringQuoted() throws IOException { + void testDelimeterStringQuoted() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.builder().setDelimiter("[|]").setQuote('\'').get())) { assertInitialState(printer); @@ -411,7 +411,7 @@ public void testDelimeterStringQuoted() throws IOException { } @Test - public void testDelimeterStringQuoteNone() throws IOException { + 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)) { @@ -424,7 +424,7 @@ public void testDelimeterStringQuoteNone() throws IOException { } @Test - public void testDelimiterEscaped() throws IOException { + void testDelimiterEscaped() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape('!').withQuote(null))) { assertInitialState(printer); @@ -435,7 +435,7 @@ public void testDelimiterEscaped() throws IOException { } @Test - public void testDelimiterPlain() throws IOException { + void testDelimiterPlain() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) { assertInitialState(printer); @@ -446,7 +446,7 @@ public void testDelimiterPlain() throws IOException { } @Test - public void testDelimiterStringEscaped() throws IOException { + 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); @@ -457,7 +457,7 @@ public void testDelimiterStringEscaped() throws IOException { } @Test - public void testDisabledComment() throws IOException { + void testDisabledComment() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -468,7 +468,7 @@ public void testDisabledComment() throws IOException { } @Test - public void testDontQuoteEuroFirstChar() throws IOException { + void testDontQuoteEuroFirstChar() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) { assertInitialState(printer); @@ -478,7 +478,7 @@ public void testDontQuoteEuroFirstChar() throws IOException { } @Test - public void testEolEscaped() throws IOException { + void testEolEscaped() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) { assertInitialState(printer); @@ -489,7 +489,7 @@ public void testEolEscaped() throws IOException { } @Test - public void testEolPlain() throws IOException { + void testEolPlain() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) { assertInitialState(printer); @@ -500,7 +500,7 @@ public void testEolPlain() throws IOException { } @Test - public void testEolQuoted() throws IOException { + void testEolQuoted() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) { assertInitialState(printer); @@ -512,7 +512,7 @@ public void testEolQuoted() throws IOException { @SuppressWarnings("unlikely-arg-type") @Test - public void testEquals() throws IOException { + void testEquals() throws IOException { // Don't use assertNotEquals here assertFalse(CSVFormat.DEFAULT.equals(null)); // Don't use assertNotEquals here @@ -520,7 +520,7 @@ public void testEquals() throws IOException { } @Test - public void testEscapeBackslash1() throws IOException { + void testEscapeBackslash1() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) { assertInitialState(printer); @@ -530,7 +530,7 @@ public void testEscapeBackslash1() throws IOException { } @Test - public void testEscapeBackslash2() throws IOException { + void testEscapeBackslash2() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) { assertInitialState(printer); @@ -540,7 +540,7 @@ public void testEscapeBackslash2() throws IOException { } @Test - public void testEscapeBackslash3() throws IOException { + void testEscapeBackslash3() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) { assertInitialState(printer); @@ -550,7 +550,7 @@ public void testEscapeBackslash3() throws IOException { } @Test - public void testEscapeBackslash4() throws IOException { + void testEscapeBackslash4() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) { assertInitialState(printer); @@ -560,7 +560,7 @@ public void testEscapeBackslash4() throws IOException { } @Test - public void testEscapeBackslash5() throws IOException { + void testEscapeBackslash5() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(QUOTE_CH))) { assertInitialState(printer); @@ -570,7 +570,7 @@ public void testEscapeBackslash5() throws IOException { } @Test - public void testEscapeNull1() throws IOException { + void testEscapeNull1() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) { assertInitialState(printer); @@ -580,7 +580,7 @@ public void testEscapeNull1() throws IOException { } @Test - public void testEscapeNull2() throws IOException { + void testEscapeNull2() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) { assertInitialState(printer); @@ -590,7 +590,7 @@ public void testEscapeNull2() throws IOException { } @Test - public void testEscapeNull3() throws IOException { + void testEscapeNull3() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) { assertInitialState(printer); @@ -600,7 +600,7 @@ public void testEscapeNull3() throws IOException { } @Test - public void testEscapeNull4() throws IOException { + void testEscapeNull4() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) { assertInitialState(printer); @@ -610,7 +610,7 @@ public void testEscapeNull4() throws IOException { } @Test - public void testEscapeNull5() throws IOException { + void testEscapeNull5() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withEscape(null))) { assertInitialState(printer); @@ -620,7 +620,7 @@ public void testEscapeNull5() throws IOException { } @Test - public void testExcelPrintAllArrayOfArrays() throws IOException { + void testExcelPrintAllArrayOfArrays() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -630,7 +630,7 @@ public void testExcelPrintAllArrayOfArrays() throws IOException { } @Test - public void testExcelPrintAllArrayOfArraysWithFirstEmptyValue2() throws IOException { + void testExcelPrintAllArrayOfArraysWithFirstEmptyValue2() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -640,7 +640,7 @@ public void testExcelPrintAllArrayOfArraysWithFirstEmptyValue2() throws IOExcept } @Test - public void testExcelPrintAllArrayOfArraysWithFirstSpaceValue1() throws IOException { + void testExcelPrintAllArrayOfArraysWithFirstSpaceValue1() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -650,7 +650,7 @@ public void testExcelPrintAllArrayOfArraysWithFirstSpaceValue1() throws IOExcept } @Test - public void testExcelPrintAllArrayOfArraysWithFirstTabValue1() throws IOException { + void testExcelPrintAllArrayOfArraysWithFirstTabValue1() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -660,7 +660,7 @@ public void testExcelPrintAllArrayOfArraysWithFirstTabValue1() throws IOExceptio } @Test - public void testExcelPrintAllArrayOfLists() throws IOException { + void testExcelPrintAllArrayOfLists() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -670,7 +670,7 @@ public void testExcelPrintAllArrayOfLists() throws IOException { } @Test - public void testExcelPrintAllArrayOfListsWithFirstEmptyValue2() throws IOException { + void testExcelPrintAllArrayOfListsWithFirstEmptyValue2() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -680,7 +680,7 @@ public void testExcelPrintAllArrayOfListsWithFirstEmptyValue2() throws IOExcepti } @Test - public void testExcelPrintAllIterableOfArrays() throws IOException { + void testExcelPrintAllIterableOfArrays() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -690,7 +690,7 @@ public void testExcelPrintAllIterableOfArrays() throws IOException { } @Test - public void testExcelPrintAllIterableOfArraysWithFirstEmptyValue2() throws IOException { + void testExcelPrintAllIterableOfArraysWithFirstEmptyValue2() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -700,7 +700,7 @@ public void testExcelPrintAllIterableOfArraysWithFirstEmptyValue2() throws IOExc } @Test - public void testExcelPrintAllIterableOfLists() throws IOException { + void testExcelPrintAllIterableOfLists() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -711,7 +711,7 @@ public void testExcelPrintAllIterableOfLists() throws IOException { @ParameterizedTest @ValueSource(longs = { -1, 0, 1, 2, Long.MAX_VALUE }) - public void testExcelPrintAllStreamOfArrays(final long maxRows) throws IOException { + void testExcelPrintAllStreamOfArrays(final long maxRows) throws IOException { final StringWriter sw = new StringWriter(); final CSVFormat format = CSVFormat.EXCEL.builder().setMaxRows(maxRows).get(); try (CSVPrinter printer = new CSVPrinter(sw, format)) { @@ -726,7 +726,7 @@ public void testExcelPrintAllStreamOfArrays(final long maxRows) throws IOExcepti } @Test - public void testExcelPrinter1() throws IOException { + void testExcelPrinter1() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -736,7 +736,7 @@ public void testExcelPrinter1() throws IOException { } @Test - public void testExcelPrinter2() throws IOException { + void testExcelPrinter2() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.EXCEL)) { assertInitialState(printer); @@ -746,7 +746,7 @@ public void testExcelPrinter2() throws IOException { } @Test - public void testHeader() throws IOException { + 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()); @@ -757,7 +757,7 @@ public void testHeader() throws IOException { } @Test - public void testHeaderCommentExcel() throws IOException { + void testHeaderCommentExcel() throws IOException { final StringWriter sw = new StringWriter(); final Date now = new Date(); final CSVFormat format = CSVFormat.EXCEL; @@ -767,7 +767,7 @@ public void testHeaderCommentExcel() throws IOException { } @Test - public void testHeaderCommentTdf() throws IOException { + void testHeaderCommentTdf() throws IOException { final StringWriter sw = new StringWriter(); final Date now = new Date(); final CSVFormat format = CSVFormat.TDF; @@ -777,7 +777,7 @@ public void testHeaderCommentTdf() throws IOException { } @Test - public void testHeaderNotSet() throws IOException { + void testHeaderNotSet() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) { assertInitialState(printer); @@ -788,12 +788,12 @@ public void testHeaderNotSet() throws IOException { } @Test - public void testInvalidFormat() { + void testInvalidFormat() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withDelimiter(CR)); } @Test - public void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException { + void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); final CSVFormat csvFormat = CSVFormat.DEFAULT; try (Connection connection = getH2Connection()) { @@ -827,7 +827,7 @@ record = csvParser.nextRecord(); } @Test - public void testJdbcPrinterWithFirstEmptyValue2() throws IOException, ClassNotFoundException, SQLException { + void testJdbcPrinterWithFirstEmptyValue2() throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); try (Connection connection = getH2Connection()) { try (Statement stmt = connection.createStatement(); @@ -841,7 +841,7 @@ public void testJdbcPrinterWithFirstEmptyValue2() throws IOException, ClassNotFo @ParameterizedTest @ValueSource(longs = { -1, 0, 1, 2, 3, 4, Long.MAX_VALUE }) - public void testJdbcPrinterWithResultSet(final long maxRows) throws IOException, ClassNotFoundException, SQLException { + void testJdbcPrinterWithResultSet(final long maxRows) throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); final CSVFormat format = CSVFormat.DEFAULT.builder().setMaxRows(maxRows).get(); try (Connection connection = getH2Connection()) { @@ -869,7 +869,7 @@ public void testJdbcPrinterWithResultSet(final long maxRows) throws IOException, @ParameterizedTest @ValueSource(longs = { -1, 0, 3, 4, Long.MAX_VALUE }) - public void testJdbcPrinterWithResultSetHeader(final long maxRows) throws IOException, ClassNotFoundException, SQLException { + void testJdbcPrinterWithResultSetHeader(final long maxRows) throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); try (Connection connection = getH2Connection()) { setUpTable(connection); @@ -894,7 +894,7 @@ public void testJdbcPrinterWithResultSetHeader(final long maxRows) throws IOExce @ParameterizedTest @ValueSource(longs = { -1, 0, 3, 4, Long.MAX_VALUE }) - public void testJdbcPrinterWithResultSetMetaData(final long maxRows) throws IOException, ClassNotFoundException, SQLException { + void testJdbcPrinterWithResultSetMetaData(final long maxRows) throws IOException, ClassNotFoundException, SQLException { final StringWriter sw = new StringWriter(); try (Connection connection = getH2Connection()) { setUpTable(connection); @@ -914,7 +914,7 @@ public void testJdbcPrinterWithResultSetMetaData(final long maxRows) throws IOEx } @Test - public void testJira135_part1() throws IOException { + 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<>(); @@ -930,7 +930,7 @@ public void testJira135_part1() throws IOException { @Test @Disabled - public void testJira135_part2() throws IOException { + 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<>(); @@ -945,7 +945,7 @@ public void testJira135_part2() throws IOException { } @Test - public void testJira135_part3() throws IOException { + 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<>(); @@ -961,7 +961,7 @@ public void testJira135_part3() throws IOException { @Test @Disabled - public void testJira135All() throws IOException { + 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<>(); @@ -978,7 +978,7 @@ public void testJira135All() throws IOException { } @Test - public void testMongoDbCsvBasic() throws IOException { + void testMongoDbCsvBasic() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) { printer.printRecord("a", "b"); @@ -988,7 +988,7 @@ public void testMongoDbCsvBasic() throws IOException { } @Test - public void testMongoDbCsvCommaInValue() throws IOException { + void testMongoDbCsvCommaInValue() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) { printer.printRecord("a,b", "c"); @@ -998,7 +998,7 @@ public void testMongoDbCsvCommaInValue() throws IOException { } @Test - public void testMongoDbCsvDoubleQuoteInValue() throws IOException { + void testMongoDbCsvDoubleQuoteInValue() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) { printer.printRecord("a \"c\" b", "d"); @@ -1008,7 +1008,7 @@ public void testMongoDbCsvDoubleQuoteInValue() throws IOException { } @Test - public void testMongoDbCsvTabInValue() throws IOException { + void testMongoDbCsvTabInValue() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_CSV)) { printer.printRecord("a\tb", "c"); @@ -1018,7 +1018,7 @@ public void testMongoDbCsvTabInValue() throws IOException { } @Test - public void testMongoDbTsvBasic() throws IOException { + void testMongoDbTsvBasic() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) { printer.printRecord("a", "b"); @@ -1028,7 +1028,7 @@ public void testMongoDbTsvBasic() throws IOException { } @Test - public void testMongoDbTsvCommaInValue() throws IOException { + void testMongoDbTsvCommaInValue() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) { printer.printRecord("a,b", "c"); @@ -1038,7 +1038,7 @@ public void testMongoDbTsvCommaInValue() throws IOException { } @Test - public void testMongoDbTsvTabInValue() throws IOException { + void testMongoDbTsvTabInValue() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.MONGODB_TSV)) { printer.printRecord("a\tb", "c"); @@ -1047,7 +1047,7 @@ public void testMongoDbTsvTabInValue() throws IOException { } @Test - public void testMultiLineComment() throws IOException { + 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"); @@ -1057,7 +1057,7 @@ public void testMultiLineComment() throws IOException { } @Test - public void testMySqlNullOutput() throws IOException { + 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(); @@ -1159,22 +1159,22 @@ public void testMySqlNullOutput() throws IOException { } @Test - public void testMySqlNullStringDefault() { + void testMySqlNullStringDefault() { assertEquals("\\N", CSVFormat.MYSQL.getNullString()); } @Test - public void testNewCsvPrinterAppendableNullFormat() { + void testNewCsvPrinterAppendableNullFormat() { assertThrows(NullPointerException.class, () -> new CSVPrinter(new StringWriter(), null)); } @Test - public void testNewCsvPrinterNullAppendableFormat() { + void testNewCsvPrinterNullAppendableFormat() { assertThrows(NullPointerException.class, () -> new CSVPrinter(null, CSVFormat.DEFAULT)); } @Test - public void testNotFlushable() throws IOException { + void testNotFlushable() throws IOException { final Appendable out = new StringBuilder(); try (CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT)) { printer.printRecord("a", "b", "c"); @@ -1184,7 +1184,7 @@ public void testNotFlushable() throws IOException { } @Test - public void testParseCustomNullValues() throws IOException { + void testParseCustomNullValues() throws IOException { final StringWriter sw = new StringWriter(); final CSVFormat format = CSVFormat.DEFAULT.withNullString("NULL"); try (CSVPrinter printer = new CSVPrinter(sw, format)) { @@ -1203,7 +1203,7 @@ public void testParseCustomNullValues() throws IOException { } @Test - public void testPlainEscaped() throws IOException { + void testPlainEscaped() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null).withEscape('!'))) { printer.print("abc"); @@ -1213,7 +1213,7 @@ public void testPlainEscaped() throws IOException { } @Test - public void testPlainPlain() throws IOException { + void testPlainPlain() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) { printer.print("abc"); @@ -1223,7 +1223,7 @@ public void testPlainPlain() throws IOException { } @Test - public void testPlainQuoted() throws IOException { + void testPlainQuoted() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) { printer.print("abc"); @@ -1233,7 +1233,7 @@ public void testPlainQuoted() throws IOException { @Test @Disabled - public void testPostgreSqlCsvNullOutput() throws IOException { + 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(); @@ -1336,7 +1336,7 @@ public void testPostgreSqlCsvNullOutput() throws IOException { @Test @Disabled - public void testPostgreSqlCsvTextOutput() throws IOException { + 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(); @@ -1438,17 +1438,17 @@ public void testPostgreSqlCsvTextOutput() throws IOException { } @Test - public void testPostgreSqlNullStringDefaultCsv() { + void testPostgreSqlNullStringDefaultCsv() { assertEquals("", CSVFormat.POSTGRESQL_CSV.getNullString()); } @Test - public void testPostgreSqlNullStringDefaultText() { + void testPostgreSqlNullStringDefaultText() { assertEquals("\\N", CSVFormat.POSTGRESQL_TEXT.getNullString()); } @Test - public void testPrint() throws IOException { + void testPrint() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = CSVFormat.DEFAULT.print(sw)) { assertInitialState(printer); @@ -1458,7 +1458,7 @@ public void testPrint() throws IOException { } @Test - public void testPrintCSVParser() throws IOException { + void testPrintCSVParser() throws IOException { // @formatter:off final String code = "a1,b1\n" + // 1) "a2,b2\n" + // 2) @@ -1481,7 +1481,7 @@ public void testPrintCSVParser() throws IOException { } @Test - public void testPrintCSVRecord() throws IOException { + void testPrintCSVRecord() throws IOException { // @formatter:off final String code = "a1,b1\n" + // 1) "a2,b2\n" + // 2) @@ -1510,7 +1510,7 @@ public void testPrintCSVRecord() throws IOException { @ParameterizedTest @ValueSource(longs = { -1, 0, 3, 4, Long.MAX_VALUE }) - public void testPrintCSVRecords(final long maxRows) throws IOException { + void testPrintCSVRecords(final long maxRows) throws IOException { // @formatter:off final String code = "a1,b1\n" + // 1) "a2,b2\n" + // 2) @@ -1533,7 +1533,7 @@ public void testPrintCSVRecords(final long maxRows) throws IOException { } @Test - public void testPrintCustomNullValues() throws IOException { + void testPrintCustomNullValues() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withNullString("NULL"))) { assertInitialState(printer); @@ -1543,7 +1543,7 @@ public void testPrintCustomNullValues() throws IOException { } @Test - public void testPrinter1() throws IOException { + void testPrinter1() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1554,7 +1554,7 @@ public void testPrinter1() throws IOException { } @Test - public void testPrinter2() throws IOException { + void testPrinter2() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1564,7 +1564,7 @@ public void testPrinter2() throws IOException { } @Test - public void testPrinter3() throws IOException { + void testPrinter3() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1574,7 +1574,7 @@ public void testPrinter3() throws IOException { } @Test - public void testPrinter4() throws IOException { + void testPrinter4() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1584,7 +1584,7 @@ public void testPrinter4() throws IOException { } @Test - public void testPrinter5() throws IOException { + void testPrinter5() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1594,7 +1594,7 @@ public void testPrinter5() throws IOException { } @Test - public void testPrinter6() throws IOException { + void testPrinter6() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1604,7 +1604,7 @@ public void testPrinter6() throws IOException { } @Test - public void testPrinter7() throws IOException { + void testPrinter7() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1614,7 +1614,7 @@ public void testPrinter7() throws IOException { } @Test - public void testPrintNullValues() throws IOException { + void testPrintNullValues() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT)) { assertInitialState(printer); @@ -1624,7 +1624,7 @@ public void testPrintNullValues() throws IOException { } @Test - public void testPrintOnePositiveInteger() throws IOException { + void testPrintOnePositiveInteger() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.MINIMAL))) { assertInitialState(printer); @@ -1644,7 +1644,7 @@ public void testPrintOnePositiveInteger() throws IOException { * @throws IOException Not expected to happen */ @Test - public void testPrintReaderWithoutQuoteToAppendable() throws IOException { + void testPrintReaderWithoutQuoteToAppendable() throws IOException { final StringBuilder sb = new StringBuilder(); final String content = "testValue"; try (CSVPrinter printer = new CSVPrinter(sb, CSVFormat.DEFAULT.withQuote(null))) { @@ -1665,7 +1665,7 @@ public void testPrintReaderWithoutQuoteToAppendable() throws IOException { * @throws IOException Not expected to happen */ @Test - public void testPrintReaderWithoutQuoteToWriter() throws IOException { + void testPrintReaderWithoutQuoteToWriter() throws IOException { final StringWriter sw = new StringWriter(); final String content = "testValue"; try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote(null))) { @@ -1676,7 +1676,7 @@ public void testPrintReaderWithoutQuoteToWriter() throws IOException { } @Test - public void testPrintRecordStream() throws IOException { + void testPrintRecordStream() throws IOException { // @formatter:off final String code = "a1,b1\n" + // 1) "a2,b2\n" + // 2) @@ -1702,7 +1702,7 @@ public void testPrintRecordStream() throws IOException { } @Test - public void testPrintRecordsWithCSVRecord() throws IOException { + void testPrintRecordsWithCSVRecord() throws IOException { final String[] values = { "A", "B", "C" }; final String rowData = StringUtils.join(values, ','); final CharArrayWriter charArrayWriter = new CharArrayWriter(0); @@ -1719,7 +1719,7 @@ public void testPrintRecordsWithCSVRecord() throws IOException { } @Test - public void testPrintRecordsWithEmptyVector() throws IOException { + void testPrintRecordsWithEmptyVector() throws IOException { final PrintStream out = System.out; try { System.setOut(new PrintStream(NullOutputStream.INSTANCE)); @@ -1737,7 +1737,7 @@ public void testPrintRecordsWithEmptyVector() throws IOException { } @Test - public void testPrintRecordsWithObjectArray() throws IOException { + void testPrintRecordsWithObjectArray() throws IOException { final CharArrayWriter charArrayWriter = new CharArrayWriter(0); final Object[] objectArray = new Object[6]; try (CSVPrinter printer = CSVFormat.INFORMIX_UNLOAD.print(charArrayWriter)) { @@ -1751,7 +1751,7 @@ public void testPrintRecordsWithObjectArray() throws IOException { } @Test - public void testPrintRecordsWithResultSetOneRow() throws IOException, SQLException { + void testPrintRecordsWithResultSetOneRow() throws IOException, SQLException { try (CSVPrinter printer = CSVFormat.MYSQL.printer()) { try (ResultSet resultSet = new SimpleResultSet()) { assertInitialState(printer); @@ -1763,7 +1763,7 @@ public void testPrintRecordsWithResultSetOneRow() throws IOException, SQLExcepti } @Test - public void testPrintToFileWithCharsetUtf16Be() throws IOException { + void testPrintToFileWithCharsetUtf16Be() throws IOException { final File file = createTempFile(); try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, StandardCharsets.UTF_16BE)) { printer.printRecord("a", "b\\c"); @@ -1772,7 +1772,7 @@ public void testPrintToFileWithCharsetUtf16Be() throws IOException { } @Test - public void testPrintToFileWithDefaultCharset() throws IOException { + void testPrintToFileWithDefaultCharset() throws IOException { final File file = createTempFile(); try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, Charset.defaultCharset())) { printer.printRecord("a", "b\\c"); @@ -1781,7 +1781,7 @@ public void testPrintToFileWithDefaultCharset() throws IOException { } @Test - public void testPrintToPathWithDefaultCharset() throws IOException { + void testPrintToPathWithDefaultCharset() throws IOException { final Path file = createTempPath(); try (CSVPrinter printer = CSVFormat.DEFAULT.print(file, Charset.defaultCharset())) { printer.printRecord("a", "b\\c"); @@ -1790,7 +1790,7 @@ public void testPrintToPathWithDefaultCharset() throws IOException { } @Test - public void testQuoteAll() throws IOException { + 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"); @@ -1799,7 +1799,7 @@ public void testQuoteAll() throws IOException { } @Test - public void testQuoteCommaFirstChar() throws IOException { + void testQuoteCommaFirstChar() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.RFC4180)) { printer.printRecord(","); @@ -1808,7 +1808,7 @@ public void testQuoteCommaFirstChar() throws IOException { } @Test - public void testQuoteNonNumeric() throws IOException { + 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)); @@ -1817,55 +1817,55 @@ public void testQuoteNonNumeric() throws IOException { } @Test - public void testRandomDefault() throws Exception { + void testRandomDefault() throws Exception { doRandom(CSVFormat.DEFAULT, ITERATIONS_FOR_RANDOM_TEST); } @Test - public void testRandomExcel() throws Exception { + void testRandomExcel() throws Exception { doRandom(CSVFormat.EXCEL, ITERATIONS_FOR_RANDOM_TEST); } @Test @Disabled - public void testRandomMongoDbCsv() throws Exception { + void testRandomMongoDbCsv() throws Exception { doRandom(CSVFormat.MONGODB_CSV, ITERATIONS_FOR_RANDOM_TEST); } @Test - public void testRandomMySql() throws Exception { + void testRandomMySql() throws Exception { doRandom(CSVFormat.MYSQL, ITERATIONS_FOR_RANDOM_TEST); } @Test @Disabled - public void testRandomOracle() throws Exception { + void testRandomOracle() throws Exception { doRandom(CSVFormat.ORACLE, ITERATIONS_FOR_RANDOM_TEST); } @Test @Disabled - public void testRandomPostgreSqlCsv() throws Exception { + void testRandomPostgreSqlCsv() throws Exception { doRandom(CSVFormat.POSTGRESQL_CSV, ITERATIONS_FOR_RANDOM_TEST); } @Test - public void testRandomPostgreSqlText() throws Exception { + void testRandomPostgreSqlText() throws Exception { doRandom(CSVFormat.POSTGRESQL_TEXT, ITERATIONS_FOR_RANDOM_TEST); } @Test - public void testRandomRfc4180() throws Exception { + void testRandomRfc4180() throws Exception { doRandom(CSVFormat.RFC4180, ITERATIONS_FOR_RANDOM_TEST); } @Test - public void testRandomTdf() throws Exception { + void testRandomTdf() throws Exception { doRandom(CSVFormat.TDF, ITERATIONS_FOR_RANDOM_TEST); } @Test - public void testSingleLineComment() throws IOException { + void testSingleLineComment() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withCommentMarker('#'))) { printer.printComment("This is a comment"); @@ -1875,7 +1875,7 @@ public void testSingleLineComment() throws IOException { } @Test - public void testSingleQuoteQuoted() throws IOException { + void testSingleQuoteQuoted() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withQuote('\''))) { printer.print("a'b'c"); @@ -1885,7 +1885,7 @@ public void testSingleQuoteQuoted() throws IOException { } @Test - public void testSkipHeaderRecordFalse() throws IOException { + 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))) { @@ -1896,7 +1896,7 @@ public void testSkipHeaderRecordFalse() throws IOException { } @Test - public void testSkipHeaderRecordTrue() throws IOException { + 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))) { @@ -1907,7 +1907,7 @@ public void testSkipHeaderRecordTrue() throws IOException { } @Test - public void testTrailingDelimiterOnTwoColumns() throws IOException { + void testTrailingDelimiterOnTwoColumns() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrailingDelimiter())) { printer.printRecord("A", "B"); @@ -1916,7 +1916,7 @@ public void testTrailingDelimiterOnTwoColumns() throws IOException { } @Test - public void testTrimOffOneColumn() throws IOException { + void testTrimOffOneColumn() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim(false))) { printer.print(" A "); @@ -1925,7 +1925,7 @@ public void testTrimOffOneColumn() throws IOException { } @Test - public void testTrimOnOneColumn() throws IOException { + void testTrimOnOneColumn() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) { printer.print(" A "); @@ -1934,7 +1934,7 @@ public void testTrimOnOneColumn() throws IOException { } @Test - public void testTrimOnTwoColumns() throws IOException { + void testTrimOnTwoColumns() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, CSVFormat.DEFAULT.withTrim())) { printer.print(" A "); diff --git a/src/test/java/org/apache/commons/csv/CSVRecordTest.java b/src/test/java/org/apache/commons/csv/CSVRecordTest.java index f9fedc4b9..1c0e05d36 100644 --- a/src/test/java/org/apache/commons/csv/CSVRecordTest.java +++ b/src/test/java/org/apache/commons/csv/CSVRecordTest.java @@ -86,7 +86,7 @@ record = parser.iterator().next(); } @Test - public void testCSVRecordNULLValues() throws IOException { + void testCSVRecordNULLValues() throws IOException { try (CSVParser parser = CSVParser.parse("A,B\r\nONE,TWO", CSVFormat.DEFAULT.withHeader())) { final CSVRecord csvRecord = new CSVRecord(parser, null, null, 0L, 0L, 0L); assertEquals(0, csvRecord.size()); @@ -95,7 +95,7 @@ public void testCSVRecordNULLValues() throws IOException { } @Test - public void testDuplicateHeaderGet() throws IOException { + void testDuplicateHeaderGet() throws IOException { final String csv = "A,A,B,B\n1,2,5,6\n"; final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader().get(); @@ -110,7 +110,7 @@ public void testDuplicateHeaderGet() throws IOException { } @Test - public void testDuplicateHeaderToMap() throws IOException { + void testDuplicateHeaderToMap() throws IOException { final String csv = "A,A,B,B\n1,2,5,6\n"; final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader().get(); @@ -126,64 +126,64 @@ public void testDuplicateHeaderToMap() throws IOException { } @Test - public void testGetInt() { + void testGetInt() { assertEquals(values[0], record.get(0)); assertEquals(values[1], record.get(1)); assertEquals(values[2], record.get(2)); } @Test - public void testGetNullEnum() { + void testGetNullEnum() { assertThrows(IllegalArgumentException.class, () -> recordWithHeader.get((Enum) null)); } @Test - public void testGetString() { + void testGetString() { assertEquals(values[0], recordWithHeader.get(EnumHeader.FIRST.name())); assertEquals(values[1], recordWithHeader.get(EnumHeader.SECOND.name())); assertEquals(values[2], recordWithHeader.get(EnumHeader.THIRD.name())); } @Test - public void testGetStringInconsistentRecord() { + void testGetStringInconsistentRecord() { headerMap.put("fourth", Integer.valueOf(4)); assertThrows(IllegalArgumentException.class, () -> recordWithHeader.get("fourth")); } @Test - public void testGetStringNoHeader() { + void testGetStringNoHeader() { assertThrows(IllegalStateException.class, () -> record.get("first")); } @Test - public void testGetUnmappedEnum() { + void testGetUnmappedEnum() { assertThrows(IllegalArgumentException.class, () -> recordWithHeader.get(EnumFixture.UNKNOWN_COLUMN)); } @Test - public void testGetUnmappedName() { + void testGetUnmappedName() { assertThrows(IllegalArgumentException.class, () -> assertNull(recordWithHeader.get("fourth"))); } @Test - public void testGetUnmappedNegativeInt() { + void testGetUnmappedNegativeInt() { assertThrows(ArrayIndexOutOfBoundsException.class, () -> recordWithHeader.get(Integer.MIN_VALUE)); } @Test - public void testGetUnmappedPositiveInt() { + void testGetUnmappedPositiveInt() { assertThrows(ArrayIndexOutOfBoundsException.class, () -> recordWithHeader.get(Integer.MAX_VALUE)); } @Test - public void testGetWithEnum() { + void testGetWithEnum() { assertEquals(recordWithHeader.get("FIRST"), recordWithHeader.get(EnumHeader.FIRST)); assertEquals(recordWithHeader.get("SECOND"), recordWithHeader.get(EnumHeader.SECOND)); assertThrows(IllegalArgumentException.class, () -> recordWithHeader.get(EnumFixture.UNKNOWN_COLUMN)); } @Test - public void testIsConsistent() { + void testIsConsistent() { assertTrue(record.isConsistent()); assertTrue(recordWithHeader.isConsistent()); final Map map = recordWithHeader.getParser().getHeaderMap(); @@ -193,7 +193,7 @@ public void testIsConsistent() { } @Test - public void testIsInconsistent() throws IOException { + void testIsInconsistent() throws IOException { final String[] headers = { "first", "second", "third" }; final String rowData = StringUtils.join(values, ','); try (CSVParser parser = CSVFormat.DEFAULT.withHeader(headers).parse(new StringReader(rowData))) { @@ -205,14 +205,14 @@ public void testIsInconsistent() throws IOException { } @Test - public void testIsMapped() { + void testIsMapped() { assertFalse(record.isMapped("first")); assertTrue(recordWithHeader.isMapped(EnumHeader.FIRST.name())); assertFalse(recordWithHeader.isMapped("fourth")); } @Test - public void testIsSetInt() { + void testIsSetInt() { assertFalse(record.isSet(-1)); assertTrue(record.isSet(0)); assertTrue(record.isSet(2)); @@ -222,14 +222,14 @@ public void testIsSetInt() { } @Test - public void testIsSetString() { + void testIsSetString() { assertFalse(record.isSet("first")); assertTrue(recordWithHeader.isSet(EnumHeader.FIRST.name())); assertFalse(recordWithHeader.isSet("DOES NOT EXIST")); } @Test - public void testIterator() { + void testIterator() { int i = 0; for (final String value : record) { assertEquals(values[i], value); @@ -238,7 +238,7 @@ public void testIterator() { } @Test - public void testPutInMap() { + void testPutInMap() { final Map map = new ConcurrentHashMap<>(); this.recordWithHeader.putIn(map); validateMap(map, false); @@ -248,7 +248,7 @@ public void testPutInMap() { } @Test - public void testRemoveAndAddColumns() throws IOException { + void testRemoveAndAddColumns() throws IOException { // do: try (CSVPrinter printer = new CSVPrinter(new StringBuilder(), CSVFormat.DEFAULT)) { final Map map = recordWithHeader.toMap(); @@ -263,7 +263,7 @@ public void testRemoveAndAddColumns() throws IOException { } @Test - public void testSerialization() throws IOException, ClassNotFoundException { + void testSerialization() throws IOException, ClassNotFoundException { final CSVRecord shortRec; try (CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", CSVFormat.DEFAULT.withHeader().withCommentMarker('#'))) { shortRec = parser.iterator().next(); @@ -296,7 +296,7 @@ public void testSerialization() throws IOException, ClassNotFoundException { } @Test - public void testStream() { + void testStream() { final AtomicInteger i = new AtomicInteger(); record.stream().forEach(value -> { assertEquals(values[i.get()], value); @@ -305,7 +305,7 @@ public void testStream() { } @Test - public void testToListAdd() { + void testToListAdd() { final String[] expected = values.clone(); final List list = record.toList(); list.add("Last"); @@ -315,7 +315,7 @@ public void testToListAdd() { } @Test - public void testToListFor() { + void testToListFor() { int i = 0; for (final String value : record.toList()) { assertEquals(values[i], value); @@ -324,7 +324,7 @@ public void testToListFor() { } @Test - public void testToListForEach() { + void testToListForEach() { final AtomicInteger i = new AtomicInteger(); record.toList().forEach(e -> { assertEquals(values[i.getAndIncrement()], e); @@ -332,7 +332,7 @@ public void testToListForEach() { } @Test - public void testToListSet() { + void testToListSet() { final String[] expected = values.clone(); final List list = record.toList(); list.set(list.size() - 1, "Last"); @@ -342,13 +342,13 @@ public void testToListSet() { } @Test - public void testToMap() { + void testToMap() { final Map map = this.recordWithHeader.toMap(); validateMap(map, true); } @Test - public void testToMapWithNoHeader() throws Exception { + void testToMapWithNoHeader() throws Exception { try (CSVParser parser = CSVParser.parse("a,b", CSVFormat.newFormat(','))) { final CSVRecord shortRec = parser.iterator().next(); final Map map = shortRec.toMap(); @@ -358,7 +358,7 @@ public void testToMapWithNoHeader() throws Exception { } @Test - public void testToMapWithShortRecord() throws Exception { + void testToMapWithShortRecord() throws Exception { try (CSVParser parser = CSVParser.parse("a,b", CSVFormat.DEFAULT.withHeader("A", "B", "C"))) { final CSVRecord shortRec = parser.iterator().next(); shortRec.toMap(); @@ -366,7 +366,7 @@ public void testToMapWithShortRecord() throws Exception { } @Test - public void testToString() { + void testToString() { assertNotNull(recordWithHeader.toString()); assertTrue(recordWithHeader.toString().contains("comment=")); assertTrue(recordWithHeader.toString().contains("recordNumber=")); diff --git a/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java b/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java index b7db39f52..9d929c655 100644 --- a/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java +++ b/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java @@ -44,7 +44,7 @@ private ExtendedBufferedReader createBufferedReader(final String s) { } @Test - public void testEmptyInput() throws Exception { + void testEmptyInput() throws Exception { try (ExtendedBufferedReader br = createBufferedReader("")) { assertEquals(EOF, br.read()); assertEquals(EOF, br.peek()); @@ -58,7 +58,7 @@ public void testEmptyInput() throws Exception { * Test to illustrate https://issues.apache.org/jira/browse/CSV-75 */ @Test - public void testReadChar() throws Exception { + void testReadChar() throws Exception { final String test = "a" + LF + "b" + CR + "c" + LF + LF + "d" + CR + CR + "e" + LFCR + "f " + CRLF; // EOL eol EOL EOL eol eol EOL+CR EOL final int eolCount = 9; @@ -94,7 +94,7 @@ public void testReadChar() throws Exception { } @Test - public void testReadingInDifferentBuffer() throws Exception { + void testReadingInDifferentBuffer() throws Exception { final char[] tmp1 = new char[2]; final char[] tmp2 = new char[4]; try (ExtendedBufferedReader reader = createBufferedReader("1\r\n2\r\n")) { @@ -105,7 +105,7 @@ public void testReadingInDifferentBuffer() throws Exception { } @Test - public void testReadLine() throws Exception { + void testReadLine() throws Exception { try (ExtendedBufferedReader br = createBufferedReader("")) { assertNull(br.readLine()); } @@ -148,7 +148,7 @@ public void testReadLine() throws Exception { } @Test - public void testReadLookahead1() throws Exception { + void testReadLookahead1() throws Exception { try (ExtendedBufferedReader br = createBufferedReader("1\n2\r3\n")) { assertEquals(0, br.getLineNumber()); assertEquals('1', br.peek()); @@ -207,7 +207,7 @@ public void testReadLookahead1() throws Exception { } @Test - public void testReadLookahead2() throws Exception { + void testReadLookahead2() throws Exception { final char[] ref = new char[5]; final char[] res = new char[5]; diff --git a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java index ef94efe0f..2beae36ad 100644 --- a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java +++ b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java @@ -35,7 +35,7 @@ private Reader getTestInput(final String path) { } @Test - public void testParseFourBytes() throws IOException { + void testParseFourBytes() throws IOException { final CSVFormat format = CSVFormat.Builder.create().setDelimiter(',').setQuote('\'').get(); // @formatter:off try (@SuppressWarnings("resource") // parser closes the reader. @@ -55,7 +55,7 @@ public void testParseFourBytes() throws IOException { } @Test - public void testParseThreeBytes() throws IOException { + void testParseThreeBytes() throws IOException { final CSVFormat format = CSVFormat.Builder.create().setDelimiter(',').setQuote('\'').get(); // @formatter:off try (@SuppressWarnings("resource") // parser closes the reader. diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index 38ab12553..2c9742692 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -71,7 +71,7 @@ public void setUp() { // simple token with escaping enabled @Test - public void testBackslashWithEscaping() throws IOException { + void testBackslashWithEscaping() throws IOException { /* * file: a,\,,b \,, */ @@ -91,7 +91,7 @@ public void testBackslashWithEscaping() throws IOException { // simple token with escaping not enabled @Test - public void testBackslashWithoutEscaping() throws IOException { + void testBackslashWithoutEscaping() throws IOException { /* * file: a,\,,b \,, */ @@ -113,14 +113,14 @@ public void testBackslashWithoutEscaping() throws IOException { } @Test - public void testBackspace() throws Exception { + void testBackspace() throws Exception { try (Lexer lexer = createLexer("character" + BACKSPACE + "NotEscaped", formatWithEscaping)) { assertNextToken("character" + BACKSPACE + "NotEscaped", lexer); } } @Test - public void testComments() throws IOException { + void testComments() throws IOException { final String code = "first,line,\n" + "second,line,tokenWith#no-comment\n" + "# comment line \n" + "third,line,#no-comment\n" + "# penultimate comment\n" + "# Final comment\n"; final CSVFormat format = CSVFormat.DEFAULT.withCommentMarker('#'); @@ -143,7 +143,7 @@ public void testComments() throws IOException { } @Test - public void testCommentsAndEmptyLines() throws IOException { + void testCommentsAndEmptyLines() throws IOException { final String code = "1,2,3,\n" + // 1 "\n" + // 1b "\n" + // 1c @@ -189,7 +189,7 @@ public void testCommentsAndEmptyLines() throws IOException { } @Test - public void testCR() throws Exception { + void testCR() throws Exception { try (Lexer lexer = createLexer("character" + CR + "NotEscaped", formatWithEscaping)) { assertNextToken("character", lexer); assertNextToken("NotEscaped", lexer); @@ -198,7 +198,7 @@ public void testCR() throws Exception { // From CSV-1 @Test - public void testDelimiterIsWhitespace() throws IOException { + void testDelimiterIsWhitespace() throws IOException { final String code = "one\ttwo\t\tfour \t five\t six"; try (Lexer lexer = createLexer(code, CSVFormat.TDF)) { assertNextToken(TOKEN, "one", lexer); @@ -211,7 +211,7 @@ public void testDelimiterIsWhitespace() throws IOException { } @Test - public void testEOFWithoutClosingQuote() throws Exception { + void testEOFWithoutClosingQuote() throws Exception { final String code = "a,\"b"; try (Lexer lexer = createLexer(code, CSVFormat.Builder.create().setLenientEof(true).get())) { assertNextToken(TOKEN, "a", lexer); @@ -224,21 +224,21 @@ public void testEOFWithoutClosingQuote() throws Exception { } @Test // TODO is this correct? Do we expect BACKSPACE to be unescaped? - public void testEscapedBackspace() throws Exception { + void testEscapedBackspace() throws Exception { try (Lexer lexer = createLexer("character\\" + BACKSPACE + "Escaped", formatWithEscaping)) { assertNextToken("character" + BACKSPACE + "Escaped", lexer); } } @Test - public void testEscapedCharacter() throws Exception { + void testEscapedCharacter() throws Exception { try (Lexer lexer = createLexer("character\\aEscaped", formatWithEscaping)) { assertNextToken("character\\aEscaped", lexer); } } @Test - public void testEscapedControlCharacter() throws Exception { + void testEscapedControlCharacter() throws Exception { // we are explicitly using an escape different from \ here try (Lexer lexer = createLexer("character!rEscaped", CSVFormat.DEFAULT.withEscape('!'))) { assertNextToken("character" + CR + "Escaped", lexer); @@ -246,35 +246,35 @@ public void testEscapedControlCharacter() throws Exception { } @Test - public void testEscapedControlCharacter2() throws Exception { + void testEscapedControlCharacter2() throws Exception { try (Lexer lexer = createLexer("character\\rEscaped", CSVFormat.DEFAULT.withEscape('\\'))) { assertNextToken("character" + CR + "Escaped", lexer); } } @Test - public void testEscapedCR() throws Exception { + void testEscapedCR() throws Exception { try (Lexer lexer = createLexer("character\\" + CR + "Escaped", formatWithEscaping)) { assertNextToken("character" + CR + "Escaped", lexer); } } @Test // TODO is this correct? Do we expect FF to be unescaped? - public void testEscapedFF() throws Exception { + void testEscapedFF() throws Exception { try (Lexer lexer = createLexer("character\\" + FF + "Escaped", formatWithEscaping)) { assertNextToken("character" + FF + "Escaped", lexer); } } @Test - public void testEscapedLF() throws Exception { + void testEscapedLF() throws Exception { try (Lexer lexer = createLexer("character\\" + LF + "Escaped", formatWithEscaping)) { assertNextToken("character" + LF + "Escaped", lexer); } } @Test - public void testEscapedMySqlNullValue() throws Exception { + void testEscapedMySqlNullValue() throws Exception { // MySQL uses \N to symbolize null values. We have to restore this try (Lexer lexer = createLexer("character\\NEscaped", formatWithEscaping)) { assertNextToken("character\\NEscaped", lexer); @@ -282,7 +282,7 @@ public void testEscapedMySqlNullValue() throws Exception { } @Test // TODO is this correct? Do we expect TAB to be unescaped? - public void testEscapedTab() throws Exception { + void testEscapedTab() throws Exception { try (Lexer lexer = createLexer("character\\" + TAB + "Escaped", formatWithEscaping)) { assertNextToken("character" + TAB + "Escaped", lexer); } @@ -290,7 +290,7 @@ public void testEscapedTab() throws Exception { } @Test - public void testEscapingAtEOF() throws Exception { + void testEscapingAtEOF() throws Exception { final String code = "escaping at EOF is evil\\"; try (Lexer lexer = createLexer(code, formatWithEscaping)) { assertThrows(IOException.class, () -> lexer.nextToken(new Token())); @@ -298,14 +298,14 @@ public void testEscapingAtEOF() throws Exception { } @Test - public void testFF() throws Exception { + void testFF() throws Exception { try (Lexer lexer = createLexer("character" + FF + "NotEscaped", formatWithEscaping)) { assertNextToken("character" + FF + "NotEscaped", lexer); } } @Test - public void testIgnoreEmptyLines() throws IOException { + void testIgnoreEmptyLines() throws IOException { final String code = "first,line,\n" + "\n" + "\n" + "second,line\n" + "\n" + "\n" + "third line \n" + "\n" + "\n" + "last, line \n" + "\n" + "\n" + "\n"; final CSVFormat format = CSVFormat.DEFAULT.withIgnoreEmptyLines(); @@ -324,7 +324,7 @@ public void testIgnoreEmptyLines() throws IOException { } @Test - public void testIsMetaCharCommentStart() throws IOException { + void testIsMetaCharCommentStart() throws IOException { try (Lexer lexer = createLexer("#", CSVFormat.DEFAULT.withCommentMarker('#'))) { final int ch = lexer.readEscape(); assertEquals('#', ch); @@ -332,7 +332,7 @@ public void testIsMetaCharCommentStart() throws IOException { } @Test - public void testLF() throws Exception { + void testLF() throws Exception { try (Lexer lexer = createLexer("character" + LF + "NotEscaped", formatWithEscaping)) { assertNextToken("character", lexer); assertNextToken("NotEscaped", lexer); @@ -341,7 +341,7 @@ public void testLF() throws Exception { // encapsulator tokenizer (single line) @Test - public void testNextToken4() throws IOException { + void testNextToken4() throws IOException { /* * file: a,"foo",b a, " foo",b a,"foo " ,b // whitespace after closing encapsulator a, " foo " ,b */ @@ -365,7 +365,7 @@ public void testNextToken4() throws IOException { // encapsulator tokenizer (multi line, delimiter in string) @Test - public void testNextToken5() throws IOException { + void testNextToken5() throws IOException { final String code = "a,\"foo\n\",b\n\"foo\n baar ,,,\"\n\"\n\t \n\""; try (Lexer lexer = createLexer(code, CSVFormat.DEFAULT)) { assertNextToken(TOKEN, "a", lexer); @@ -378,7 +378,7 @@ public void testNextToken5() throws IOException { // change delimiters, comment, encapsulater @Test - public void testNextToken6() throws IOException { + void testNextToken6() throws IOException { /* * file: a;'b and \' more ' !comment;;;; ;; */ @@ -391,7 +391,7 @@ public void testNextToken6() throws IOException { } @Test - public void testReadEscapeBackspace() throws IOException { + void testReadEscapeBackspace() throws IOException { try (Lexer lexer = createLexer("b", CSVFormat.DEFAULT.withEscape('\b'))) { final int ch = lexer.readEscape(); assertEquals(BACKSPACE, ch); @@ -399,7 +399,7 @@ public void testReadEscapeBackspace() throws IOException { } @Test - public void testReadEscapeFF() throws IOException { + void testReadEscapeFF() throws IOException { try (Lexer lexer = createLexer("f", CSVFormat.DEFAULT.withEscape('\f'))) { final int ch = lexer.readEscape(); assertEquals(FF, ch); @@ -407,7 +407,7 @@ public void testReadEscapeFF() throws IOException { } @Test - public void testReadEscapeTab() throws IOException { + void testReadEscapeTab() throws IOException { try (Lexer lexer = createLexer("t", CSVFormat.DEFAULT.withEscape('\t'))) { final int ch = lexer.readEscape(); assertNextToken(EOF, "", lexer); @@ -416,7 +416,7 @@ public void testReadEscapeTab() throws IOException { } @Test - public void testSurroundingSpacesAreDeleted() throws IOException { + void testSurroundingSpacesAreDeleted() throws IOException { final String code = "noSpaces, leadingSpaces,trailingSpaces , surroundingSpaces , ,,"; try (Lexer lexer = createLexer(code, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) { assertNextToken(TOKEN, "noSpaces", lexer); @@ -430,7 +430,7 @@ public void testSurroundingSpacesAreDeleted() throws IOException { } @Test - public void testSurroundingTabsAreDeleted() throws IOException { + void testSurroundingTabsAreDeleted() throws IOException { final String code = "noTabs,\tleadingTab,trailingTab\t,\tsurroundingTabs\t,\t\t,,"; try (Lexer lexer = createLexer(code, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) { assertNextToken(TOKEN, "noTabs", lexer); @@ -444,14 +444,14 @@ public void testSurroundingTabsAreDeleted() throws IOException { } @Test - public void testTab() throws Exception { + void testTab() throws Exception { try (Lexer lexer = createLexer("character" + TAB + "NotEscaped", formatWithEscaping)) { assertNextToken("character" + TAB + "NotEscaped", lexer); } } @Test - public void testTrailingTextAfterQuote() throws Exception { + void testTrailingTextAfterQuote() throws Exception { final String code = "\"a\" b,\"a\" \" b,\"a\" b \"\""; try (Lexer lexer = createLexer(code, CSVFormat.Builder.create().setTrailingData(true).get())) { assertNextToken(TOKEN, "a b", lexer); @@ -464,7 +464,7 @@ public void testTrailingTextAfterQuote() throws Exception { } @Test - public void testTrimTrailingSpacesZeroLength() throws Exception { + void testTrimTrailingSpacesZeroLength() throws Exception { final StringBuilder buffer = new StringBuilder(""); try (Lexer lexer = createLexer(buffer.toString(), CSVFormat.DEFAULT)) { lexer.trimTrailingSpaces(buffer); diff --git a/src/test/java/org/apache/commons/csv/TokenTest.java b/src/test/java/org/apache/commons/csv/TokenTest.java index 0f7f2f1ee..0a90a11ea 100644 --- a/src/test/java/org/apache/commons/csv/TokenTest.java +++ b/src/test/java/org/apache/commons/csv/TokenTest.java @@ -32,7 +32,7 @@ public class TokenTest { @ParameterizedTest @EnumSource(Token.Type.class) - public void testToString(final Token.Type type) { + void testToString(final Token.Type type) { // Should never blow up final Token token = new Token(); final String resetName = Token.Type.INVALID.name(); diff --git a/src/test/java/org/apache/commons/csv/UserGuideTest.java b/src/test/java/org/apache/commons/csv/UserGuideTest.java index 6b97ccded..6f3f77bf6 100644 --- a/src/test/java/org/apache/commons/csv/UserGuideTest.java +++ b/src/test/java/org/apache/commons/csv/UserGuideTest.java @@ -54,7 +54,7 @@ public InputStreamReader newReader(final Path path) throws IOException { } @Test - public void testBomFull() throws UnsupportedEncodingException, IOException { + void testBomFull() throws UnsupportedEncodingException, IOException { final Path path = tempDir.resolve("test1.csv"); Files.copy(Utils.createUtf8Input("ColumnA, ColumnB, ColumnC\r\nA, B, C\r\n".getBytes(StandardCharsets.UTF_8), true), path); // @formatter:off @@ -74,7 +74,7 @@ public void testBomFull() throws UnsupportedEncodingException, IOException { } @Test - public void testBomUtil() throws UnsupportedEncodingException, IOException { + void testBomUtil() throws UnsupportedEncodingException, IOException { final Path path = tempDir.resolve("test2.csv"); Files.copy(Utils.createUtf8Input("ColumnA, ColumnB, ColumnC\r\nA, B, C\r\n".getBytes(StandardCharsets.UTF_8), true), path); try (Reader reader = newReader(path); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java index 71b056834..5289b4a93 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java @@ -27,7 +27,7 @@ public class JiraCsv148Test { @Test - public void testWithIgnoreSurroundingSpacesEmpty() { + void testWithIgnoreSurroundingSpacesEmpty() { // @formatter:off final CSVFormat format = CSVFormat.DEFAULT.builder() .setQuoteMode(QuoteMode.ALL) @@ -47,7 +47,7 @@ public void testWithIgnoreSurroundingSpacesEmpty() { * quotation marks, while withIgnoreSurroundingSpace() cannot The same point: you can remove the leading and trailing spaces, tabs and other symbols. */ @Test - public void testWithTrimEmpty() { + void testWithTrimEmpty() { // @formatter:off final CSVFormat format = CSVFormat.DEFAULT.builder() .setQuoteMode(QuoteMode.ALL) diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java index 5b3d40c9f..c12574f28 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java @@ -34,7 +34,7 @@ public class JiraCsv149Test { private static final String CR_LF = "\r\n"; @Test - public void testJiraCsv149EndWithEOL() throws IOException { + void testJiraCsv149EndWithEOL() throws IOException { testJiraCsv149EndWithEolAtEof(true); } @@ -61,7 +61,7 @@ private void testJiraCsv149EndWithEolAtEof(final boolean eolAtEof) throws IOExce } @Test - public void testJiraCsv149EndWithoutEOL() throws IOException { + void testJiraCsv149EndWithoutEOL() throws IOException { testJiraCsv149EndWithEolAtEof(false); } } diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java index f10477292..5e9feb7dd 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java @@ -36,19 +36,19 @@ private void testDisable(final CSVFormat format, final StringReader reader) thro } @Test - public void testDisableComment() throws IOException { + void testDisableComment() throws IOException { final StringReader stringReader = new StringReader("\"66\u2441\",,\"\",\"DeutscheBK\ufffe\",\"000\"\r\n"); testDisable(CSVFormat.DEFAULT.builder().setCommentMarker(null).get(), stringReader); } @Test - public void testDisableEncapsulation() throws IOException { + void testDisableEncapsulation() throws IOException { final StringReader stringReader = new StringReader("66\u2441,,\"\",\ufffeDeutscheBK,\"000\"\r\n"); testDisable(CSVFormat.DEFAULT.builder().setQuote(null).get(), stringReader); } @Test - public void testDisableEscaping() throws IOException { + void testDisableEscaping() throws IOException { final StringReader stringReader = new StringReader("\"66\u2441\",,\"\",\"DeutscheBK\ufffe\",\"000\"\r\n"); testDisable(CSVFormat.DEFAULT.builder().setEscape(null).get(), stringReader); } diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java index c045cdd26..6276775c9 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java @@ -29,7 +29,7 @@ public class JiraCsv154Test { @Test - public void testJiraCsv154_withCommentMarker() throws IOException { + void testJiraCsv154_withCommentMarker() throws IOException { final String comment = "This is a header comment"; // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() @@ -48,7 +48,7 @@ public void testJiraCsv154_withCommentMarker() throws IOException { } @Test - public void testJiraCsv154_withHeaderComments() throws IOException { + void testJiraCsv154_withHeaderComments() throws IOException { final String comment = "This is a header comment"; // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java index 5caeecd6d..32dd23575 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java @@ -39,7 +39,7 @@ private Reader getTestReader() { } @Test - public void testParse() throws IOException { + void testParse() throws IOException { int totcomment = 0; int totrecs = 0; try (Reader reader = getTestReader(); BufferedReader br = new BufferedReader(reader)) { 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 641797fe8..80b86b611 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java @@ -42,7 +42,7 @@ public class JiraCsv198Test { // @formatter:on @Test - public void test() throws UnsupportedEncodingException, IOException { + 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") diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java index 8eee04156..f467c6785 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java @@ -32,7 +32,7 @@ public class JiraCsv203Test { @Test - public void testQuoteModeAll() throws Exception { + void testQuoteModeAll() throws Exception { // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() .setNullString("N/A") @@ -48,7 +48,7 @@ public void testQuoteModeAll() throws Exception { } @Test - public void testQuoteModeAllNonNull() throws Exception { + void testQuoteModeAllNonNull() throws Exception { // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() .setNullString("N/A") @@ -64,7 +64,7 @@ public void testQuoteModeAllNonNull() throws Exception { } @Test - public void testQuoteModeMinimal() throws Exception { + void testQuoteModeMinimal() throws Exception { // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() .setNullString("N/A") @@ -80,7 +80,7 @@ public void testQuoteModeMinimal() throws Exception { } @Test - public void testQuoteModeNonNumeric() throws Exception { + void testQuoteModeNonNumeric() throws Exception { // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() .setNullString("N/A") @@ -96,7 +96,7 @@ public void testQuoteModeNonNumeric() throws Exception { } @Test - public void testWithEmptyValues() throws Exception { + void testWithEmptyValues() throws Exception { // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() .setNullString("N/A") @@ -113,7 +113,7 @@ public void testWithEmptyValues() throws Exception { } @Test - public void testWithoutNullString() throws Exception { + void testWithoutNullString() throws Exception { // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() //.setNullString("N/A") @@ -129,7 +129,7 @@ public void testWithoutNullString() throws Exception { } @Test - public void testWithoutQuoteMode() throws Exception { + void testWithoutQuoteMode() throws Exception { // @formatter:off final CSVFormat format = CSVFormat.EXCEL.builder() .setNullString("N/A") diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java index 3b69b173b..cf9a0ad3d 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java @@ -33,7 +33,7 @@ public class JiraCsv206Test { @Test - public void testJiraCsv206MultipleCharacterDelimiter() throws IOException { + void testJiraCsv206MultipleCharacterDelimiter() throws IOException { // Read with multiple character delimiter final String source = "FirstName[|]LastName[|]Address\r\nJohn[|]Smith[|]123 Main St."; final StringReader reader = new StringReader(source); 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 a4e3960c9..04b4d06d5 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java @@ -31,7 +31,7 @@ public class JiraCsv211Test { @Test - public void testJiraCsv211Format() throws IOException { + void testJiraCsv211Format() throws IOException { // @formatter:off final CSVFormat printFormat = CSVFormat.DEFAULT.builder() .setDelimiter('\t') diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java index d700843f4..f32a6fc40 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java @@ -64,7 +64,7 @@ private void createEndChannel(final File csvFile) { } @Test - public void test() { + void test() { createEndChannel(new File("src/test/resources/org/apache/commons/csv/CSV-213/999751170.patch.csv")); } } diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java index 85d9676fd..a460250b5 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java @@ -37,7 +37,7 @@ public class JiraCsv247Test { @Test - public void testHeadersMissingOneColumnWhenAllowingMissingColumnNames() throws Exception { + void testHeadersMissingOneColumnWhenAllowingMissingColumnNames() throws Exception { final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader().setAllowMissingColumnNames(true).get(); assertTrue(format.getAllowMissingColumnNames(), "We should allow missing column names"); @@ -63,7 +63,7 @@ record = iterator.next(); } @Test - public void testHeadersMissingThrowsWhenNotAllowingMissingColumnNames() { + void testHeadersMissingThrowsWhenNotAllowingMissingColumnNames() { final CSVFormat format = CSVFormat.DEFAULT.builder().setHeader().get(); assertFalse(format.getAllowMissingColumnNames(), "By default we should not allow missing column names"); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java index 08cfe13fa..7a9c0aa99 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java @@ -50,7 +50,7 @@ private static InputStream getTestInput() { * @throws ClassNotFoundException If the CSVRecord cannot be deserialized */ @Test - public void testJiraCsv248() throws IOException, ClassNotFoundException { + void testJiraCsv248() throws IOException, ClassNotFoundException { // Record was originally created using CSV version 1.6 with the following code: // try (CSVParser parser = CSVParser.parse("A,B\n#my comment\nOne,Two", // CSVFormat.DEFAULT.builder().setHeader().setCommentMarker('#'))) { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java index f5fe47ca6..8e2a5168f 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java @@ -35,7 +35,7 @@ public class JiraCsv249Test { @Test - public void testJiraCsv249() throws IOException { + void testJiraCsv249() throws IOException { final CSVFormat format = CSVFormat.DEFAULT.builder().setEscape('\\').get(); final StringWriter stringWriter = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(stringWriter, format)) { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java index 5b266a3e3..3d7498008 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java @@ -42,7 +42,7 @@ private void assertArrayEqual(final String[] expected, final CSVRecord actual) { } @Test - public void testHandleAbsentValues() throws IOException { + void testHandleAbsentValues() throws IOException { final String source = "\"John\",,\"Doe\"\n" + ",\"AA\",123\n" + "\"John\",90,\n" + "\"\",,90"; final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.NON_NUMERIC).get(); try (CSVParser parser = csvFormat.parse(new StringReader(source))) { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java index abae0ea2f..28377bb84 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java @@ -35,7 +35,7 @@ public class JiraCsv263Test { @Test - public void testPrintFromReaderWithQuotes() throws IOException { + void testPrintFromReaderWithQuotes() throws IOException { // @formatter:off final CSVFormat format = CSVFormat.RFC4180.builder() .setDelimiter(',') diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java index d910ef582..e64495267 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java @@ -49,7 +49,7 @@ public class JiraCsv264Test { "\"6\",\"7\",\"\",\"\",\"10\""; @Test - public void testJiraCsv264() { + void testJiraCsv264() { final CSVFormat csvFormat = CSVFormat.DEFAULT .builder() .setHeader() @@ -62,7 +62,7 @@ public void testJiraCsv264() { } @Test - public void testJiraCsv264WithGapAllowEmpty() throws IOException { + void testJiraCsv264WithGapAllowEmpty() throws IOException { final CSVFormat csvFormat = CSVFormat.DEFAULT .builder() .setHeader() @@ -75,7 +75,7 @@ public void testJiraCsv264WithGapAllowEmpty() throws IOException { } @Test - public void testJiraCsv264WithGapDisallow() { + void testJiraCsv264WithGapDisallow() { final CSVFormat csvFormat = CSVFormat.DEFAULT .builder() .setHeader() diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java index 4853672dc..286fa7f18 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java @@ -36,7 +36,7 @@ public class JiraCsv265Test { @Test - public void testCharacterPositionWithComments() throws IOException { + void testCharacterPositionWithComments() throws IOException { // @formatter:off final String csv = "# Comment1\n" + @@ -62,7 +62,7 @@ public void testCharacterPositionWithComments() throws IOException { } @Test - public void testCharacterPositionWithCommentsSpanningMultipleLines() throws IOException { + void testCharacterPositionWithCommentsSpanningMultipleLines() throws IOException { // @formatter:off final String csv = "# Comment1\n" + diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java index 5ee5e0a01..9abdbbe6d 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java @@ -32,7 +32,7 @@ public class JiraCsv271Test { @Test - public void testJiraCsv271_withArray() throws IOException { + void testJiraCsv271_withArray() throws IOException { final CSVFormat csvFormat = CSVFormat.DEFAULT; final StringWriter stringWriter = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(stringWriter, csvFormat)) { @@ -43,7 +43,7 @@ public void testJiraCsv271_withArray() throws IOException { } @Test - public void testJiraCsv271_withList() throws IOException { + void testJiraCsv271_withList() throws IOException { final CSVFormat csvFormat = CSVFormat.DEFAULT; final StringWriter stringWriter = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(stringWriter, csvFormat)) { 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 0be6a52f8..6626964f9 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java @@ -42,7 +42,7 @@ private void print(final CSVRecord csvRecord, final CSVPrinter csvPrinter) throw @Test // Before fix: // expected: but was: - public void testParseWithABADelimiter() throws Exception { + 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); @@ -57,7 +57,7 @@ public void testParseWithABADelimiter() throws Exception { @Test // Before fix: // expected: but was: - public void testParseWithDoublePipeDelimiter() throws Exception { + 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); @@ -72,7 +72,7 @@ public void testParseWithDoublePipeDelimiter() throws Exception { @Test // Regression, already passed before fix - public void testParseWithDoublePipeDelimiterDoubleCharValue() throws Exception { + 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); @@ -87,7 +87,7 @@ public void testParseWithDoublePipeDelimiterDoubleCharValue() throws Exception { @Test // Before fix: // expected: but was: - public void testParseWithDoublePipeDelimiterEndsWithDelimiter() throws Exception { + 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); @@ -102,7 +102,7 @@ public void testParseWithDoublePipeDelimiterEndsWithDelimiter() throws Exception @Test // Before fix: // expected: but was: - public void testParseWithDoublePipeDelimiterQuoted() throws Exception { + 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); @@ -116,7 +116,7 @@ public void testParseWithDoublePipeDelimiterQuoted() throws Exception { @Test // Regression, already passed before fix - public void testParseWithSinglePipeDelimiterEndsWithDelimiter() throws Exception { + 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); @@ -131,7 +131,7 @@ public void testParseWithSinglePipeDelimiterEndsWithDelimiter() throws Exception @Test // Before fix: // expected: but was: - public void testParseWithTriplePipeDelimiter() throws Exception { + 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); @@ -145,7 +145,7 @@ public void testParseWithTriplePipeDelimiter() throws Exception { @Test // Regression, already passed before fix - public void testParseWithTwoCharDelimiter1() throws Exception { + 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); @@ -159,7 +159,7 @@ public void testParseWithTwoCharDelimiter1() throws Exception { @Test // Regression, already passed before fix - public void testParseWithTwoCharDelimiter2() throws Exception { + 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); @@ -173,7 +173,7 @@ public void testParseWithTwoCharDelimiter2() throws Exception { @Test // Regression, already passed before fix - public void testParseWithTwoCharDelimiter3() throws Exception { + 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); @@ -187,7 +187,7 @@ public void testParseWithTwoCharDelimiter3() throws Exception { @Test // Regression, already passed before fix - public void testParseWithTwoCharDelimiter4() throws Exception { + 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); @@ -202,7 +202,7 @@ public void testParseWithTwoCharDelimiter4() throws Exception { @Test // Before fix: // expected: but was: - public void testParseWithTwoCharDelimiterEndsWithDelimiter() throws Exception { + 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); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java index f9dd6e953..bfc0f1d5b 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java @@ -84,17 +84,17 @@ private void testHelper(final String fileName, final CSVFormat format) throws Ex } @Test - public void testPostgresqlCsv() throws Exception { + void testPostgresqlCsv() throws Exception { testHelper("psql.csv", CSVFormat.POSTGRESQL_CSV); } @Test - public void testPostgresqlText() throws Exception { + void testPostgresqlText() throws Exception { testHelper("psql.tsv", CSVFormat.POSTGRESQL_TEXT); } @Test - public void testWriteThenRead() throws Exception { + void testWriteThenRead() throws Exception { final StringWriter sw = new StringWriter(); final CSVFormat format = CSVFormat.POSTGRESQL_CSV.builder().setHeader().setSkipHeaderRecord(true).get(); try (CSVPrinter printer = new CSVPrinter(sw, format)) { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java index 2cc62628e..75e26cf69 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java @@ -58,24 +58,24 @@ private static void testInternal(final CSVFormat format, final String expectedSu } @Test - public void testDefaultCsvFormatWithBackslashEscapeWorks() throws IOException { + void testDefaultCsvFormatWithBackslashEscapeWorks() throws IOException { testInternal(CSVFormat.Builder.create().setEscape('\\').get(), ",\"b \\\"\\\"\","); } @Test - public void testDefaultCsvFormatWithNullEscapeWorks() throws IOException { + void testDefaultCsvFormatWithNullEscapeWorks() throws IOException { testInternal(CSVFormat.Builder.create().setEscape(null).get(), ",\"b \"\"\"\"\","); } @Test - public void testDefaultCsvFormatWithQuoteEscapeWorks() throws IOException { + void testDefaultCsvFormatWithQuoteEscapeWorks() throws IOException { // this one doesn't actually work but should behave like setEscape(null) // Printer is writing the expected content but Parser is unable to consume it testInternal(CSVFormat.Builder.create().setEscape('"').get(), ",\"b \"\"\"\"\","); } @Test - public void testDefaultCsvFormatWorks() throws IOException { + void testDefaultCsvFormatWorks() throws IOException { testInternal(CSVFormat.Builder.create().get(), ",\"b \"\"\"\"\","); } } diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java index e34a8b02f..e52739dd1 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java @@ -61,7 +61,7 @@ private void every(final CSVFormat csvFormat, final Object[] objects, final Stri } @Test - public void testWithNotSetNullString() throws IOException { + void testWithNotSetNullString() throws IOException { // @formatter:off every(CSVFormat.DEFAULT, objects1, @@ -91,7 +91,7 @@ public void testWithNotSetNullString() throws IOException { } @Test - public void testWithSetNullStringEmptyString() throws IOException { + void testWithSetNullStringEmptyString() throws IOException { // @formatter:off every(CSVFormat.DEFAULT.builder().setNullString("").get(), objects1, @@ -121,7 +121,7 @@ public void testWithSetNullStringEmptyString() throws IOException { } @Test - public void testWithSetNullStringNULL() throws IOException { + void testWithSetNullStringNULL() throws IOException { // @formatter:off every(CSVFormat.DEFAULT.builder().setNullString("NULL").get(), objects2, diff --git a/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java b/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java index efdb8f041..a7f081027 100644 --- a/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java +++ b/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java @@ -110,7 +110,7 @@ public long testParseBigFile(final boolean traverseColumns) throws Exception { } @Test - public void testParseBigFileRepeat() throws Exception { + void testParseBigFileRepeat() throws Exception { long bestTime = Long.MAX_VALUE; for (int i = 0; i < this.max; i++) { bestTime = Math.min(testParseBigFile(false), bestTime); @@ -119,7 +119,7 @@ public void testParseBigFileRepeat() throws Exception { } @Test - public void testReadBigFile() throws Exception { + void testReadBigFile() throws Exception { long bestTime = Long.MAX_VALUE; long count; for (int i = 0; i < this.max; i++) { From ebc85238734a0c8bf24a72742c66705ce81f488a Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 8 Jun 2025 14:15:53 -0400 Subject: [PATCH 018/245] Use JUnit 5 convention for class visibility --- .../java/org/apache/commons/csv/CSVDuplicateHeaderTest.java | 2 +- src/test/java/org/apache/commons/csv/CSVFileParserTest.java | 2 +- .../java/org/apache/commons/csv/CSVFormatPredefinedTest.java | 2 +- src/test/java/org/apache/commons/csv/CSVFormatTest.java | 2 +- src/test/java/org/apache/commons/csv/CSVParserTest.java | 2 +- src/test/java/org/apache/commons/csv/CSVPrinterTest.java | 2 +- src/test/java/org/apache/commons/csv/CSVRecordTest.java | 2 +- .../java/org/apache/commons/csv/ExtendedBufferedReaderTest.java | 2 +- src/test/java/org/apache/commons/csv/JiraCsv196Test.java | 2 +- src/test/java/org/apache/commons/csv/JiraCsv318Test.java | 2 +- src/test/java/org/apache/commons/csv/LexerTest.java | 2 +- src/test/java/org/apache/commons/csv/PerformanceTest.java | 2 +- src/test/java/org/apache/commons/csv/TokenTest.java | 2 +- src/test/java/org/apache/commons/csv/UserGuideTest.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java | 2 +- src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java | 2 +- src/test/java/org/apache/commons/csv/perf/PerformanceTest.java | 2 +- 37 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java b/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java index c5705e28e..cc47b999a 100644 --- a/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java +++ b/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java @@ -34,7 +34,7 @@ * Tests parsing of duplicate column names in a CSV header. * The test verifies that headers are consistently handled by CSVFormat and CSVParser. */ -public class CSVDuplicateHeaderTest { +class CSVDuplicateHeaderTest { /** * Return test cases for duplicate header data for use in CSVFormat. diff --git a/src/test/java/org/apache/commons/csv/CSVFileParserTest.java b/src/test/java/org/apache/commons/csv/CSVFileParserTest.java index cb01de376..e74d0e688 100644 --- a/src/test/java/org/apache/commons/csv/CSVFileParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFileParserTest.java @@ -40,7 +40,7 @@ /** * Parse tests using test files */ -public class CSVFileParserTest { +class CSVFileParserTest { private static final File BASE_DIR = new File("src/test/resources/org/apache/commons/csv/CSVFileParser"); diff --git a/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java b/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java index 8ff96e968..dad08cdb1 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatPredefinedTest.java @@ -26,7 +26,7 @@ /** * Tests {@link CSVFormat.Predefined}. */ -public class CSVFormatPredefinedTest { +class CSVFormatPredefinedTest { private void test(final CSVFormat format, final String enumName) { assertEquals(format, CSVFormat.Predefined.valueOf(enumName).getFormat()); diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index 31ad476e7..99c7dc52c 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -54,7 +54,7 @@ /** * Tests {@link CSVFormat}. */ -public class CSVFormatTest { +class CSVFormatTest { public enum EmptyEnum { // empty enum. diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 8304a568c..1d12357ee 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -71,7 +71,7 @@ * 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 { +class CSVParserTest { private static final CSVFormat EXCEL_WITH_HEADER = CSVFormat.EXCEL.withHeader(); diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index d9d751987..341091e57 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -75,7 +75,7 @@ /** * Tests {@link CSVPrinter}. */ -public class CSVPrinterTest { +class CSVPrinterTest { private static final int TABLE_RECORD_COUNT = 2; private static final int TABLE_AND_HEADER_RECORD_COUNT = TABLE_RECORD_COUNT + 1; diff --git a/src/test/java/org/apache/commons/csv/CSVRecordTest.java b/src/test/java/org/apache/commons/csv/CSVRecordTest.java index 1c0e05d36..94060d62b 100644 --- a/src/test/java/org/apache/commons/csv/CSVRecordTest.java +++ b/src/test/java/org/apache/commons/csv/CSVRecordTest.java @@ -45,7 +45,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -public class CSVRecordTest { +class CSVRecordTest { private enum EnumFixture { UNKNOWN_COLUMN diff --git a/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java b/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java index 9d929c655..056b8a9c9 100644 --- a/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java +++ b/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java @@ -32,7 +32,7 @@ /** * Test {@link ExtendedBufferedReader}. */ -public class ExtendedBufferedReaderTest { +class ExtendedBufferedReaderTest { static final String LF = "\n"; static final String CR = "\r"; diff --git a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java index 2beae36ad..aaf8e206b 100644 --- a/src/test/java/org/apache/commons/csv/JiraCsv196Test.java +++ b/src/test/java/org/apache/commons/csv/JiraCsv196Test.java @@ -28,7 +28,7 @@ import org.junit.jupiter.api.Test; -public class JiraCsv196Test { +class JiraCsv196Test { private Reader getTestInput(final String path) { return new InputStreamReader(ClassLoader.getSystemClassLoader().getResourceAsStream(path)); diff --git a/src/test/java/org/apache/commons/csv/JiraCsv318Test.java b/src/test/java/org/apache/commons/csv/JiraCsv318Test.java index 1424809cc..984509e87 100644 --- a/src/test/java/org/apache/commons/csv/JiraCsv318Test.java +++ b/src/test/java/org/apache/commons/csv/JiraCsv318Test.java @@ -38,7 +38,7 @@ * * @see CSVPrinter */ -public class JiraCsv318Test { +class JiraCsv318Test { private void checkOutput(final ByteArrayOutputStream baos) { checkOutput(baos.toString()); diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index 2c9742692..af0c69a77 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -41,7 +41,7 @@ /** */ -public class LexerTest { +class LexerTest { private static void assertContent(final String expectedContent, final Token actualToken) { assertEquals(expectedContent, actualToken.content.toString()); diff --git a/src/test/java/org/apache/commons/csv/PerformanceTest.java b/src/test/java/org/apache/commons/csv/PerformanceTest.java index bf0d48389..9284828e6 100644 --- a/src/test/java/org/apache/commons/csv/PerformanceTest.java +++ b/src/test/java/org/apache/commons/csv/PerformanceTest.java @@ -44,7 +44,7 @@ * Basic test harness. */ @SuppressWarnings("boxing") -public class PerformanceTest { +class PerformanceTest { @FunctionalInterface private interface CSVParserFactory { diff --git a/src/test/java/org/apache/commons/csv/TokenTest.java b/src/test/java/org/apache/commons/csv/TokenTest.java index 0a90a11ea..075c1b1d9 100644 --- a/src/test/java/org/apache/commons/csv/TokenTest.java +++ b/src/test/java/org/apache/commons/csv/TokenTest.java @@ -28,7 +28,7 @@ /** * Tests {@link Token}. */ -public class TokenTest { +class TokenTest { @ParameterizedTest @EnumSource(Token.Type.class) diff --git a/src/test/java/org/apache/commons/csv/UserGuideTest.java b/src/test/java/org/apache/commons/csv/UserGuideTest.java index 6f3f77bf6..6cd8c72d7 100644 --- a/src/test/java/org/apache/commons/csv/UserGuideTest.java +++ b/src/test/java/org/apache/commons/csv/UserGuideTest.java @@ -35,7 +35,7 @@ /** * Tests for the user guide. */ -public class UserGuideTest { +class UserGuideTest { @TempDir Path tempDir; diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java index 5289b4a93..befe3b5c3 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java @@ -24,7 +24,7 @@ import org.apache.commons.csv.QuoteMode; import org.junit.jupiter.api.Test; -public class JiraCsv148Test { +class JiraCsv148Test { @Test void testWithIgnoreSurroundingSpacesEmpty() { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java index c12574f28..b32e96566 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv149Test.java @@ -29,7 +29,7 @@ import org.apache.commons.csv.CSVRecord; import org.junit.jupiter.api.Test; -public class JiraCsv149Test { +class JiraCsv149Test { private static final String CR_LF = "\r\n"; diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java index 5e9feb7dd..eec91d52d 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv150Test.java @@ -27,7 +27,7 @@ import org.apache.commons.csv.CSVParser; import org.junit.jupiter.api.Test; -public class JiraCsv150Test { +class JiraCsv150Test { private void testDisable(final CSVFormat format, final StringReader reader) throws IOException { try (CSVParser csvParser = CSVParser.builder().setReader(reader).setFormat(format).get()) { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java index 6276775c9..90d657fcd 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv154Test.java @@ -26,7 +26,7 @@ import org.apache.commons.csv.CSVPrinter; import org.junit.jupiter.api.Test; -public class JiraCsv154Test { +class JiraCsv154Test { @Test void testJiraCsv154_withCommentMarker() throws IOException { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java index 32dd23575..607d0cf2a 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv167Test.java @@ -31,7 +31,7 @@ import org.apache.commons.csv.QuoteMode; import org.junit.jupiter.api.Test; -public class JiraCsv167Test { +class JiraCsv167Test { private Reader getTestReader() { return new InputStreamReader( 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 80b86b611..1117c12ac 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv198Test.java @@ -31,7 +31,7 @@ import org.apache.commons.csv.CSVParser; import org.junit.jupiter.api.Test; -public class JiraCsv198Test { +class JiraCsv198Test { // @formatter:off private static final CSVFormat CSV_FORMAT = CSVFormat.EXCEL.builder() diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java index f467c6785..2c9226506 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv203Test.java @@ -29,7 +29,7 @@ * JIRA: withNullString value is printed without quotes when * QuoteMode.ALL is specified */ -public class JiraCsv203Test { +class JiraCsv203Test { @Test void testQuoteModeAll() throws Exception { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java index cf9a0ad3d..2fecd10f1 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv206Test.java @@ -30,7 +30,7 @@ import org.apache.commons.csv.CSVRecord; import org.junit.jupiter.api.Test; -public class JiraCsv206Test { +class JiraCsv206Test { @Test void testJiraCsv206MultipleCharacterDelimiter() throws IOException { 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 04b4d06d5..28b559d1e 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv211Test.java @@ -28,7 +28,7 @@ import org.apache.commons.csv.CSVParser; import org.junit.jupiter.api.Test; -public class JiraCsv211Test { +class JiraCsv211Test { @Test void testJiraCsv211Format() throws IOException { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java index f32a6fc40..90f5da4c5 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv213Test.java @@ -38,7 +38,7 @@ * you want, you need to open a new CSVParser. *

*/ -public class JiraCsv213Test { +class JiraCsv213Test { private void createEndChannel(final File csvFile) { // @formatter:off diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java index a460250b5..c2d9ac591 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv247Test.java @@ -34,7 +34,7 @@ import org.apache.commons.csv.CSVRecord; import org.junit.jupiter.api.Test; -public class JiraCsv247Test { +class JiraCsv247Test { @Test void testHeadersMissingOneColumnWhenAllowingMissingColumnNames() throws Exception { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java index 7a9c0aa99..480a9dffa 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv248Test.java @@ -33,7 +33,7 @@ import org.apache.commons.csv.CSVRecord; import org.junit.jupiter.api.Test; -public class JiraCsv248Test { +class JiraCsv248Test { private static InputStream getTestInput() { return ClassLoader.getSystemClassLoader().getResourceAsStream("org/apache/commons/csv/CSV-248/csvRecord.bin"); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java index 8e2a5168f..4034b04bd 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv249Test.java @@ -32,7 +32,7 @@ import org.apache.commons.csv.CSVRecord; import org.junit.jupiter.api.Test; -public class JiraCsv249Test { +class JiraCsv249Test { @Test void testJiraCsv249() throws IOException { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java index 3d7498008..b78c1baa4 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java @@ -33,7 +33,7 @@ /** * Setting QuoteMode:ALL_NON_NULL or NON_NUMERIC can distinguish between empty string columns and absent value columns. */ -public class JiraCsv253Test { +class JiraCsv253Test { private void assertArrayEqual(final String[] expected, final CSVRecord actual) { for (int i = 0; i < expected.length; i++) { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java index 28377bb84..18bb9580a 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv263Test.java @@ -32,7 +32,7 @@ /** * Tests [CSV-263] Print from Reader with embedded quotes generates incorrect output. */ -public class JiraCsv263Test { +class JiraCsv263Test { @Test void testPrintFromReaderWithQuotes() throws IOException { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java index e64495267..857e42cb8 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv264Test.java @@ -35,7 +35,7 @@ * * @see Jira Ticker */ -public class JiraCsv264Test { +class JiraCsv264Test { private static final String CSV_STRING = "\"\",\"B\",\"\"\n" + "\"1\",\"2\",\"3\"\n" + diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java index 286fa7f18..1bccad702 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv265Test.java @@ -33,7 +33,7 @@ /** * Tests [CSV-265] {@link CSVRecord#getCharacterPosition()} returns the correct position after encountering a comment. */ -public class JiraCsv265Test { +class JiraCsv265Test { @Test void testCharacterPositionWithComments() throws IOException { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java index 9abdbbe6d..0269dec5d 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv271Test.java @@ -29,7 +29,7 @@ import org.apache.commons.csv.CSVPrinter; import org.junit.jupiter.api.Test; -public class JiraCsv271Test { +class JiraCsv271Test { @Test void testJiraCsv271_withArray() throws IOException { 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 6626964f9..065ee6bb3 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv288Test.java @@ -31,7 +31,7 @@ import org.apache.commons.csv.CSVRecord; import org.junit.jupiter.api.Test; -public class JiraCsv288Test { +class JiraCsv288Test { private void print(final CSVRecord csvRecord, final CSVPrinter csvPrinter) throws IOException { for (final String value : csvRecord) { diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java index bfc0f1d5b..f251eeb7a 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv290Test.java @@ -58,7 +58,7 @@ // 2 xyz \\b:\b \\t:\t \\n:\n \\r:\r a b // 3 a b,c,d "quoted" e // -public class JiraCsv290Test { +class JiraCsv290Test { private void testHelper(final String fileName, final CSVFormat format) throws Exception { List> content = new ArrayList<>(); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java index 75e26cf69..0e5de0751 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv294Test.java @@ -36,7 +36,7 @@ import org.apache.commons.csv.CSVRecord; import org.junit.jupiter.api.Test; -public class JiraCsv294Test { +class JiraCsv294Test { private static void testInternal(final CSVFormat format, final String expectedSubstring) throws IOException { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java index e52739dd1..781641226 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv93Test.java @@ -43,7 +43,7 @@ * Jira CSV-253 to a certain extent. *

*/ -public class JiraCsv93Test { +class JiraCsv93Test { private static Object[] objects1 = {"abc", "", null, "a,b,c", 123}; private static Object[] objects2 = {"abc", "NULL", null, "a,b,c", 123}; diff --git a/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java b/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java index a7f081027..bead12378 100644 --- a/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java +++ b/src/test/java/org/apache/commons/csv/perf/PerformanceTest.java @@ -43,7 +43,7 @@ * * To run this test, use: mvn test -Dtest=PerformanceTest */ -public class PerformanceTest { +class PerformanceTest { private static final String TEST_RESRC = "org/apache/commons/csv/perf/worldcitiespop.txt.gz"; From 9588c7ef7e7ab003bb58a6a0ece3b8df559c9f13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Jun 2025 12:54:56 +0000 Subject: [PATCH 019/245] Bump github/codeql-action from 3.28.19 to 3.29.0 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.19 to 3.29.0. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/fca7ace96b7d713c7035871441bd52efbe39e27e...ce28f5bb42b7a9f2c824e633a3f6ee835bab6858) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3f2fc9e55..1f3a099bd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 + uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 + uses: github/codeql-action/autobuild@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 + uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 22cd0a2d1..25c086a73 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # 3.28.19 + uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 with: sarif_file: results.sarif From 701a64fed94d79096dd2f35be8c4c119fbb8ad4c Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Thu, 19 Jun 2025 10:39:26 -0400 Subject: [PATCH 020/245] Bump org.apache.commons:commons-parent from 84 to 85 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ec93a5b3b..45928257e 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 84 + 85 commons-csv 1.14.1-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c86f459da..bff6748a4 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,8 +47,8 @@ org.apache.commons.csv.CSVPrinter.printRecords(ResultSet) now writes one record at a time using a lock. + Bump org.apache.commons:commons-parent from 81 to 85 #542. Bump commons-io:commons-io from 2.18.0 to 2.19.0. - Bump org.apache.commons:commons-parent from 81 to 84 #542. Bump com.opencsv:opencsv from 5.10 to 5.11.1 #545, #551.
From 6bbb815a0a317e620a91ceb055687eb0ec9669fb Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 21 Jun 2025 15:44:30 -0400 Subject: [PATCH 021/245] Test refactoring --- .../org/apache/commons/csv/CSVParserTest.java | 62 +++++++++---------- .../org/apache/commons/csv/CsvAssertions.java | 29 +++++++++ .../commons/csv/issues/JiraCsv253Test.java | 16 ++--- 3 files changed, 65 insertions(+), 42 deletions(-) create mode 100644 src/test/java/org/apache/commons/csv/CsvAssertions.java diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 1d12357ee..22b1417c8 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -22,7 +22,7 @@ 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.apache.commons.csv.CsvAssertions.assertValuesEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertInstanceOf; @@ -217,7 +217,7 @@ void testBackslashEscapingOld() throws IOException { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -479,7 +479,7 @@ void testEmptyLineBehaviorCSV() throws Exception { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -496,7 +496,7 @@ void testEmptyLineBehaviorExcel() throws Exception { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -521,7 +521,7 @@ void testEndOfFileBehaviorCSV() throws Exception { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -540,7 +540,7 @@ void testEndOfFileBehaviorExcel() throws Exception { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -556,7 +556,7 @@ void testExcelFormat1() throws IOException { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -570,7 +570,7 @@ void testExcelFormat2() throws Exception { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -629,9 +629,9 @@ void testForEach() throws Exception { 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()); + assertValuesEquals(new String[] { "a", "b", "c" }, records.get(0)); + assertValuesEquals(new String[] { "1", "2", "3" }, records.get(1)); + assertValuesEquals(new String[] { "x", "y", "z" }, records.get(2)); } } @@ -756,7 +756,7 @@ void testGetHeaderNamesReadOnly() throws IOException { void testGetLine() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces())) { for (final String[] re : RESULT) { - assertArrayEquals(re, parser.nextRecord().values()); + assertValuesEquals(re, parser.nextRecord()); } assertNull(parser.nextRecord()); @@ -782,7 +782,7 @@ void testGetLineNumberWithLF() throws Exception { 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()); + assertValuesEquals(RESULT[0], record); } } @@ -803,11 +803,11 @@ void testGetOneLineOneParser() throws IOException { writer.append(CSV_INPUT_1); writer.append(format.getRecordSeparator()); final CSVRecord record1 = parser.nextRecord(); - assertArrayEquals(RESULT[0], record1.values()); + assertValuesEquals(RESULT[0], record1); writer.append(CSV_INPUT_2); writer.append(format.getRecordSeparator()); final CSVRecord record2 = parser.nextRecord(); - assertArrayEquals(RESULT[1], record2.values()); + assertValuesEquals(RESULT[1], record2); } } @@ -877,7 +877,7 @@ void testGetRecords() throws IOException { assertEquals(RESULT.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < RESULT.length; i++) { - assertArrayEquals(RESULT[i], records.get(i).values()); + assertValuesEquals(RESULT[i], records.get(i)); } } } @@ -899,7 +899,7 @@ void testGetRecordsMaxRows(final long maxRows) throws IOException { assertEquals(expectedLength, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < expectedLength; i++) { - assertArrayEquals(RESULT[i], records.get(i).values()); + assertValuesEquals(RESULT[i], records.get(i)); } } } @@ -1155,12 +1155,12 @@ void testIterator() throws Exception { 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()); + assertValuesEquals(new String[] { "a", "b", "c" }, iterator.next()); + assertValuesEquals(new String[] { "1", "2", "3" }, iterator.next()); assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); assertTrue(iterator.hasNext()); - assertArrayEquals(new String[] { "x", "y", "z" }, iterator.next().values()); + assertValuesEquals(new String[] { "x", "y", "z" }, iterator.next()); assertFalse(iterator.hasNext()); assertThrows(NoSuchElementException.class, iterator::next); } @@ -1174,20 +1174,20 @@ void testIteratorMaxRows(final long maxRows) throws Exception { final Iterator iterator = parser.iterator(); assertTrue(iterator.hasNext()); assertThrows(UnsupportedOperationException.class, iterator::remove); - assertArrayEquals(new String[] { "a", "b", "c" }, iterator.next().values()); + assertValuesEquals(new String[] { "a", "b", "c" }, iterator.next()); final boolean noLimit = maxRows <= 0; final int fixtureLen = 3; final long expectedLen = noLimit ? fixtureLen : Math.min(fixtureLen, maxRows); if (expectedLen > 1) { assertTrue(iterator.hasNext()); - assertArrayEquals(new String[] { "1", "2", "3" }, iterator.next().values()); + assertValuesEquals(new String[] { "1", "2", "3" }, iterator.next()); } assertEquals(expectedLen > 2, iterator.hasNext()); // again assertEquals(expectedLen > 2, iterator.hasNext()); if (expectedLen == fixtureLen) { assertTrue(iterator.hasNext()); - assertArrayEquals(new String[] { "x", "y", "z" }, iterator.next().values()); + assertValuesEquals(new String[] { "x", "y", "z" }, iterator.next()); } assertFalse(iterator.hasNext()); assertThrows(NoSuchElementException.class, iterator::next); @@ -1584,7 +1584,7 @@ void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format) throw .setFormat(format.getFormat()) .get()) { for (final String[] line : lines) { - assertArrayEquals(line, csvRecords.nextRecord().values()); + assertValuesEquals(line, csvRecords.nextRecord()); } assertNull(csvRecords.nextRecord()); } @@ -1715,7 +1715,7 @@ void testStartWithEmptyLinesThenHeaders() throws Exception { assertEquals(res.length, records.size()); assertFalse(records.isEmpty()); for (int i = 0; i < res.length; i++) { - assertArrayEquals(res[i], records.get(i).values()); + assertValuesEquals(res[i], records.get(i)); } } } @@ -1727,9 +1727,9 @@ void testStream() throws Exception { 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()); + assertValuesEquals(new String[] { "a", "b", "c" }, list.get(0)); + assertValuesEquals(new String[] { "1", "2", "3" }, list.get(1)); + assertValuesEquals(new String[] { "x", "y", "z" }, list.get(2)); } } @@ -1740,12 +1740,12 @@ void testStreamMaxRows(final long maxRows) throws Exception { try (CSVParser parser = CSVFormat.DEFAULT.builder().setMaxRows(maxRows).get().parse(in)) { final List list = parser.stream().collect(Collectors.toList()); assertFalse(list.isEmpty()); - assertArrayEquals(new String[] { "a", "b", "c" }, list.get(0).values()); + assertValuesEquals(new String[] { "a", "b", "c" }, list.get(0)); if (maxRows <= 0 || maxRows > 1) { - assertArrayEquals(new String[] { "1", "2", "3" }, list.get(1).values()); + assertValuesEquals(new String[] { "1", "2", "3" }, list.get(1)); } if (maxRows <= 0 || maxRows > 2) { - assertArrayEquals(new String[] { "x", "y", "z" }, list.get(2).values()); + assertValuesEquals(new String[] { "x", "y", "z" }, list.get(2)); } } } diff --git a/src/test/java/org/apache/commons/csv/CsvAssertions.java b/src/test/java/org/apache/commons/csv/CsvAssertions.java new file mode 100644 index 000000000..b6c2b5d9c --- /dev/null +++ b/src/test/java/org/apache/commons/csv/CsvAssertions.java @@ -0,0 +1,29 @@ +/* + * 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.junit.jupiter.api.Assertions.assertArrayEquals; + +public class CsvAssertions { + + public static void assertValuesEquals(final String[] expected, final CSVRecord actual) { + assertArrayEquals(expected, actual.values()); + } +} diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java index b78c1baa4..136940859 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java @@ -18,7 +18,7 @@ */ package org.apache.commons.csv.issues; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.apache.commons.csv.CsvAssertions.assertValuesEquals; import java.io.IOException; import java.io.StringReader; @@ -35,22 +35,16 @@ */ class JiraCsv253Test { - private void assertArrayEqual(final String[] expected, final CSVRecord actual) { - for (int i = 0; i < expected.length; i++) { - assertEquals(expected[i], actual.get(i)); - } - } - @Test void testHandleAbsentValues() throws IOException { final String source = "\"John\",,\"Doe\"\n" + ",\"AA\",123\n" + "\"John\",90,\n" + "\"\",,90"; final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.NON_NUMERIC).get(); try (CSVParser parser = csvFormat.parse(new StringReader(source))) { final Iterator csvRecords = parser.iterator(); - assertArrayEqual(new String[] {"John", null, "Doe"}, csvRecords.next()); - assertArrayEqual(new String[] {null, "AA", "123"}, csvRecords.next()); - assertArrayEqual(new String[] {"John", "90", null}, csvRecords.next()); - assertArrayEqual(new String[] {"", null, "90"}, csvRecords.next()); + assertValuesEquals(new String[] {"John", null, "Doe"}, csvRecords.next()); + assertValuesEquals(new String[] {null, "AA", "123"}, csvRecords.next()); + assertValuesEquals(new String[] {"John", "90", null}, csvRecords.next()); + assertValuesEquals(new String[] {"", null, "90"}, csvRecords.next()); } } } From 0aa9c47fbd60d67f58361676a6b6d30f319fada6 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 21 Jun 2025 15:57:55 -0400 Subject: [PATCH 022/245] [CSV-254] POSTGRESQL_CSV cannot parse correctly (null vs zero-length string) Add test --- pom.xml | 1 + .../commons/csv/issues/JiraCsv254Test.java | 52 +++++++++++++++++++ .../apache/commons/csv/CSV-254/csv-254.csv | 3 ++ 3 files changed, 56 insertions(+) create mode 100644 src/test/java/org/apache/commons/csv/issues/JiraCsv254Test.java create mode 100644 src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv diff --git a/pom.xml b/pom.xml index 45928257e..a1eca0578 100644 --- a/pom.xml +++ b/pom.xml @@ -183,6 +183,7 @@ src/test/resources/org/apache/commons/csv/CSV-196/emoji.csv src/test/resources/org/apache/commons/csv/CSV-196/japanese.csv src/test/resources/org/apache/commons/csv/CSV-213/999751170.patch.csv + src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv src/test/resources/org/apache/commons/csv/CSVFileParser/bom.csv src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv src/test/resources/org/apache/commons/csv/CSVFileParser/test_default.txt diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv254Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv254Test.java new file mode 100644 index 000000000..629b42ee6 --- /dev/null +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv254Test.java @@ -0,0 +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 + * + * 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.apache.commons.csv.CsvAssertions.assertValuesEquals; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Iterator; + +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import org.junit.jupiter.api.Test; + +/** + * Tests https://issues.apache.org/jira/browse/CSV-254. + */ +class JiraCsv254Test { + + @Test + void test() throws IOException { + final CSVFormat csvFormat = CSVFormat.POSTGRESQL_CSV; + try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv"), + StandardCharsets.UTF_8); CSVParser parser = csvFormat.parse(reader)) { + final Iterator csvRecords = parser.iterator(); + assertValuesEquals(new String[] { "AA", "33", null }, csvRecords.next()); + assertValuesEquals(new String[] { "AA", null, "" }, csvRecords.next()); + assertValuesEquals(new String[] { null, "33", "CC" }, csvRecords.next()); + } + } +} diff --git a/src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv b/src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv new file mode 100644 index 000000000..e7d2972c5 --- /dev/null +++ b/src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv @@ -0,0 +1,3 @@ +AA,33, +AA,,"" +,33,CC From b62ddc54e2063ed37b6d546bbab7caf567c82446 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 22 Jun 2025 14:57:06 -0400 Subject: [PATCH 023/245] [CSV-257] Updating from 1.6 to 1.7 breaks a header line with a missing header name Document the current behavior: Throw a IllegalArgumentException is a header name is missing. --- .../commons/csv/issues/JiraCsv257Test.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/test/java/org/apache/commons/csv/issues/JiraCsv257Test.java diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv257Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv257Test.java new file mode 100644 index 000000000..4234a7a0f --- /dev/null +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv257Test.java @@ -0,0 +1,84 @@ +/* + * 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.assertThrows; + +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; + +/** + * Tests https://issues.apache.org/jira/browse/CSV-257 + */ +class JiraCsv257Test { + + private static final String INPUT = ","; + + @Test + void testHeaderBuilder() throws IOException { + // @formatter:off + final CSVFormat format = CSVFormat.RFC4180.builder() + .setDelimiter(INPUT.charAt(0)) + .setHeader() + .setSkipHeaderRecord(true) + .setIgnoreSurroundingSpaces(true) + .get(); + // @formatter:on + // Document the current behavior: Throw a IllegalArgumentException is a header name is missing. + assertThrows(IllegalArgumentException.class, () -> { + try (CSVParser parser = CSVParser.parse(INPUT, format)) { + // empty + } + }); + } + + @Test + void testHeaderDepreacted() throws IOException { + // @formatter:off + final CSVFormat format = CSVFormat.RFC4180 + .withDelimiter(INPUT.charAt(0)) + .withFirstRecordAsHeader() + .withIgnoreSurroundingSpaces(); + // @formatter:on + // Document the current behavior: Throw a IllegalArgumentException is a header name is missing. + assertThrows(IllegalArgumentException.class, () -> { + try (CSVParser parser = new CSVParser(new StringReader(INPUT), format)) { + // empty + } + }); + } + + @Test + void testNoHeaderBuilder() throws IOException { + // @formatter:off + final CSVFormat format = CSVFormat.RFC4180.builder() + .setDelimiter(INPUT.charAt(0)) + .setIgnoreSurroundingSpaces(true) + .get(); + // @formatter:on + try (CSVParser parser = CSVParser.parse(INPUT, format)) { + // empty + } + } +} From cf6a90d1b9064e38cc785cab4ad9ebf6b18cfda3 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 22 Jun 2025 15:10:06 -0400 Subject: [PATCH 024/245] Use longer lines --- .../org/apache/commons/csv/CSVRecord.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVRecord.java b/src/main/java/org/apache/commons/csv/CSVRecord.java index 148c76ca8..f619717d0 100644 --- a/src/main/java/org/apache/commons/csv/CSVRecord.java +++ b/src/main/java/org/apache/commons/csv/CSVRecord.java @@ -125,20 +125,20 @@ public String get(final int i) { public String get(final String name) { final Map headerMap = getHeaderMapRaw(); if (headerMap == null) { - throw new IllegalStateException( - "No header mapping was specified, the record values can't be accessed by name"); + throw new IllegalStateException("No header mapping was specified, the record values can't be accessed by name"); } final Integer index = headerMap.get(name); if (index == null) { - throw new IllegalArgumentException(String.format("Mapping for %s not found, expected one of %s", name, - headerMap.keySet())); + throw new IllegalArgumentException(String.format("Mapping for %s not found, expected one of %s", name, headerMap.keySet())); } try { - return values[index.intValue()]; // Explicit (un)boxing is intentional + return values[index.intValue()]; // Explicit (un)boxing is intentional } catch (final ArrayIndexOutOfBoundsException e) { - throw new IllegalArgumentException(String.format( - "Index for header '%s' is %d but CSVRecord only has %d values!", name, index, - Integer.valueOf(values.length))); // Explicit (un)boxing is intentional + throw new IllegalArgumentException( + String.format("Index for header '%s' is %d but CSVRecord only has %d values!", name, index, Integer.valueOf(values.length))); // Explicit + // (un)boxing + // is + // intentional } } @@ -354,8 +354,7 @@ public Map toMap() { */ @Override public String toString() { - return "CSVRecord [comment='" + comment + "', recordNumber=" + recordNumber + ", values=" + - Arrays.toString(values) + "]"; + return "CSVRecord [comment='" + comment + "', recordNumber=" + recordNumber + ", values=" + Arrays.toString(values) + "]"; } /** From 32dbbf60459a86f5320b57ac74d81480013564f1 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 22 Jun 2025 15:12:35 -0400 Subject: [PATCH 025/245] Reduce use of magic chars --- .../java/org/apache/commons/csv/CSVFormat.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 9bcf9d189..eea5a53e1 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2536,27 +2536,27 @@ public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("Delimiter=<").append(delimiter).append('>'); if (isEscapeCharacterSet()) { - sb.append(' '); + sb.append(Constants.SP); sb.append("Escape=<").append(escapeCharacter).append('>'); } if (isQuoteCharacterSet()) { - sb.append(' '); + sb.append(Constants.SP); sb.append("QuoteChar=<").append(quoteCharacter).append('>'); } if (quoteMode != null) { - sb.append(' '); + sb.append(Constants.SP); sb.append("QuoteMode=<").append(quoteMode).append('>'); } if (isCommentMarkerSet()) { - sb.append(' '); + sb.append(Constants.SP); sb.append("CommentStart=<").append(commentMarker).append('>'); } if (isNullStringSet()) { - sb.append(' '); + sb.append(Constants.SP); sb.append("NullString=<").append(nullString).append('>'); } if (recordSeparator != null) { - sb.append(' '); + sb.append(Constants.SP); sb.append("RecordSeparator=<").append(recordSeparator).append('>'); } if (getIgnoreEmptyLines()) { @@ -2570,11 +2570,11 @@ public String toString() { } sb.append(" SkipHeaderRecord:").append(skipHeaderRecord); if (headerComments != null) { - sb.append(' '); + sb.append(Constants.SP); sb.append("HeaderComments:").append(Arrays.toString(headerComments)); } if (headers != null) { - sb.append(' '); + sb.append(Constants.SP); sb.append("Header:").append(Arrays.toString(headers)); } return sb.toString(); From f7581b7c92849c66787e2647aedfd9549267be50 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 22 Jun 2025 15:13:31 -0400 Subject: [PATCH 026/245] Reduce vertical whitespace --- src/main/java/org/apache/commons/csv/Lexer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/Lexer.java b/src/main/java/org/apache/commons/csv/Lexer.java index 0e5f36866..3d00fe0bf 100644 --- a/src/main/java/org/apache/commons/csv/Lexer.java +++ b/src/main/java/org/apache/commons/csv/Lexer.java @@ -340,7 +340,6 @@ private Token parseEncapsulatedToken(final Token token) throws IOException { int c; while (true) { c = reader.read(); - if (isQuoteChar(c)) { if (isQuoteChar(reader.peek())) { // double or escaped encapsulator -> add single encapsulator to token From dfb8888f5aa3d50cb50698a94b8eaa96789932f0 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 22 Jun 2025 15:15:01 -0400 Subject: [PATCH 027/245] Javadoc --- src/main/java/org/apache/commons/csv/QuoteMode.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/QuoteMode.java b/src/main/java/org/apache/commons/csv/QuoteMode.java index d9c032ffc..79bb1b34e 100644 --- a/src/main/java/org/apache/commons/csv/QuoteMode.java +++ b/src/main/java/org/apache/commons/csv/QuoteMode.java @@ -20,6 +20,8 @@ /** * Defines quoting behavior. + * + * @see CSVFormat.Builder#setQuoteMode(QuoteMode) */ public enum QuoteMode { From bd9793b4ef16746aee81cf663e4910c311b9963b Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 22 Jun 2025 15:16:08 -0400 Subject: [PATCH 028/245] Fix indentation --- src/main/java/org/apache/commons/csv/CSVFormat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index eea5a53e1..e8cb5e772 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -216,7 +216,7 @@ public static Builder create() { .setRecordSeparator(Constants.CRLF) .setIgnoreEmptyLines(true) .setDuplicateHeaderMode(DuplicateHeaderMode.ALLOW_ALL); - // @formatter:on + // @formatter:on } /** From 7b2f013521eb18f1bf6d065a1bc724199be61dce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:07:22 +0000 Subject: [PATCH 029/245] Bump com.opencsv:opencsv from 5.11.1 to 5.11.2 Bumps com.opencsv:opencsv from 5.11.1 to 5.11.2. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-version: 5.11.2 dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a1eca0578..96dfa9bb6 100644 --- a/pom.xml +++ b/pom.xml @@ -387,7 +387,7 @@ com.opencsv opencsv - 5.11.1 + 5.11.2 test From 08030900e0fd36ef9aa90a339429fdd6180d1434 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:26:24 +0000 Subject: [PATCH 030/245] Bump github/codeql-action from 3.29.0 to 3.29.1 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.0 to 3.29.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ce28f5bb42b7a9f2c824e633a3f6ee835bab6858...39edc492dbe16b1465b0cafca41432d857bdb31a) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1f3a099bd..922ca638b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 + uses: github/codeql-action/init@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 + uses: github/codeql-action/autobuild@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 + uses: github/codeql-action/analyze@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 25c086a73..5ccb0d4a4 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # 3.29.0 + uses: github/codeql-action/upload-sarif@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 with: sarif_file: results.sarif From fbe886c7aa7e2ecfb2a2b0ca421a78c902a14767 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Jul 2025 12:07:46 +0000 Subject: [PATCH 031/245] Bump github/codeql-action from 3.29.1 to 3.29.2 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.1 to 3.29.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/39edc492dbe16b1465b0cafca41432d857bdb31a...181d5eefc20863364f96762470ba6f862bdef56b) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 922ca638b..5bb1f901d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/autobuild@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 5ccb0d4a4..b15d73c9a 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@39edc492dbe16b1465b0cafca41432d857bdb31a # 3.29.1 + uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 with: sarif_file: results.sarif From c7be7564f108facd61c29e237d6947c2ee22acad Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 6 Jul 2025 09:52:33 -0400 Subject: [PATCH 032/245] Use HTTPS in Git URL --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a1eca0578..443907eab 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,7 @@ - scm:git:http://gitbox.apache.org/repos/asf/commons-csv.git + scm:git:https://gitbox.apache.org/repos/asf/commons-csv.git scm:git:https://gitbox.apache.org/repos/asf/commons-csv.git https://gitbox.apache.org/repos/asf?p=commons-csv.git From 0479be21bb3301a812584242eafe9ea130c2ea97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Jul 2025 21:54:20 +0000 Subject: [PATCH 033/245] Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 Bumps org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0. --- updated-dependencies: - dependency-name: org.apache.commons:commons-lang3 dependency-version: 3.18.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 443907eab..a4dcd2adb 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ org.apache.commons commons-lang3 - 3.17.0 + 3.18.0 test @@ -416,7 +416,7 @@ org.apache.commons commons-lang3 - 3.17.0 + 3.18.0 From 427151c0644e3a3976724dccf2d09e61aa186116 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 9 Jul 2025 18:11:28 -0400 Subject: [PATCH 034/245] Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #556 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bff6748a4..3cbc76ea6 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,7 @@ Bump org.apache.commons:commons-parent from 81 to 85 #542. Bump commons-io:commons-io from 2.18.0 to 2.19.0. Bump com.opencsv:opencsv from 5.10 to 5.11.1 #545, #551. + Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #556. From 59164c8b795ebd4cc0362c4c74d7c893c4a50303 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 9 Jul 2025 18:12:16 -0400 Subject: [PATCH 035/245] Bump com.opencsv:opencsv from 5.11.1 to 5.11.2 #553 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 3cbc76ea6..68a2295e5 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,7 @@ Bump org.apache.commons:commons-parent from 81 to 85 #542. Bump commons-io:commons-io from 2.18.0 to 2.19.0. - Bump com.opencsv:opencsv from 5.10 to 5.11.1 #545, #551. + Bump com.opencsv:opencsv from 5.10 to 5.11.2 #545, #551, #553. Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #556. From 67192a9e0af58bdf49edf4e0d29f50343da82c70 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 18 Jul 2025 17:30:07 -0400 Subject: [PATCH 036/245] Bump commons-io:commons-io from 2.19.0 to 2.20.0 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0db0836ad..f9a442bd8 100644 --- a/pom.xml +++ b/pom.xml @@ -116,7 +116,7 @@ true 2025-03-19T22:12:04Z 1.18.0 - 2.19.0 + 2.20.0 org.apache.commons.codec.binary;version="${commons.codec.version}", diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 68a2295e5..a34b7a336 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ Bump org.apache.commons:commons-parent from 81 to 85 #542. - Bump commons-io:commons-io from 2.18.0 to 2.19.0. + Bump commons-io:commons-io from 2.18.0 to 2.20.0. Bump com.opencsv:opencsv from 5.10 to 5.11.2 #545, #551, #553. Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #556. From 96583732b6be55d459a5b430c4a3a3bb2126db10 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 13:28:32 -0400 Subject: [PATCH 037/245] Update the GitHub pull request template for AI Better grammar --- .github/pull_request_template.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e17973cb0..7578b4da0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -22,7 +22,9 @@ Thanks for your contribution to [Apache Commons](https://commons.apache.org/)! Y Before you push a pull request, review this list: - [ ] Read the [contribution guidelines](CONTRIBUTING.md) for this project. +- [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI). +- [ ] I used AI to create any part of, or all of, this pull request. - [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. -- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best-practice. +- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best-practice. - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. -- [ ] Each commit in the pull request should have a meaningful subject line and body. Note that commits might be squashed by a maintainer on merge. +- [ ] Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process. From 7b72c509f73e05ca2bf2f0945a6a1cb03f87bd39 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 20 Jul 2025 17:36:44 -0400 Subject: [PATCH 038/245] Merge some string literals --- .../org/apache/commons/csv/CSVFormatTest.java | 2 +- .../org/apache/commons/csv/CSVParserTest.java | 25 ++++++++++++----- .../org/apache/commons/csv/LexerTest.java | 27 ++++++++++++++++--- .../commons/csv/issues/JiraCsv148Test.java | 2 +- .../commons/csv/issues/JiraCsv253Test.java | 8 +++++- 5 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index 99c7dc52c..d1d19f755 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -1218,7 +1218,7 @@ void testToStringAndWithCommentMarkerTakingCharacter() { Assertions.assertNotEquals(csvFormat, csvFormatTwo); Assertions.assertNotEquals(csvFormatTwo, csvFormat); - assertEquals("Delimiter=<,> QuoteChar=<\"> CommentStart= " + "RecordSeparator=<\r\n> EmptyLines:ignored SkipHeaderRecord:false", + assertEquals("Delimiter=<,> QuoteChar=<\"> CommentStart= RecordSeparator=<\r\n> EmptyLines:ignored SkipHeaderRecord:false", csvFormatTwo.toString()); } diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 22b1417c8..d9dd4e545 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -79,9 +79,13 @@ class CSVParserTest { 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" + + // @formatter:off + 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 + // @formatter:on private static final String CSV_INPUT_1 = "a,b,c,d"; @@ -181,7 +185,7 @@ void testBackslashEscaping2() throws IOException { // 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) + final String code = " , , \n" + // 1) " \t , , \n" + // 2) " // , /, , /,\n" + // 3) ""; @@ -201,8 +205,17 @@ void testBackslashEscaping2() throws IOException { @Test @Disabled 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\""; + // @formatter:off + 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\""; + // @formatter:on final String[][] res = { { "one", "two", "three" }, { "on\\\"e", "two" }, { "on\"e", "two" }, { "one", "tw\"o" }, { "one", "t\\,wo" }, // backslash in // quotes only // escapes a @@ -417,7 +430,7 @@ void testCSV57() throws Exception { @Test void testDefaultFormat() throws IOException { // @formatter:off - final String code = "" + "a,b#\n" + // 1) + final String code = "a,b#\n" + // 1) "\"\n\",\" \",#\n" + // 2) "#,\"\"\n" + // 3) "# Final comment\n" // 4) @@ -548,7 +561,7 @@ void testEndOfFileBehaviorExcel() throws Exception { @Test 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 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)) { diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index af0c69a77..e54e93365 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -121,8 +121,14 @@ void testBackspace() throws Exception { @Test void testComments() throws IOException { - final String code = "first,line,\n" + "second,line,tokenWith#no-comment\n" + "# comment line \n" + - "third,line,#no-comment\n" + "# penultimate comment\n" + "# Final comment\n"; + // @formatter:off + final String code = "first,line,\n" + + "second,line,tokenWith#no-comment\n" + + "# comment line \n" + + "third,line,#no-comment\n" + + "# penultimate comment\n" + + "# Final comment\n"; + // @formatter:on final CSVFormat format = CSVFormat.DEFAULT.withCommentMarker('#'); try (Lexer lexer = createLexer(code, format)) { assertNextToken(TOKEN, "first", lexer); @@ -306,8 +312,21 @@ void testFF() throws Exception { @Test void testIgnoreEmptyLines() throws IOException { - final String code = "first,line,\n" + "\n" + "\n" + "second,line\n" + "\n" + "\n" + "third line \n" + "\n" + - "\n" + "last, line \n" + "\n" + "\n" + "\n"; + // @formatter:off + final String code = "first,line,\n" + + "\n" + + "\n" + + "second,line\n" + + "\n" + + "\n" + + "third line \n" + + "\n" + + "\n" + + "last, line \n" + + "\n" + + "\n" + + "\n"; + // @formatter:on final CSVFormat format = CSVFormat.DEFAULT.withIgnoreEmptyLines(); try (Lexer lexer = createLexer(code, format)) { assertNextToken(TOKEN, "first", lexer); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java index befe3b5c3..67f1b785d 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv148Test.java @@ -55,7 +55,7 @@ void testWithTrimEmpty() { .get(); // @formatter:on assertEquals( - "\"\",\"\",\"Single space on the left\",\"Single space on the right\"," + "\"Single spaces on both sides\",\"Multiple spaces on the left\"," + + "\"\",\"\",\"Single space on the left\",\"Single space on the right\",\"Single spaces on both sides\",\"Multiple spaces on the left\"," + "\"Multiple spaces on the right\",\"Multiple spaces on both sides\"", format.format("", " ", " Single space on the left", "Single space on the right ", " Single spaces on both sides ", " Multiple spaces on the left", "Multiple spaces on the right ", " Multiple spaces on both sides ")); diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java index 136940859..13bb6a827 100644 --- a/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv253Test.java @@ -37,7 +37,13 @@ class JiraCsv253Test { @Test void testHandleAbsentValues() throws IOException { - final String source = "\"John\",,\"Doe\"\n" + ",\"AA\",123\n" + "\"John\",90,\n" + "\"\",,90"; + // @formatter:off + final String source = + "\"John\",,\"Doe\"\n" + + ",\"AA\",123\n" + + "\"John\",90,\n" + + "\"\",,90"; + // @formatter:on final CSVFormat csvFormat = CSVFormat.DEFAULT.builder().setQuoteMode(QuoteMode.NON_NUMERIC).get(); try (CSVParser parser = csvFormat.parse(new StringReader(source))) { final Iterator csvRecords = parser.iterator(); From 1fb37163f9fe59aa13c63efd53e71d7a0392be4c Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 22 Jul 2025 15:28:53 -0400 Subject: [PATCH 039/245] Bump commons-codec:commons-codec from 1.18.0 to 1.19.0 --- pom.xml | 2 +- src/changes/changes.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f9a442bd8..b1dfa7756 100644 --- a/pom.xml +++ b/pom.xml @@ -115,7 +115,7 @@ false true 2025-03-19T22:12:04Z - 1.18.0 + 1.19.0 2.20.0 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a34b7a336..315175a74 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ Bump commons-io:commons-io from 2.18.0 to 2.20.0. Bump com.opencsv:opencsv from 5.10 to 5.11.2 #545, #551, #553. Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #556. + Bump commons-codec:commons-codec from 1.18.0 to 1.19.0. From 9c95e92d6aaa4d052a139158a900395646c6652e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Jul 2025 12:52:01 +0000 Subject: [PATCH 040/245] Bump github/codeql-action from 3.29.2 to 3.29.4 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.2 to 3.29.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/181d5eefc20863364f96762470ba6f862bdef56b...4e828ff8d448a8a6e532957b1811f387a63867e8) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5bb1f901d..7400fb888 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/autobuild@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/analyze@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b15d73c9a..35000d4fe 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # 3.29.2 + uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 with: sarif_file: results.sarif From b76971c25af176f901c003b25d6a5f4f6edc87ad Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 27 Jul 2025 13:07:47 +0000 Subject: [PATCH 041/245] Prepare for the next release candidate --- README.md | 6 +-- RELEASE-NOTES.txt | 92 ++++++++++++++++++++++++++++------ pom.xml | 6 +-- src/changes/changes.xml | 2 +- src/site/xdoc/download_csv.xml | 26 +++++----- 5 files changed, 98 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 42c9894d1..f30de4b9c 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Apache Commons CSV [![Java CI](https://github.com/apache/commons-csv/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-csv/actions/workflows/maven.yml) [![Maven Central](https://img.shields.io/maven-central/v/org.apache.commons/commons-csv?label=Maven%20Central)](https://search.maven.org/artifact/org.apache.commons/commons-csv) -[![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-csv/1.14.0.svg)](https://javadoc.io/doc/org.apache.commons/commons-csv/1.14.0) +[![Javadocs](https://javadoc.io/badge/org.apache.commons/commons-csv/1.14.1.svg)](https://javadoc.io/doc/org.apache.commons/commons-csv/1.14.1) [![CodeQL](https://github.com/apache/commons-csv/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-csv/actions/workflows/codeql-analysis.yml) [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-csv/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-csv) @@ -68,7 +68,7 @@ Alternatively, you can pull it from the central Maven repositories: org.apache.commons commons-csv - 1.14.0 + 1.14.1 ``` @@ -90,7 +90,7 @@ There are some guidelines which will make applying PRs easier for us: + Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change. + Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running `mvn`. + Before you pushing a PR, run `mvn` (by itself), this runs the default goal, which contains all build checks. -+ To see the code coverage report, regardless of coverage failures, run `mvn clean site -Dcommons.jacoco.haltOnFailure=false` ++ To see the code coverage report, regardless of coverage failures, run `mvn clean site -Dcommons.jacoco.haltOnFailure=false -Pjacoco` If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas). You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md). diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 599f0d1f8..bfeb4bb8d 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,4 +1,54 @@ +Apache Commons CSV 1.14.1 Release Notes +--------------------------------------- + +The Apache Commons CSV team is pleased to announce the release of Apache Commons CSV 1.14.1. + + +This document contains the release notes for the 1.14.1 version of Apache Commons CSV. +Commons CSV reads and writes files in Comma Separated Value (CSV) format variations. + +Commons CSV requires at least Java 8. + +The Apache Commons CSV library provides a simple interface for reading and writing CSV files of various types. + +This is a feature and maintenance release. Java 8 or later is required. + +Changes in this version include: + + +Fixed Bugs +---------- + +* CSV-318: CSVPrinter.printRecord(Stream) hangs if given a parallel stream. Thanks to Joseph Shraibman, Gary Gregory. +* CSV-318: CSVPrinter now uses an internal lock instead of synchronized methods. Thanks to Joseph Shraibman, Gary Gregory. +* org.apache.commons.csv.CSVPrinter.printRecords(ResultSet) now writes one record at a time using a lock. Thanks to Gary Gregory. + +Changes +------- + +* Bump org.apache.commons:commons-parent from 81 to 85 #542. Thanks to Gary Gregory, Dependabot. +* Bump commons-io:commons-io from 2.18.0 to 2.20.0. Thanks to Gary Gregory. +* Bump com.opencsv:opencsv from 5.10 to 5.11.2 #545, #551, #553. Thanks to Gary Gregory, Dependabot. +* Bump org.apache.commons:commons-lang3 from 3.17.0 to 3.18.0 #556. Thanks to Gary Gregory, Dependabot. +* Bump commons-codec:commons-codec from 1.18.0 to 1.19.0. Thanks to Gary Gregory. + + +Historical list of changes: https://commons.apache.org/proper/commons-csv/changes.html + +For complete information on Apache Commons CSV, including instructions on how to submit bug reports, +patches, or suggestions for improvement, see the Apache Commons CSV website: + +https://commons.apache.org/proper/commons-csv/ + +Download page: https://commons.apache.org/proper/commons-csv/download_csv.cgi + +Have fun! +-Apache Commons CSV team + +------------------------------------------------------------------------------ + Apache Commons CSV 1.14.0 Release Notes +--------------------------------------- This document contains the release notes for the 1.14.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -59,7 +109,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.13.0 Release Notes +Apache Commons CSV 1.13.0 Release Notes +--------------------------------------- This document contains the release notes for the 1.13.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -111,7 +162,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.12.0 Release Notes +Apache Commons CSV 1.12.0 Release Notes +--------------------------------------- This document contains the release notes for the 1.12.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -167,7 +219,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.11.0 Release Notes +Apache Commons CSV 1.11.0 Release Notes +--------------------------------------- This document contains the release notes for the 1.11.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -227,7 +280,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.10.0 Release Notes +Apache Commons CSV 1.10.0 Release Notes +--------------------------------------- This document contains the release notes for the 1.10.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -308,7 +362,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.9.0 Release Notes +Apache Commons CSV 1.9.0 Release Notes +-------------------------------------- This document contains the release notes for the 1.9.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -410,7 +465,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.8 Release Notes +Apache Commons CSV 1.8 Release Notes +------------------------------------ This document contains the release notes for the 1.8 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -465,7 +521,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.7 Release Notes +Apache Commons CSV 1.7 Release Notes +------------------------------------ This document contains the release notes for the 1.7 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -512,7 +569,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.6 Release Notes +Apache Commons CSV 1.6 Release Notes +------------------------------------ This document contains the release notes for the 1.6 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the @@ -561,7 +619,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.5 Release Notes +Apache Commons CSV 1.5 Release Notes +------------------------------------ This document contains the release notes for the 1.5 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -613,7 +672,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.4 Release Notes +Apache Commons CSV 1.4 Release Notes +------------------------------------ This document contains the release notes for the 1.4 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -652,7 +712,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.3 Release Notes +Apache Commons CSV 1.3 Release Notes +------------------------------------ This document contains the release notes for the 1.3 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -696,7 +757,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.2 Release Notes +Apache Commons CSV 1.2 Release Notes +------------------------------------ This document contains the release notes for the 1.2 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -734,7 +796,8 @@ Have fun! ------------------------------------------------------------------------------ -Apache Commons CSV Version 1.1 Release Notes +Apache Commons CSV 1.1 Release Notes +------------------------------------ This document contains the release notes for the 1.1 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. @@ -775,7 +838,8 @@ Have fun! ------------------------------------------------------------------------------- -Apache Commons CSV Version 1.0 Release Notes +Apache Commons CSV 1.0 Release Notes +------------------------------------ This document contains the release notes for the 1.0 version of Apache Commons CSV. Commons CSV reads and writes files in variations of the Comma Separated Value (CSV) format. diff --git a/pom.xml b/pom.xml index b1dfa7756..9a824734f 100644 --- a/pom.xml +++ b/pom.xml @@ -96,12 +96,12 @@ - 1.14.0 + 1.14.1 (Java 8 or above) RC1 - 1.13.0 - 1.14.1 + 1.14.0 + 1.14.2 csv org.apache.commons.csv CSV diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 315175a74..c9c31d25d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -40,7 +40,7 @@ Apache Commons CSV Release Notes - + CSVPrinter.printRecord(Stream) hangs if given a parallel stream. CSVPrinter now uses an internal lock instead of synchronized methods. diff --git a/src/site/xdoc/download_csv.xml b/src/site/xdoc/download_csv.xml index b5e7881dc..151c3f69e 100644 --- a/src/site/xdoc/download_csv.xml +++ b/src/site/xdoc/download_csv.xml @@ -115,32 +115,32 @@ limitations under the License.

-
+
- - - + + + - - - + + +
commons-csv-1.14.0-bin.tar.gzsha512pgpcommons-csv-1.14.1-bin.tar.gzsha512pgp
commons-csv-1.14.0-bin.zipsha512pgpcommons-csv-1.14.1-bin.zipsha512pgp
- - - + + + - - - + + +
commons-csv-1.14.0-src.tar.gzsha512pgpcommons-csv-1.14.1-src.tar.gzsha512pgp
commons-csv-1.14.0-src.zipsha512pgpcommons-csv-1.14.1-src.zipsha512pgp
From d8724bf76a7d6abbb93aad65e316f050f86a256d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 27 Jul 2025 13:08:59 +0000 Subject: [PATCH 042/245] Prepare for the release candidate 1.14.1 RC1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 9a824734f..404e7b4cc 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 85 commons-csv - 1.14.1-SNAPSHOT + 1.14.1 Apache Commons CSV https://commons.apache.org/proper/commons-csv/ 2005 @@ -114,7 +114,7 @@ UTF-8 false true - 2025-03-19T22:12:04Z + 2025-07-27T13:07:58Z 1.19.0 2.20.0 From e14ef86d34211f9d1b9b6040c5f6dbafc93ba907 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Tue, 29 Jul 2025 08:39:37 -0400 Subject: [PATCH 043/245] Ignore macOS file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4b377d576..e0f2c4514 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ buildNumber.properties *.iml /.vscode/ +/.DS_Store From 5fb018a90f3f9ba53b15f2c3edbbcbcbe67e670d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 30 Jul 2025 14:51:44 +0000 Subject: [PATCH 044/245] Bump to next development version --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 404e7b4cc..37101a3b3 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 85 commons-csv - 1.14.1 + 1.14.2-SNAPSHOT Apache Commons CSV https://commons.apache.org/proper/commons-csv/ 2005 @@ -114,7 +114,7 @@ UTF-8 false true - 2025-07-27T13:07:58Z + 2025-07-30T14:51:35Z 1.19.0 2.20.0 From da1eafd78cb4d9e697f46b3d117617c728fdac11 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 30 Jul 2025 14:52:35 +0000 Subject: [PATCH 045/245] Updates for the next release --- src/changes/changes.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c9c31d25d..2e2e3b315 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -40,6 +40,11 @@ Apache Commons CSV Release Notes + + + + + CSVPrinter.printRecord(Stream) hangs if given a parallel stream. From e585a6dbb4c4adda8b595ee2355e80ae5eefc09e Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 30 Jul 2025 15:02:02 +0000 Subject: [PATCH 046/245] Updates for the next release --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 37101a3b3..1d8ac4029 100644 --- a/pom.xml +++ b/pom.xml @@ -96,12 +96,12 @@ - 1.14.1 + 1.14.2 (Java 8 or above) RC1 - 1.14.0 - 1.14.2 + 1.14.1 + 1.14.3 csv org.apache.commons.csv CSV From 9d20379603315a35a9da0367b37e723f718f3414 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:12:17 +0000 Subject: [PATCH 047/245] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 Bumps com.opencsv:opencsv from 5.11.2 to 5.12.0. --- updated-dependencies: - dependency-name: com.opencsv:opencsv dependency-version: 5.12.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1d8ac4029..44b1dbd75 100644 --- a/pom.xml +++ b/pom.xml @@ -387,7 +387,7 @@ com.opencsv opencsv - 5.11.2 + 5.12.0 test From eaa8bdbe2a6cf587704e5862d17bcbb31218236e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 1 Aug 2025 08:27:13 -0400 Subject: [PATCH 048/245] [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558 --- src/changes/changes.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2e2e3b315..925c704c2 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -43,7 +43,8 @@ - + + [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. From 0922aed80dfce4946d22cdc647e8a402d370ea56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Aug 2025 12:54:55 +0000 Subject: [PATCH 049/245] Bump github/codeql-action from 3.29.4 to 3.29.5 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.4 to 3.29.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/4e828ff8d448a8a6e532957b1811f387a63867e8...51f77329afa6477de8c49fc9c7046c15b9a4e79d) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7400fb888..0ade2ded2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/autobuild@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 35000d4fe..359d5f95a 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@4e828ff8d448a8a6e532957b1811f387a63867e8 # 3.29.4 + uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 with: sarif_file: results.sarif From 6bba74633f22969f49e7a73759f581369d9f5e02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 12:27:01 +0000 Subject: [PATCH 050/245] Bump actions/cache from 4.2.3 to 4.2.4 Bumps [actions/cache](https://github.com/actions/cache) from 4.2.3 to 4.2.4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/5a3ec84eff668545956fd18022155c47e93e2684...0400d5f644dc74513175e3cd8d07132dd4860809) --- updated-dependencies: - dependency-name: actions/cache dependency-version: 4.2.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0ade2ded2..9ef257027 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: persist-credentials: false - - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 630852b56..9a9c25f17 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 with: persist-credentials: false - - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 + - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 56d4b299281fcde31e14d63f49dce36218aa3976 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 12:27:14 +0000 Subject: [PATCH 051/245] Bump github/codeql-action from 3.29.7 to 3.29.8 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.7 to 3.29.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/51f77329afa6477de8c49fc9c7046c15b9a4e79d...76621b61decf072c1cee8dd1ce2d2a82d33c17ed) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0ade2ded2..3f47f8ec1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/init@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/autobuild@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/analyze@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 359d5f95a..e3d3d9bd0 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # 3.29.5 + uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 with: sarif_file: results.sarif From cf87e85336003555485f5e829f5202ed8211678d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 12:42:39 +0000 Subject: [PATCH 052/245] Bump github/codeql-action from 3.29.8 to 3.29.9 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.8 to 3.29.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/76621b61decf072c1cee8dd1ce2d2a82d33c17ed...df559355d593797519d70b90fc8edd5db049e7a2) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6a66f14e9..f6956cda2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/autobuild@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/analyze@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index e3d3d9bd0..8b2745369 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@76621b61decf072c1cee8dd1ce2d2a82d33c17ed # 3.29.5 + uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 with: sarif_file: results.sarif From 4aac088e88b83a14c62004d339622a551dadd765 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Aug 2025 12:42:46 +0000 Subject: [PATCH 053/245] Bump actions/checkout from 4.2.2 to 5.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/11bd71901bbe5b1630ceea73d27597364c9af683...08c6903cd8c0fde910a37f88322edcfb5dd907a8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- .github/workflows/scorecards-analysis.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6a66f14e9..af9e41c42 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 with: persist-credentials: false - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 33573cf94..e8d1ed678 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9a9c25f17..df668a8ab 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 with: persist-credentials: false - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index e3d3d9bd0..6f557e72d 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 with: persist-credentials: false From 60287cac08b675f1564d7f18209c8def3a941e40 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 20 Aug 2025 06:53:46 -0400 Subject: [PATCH 054/245] Javadoc --- src/main/java/org/apache/commons/csv/CSVParser.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 9b96f7c7f..538bb395c 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -175,7 +175,7 @@ public CSVParser get() throws IOException { * Sets the lexer offset when the parser does not start parsing at the beginning of the source. * * @param characterOffset the lexer offset. - * @return this instance. + * @return {@code this} instance. */ public Builder setCharacterOffset(final long characterOffset) { this.characterOffset = characterOffset; @@ -186,7 +186,7 @@ public Builder setCharacterOffset(final long characterOffset) { * Sets the CSV format. A copy of the given format is kept. * * @param format the CSV format, {@code null} resets to {@link CSVFormat#DEFAULT}. - * @return this instance. + * @return {@code this} instance. */ public Builder setFormat(final CSVFormat format) { this.format = CSVFormat.copy(format); @@ -197,7 +197,7 @@ public Builder setFormat(final CSVFormat format) { * Sets the next record number to assign, defaults to {@code 1}. * * @param recordNumber the next record number to assign. - * @return this instance. + * @return {@code this} instance. */ public Builder setRecordNumber(final long recordNumber) { this.recordNumber = recordNumber; @@ -208,7 +208,7 @@ public Builder setRecordNumber(final long recordNumber) { * Sets whether to enable byte tracking for the parser. * * @param trackBytes {@code true} to enable byte tracking; {@code false} to disable it. - * @return this instance. + * @return {@code this} instance. * @since 1.13.0 */ public Builder setTrackBytes(final boolean trackBytes) { From 13d10d724a27868eeaefa00bc08cd115b2af75da Mon Sep 17 00:00:00 2001 From: Jan Burkhardt Date: Thu, 21 Aug 2025 11:09:21 +0200 Subject: [PATCH 055/245] CSV-320: Remove Spotbugs Dependency and use exclude-filter instead (#564) Removes the Spotbugs dependency that introduces a compile time dependency to CsvPrinter. --- pom.xml | 6 ------ src/main/java/org/apache/commons/csv/CSVPrinter.java | 3 --- src/site/resources/spotbugs/spotbugs-exclude-filter.xml | 7 +++++++ 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 44b1dbd75..f33337cbb 100644 --- a/pom.xml +++ b/pom.xml @@ -68,12 +68,6 @@ ${commons.jmh.version} test - - com.github.spotbugs - spotbugs-annotations - ${commons.spotbugs.impl.version} - true - scm:git:https://gitbox.apache.org/repos/asf/commons-csv.git diff --git a/src/main/java/org/apache/commons/csv/CSVPrinter.java b/src/main/java/org/apache/commons/csv/CSVPrinter.java index 59948557e..087129ec5 100644 --- a/src/main/java/org/apache/commons/csv/CSVPrinter.java +++ b/src/main/java/org/apache/commons/csv/CSVPrinter.java @@ -40,8 +40,6 @@ import org.apache.commons.io.function.IOStream; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - /** * Prints values in a {@link CSVFormat CSV format}. * @@ -153,7 +151,6 @@ public void close(final boolean flush) throws IOException { * @throws IOException * If an I/O error occurs */ - @SuppressFBWarnings(value = "AT_NONATOMIC_OPERATIONS_ON_SHARED_VARIABLE", justification = "https://github.com/spotbugs/spotbugs/issues/3428") private void endOfRecord() throws IOException { println(); recordCount++; diff --git a/src/site/resources/spotbugs/spotbugs-exclude-filter.xml b/src/site/resources/spotbugs/spotbugs-exclude-filter.xml index a58e09e24..79c57d3ae 100644 --- a/src/site/resources/spotbugs/spotbugs-exclude-filter.xml +++ b/src/site/resources/spotbugs/spotbugs-exclude-filter.xml @@ -54,5 +54,12 @@ + + + + + + + From e46fea81ec00cdcf7fc5eef7e7d3bc9f7c2d2bba Mon Sep 17 00:00:00 2001 From: Alex Herbert Date: Thu, 21 Aug 2025 10:14:07 +0100 Subject: [PATCH 056/245] Track changes --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 925c704c2..ead39353f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -42,6 +42,7 @@ + Remove Spotbugs dependency and use exclude-filter instead #564. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. From c9a4f4b2514b3d75e24f9fd02ed7d5e7bb90fe73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:57:09 +0000 Subject: [PATCH 057/245] Bump actions/dependency-review-action from 4.7.1 to 4.7.2 Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.1 to 4.7.2. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/da24556b548a50705dd671f47852072ea4c105d9...bc41886e18ea39df68b1b1245f4184881938e050) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.7.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index e8d1ed678..daed9687f 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 + uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # v4.7.2 From f97ba23aae8898b3a1406f7563a9ca7b27230c5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:57:21 +0000 Subject: [PATCH 058/245] Bump github/codeql-action from 3.29.9 to 3.29.11 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.9 to 3.29.11. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/df559355d593797519d70b90fc8edd5db049e7a2...3c3833e0f8c1c83d449a7478aa59c036a9165498) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.29.11 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 12726317c..90e7c8f32 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/autobuild@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 1f53594dc..d580164b9 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # 3.29.5 + uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 with: sarif_file: results.sarif From 9d715221792ccb6d1a685ba02534c90246657f5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 12:57:24 +0000 Subject: [PATCH 059/245] Bump actions/setup-java from 4.7.1 to 5.0.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 4.7.1 to 5.0.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/c5195efecf7bdfc987ee8bae7a71cb8b11521c00...dded0888837ed1f317902acf8a20df0ad188d165) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index df668a8ab..2996e062a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -48,7 +48,7 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} From f95fa5e7d52f3c2da484f647e8d824b96547f70d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 16:03:13 +0000 Subject: [PATCH 060/245] Bump org.apache.commons:commons-parent from 85 to 87 Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 85 to 87. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '87' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f33337cbb..301246898 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 85 + 87 commons-csv 1.14.2-SNAPSHOT From ee86bd6908f79da2778dad9a995f70fd47acd938 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 24 Aug 2025 15:06:13 -0400 Subject: [PATCH 061/245] Bump org.apache.commons:commons-parent from 85 to 87 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ead39353f..615b5adb2 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,6 +46,7 @@ [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. + Bump org.apache.commons:commons-parent from 85 to 87. From 71e9846a4916772e50c692128305fc710b18f109 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 12:00:48 +0000 Subject: [PATCH 062/245] Bump actions/dependency-review-action from 4.7.2 to 4.7.3 Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.2 to 4.7.3. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/bc41886e18ea39df68b1b1245f4184881938e050...595b5aeba73380359d98a5e087f648dbb0edce1b) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.7.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index daed9687f..1e0439242 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@bc41886e18ea39df68b1b1245f4184881938e050 # v4.7.2 + uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3 From 8b99b509f1b51f1e0f65d75b98a04276f1c5193f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Sep 2025 12:01:07 +0000 Subject: [PATCH 063/245] Bump github/codeql-action from 3.29.11 to 3.30.1 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.11 to 3.30.1. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/3c3833e0f8c1c83d449a7478aa59c036a9165498...f1f6e5f6af878fb37288ce1c627459e94dbf7d01) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 90e7c8f32..657f62102 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/init@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/autobuild@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/analyze@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index d580164b9..7bcf25e98 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # 3.29.5 + uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 with: sarif_file: results.sarif From c4baa00172e3f831a5e514236b0613360a3438cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Sep 2025 12:00:52 +0000 Subject: [PATCH 064/245] Bump github/codeql-action from 3.30.1 to 3.30.3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 3.30.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f1f6e5f6af878fb37288ce1c627459e94dbf7d01...192325c86100d080feab897ff886c34abd4c83a3) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 657f62102..be3841cb3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/autobuild@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 7bcf25e98..eb5a3812f 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f1f6e5f6af878fb37288ce1c627459e94dbf7d01 # 3.29.5 + uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 with: sarif_file: results.sarif From ad92c016cb0d42d438ffd779b28f535eb5749504 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 20 Sep 2025 02:06:48 +0000 Subject: [PATCH 065/245] Bump org.apache.commons:commons-parent from 87 to 88 Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 87 to 88. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '88' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 301246898..decb869c7 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 87 + 88 commons-csv 1.14.2-SNAPSHOT From 589a120b5d2d9e2beec56e9f110b4b8125b589b9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Sep 2025 22:10:48 -0400 Subject: [PATCH 066/245] Bump org.apache.commons:commons-parent from 87 to 88 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 615b5adb2..31f186264 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,8 +45,8 @@ Remove Spotbugs dependency and use exclude-filter instead #564. + Bump org.apache.commons:commons-parent from 85 to 88 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. - Bump org.apache.commons:commons-parent from 85 to 87. From e4ad3171a78d9425ea72e6f1a7855f4f185be65d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 24 Sep 2025 10:17:28 -0400 Subject: [PATCH 067/245] Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0 --- pom.xml | 4 ++-- src/changes/changes.xml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index decb869c7..2a6a583ed 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ org.apache.commons commons-lang3 - 3.18.0 + 3.19.0 test @@ -410,7 +410,7 @@ org.apache.commons commons-lang3 - 3.18.0 + 3.19.0 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 31f186264..dd8e4c07f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,6 +47,7 @@ Bump org.apache.commons:commons-parent from 85 to 88 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. + Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 6b0789fbdafb13d857ad35c8f729afd45be56729 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:01:01 +0000 Subject: [PATCH 068/245] Bump actions/cache from 4.2.4 to 4.3.0 Bumps [actions/cache](https://github.com/actions/cache) from 4.2.4 to 4.3.0. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/0400d5f644dc74513175e3cd8d07132dd4860809...0057852bfaa89a56745cba8c7296529d2fc39830) --- updated-dependencies: - dependency-name: actions/cache dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index be3841cb3..73fb0aace 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 with: persist-credentials: false - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2996e062a..dc7a2a88c 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 with: persist-credentials: false - - uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From ecbd2821b744b3a1bf5379c37176ef7c09f9253e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 12:01:15 +0000 Subject: [PATCH 069/245] Bump github/codeql-action from 3.30.3 to 3.30.4 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.3 to 3.30.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/192325c86100d080feab897ff886c34abd4c83a3...303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.4 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index be3841cb3..f00c33c61 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/init@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/autobuild@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/analyze@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index eb5a3812f..ba1650951 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # 3.29.5 + uses: github/codeql-action/upload-sarif@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 with: sarif_file: results.sarif From 89eb1f053cd374b72866a77245b5c69fcb87fbf6 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 26 Sep 2025 10:16:15 -0400 Subject: [PATCH 070/245] Replace GH CI Java 24 with 25 Replace Java 25-ea with Java 26-ea --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index dc7a2a88c..9a24b4974 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -29,12 +29,12 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-13] - java: [ 8, 11, 17, 21, 24 ] + java: [ 8, 11, 17, 21, 25 ] experimental: [false] # Keep the same parameter order as the matrix above include: - os: ubuntu-latest - java: 25-ea + java: 26-ea experimental: true steps: From 9404f29023a7cad5969f29e9c3d3b30bd09dd9a8 Mon Sep 17 00:00:00 2001 From: Cassio Santos Date: Mon, 29 Sep 2025 00:24:12 +0200 Subject: [PATCH 071/245] Remove broken link --- src/site/xdoc/index.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index a133db619..26bb91567 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -105,7 +105,7 @@ For previous releases, see the Skife CSV
  • Open CSV
  • -
  • Genjava CSV
  • +
  • Genjava CSV
  • In addition to the code from Netcetera (org.apache.commons.csv), Martin van den Bemt has added an additional writer API.

    Other CSV implementations:

    From 3d951f20f67b85e3a08681ff79ca1c63385049a9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 29 Sep 2025 06:46:21 -0400 Subject: [PATCH 072/245] Remove broken website link #577 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index dd8e4c07f..4e6532850 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -43,6 +43,7 @@ Remove Spotbugs dependency and use exclude-filter instead #564. + Remove broken website link #577. Bump org.apache.commons:commons-parent from 85 to 88 #573. From 3aec0d4b2fa7aeec4dc72279ff9fe92be33a1fbb Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Mon, 29 Sep 2025 06:59:02 -0400 Subject: [PATCH 073/245] Update site with new Oak logotype --- src/media/logo-large.xcf | Bin 0 -> 143556 bytes src/media/logo.png | Bin 0 -> 10083 bytes src/media/logo.xcf | Bin 0 -> 22088 bytes src/site/resources/images/logo.png | Bin 20042 -> 10083 bytes src/site/resources/images/logo.xcf | Bin 141911 -> 0 bytes src/site/xdoc/index.xml | 3 +++ 6 files changed, 3 insertions(+) create mode 100644 src/media/logo-large.xcf create mode 100644 src/media/logo.png create mode 100644 src/media/logo.xcf delete mode 100644 src/site/resources/images/logo.xcf diff --git a/src/media/logo-large.xcf b/src/media/logo-large.xcf new file mode 100644 index 0000000000000000000000000000000000000000..7bb07af3eb06c4b961e2b27ee4cbdf9e0ba50828 GIT binary patch literal 143556 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 literal 0 HcmV?d00001 diff --git a/src/media/logo.png b/src/media/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..582fba9806c9b77d605e1145ed2d246e18e91d78 GIT binary patch literal 10083 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 literal 0 HcmV?d00001 diff --git a/src/media/logo.xcf b/src/media/logo.xcf new file mode 100644 index 0000000000000000000000000000000000000000..ac6376f71f1406c121ce0c160dfda147103f2019 GIT binary patch literal 22088 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 literal 0 HcmV?d00001 diff --git a/src/site/resources/images/logo.png b/src/site/resources/images/logo.png index 77e721d2c7ea1966ab80c411b8dc2b66d4e76c1d..582fba9806c9b77d605e1145ed2d246e18e91d78 100644 GIT binary patch literal 10083 zcmZu%bzD>L+a`vTG*W_ecM8(o-65q6>5`5Cg3=w*(p|zxVTjV*4MR#mItSZ$_x=6- zZlANW^PKZ};*RUOpZnagdOE5Ecr@`)DQ2nF6-+C(3Q7yQhYUVy@Xnf579q0k&vVN#W?2qc&%Gigv zba*0cVp>SlC=6)oO7cblt0x749pnR@PqH3U`2_2F2^th~gaUM)n(hf}Q_?e4Uhz~O zKQ{Af^&3YfdaJZ_MGjvH@CnAgc8^tGPlQs4I*X|2?@+uT{%0q_6Bk~>gW;HW*sw+a zR`pAiOlTP@LDHZdei5hb9ScQOOn-Ch$D0_#tJvjDc;! zvCkN?$t zZ}PiQSS8`F8lhCGzXw^WVZ;>rtMjzRdBmrww@q9|8xX%cAW7KUPbO)A73!D~dgj3_ z1?0_Ak~8IY7=v-iY~x{9*nDR1pV^-WejnY=^BA`PgG-(-u|EE961>0ni$J3t^4yi} zTJnNyy9Xx`@dVqQsO99Gx!^7((-2zG8uU_{+3cGflRG=XxlprI80Kf%`Ww2m+83R4@Q3@|2H

  • < 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

    From f624260148e38a289879b903939077c9cdf54401 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 12:00:56 +0000 Subject: [PATCH 074/245] Bump github/codeql-action from 3.30.4 to 3.30.6 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.4 to 3.30.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9...64d10c13136e1c5bce3e5fbde8d4906eeaafc885) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 3.30.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2e3e78081..05a84b913 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 + uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 + uses: github/codeql-action/autobuild@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 + uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index ba1650951..8f86e32ba 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5 + uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 with: sarif_file: results.sarif From 29d37ce2a20496d8b774ed04d63b23fc4519adb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 12:01:00 +0000 Subject: [PATCH 075/245] Bump ossf/scorecard-action from 2.4.2 to 2.4.3 Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.4.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/05b42c624433fc40578a4040d5cf5e36ddca8cde...4eaacf0543bb3f2c246792bd56e8cdeffafb205a) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-version: 2.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index ba1650951..f94cd0ee2 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -45,7 +45,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # 2.4.2 + uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # 2.4.3 with: results_file: results.sarif results_format: sarif From b4647531c6dc7a644bfa7524a61787b9212081ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 12:01:03 +0000 Subject: [PATCH 076/245] Bump actions/dependency-review-action from 4.7.3 to 4.8.0 Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.3 to 4.8.0. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/595b5aeba73380359d98a5e087f648dbb0edce1b...56339e523c0409420f6c2c9a2f4292bbb3c07dd3) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 1e0439242..edfe87566 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3 + uses: actions/dependency-review-action@56339e523c0409420f6c2c9a2f4292bbb3c07dd3 # v4.8.0 From d23229eb71e3b8d744a103fad093708be9912974 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Wed, 8 Oct 2025 14:45:12 -0400 Subject: [PATCH 077/245] Bump org.apache.commons:commons-parent from 88 to 89 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2a6a583ed..996195e3a 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 88 + 89 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4e6532850..1e5e72b51 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,7 +46,7 @@ Remove broken website link #577. - Bump org.apache.commons:commons-parent from 85 to 88 #573. + Bump org.apache.commons:commons-parent from 85 to 89 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 3dacbcb2235a7196327f2f4c15bf78a922a059db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Oct 2025 12:01:07 +0000 Subject: [PATCH 078/245] Bump github/codeql-action from 3.30.6 to 4.30.7 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.6 to 4.30.7. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/64d10c13136e1c5bce3e5fbde8d4906eeaafc885...e296a935590eb16afc0c0108289f68c87e2a89a5) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.7 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 05a84b913..c8aeb8c13 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b666ba680..5ba6ff465 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # 3.29.5 + uses: github/codeql-action/upload-sarif@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 with: sarif_file: results.sarif From 2777a67538a8a194c194250b1a26d1f8c4f3bd6d Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 11 Oct 2025 06:58:35 -0400 Subject: [PATCH 079/245] PMD: Discontinue using Rule name category/java/errorprone.xml/UselessOperationOnImmutable as it is scheduled for removal from PMD. PMD 8.0.0 will remove support for this Rule. --- src/site/resources/pmd/pmd-ruleset.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/site/resources/pmd/pmd-ruleset.xml b/src/site/resources/pmd/pmd-ruleset.xml index a7ccc9216..74e41f991 100644 --- a/src/site/resources/pmd/pmd-ruleset.xml +++ b/src/site/resources/pmd/pmd-ruleset.xml @@ -59,7 +59,6 @@ - From fb42f550eed418cb7c0c6cebd917a3a6d7a05f6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 12:00:57 +0000 Subject: [PATCH 080/245] Bump github/codeql-action from 4.30.7 to 4.30.8 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.7 to 4.30.8. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/e296a935590eb16afc0c0108289f68c87e2a89a5...f443b600d91635bebf5b0d9ebc620189c0d6fba5) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.8 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c8aeb8c13..6173c37a0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 + uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 + uses: github/codeql-action/autobuild@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 + uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 5ba6ff465..20fc9d3e1 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@e296a935590eb16afc0c0108289f68c87e2a89a5 # 3.29.5 + uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 with: sarif_file: results.sarif From f4f06c9f9869c19e27f17e9378761a7619c35253 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 12:01:01 +0000 Subject: [PATCH 081/245] Bump actions/dependency-review-action from 4.8.0 to 4.8.1 Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.0 to 4.8.1. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/56339e523c0409420f6c2c9a2f4292bbb3c07dd3...40c09b7dc99638e5ddb0bfd91c1673effc064d8a) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index edfe87566..a657a4ae2 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@56339e523c0409420f6c2c9a2f4292bbb3c07dd3 # v4.8.0 + uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1 From ea6fd2e951efc13e30214c1b0e7450537e81008e Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sun, 19 Oct 2025 08:56:23 -0400 Subject: [PATCH 082/245] Fix grammar --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7578b4da0..4cbe168c3 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -25,6 +25,6 @@ Before you push a pull request, review this list: - [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI). - [ ] I used AI to create any part of, or all of, this pull request. - [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. -- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best-practice. +- [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice. - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. - [ ] Each commit in the pull request should have a meaningful subject line and body. Note that a maintainer may squash commits during the merge process. From 2ff7a0c95f01d61a7ff5bd6f254c36f0cce34131 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:01:04 +0000 Subject: [PATCH 083/245] Bump github/codeql-action from 4.30.8 to 4.30.9 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.8 to 4.30.9. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f443b600d91635bebf5b0d9ebc620189c0d6fba5...16140ae1a102900babc80a33c44059580f687047) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.30.9 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6173c37a0..556c22bbf 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/autobuild@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 20fc9d3e1..e181b827c 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # 3.29.5 + uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 with: sarif_file: results.sarif From 792906f91288d75c80a2499e4a0e1aa01d76bea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:01:31 +0000 Subject: [PATCH 084/245] Bump org.apache.commons:commons-parent from 89 to 90 Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 89 to 90. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '90' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 996195e3a..68837a9e5 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 89 + 90 commons-csv 1.14.2-SNAPSHOT From 5e7347346df53f5d35aa173f6d869506de73c8fc Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 24 Oct 2025 14:53:56 -0400 Subject: [PATCH 085/245] Bump org.apache.commons:commons-parent from 89 to 90 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 1e5e72b51..c74e7c9ef 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,7 +46,7 @@ Remove broken website link #577. - Bump org.apache.commons:commons-parent from 85 to 89 #573. + Bump org.apache.commons:commons-parent from 85 to 90 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 61e4eef441e015b83ad72c5a164f84e32547d54d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 12:01:04 +0000 Subject: [PATCH 086/245] Bump github/codeql-action from 4.30.9 to 4.31.2 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.9 to 4.31.2. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/16140ae1a102900babc80a33c44059580f687047...0499de31b99561a6d14a36a5f662c2a54f91beee) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 556c22bbf..f8db33bf4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/autobuild@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index e181b827c..7301aaf3c 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@16140ae1a102900babc80a33c44059580f687047 # 3.29.5 + uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 with: sarif_file: results.sarif From ae842332e234ee66e1a8c1054bceb667497a8255 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 12:01:07 +0000 Subject: [PATCH 087/245] Bump org.apache.commons:commons-parent from 90 to 91 Bumps [org.apache.commons:commons-parent](https://github.com/apache/commons-parent) from 90 to 91. - [Changelog](https://github.com/apache/commons-parent/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-parent/commits) --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '91' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 68837a9e5..8e2ffc1ea 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 90 + 91 commons-csv 1.14.2-SNAPSHOT From 278c7d109a4336f217df20752464bc6cd8a60992 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 Oct 2025 12:01:07 +0000 Subject: [PATCH 088/245] Bump actions/upload-artifact from 4.6.2 to 5.0.0 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 5.0.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/ea165f8d65b6e75b540449e92b4886f43607fa02...330a01c490aca151604b8cf639adc76d48f6c5d4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: 5.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index e181b827c..03cdbde2b 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -57,7 +57,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 with: name: SARIF file path: results.sarif From 6213812863936762e59b640115f33d62c73d0de0 Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Fri, 31 Oct 2025 17:33:47 -0400 Subject: [PATCH 089/245] Bump org.apache.commons:commons-parent from 90 to 91 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c74e7c9ef..901bce30e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,7 +46,7 @@ Remove broken website link #577. - Bump org.apache.commons:commons-parent from 85 to 90 #573. + Bump org.apache.commons:commons-parent from 85 to 91 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. From 864e300c7055993dd3570f94b2a99f2e384ae5fd Mon Sep 17 00:00:00 2001 From: "Gary D. Gregory" Date: Sat, 1 Nov 2025 06:49:32 -0400 Subject: [PATCH 090/245] Javadoc --- src/test/java/org/apache/commons/csv/CSVPrinterTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index 341091e57..ed88d8379 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -157,8 +157,8 @@ private void doRandom(final CSVFormat format, final int iter) throws Exception { } /** - * 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. + * Converts an input CSV array into expected output values, including 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(); From 39909dfc49328004b90a99d7a15d558d92dfc049 Mon Sep 17 00:00:00 2001 From: Sebb Date: Sat, 1 Nov 2025 16:59:40 +0000 Subject: [PATCH 091/245] Add dependabot email [skip ci] --- .asf.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.asf.yaml b/.asf.yaml index a2dc85766..cdb8cd101 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -23,7 +23,8 @@ notifications: pullrequests: issues@commons.apache.org jira_options: link label jobs: notifications@commons.apache.org - issues_bot_dependabot: notifications@commons.apache.org - pullrequests_bot_dependabot: notifications@commons.apache.org + # commits_bot_dependabot: dependabot@commons.apache.org + issues_bot_dependabot: dependabot@commons.apache.org + pullrequests_bot_dependabot: dependabot@commons.apache.org issues_bot_codecov-commenter: notifications@commons.apache.org pullrequests_bot_codecov-commenter: notifications@commons.apache.org From a1d3c7e9283a943be414bc3ce2389a43fc8bc461 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 2 Nov 2025 10:15:02 -0500 Subject: [PATCH 092/245] Convert "unsafe" link to text --- src/site/xdoc/index.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index 7494b324b..1e397d463 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -106,7 +106,7 @@ For previous releases, see the

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

    From de3ed33dbe862665558393f5d242e02294b1e5d7 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 5 Nov 2025 09:46:35 +0100 Subject: [PATCH 093/245] Upgrade from deprecated macos-13 to macos-latest in CI Fixes: #590 * #590 --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 9a24b4974..24b847399 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -28,7 +28,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-13] + os: [ubuntu-latest, macos-latest] java: [ 8, 11, 17, 21, 25 ] experimental: [false] # Keep the same parameter order as the matrix above From 828f06aac7286c6ac6bdc544a7391197386de87e Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Wed, 5 Nov 2025 09:55:41 +0100 Subject: [PATCH 094/245] Run Java 8 distribution zulu --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 24b847399..e7ef8dbd4 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -50,7 +50,7 @@ jobs: - name: Set up JDK ${{ matrix.java }} uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 with: - distribution: 'temurin' + distribution: ${{ runner.os == 'macOS' && matrix.java == '8' && 'zulu' || 'temurin' }} java-version: ${{ matrix.java }} - name: Build with Maven run: mvn -Ddoclint=all --show-version --batch-mode --no-transfer-progress From c55316f0847e1ffdb2d260cef3658344597bcc0b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 5 Nov 2025 07:19:15 -0500 Subject: [PATCH 095/245] Remove incorrect issue attribute --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 901bce30e..6c86450d5 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -43,7 +43,7 @@ Remove Spotbugs dependency and use exclude-filter instead #564. - Remove broken website link #577. + Remove broken website link #577. Bump org.apache.commons:commons-parent from 85 to 91 #573. From 3470b022c380a47fb41f912e50748425add4adff Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 6 Nov 2025 16:49:20 -0500 Subject: [PATCH 096/245] Bump commons-codec:commons-codec from 1.19.0 to 1.20.0 --- pom.xml | 2 +- src/changes/changes.xml | 1 + src/test/java/org/apache/commons/csv/CSVPrinterTest.java | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 8e2ffc1ea..4bb085411 100644 --- a/pom.xml +++ b/pom.xml @@ -109,7 +109,7 @@ false true 2025-07-30T14:51:35Z - 1.19.0 + 1.20.0 2.20.0 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 6c86450d5..2dd94d680 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,6 +49,7 @@ Bump org.apache.commons:commons-parent from 85 to 91 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. + Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index ed88d8379..1ff791010 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -807,7 +807,7 @@ void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException } } final String csv = sw.toString(); - assertEquals("1,r1,\"long text 1\",\"YmluYXJ5IGRhdGEgMQ==\r\n\"" + RECORD_SEPARATOR + "2,r2,\"" + longText2 + "\",\"YmluYXJ5IGRhdGEgMg==\r\n\"" + + assertEquals("1,r1,\"long text 1\",\"YmluYXJ5IGRhdGEgMQ==\"" + RECORD_SEPARATOR + "2,r2,\"" + longText2 + "\",\"YmluYXJ5IGRhdGEgMg==\"" + RECORD_SEPARATOR, csv); // Round trip the data try (StringReader reader = new StringReader(csv); @@ -817,12 +817,12 @@ void testJdbcPrinter() throws IOException, ClassNotFoundException, SQLException assertEquals("1", record.get(0)); assertEquals("r1", record.get(1)); assertEquals("long text 1", record.get(2)); - assertEquals("YmluYXJ5IGRhdGEgMQ==\r\n", record.get(3)); + assertEquals("YmluYXJ5IGRhdGEgMQ==", 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)); + assertEquals("YmluYXJ5IGRhdGEgMg==", record.get(3)); } } From 4dd6ffc752fc108e3a97be3564503bdce2ea6ff8 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 7 Nov 2025 15:16:08 -0500 Subject: [PATCH 097/245] Typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index beb9a235a..eb15f2518 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ Making Changes + Respect the original code style: + Only use spaces for indentation; you can check for unnecessary whitespace with `git diff` before committing. + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first. -+ Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best-practice. ++ Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible but is a best practice. Unit tests are typically in the `src/test/java` directory. + Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. + Write a pull request description that is detailed enough to understand what the pull request does, how, and why. From 19da2e782c723fa4040220c468f9629b42efdf7a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 7 Nov 2025 21:58:36 -0500 Subject: [PATCH 098/245] Javadoc --- .../java/org/apache/commons/csv/ExtendedBufferedReader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java index 75748d812..3af9f625a 100644 --- a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java +++ b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java @@ -111,13 +111,13 @@ long getBytesRead() { *

    * The Unicode characters are divided into two main ranges: *

      - *
    • U+0000 to U+FFFF (Basic Multilingual Plane, BMP): + *
    • U+0000 to U+FFFF (Basic Multilingual Plane, BMP): *
        *
      • Represented using a single 16-bit {@code char}.
      • *
      • Includes UTF-8 encodings of 1-byte, 2-byte, and some 3-byte characters.
      • *
      *
    • - *
    • U+10000 to U+10FFFF (Supplementary Characters): + *
    • U+10000 to U+10FFFF (Supplementary Characters): *
        *
      • Represented as a pair of {@code char}s:
      • *
      • The first {@code char} is from the high-surrogates range (\uD800-\uDBFF).
      • From e5b9661afed435386d4898d2804398f8946f7713 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 8 Nov 2025 11:11:40 -0500 Subject: [PATCH 099/245] No need to override project/issueManagement/system --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4bb085411..81cf4086b 100644 --- a/pom.xml +++ b/pom.xml @@ -75,7 +75,6 @@ https://gitbox.apache.org/repos/asf?p=commons-csv.git - jira https://issues.apache.org/jira/browse/CSV From b848f8598070c4f926be67d16bce5de2dec52134 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 12 Nov 2025 15:50:32 -0500 Subject: [PATCH 100/245] Bump org.apache.commons:commons-parent from 91 to 92 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 81cf4086b..132de05b3 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 91 + 92 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2dd94d680..461c58053 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,7 +46,7 @@ Remove broken website link #577. - Bump org.apache.commons:commons-parent from 85 to 91 #573. + Bump org.apache.commons:commons-parent from 85 to 92 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. From e2a0341cda9b64243e3e632d62909ef22c10dd6e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 12 Nov 2025 15:53:00 -0500 Subject: [PATCH 101/245] Fix HTML syntax error --- src/site/xdoc/index.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index 1e397d463..af49476f9 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -106,7 +106,7 @@ For previous releases, see the

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

        From 2674e68f6530d7d0da9fe5bd0d6b389369cfb2e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:00:48 +0000 Subject: [PATCH 102/245] Bump github/codeql-action from 4.31.2 to 4.31.3 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.2 to 4.31.3. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/0499de31b99561a6d14a36a5f662c2a54f91beee...014f16e7ab1402f30e7c3329d33797e7948572db) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: 4.31.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f8db33bf4..7da09b5ca 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/autobuild@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 2fd2b83d4..ee7d74b8f 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@0499de31b99561a6d14a36a5f662c2a54f91beee # 3.29.5 + uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 with: sarif_file: results.sarif From 0fe9cffea65f665c172fb999ab835171645ffed0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:00:52 +0000 Subject: [PATCH 103/245] Bump actions/dependency-review-action from 4.8.1 to 4.8.2 Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.1 to 4.8.2. - [Release notes](https://github.com/actions/dependency-review-action/releases) - [Commits](https://github.com/actions/dependency-review-action/compare/40c09b7dc99638e5ddb0bfd91c1673effc064d8a...3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261) --- updated-dependencies: - dependency-name: actions/dependency-review-action dependency-version: 4.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index a657a4ae2..11834ed9d 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@40c09b7dc99638e5ddb0bfd91c1673effc064d8a # v4.8.1 + uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 From 4fbc0018d1367ac02572c077e06d227a2d4e1520 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 12:01:06 +0000 Subject: [PATCH 104/245] Bump commons-io:commons-io from 2.20.0 to 2.21.0 Bumps [commons-io:commons-io](https://github.com/apache/commons-io) from 2.20.0 to 2.21.0. - [Changelog](https://github.com/apache/commons-io/blob/master/RELEASE-NOTES.txt) - [Commits](https://github.com/apache/commons-io/compare/rel/commons-io-2.20.0...rel/commons-io-2.21.0) --- updated-dependencies: - dependency-name: commons-io:commons-io dependency-version: 2.21.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 132de05b3..e5f047439 100644 --- a/pom.xml +++ b/pom.xml @@ -109,7 +109,7 @@ true 2025-07-30T14:51:35Z 1.20.0 - 2.20.0 + 2.21.0 org.apache.commons.codec.binary;version="${commons.codec.version}", From 7bc6c6c645f5a6e601a1659c249d3bb9df2dcaf1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 14 Nov 2025 08:10:07 -0500 Subject: [PATCH 105/245] Bump commons-io:commons-io from 2.20.0 to 2.21.0 #594 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 461c58053..e880efde4 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,6 +50,7 @@ [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. + Bump commons-io:commons-io from 2.20.0 to 2.21.0 #594. From 8c47967996c3b5600f5312c98f0c0c224cf145a8 Mon Sep 17 00:00:00 2001 From: Sebb Date: Sat, 15 Nov 2025 17:45:46 +0000 Subject: [PATCH 106/245] Dependabot => quarterly --- .github/dependabot.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 00079caf1..90ec55f74 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,10 +18,8 @@ updates: - package-ecosystem: "maven" directory: "/" schedule: - interval: "weekly" - day: "friday" + interval: "quarterly" - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" - day: "friday" + interval: "quarterly" From acc52c7b0ac5ec27ebd360647235ade5f0a924b1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 16 Nov 2025 09:06:52 -0500 Subject: [PATCH 107/245] Bump commons-lang3 from 3.19.0 to 3.20.0 --- pom.xml | 4 ++-- src/changes/changes.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index e5f047439..3d0a8086a 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ org.apache.commons commons-lang3 - 3.19.0 + 3.20.0 test @@ -409,7 +409,7 @@ org.apache.commons commons-lang3 - 3.19.0 + 3.20.0 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e880efde4..c8363484c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ Bump org.apache.commons:commons-parent from 85 to 92 #573. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. - Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. + Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. Bump commons-io:commons-io from 2.20.0 to 2.21.0 #594. From f5bc0e96de8f5f51eeebaa8339b488e25ce8bdc4 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 14:14:57 +0000 Subject: [PATCH 108/245] Use HTTPS to download XML Schema --- src/site/xdoc/download_csv.xml | 2 +- src/site/xdoc/issue-tracking.xml | 2 +- src/site/xdoc/mail-lists.xml | 2 +- src/site/xdoc/security.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/site/xdoc/download_csv.xml b/src/site/xdoc/download_csv.xml index 151c3f69e..f2442cf72 100644 --- a/src/site/xdoc/download_csv.xml +++ b/src/site/xdoc/download_csv.xml @@ -58,7 +58,7 @@ limitations under the License. --> + xsi:schemaLocation="https://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Download Apache Commons CSV Apache Commons Team diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml index 3aa64b404..2bb654011 100644 --- a/src/site/xdoc/issue-tracking.xml +++ b/src/site/xdoc/issue-tracking.xml @@ -43,7 +43,7 @@ limitations under the License. --> + xsi:schemaLocation="https://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons CSV Issue tracking Apache Commons Team diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml index 345cef899..3770e7cae 100644 --- a/src/site/xdoc/mail-lists.xml +++ b/src/site/xdoc/mail-lists.xml @@ -41,7 +41,7 @@ limitations under the License. --> + xsi:schemaLocation="https://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons CSV Mailing Lists Apache Commons Team diff --git a/src/site/xdoc/security.xml b/src/site/xdoc/security.xml index ab0056049..516b64b07 100644 --- a/src/site/xdoc/security.xml +++ b/src/site/xdoc/security.xml @@ -19,7 +19,7 @@ --> + xsi:schemaLocation="https://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons Security Reports Apache Commons Team From ec51621b9425a6b58840b720157a80c470621cf6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 14:40:16 +0000 Subject: [PATCH 109/245] Bump CodeQL 4.31.4 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7da09b5ca..7220552c3 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/autobuild@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index ee7d74b8f..4bbecd83d 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # 3.29.5 + uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 with: sarif_file: results.sarif From dc84d365c1f7f35a1d73f31aa06915f2b0438dbe Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 21 Nov 2025 19:42:28 +0000 Subject: [PATCH 110/245] Bump actions/checkout from v5.0.0 to v6.0.0 --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 11834ed9d..b58ce9301 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - name: 'Dependency Review PR' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 From 7aaccac3b18a0dd30e412d7eab62deba493e2b61 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:59:53 +0000 Subject: [PATCH 111/245] Bump org.apache.commons:commons-parent from 92 to 93 Bumps org.apache.commons:commons-parent from 92 to 93. --- updated-dependencies: - dependency-name: org.apache.commons:commons-parent dependency-version: '93' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3d0a8086a..54c68cf87 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 92 + 93 commons-csv 1.14.2-SNAPSHOT From f32405ebc8ab6150b6a6484e6c51835fd5db307c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 22 Nov 2025 18:14:48 -0500 Subject: [PATCH 112/245] Bump org.apache.commons:commons-parent from 92 to 93 #595 --- src/changes/changes.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c8363484c..c66b27756 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,7 +46,7 @@ Remove broken website link #577. - Bump org.apache.commons:commons-parent from 85 to 92 #573. + Bump org.apache.commons:commons-parent from 85 to 93 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. From 29794112e145e2a1183a086e06272401cea79ad1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 23 Nov 2025 08:58:14 -0500 Subject: [PATCH 113/245] Fix Apache RAT plugin console warnings --- pom.xml | 54 ++++++++++++++++++++--------------------- src/changes/changes.xml | 1 + 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/pom.xml b/pom.xml index 54c68cf87..006dab9af 100644 --- a/pom.xml +++ b/pom.xml @@ -167,35 +167,35 @@ apache-rat-plugin - + - src/test/resources/org/apache/commons/csv/empty.txt - src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv - src/test/resources/org/apache/commons/csv/csv-167/sample1.csv - src/test/resources/org/apache/commons/csv/CSV-198/optd_por_public.csv - src/test/resources/org/apache/commons/csv/CSV-196/emoji.csv - src/test/resources/org/apache/commons/csv/CSV-196/japanese.csv - src/test/resources/org/apache/commons/csv/CSV-213/999751170.patch.csv - src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/bom.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/test_default.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/test_default_comment.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180_trim.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_default.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_ignoreEmpty.txt + src/test/resources/org/apache/commons/csv/empty.txt + src/test/resources/org/apache/commons/csv/CSV-141/csv-141.csv + src/test/resources/org/apache/commons/csv/csv-167/sample1.csv + src/test/resources/org/apache/commons/csv/CSV-198/optd_por_public.csv + src/test/resources/org/apache/commons/csv/CSV-196/emoji.csv + src/test/resources/org/apache/commons/csv/CSV-196/japanese.csv + src/test/resources/org/apache/commons/csv/CSV-213/999751170.patch.csv + src/test/resources/org/apache/commons/csv/CSV-254/csv-254.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/bom.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/test.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/test_default.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/test_default_comment.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/test_rfc4180_trim.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_default.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV85_ignoreEmpty.txt - src/test/resources/org/apache/commons/csv/ferc.gov/contract.txt - src/test/resources/org/apache/commons/csv/ferc.gov/transaction.txt - src/test/resources/**/*.bin - src/test/resources/org/apache/commons/csv/CSV-259/sample.txt - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246.csv - src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246_checkWithNoComment.txt - src/test/resources/org/apache/commons/csv/CSV-290/psql.csv - src/test/resources/org/apache/commons/csv/CSV-290/psql.tsv - + src/test/resources/org/apache/commons/csv/ferc.gov/contract.txt + src/test/resources/org/apache/commons/csv/ferc.gov/transaction.txt + src/test/resources/**/*.bin + src/test/resources/org/apache/commons/csv/CSV-259/sample.txt + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246.csv + src/test/resources/org/apache/commons/csv/CSVFileParser/testCSV246_checkWithNoComment.txt + src/test/resources/org/apache/commons/csv/CSV-290/psql.csv + src/test/resources/org/apache/commons/csv/CSV-290/psql.tsv + diff --git a/src/changes/changes.xml b/src/changes/changes.xml index c66b27756..e7a43a43d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -44,6 +44,7 @@ Remove Spotbugs dependency and use exclude-filter instead #564. Remove broken website link #577. + Fix Apache RAT plugin console warnings. Bump org.apache.commons:commons-parent from 85 to 93 #573, #595. From de33bf4e12866c9d8a6a0e60fbd046619e056462 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 28 Nov 2025 21:27:37 +0000 Subject: [PATCH 114/245] Bump github/codeql-action from 4.31.4 to 4.31.5 --- .github/workflows/codeql-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7220552c3..d2d8d268c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 + uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. From dafcb04983fa317871fd6d295a55095382f5e202 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 28 Nov 2025 21:41:59 +0000 Subject: [PATCH 115/245] Bump github/codeql-action from 4.31.4 to 4.31.5 --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d2d8d268c..c03eba96e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -68,7 +68,7 @@ jobs: # 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@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 + uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 + uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 4bbecd83d..dd9105a28 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@e12f0178983d466f2f6028f5cc7a6d786fd97f4b # 4.31.4 + uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 with: sarif_file: results.sarif From 344cf5850c499a67ed7b545207bee862abd8d445 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 1 Dec 2025 09:56:38 -0500 Subject: [PATCH 116/245] Bump github/codeql-action from 4.31.5 to 4.31.6 --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c03eba96e..a9bd0c697 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/autobuild@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 From 5460935c7425da8a4250e43ba62fc73754451036 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 1 Dec 2025 16:10:46 -0500 Subject: [PATCH 117/245] Bump github/codeql-action from 4.31.5 to 4.31.6 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index dd9105a28..c80f04133 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@fdbfb4d2750291e159f0156def62b853c2798ca2 # 4.31.5 + uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 with: sarif_file: results.sarif From f2b1c546395ed81e44b845f9d3230af79c942ca3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 16:04:40 -0500 Subject: [PATCH 118/245] Bump actions/checkout from 6.0.0 to 6.0.1 --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index b58ce9301..1df866604 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: 'Dependency Review PR' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 From d1847cf08ed8330cd477bbb7db4eb508e4c7994d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 3 Dec 2025 16:08:57 -0500 Subject: [PATCH 119/245] Bump actions/checkout from 5.0.0 to 6.0.1 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a9bd0c697..b47769e0e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e7ef8dbd4..8e884479d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 From dab284cdce202216b7e809866f8ef0bd25715350 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Dec 2025 07:40:06 -0500 Subject: [PATCH 120/245] Bump actions/setup-java from 5.0.0 to 5.1.0 --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 8e884479d..70fd029ec 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -48,7 +48,7 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: ${{ runner.os == 'macOS' && matrix.java == '8' && 'zulu' || 'temurin' }} java-version: ${{ matrix.java }} From 862d2cc456f3c825d2d94414e8d5f3cf275f545c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Dec 2025 15:06:16 -0500 Subject: [PATCH 121/245] Bump github/codeql-action from 4.31.6 to 4.31.7 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b47769e0e..c928d7b1b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index c80f04133..e211b5001 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 + uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: sarif_file: results.sarif From e665c187980932ef23d5163753274da986514161 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Dec 2025 17:02:47 -0500 Subject: [PATCH 122/245] Ask for details on AI usage in creating a pull request --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 4cbe168c3..9ff35c83e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -23,7 +23,7 @@ Before you push a pull request, review this list: - [ ] Read the [contribution guidelines](CONTRIBUTING.md) for this project. - [ ] Read the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) if you use Artificial Intelligence (AI). -- [ ] I used AI to create any part of, or all of, this pull request. +- [ ] I used AI to create any part of, or all of, this pull request. Which AI tool was used to create this pull request, and to what extent did it contribute? - [ ] Run a successful build using the default [Maven](https://maven.apache.org/) goal with `mvn`; that's `mvn` on the command line by itself. - [ ] Write unit tests that match behavioral changes, where the tests fail if the changes to the runtime are not applied. This may not always be possible, but it is a best practice. - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. From 00be0aa6d67f7b1a25fefd9f0cb2c0d73edee6d5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 6 Dec 2025 11:39:40 -0500 Subject: [PATCH 123/245] Add NetBean IDE metadata files to .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index e0f2c4514..2ff17ae4a 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ buildNumber.properties /.vscode/ /.DS_Store + +# NetBeans files +nb-configuration.xml +nbactions.xml From 2d44689ec75eb7291438973a188d26037990c29e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 08:16:52 -0500 Subject: [PATCH 124/245] Bump github/codeql-action from 4.31.7 to 4.31.8 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c928d7b1b..8223940b0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/autobuild@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index e211b5001..b591b41e5 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 + uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 with: sarif_file: results.sarif From 008568620577c8e2def41a1d9241f699a02827b7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 12 Dec 2025 14:27:06 -0500 Subject: [PATCH 125/245] Bump actions/cache from 4.3.0 to 5.0.1 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8223940b0..b1cc918df 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -48,7 +48,7 @@ jobs: uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 70fd029ec..3caee313c 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From e11da238574c756b19cc6913c32dac8a3324e131 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 17 Dec 2025 07:50:40 -0500 Subject: [PATCH 126/245] Bump github/codeql-action from 4.31.8 to 4.31.9 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b1cc918df..d7e8c4a82 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b591b41e5..897b4dcee 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 + uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 with: sarif_file: results.sarif From 8f8d450291d2dea48db66bdde74f30c6124fca2d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Dec 2025 13:51:18 -0500 Subject: [PATCH 127/245] Bump actions/upload-artifact from 5.0.0 to 6.0.0 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 897b4dcee..9fe842ec0 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -57,7 +57,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # 5.0.0 + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 6.0.0 with: name: SARIF file path: results.sarif From 8bd601d1e9e7b7dad54169ebffbf5d0b4137351c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 26 Dec 2025 16:14:54 -0500 Subject: [PATCH 128/245] Javadoc: Fix double the --- .../java/org/apache/commons/csv/ExtendedBufferedReader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java index 3af9f625a..8dcda6517 100644 --- a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java +++ b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java @@ -106,7 +106,7 @@ long getBytesRead() { } /** - * Gets the byte length of the given character based on the the original Unicode + * Gets the byte length of the given character based on the original Unicode * specification, which defined characters as fixed-width 16-bit entities. *

        * The Unicode characters are divided into two main ranges: From f69dac72c401830e20a7120874396abe6c800d2a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 29 Dec 2025 08:51:30 -0500 Subject: [PATCH 129/245] Bump notice file end year from 2025 to 2026 --- NOTICE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE.txt b/NOTICE.txt index b5c1f1445..06d3824a2 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Apache Commons CSV -Copyright 2005-2025 The Apache Software Foundation +Copyright 2005-2026 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (https://www.apache.org/). From 159b22a6bf5f1e5318058b0a23761626c7dccc11 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 31 Dec 2025 18:15:04 -0500 Subject: [PATCH 130/245] Javadoc: Empty Javadoc line before the 1st tag. --- src/main/java/org/apache/commons/csv/CSVFormat.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index e8cb5e772..7251f83dc 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -614,6 +614,7 @@ public Builder setHeader(final ResultSetMetaData resultSetMetaData) throws SQLEx *

        * This method keeps a copy of the input array. *

        + * * @param header the header, {@code null} if disabled, empty if parsed automatically, user-specified otherwise. * @return This instance. */ @@ -695,6 +696,7 @@ public Builder setHeaderComments(final Object... headerComments) { *

        * This method keeps a copy of the input array. *

        + * * @param headerComments the headerComments which will be printed by the Printer before the CSV data. * @return This instance. */ From 391e1bd8b973d32b2646c1e33709319912aa6b2f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 1 Jan 2026 07:53:16 -0500 Subject: [PATCH 131/245] Fix XML Schema xsi:schemaLocation name (as opposed to URI) --- src/site/xdoc/download_csv.xml | 2 +- src/site/xdoc/issue-tracking.xml | 2 +- src/site/xdoc/mail-lists.xml | 2 +- src/site/xdoc/security.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/site/xdoc/download_csv.xml b/src/site/xdoc/download_csv.xml index f2442cf72..151c3f69e 100644 --- a/src/site/xdoc/download_csv.xml +++ b/src/site/xdoc/download_csv.xml @@ -58,7 +58,7 @@ limitations under the License. --> + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Download Apache Commons CSV Apache Commons Team diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml index 2bb654011..3aa64b404 100644 --- a/src/site/xdoc/issue-tracking.xml +++ b/src/site/xdoc/issue-tracking.xml @@ -43,7 +43,7 @@ limitations under the License. --> + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons CSV Issue tracking Apache Commons Team diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml index 3770e7cae..345cef899 100644 --- a/src/site/xdoc/mail-lists.xml +++ b/src/site/xdoc/mail-lists.xml @@ -41,7 +41,7 @@ limitations under the License. --> + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons CSV Mailing Lists Apache Commons Team diff --git a/src/site/xdoc/security.xml b/src/site/xdoc/security.xml index 516b64b07..ab0056049 100644 --- a/src/site/xdoc/security.xml +++ b/src/site/xdoc/security.xml @@ -19,7 +19,7 @@ --> + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 https://maven.apache.org/xsd/xdoc-2.0.xsd"> Apache Commons Security Reports Apache Commons Team From 60a8d8604c66ec1c6d5dad5ee8e0544bcf7923a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Jan 2026 12:54:02 +0000 Subject: [PATCH 132/245] Bump actions/checkout from 5.0.0 to 6.0.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 6.0.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...8e8c483db84b4bee98b60c0593521ed34d9990e8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 9fe842ec0..b36aa82df 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # 5.0.0 + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1 with: persist-credentials: false From 4ed29ec59564b140994cd476e38e00acdc5c8df9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 2 Jan 2026 17:11:31 -0500 Subject: [PATCH 133/245] Bump org.apache.commons:commons-parent from 93 to 94 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 006dab9af..800d40946 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 93 + 94 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e7a43a43d..782bf414f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,7 +47,7 @@ Fix Apache RAT plugin console warnings. - Bump org.apache.commons:commons-parent from 85 to 93 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 94 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. From 04e83559bc3b81338f6ea595f1e710751fb5bee7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 4 Jan 2026 12:36:41 -0500 Subject: [PATCH 134/245] Javadoc Add an empty line before a Javadoc comment --- src/main/java/org/apache/commons/csv/CSVParser.java | 1 + src/main/java/org/apache/commons/csv/Token.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 538bb395c..bce62ea54 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -269,6 +269,7 @@ public void remove() { throw new UnsupportedOperationException(); } } + /** * Header information based on name and position. */ diff --git a/src/main/java/org/apache/commons/csv/Token.java b/src/main/java/org/apache/commons/csv/Token.java index 17eb4c77c..87af33567 100644 --- a/src/main/java/org/apache/commons/csv/Token.java +++ b/src/main/java/org/apache/commons/csv/Token.java @@ -30,6 +30,7 @@ final class Token { enum Type { + /** Token has no valid content, that is, is in its initialized state. */ INVALID, From b1f30b038f7006441d20af7135b6271ae987ac72 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 12 Jan 2026 10:49:23 -0500 Subject: [PATCH 135/245] Bump github/codeql-action from 4.31.9 to 4.31.10 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index d7e8c4a82..c4c4c6787 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/autobuild@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b36aa82df..d934cfaec 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: sarif_file: results.sarif From fd339f8e8734774e61fb0a84743f498b1136b47c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 12 Jan 2026 11:50:33 -0500 Subject: [PATCH 136/245] Bump org.apache.commons:commons-parent from 94 to 95. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 800d40946..c840dec77 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 94 + 95 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 782bf414f..f2b1b85aa 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,7 +47,7 @@ Fix Apache RAT plugin console warnings. - Bump org.apache.commons:commons-parent from 85 to 94 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 95 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. From 5cbd15ca038a913aed2659d240ffc54e73898ac7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 22 Jan 2026 15:39:23 +0000 Subject: [PATCH 137/245] Bump actions/setup-java from 5.1.0 to 5.2.0 --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3caee313c..279445ed2 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -48,7 +48,7 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: ${{ runner.os == 'macOS' && matrix.java == '8' && 'zulu' || 'temurin' }} java-version: ${{ matrix.java }} From 4ba6d187f622b90de89a3afc570a0a024e46e43f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 22 Jan 2026 18:27:32 -0500 Subject: [PATCH 138/245] Bump org.apache.commons:commons-parent from 95 to 96. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index c840dec77..20319d733 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 95 + 96 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f2b1b85aa..4114ff9dc 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,7 +47,7 @@ Fix Apache RAT plugin console warnings. - Bump org.apache.commons:commons-parent from 85 to 95 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 96 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. From 65ac63a4d1c6711b1ffb3df3020bfa870b11ecf6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 23 Jan 2026 07:44:03 -0500 Subject: [PATCH 139/245] Bump actions/checkout from 6.0.1 to 6.0.2 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c4c4c6787..cc69f5334 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 1df866604..a04da5090 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review PR' uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 279445ed2..6195a2aa8 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -38,7 +38,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 From de2e026c7b65506d485576639bbddede1beaf05f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 26 Jan 2026 09:37:02 -0500 Subject: [PATCH 140/245] Bump github/codeql-action from 4.31.10 to 4.31.11 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cc69f5334..17321f5dd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/autobuild@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index d934cfaec..e003bb1da 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/upload-sarif@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 with: sarif_file: results.sarif From 6536a5fb02b3dfe7250e3a5ba8a86aea2054049b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 28 Jan 2026 15:45:16 -0500 Subject: [PATCH 141/245] Bump github/codeql-action from 4.31.11 to 4.32.0 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 17321f5dd..658b44aef 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/autobuild@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index e003bb1da..a450deb1a 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: sarif_file: results.sarif From 4cd9c96f3efe490216b1984bf852c9083717a491 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 29 Jan 2026 17:34:24 -0500 Subject: [PATCH 142/245] Bump commons-codec:commons-codec from 1.20.0 to 1.21.0. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 20319d733..0ade7e0d4 100644 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,7 @@ false true 2025-07-30T14:51:35Z - 1.20.0 + 1.21.0 2.21.0 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 4114ff9dc..2e24024c8 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,7 +50,7 @@ Bump org.apache.commons:commons-parent from 85 to 96 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. - Bump commons-codec:commons-codec from 1.19.0 to 1.20.0. + Bump commons-codec:commons-codec from 1.19.0 to 1.21.0. Bump commons-io:commons-io from 2.20.0 to 2.21.0 #594. From 1e419bdc1fc5632e52a97526bc1ef1d04eca10b0 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Feb 2026 12:34:55 +0000 Subject: [PATCH 143/245] Bump github/codeql-action from 4.32.0 to 4.32.2 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 658b44aef..3fb81ad79 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -68,7 +68,7 @@ jobs: # 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@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -82,4 +82,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index a450deb1a..b26fc7d83 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 with: sarif_file: results.sarif From 75f9236bdf95183297447b0bdf9ce0dddd6675e5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Feb 2026 09:26:16 -0500 Subject: [PATCH 144/245] Bump commons-codec:commons-codec from 1.20.0 to 1.21.0. --- .github/workflows/codeql-analysis.yml | 1 + .github/workflows/maven.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3fb81ad79..858b59d14 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -37,6 +37,7 @@ jobs: security-events: write strategy: + max-parallel: 20 fail-fast: false matrix: language: [ 'java' ] diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 6195a2aa8..a3e53ad3a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -26,6 +26,7 @@ jobs: runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.experimental }} strategy: + max-parallel: 20 fail-fast: false matrix: os: [ubuntu-latest, macos-latest] From 6f01377cace4806d6e1b3f0835a33c1180b79adf Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 9 Feb 2026 13:11:36 +0000 Subject: [PATCH 145/245] Bump actions/cache from 5.0.2 to 5.0.3 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 858b59d14..9ccfb0327 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 #v5.0.3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a3e53ad3a..518219a1d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 #v5.0.3 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 69782dc9038ba63b29dfc71e72b867b75efb5252 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 20 Feb 2026 07:42:01 -0500 Subject: [PATCH 146/245] Bump github/codeql-action from 4.32.2 to 4.32.3 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9ccfb0327..b1f4f562d 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/autobuild@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b26fc7d83..cb3e06bc6 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: sarif_file: results.sarif From 8dd9f4e9d19262d90e01e6136e9e5ab6d8d331af Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 23 Feb 2026 10:58:37 -0500 Subject: [PATCH 147/245] Bump github/codeql-action from 4.32.0 to 4.32.4 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b1f4f562d..6c4aa3f57 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/autobuild@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index cb3e06bc6..f01ca3a11 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: sarif_file: results.sarif From 9d258736b749270d74f6f0460b8c1006c1124e67 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 26 Feb 2026 07:24:08 -0500 Subject: [PATCH 148/245] Add JiraCsv227Test See https://issues.apache.org/jira/browse/CSV-227 --- .../commons/csv/issues/JiraCsv227Test.java | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/test/java/org/apache/commons/csv/issues/JiraCsv227Test.java diff --git a/src/test/java/org/apache/commons/csv/issues/JiraCsv227Test.java b/src/test/java/org/apache/commons/csv/issues/JiraCsv227Test.java new file mode 100644 index 000000000..2b9e335a8 --- /dev/null +++ b/src/test/java/org/apache/commons/csv/issues/JiraCsv227Test.java @@ -0,0 +1,49 @@ +/* + * 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 org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.QuoteMode; +import org.junit.jupiter.api.Test; + +/** + * Tests https://issues.apache.org/jira/browse/CSV-227 + */ +class JiraCsv227Test { + + @Test + public void test() throws IOException { + final StringBuilder out = new StringBuilder(); + try (CSVPrinter printer = new CSVPrinter(out, CSVFormat.DEFAULT.withQuoteMode(QuoteMode.MINIMAL))) { + printer.printRecord("ㅁㅎㄷㄹ", "ㅁㅎㄷㄹ", "", "test2"); + printer.printRecord("한글3", "hello3", "3한글3", "test3"); + printer.printRecord("", "hello4", "", "test4"); + } + // ㅁㅎㄷㄹ,ㅁㅎㄷㄹ,,test2 + // 한글3,hello3,3한글3,test3 + // "",hello4,,test4 + assertEquals("ㅁㅎㄷㄹ,ㅁㅎㄷㄹ,,test2\r\n한글3,hello3,3한글3,test3\r\n\"\",hello4,,test4\r\n", out.toString()); + } +} From c5d2bc1decefdad0a01de3c06dee53c21107a2eb Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 26 Feb 2026 07:34:00 -0500 Subject: [PATCH 149/245] Remove meaningless comments. --- src/site/xdoc/index.xml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index af49476f9..f24175e8c 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -24,12 +24,10 @@ limitations under the License. -

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

        Read the documentation starting with the Javadoc Overview.

        -

        An overview of the functionality is provided in the @@ -48,7 +46,6 @@ The git repository can be browsed.

        -
        -

        The commons mailing lists act as the main support forum. @@ -101,8 +96,6 @@ For previous releases, see the

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

        - -
        From 533bcca147ffae99cbf967e50a1dcf97f27b0488 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 26 Feb 2026 07:42:42 -0500 Subject: [PATCH 150/245] Document Android compatibility Like PR 597 with better text and a table with links --- src/site/xdoc/index.xml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml index f24175e8c..ac5b8cfa9 100644 --- a/src/site/xdoc/index.xml +++ b/src/site/xdoc/index.xml @@ -66,12 +66,32 @@ For previous releases, see the Dependency Information

    -

    The latest code can be checked out from our git repository at https://gitbox.apache.org/repos/asf/commons-csv.git. You can build the component using Apache Maven using mvn clean package.

    +
    +

    + Apache Commons CSV requires Java 8 or above. +

    + + + + + + + + + + + + + + + +
    Commons CSVJavaAndroid
    1.10.0+8Android 7.0 (API level 24)
    +

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

    From 4edb2cf3021a925a732ebd99a8dd33f1a15536bb Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 26 Feb 2026 07:49:29 -0500 Subject: [PATCH 151/245] Add an "Android Compatibility" section to the web site. --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2e24024c8..0a702eaec 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,6 +46,7 @@ Remove broken website link #577. Fix Apache RAT plugin console warnings. + Add an "Android Compatibility" section to the web site. Bump org.apache.commons:commons-parent from 85 to 96 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. From 4f3ff11dad5ab573dcab371bb4cc7e4b45b84772 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 27 Feb 2026 20:48:34 -0500 Subject: [PATCH 152/245] Bump org.apache.commons:commons-parent from 96 to 97. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0ade7e0d4..07f030ae3 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 96 + 97 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 0a702eaec..9e4bce664 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,7 @@ Add an "Android Compatibility" section to the web site. - Bump org.apache.commons:commons-parent from 85 to 96 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 97 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.21.0. From 15602b65a9aea4f2df8156198a7915b51f480f9a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 2 Mar 2026 08:34:01 -0500 Subject: [PATCH 153/245] Bump github/codeql-action from 4.32.4 to 4.32.5 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6c4aa3f57..e2ee451b4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/autobuild@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index f01ca3a11..569f386ee 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: sarif_file: results.sarif From dce781b48086d705eb3690ed5b566d06466a5ae4 Mon Sep 17 00:00:00 2001 From: Makarand Milind Hinge Date: Mon, 2 Mar 2026 22:03:35 +0530 Subject: [PATCH 154/245] docs: clarify behavior of deprecated withFirstRecordAsHeader() --- src/main/java/org/apache/commons/csv/CSVFormat.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 7251f83dc..62d2cd785 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2788,6 +2788,9 @@ public CSVFormat withEscape(final Character escape) { * .get(); * * + *

    Note: Any previously set headers are reset to empty. + * The resulting format will have {@code skipHeaderRecord = true}.

    + * * @return A new CSVFormat that is equal to this but using the first record as header. * @see Builder#setSkipHeaderRecord(boolean) * @see Builder#setHeader(String...) From 7ef443c93d6fd34432f4d04d19a34a815a1ae97d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 2 Mar 2026 13:41:10 -0500 Subject: [PATCH 155/245] Javadoc --- src/main/java/org/apache/commons/csv/CSVFormat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 62d2cd785..fff1f055b 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2788,7 +2788,7 @@ public CSVFormat withEscape(final Character escape) { * .get(); * * - *

    Note: Any previously set headers are reset to empty. + *

    Any previously set headers are reset to empty. * The resulting format will have {@code skipHeaderRecord = true}.

    * * @return A new CSVFormat that is equal to this but using the first record as header. From a529f36b64fc1016db5eedce73bd396781980773 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 2 Mar 2026 13:44:29 -0500 Subject: [PATCH 156/245] [Javadoc] Clarify behavior of deprecated CSVFormat#withFirstRecordAsHeader() #2413. --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 9e4bce664..cadb261cf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -45,6 +45,7 @@ Remove Spotbugs dependency and use exclude-filter instead #564. Remove broken website link #577. Fix Apache RAT plugin console warnings. + [Javadoc] Clarify behavior of deprecated CSVFormat#withFirstRecordAsHeader() #2413. Add an "Android Compatibility" section to the web site. From 3ae9bc442ec3220620fc11c31efab5e160412bc3 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 2 Mar 2026 13:48:00 -0500 Subject: [PATCH 157/245] Use new Apache Commons CSV Oak leaf logo. --- src/media/commons-logo-component-100.xcf | Bin 0 -> 25347 bytes src/media/commons-logo-component.xcf | Bin 0 -> 150900 bytes src/media/logo-large.xcf | Bin 143556 -> 0 bytes src/media/logo.png | Bin 10083 -> 9881 bytes src/media/logo.xcf | Bin 22088 -> 0 bytes src/site/resources/images/logo.png | Bin 10083 -> 9881 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/media/commons-logo-component-100.xcf create mode 100644 src/media/commons-logo-component.xcf delete mode 100644 src/media/logo-large.xcf delete mode 100644 src/media/logo.xcf diff --git a/src/media/commons-logo-component-100.xcf b/src/media/commons-logo-component-100.xcf new file mode 100644 index 0000000000000000000000000000000000000000..77d92f27797075858c5b4ac2ae554bb01f9ac763 GIT binary patch literal 25347 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

    IF&1inKEbkX10uLPXxqr;x<@Z}-q6zP7}t)+zrm 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%0DT>P4EBLLaZ78HkT1s& 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 literal 0 HcmV?d00001 diff --git a/src/media/logo-large.xcf b/src/media/logo-large.xcf deleted file mode 100644 index 7bb07af3eb06c4b961e2b27ee4cbdf9e0ba50828..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143556 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 diff --git a/src/media/logo.png b/src/media/logo.png index 582fba9806c9b77d605e1145ed2d246e18e91d78..93bb6c0148a810ef06a616afa5871e286f4961e6 100644 GIT binary patch delta 9845 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 diff --git a/src/media/logo.xcf b/src/media/logo.xcf deleted file mode 100644 index ac6376f71f1406c121ce0c160dfda147103f2019..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22088 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 diff --git a/src/site/resources/images/logo.png b/src/site/resources/images/logo.png index 582fba9806c9b77d605e1145ed2d246e18e91d78..93bb6c0148a810ef06a616afa5871e286f4961e6 100644 GIT binary patch delta 9845 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 From f40411f6b463b05b595098bb97fda9144a731e37 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 6 Mar 2026 07:35:54 -0500 Subject: [PATCH 158/245] Bump github/codeql-action from 4.32.5 to 4.32.6 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e2ee451b4..4c52d9d27 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/autobuild@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 569f386ee..d41ee17be 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: sarif_file: results.sarif From 66a838202d64a9b05be4e74b846619688b26cb10 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 9 Mar 2026 08:43:40 -0400 Subject: [PATCH 159/245] Bump actions/upload-artifact from 6.0.0 to 7.0.0 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index d41ee17be..c170b0e14 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -57,7 +57,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: SARIF file path: results.sarif From f6e75453ed102741dcc7df6e8fce13ef91bc7900 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 19 Mar 2026 23:46:36 +0000 Subject: [PATCH 160/245] Add a reference to safe deserlialization --- src/site/xdoc/security.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/site/xdoc/security.xml b/src/site/xdoc/security.xml index ab0056049..47edf5d11 100644 --- a/src/site/xdoc/security.xml +++ b/src/site/xdoc/security.xml @@ -47,5 +47,10 @@

    None.

    +
    +

    + For information about safe deserialization, please see Safe Deserialization. +

    +
    \ No newline at end of file From b639f788aa3650a556630918502a463ac3f20241 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 20 Mar 2026 17:32:10 -0700 Subject: [PATCH 161/245] Bump github/codeql-action from 4.32.6 to 4.34.0 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4c52d9d27..e072e3dd7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/init@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/autobuild@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/analyze@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index c170b0e14..b7c1f9fb3 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 with: sarif_file: results.sarif From 1df69a88832fe75d8816aa9112ce5c2373209ecb Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 22 Mar 2026 22:29:26 -0700 Subject: [PATCH 162/245] Javadoc --- src/main/java/org/apache/commons/csv/CSVFormat.java | 2 +- src/main/java/org/apache/commons/csv/DuplicateHeaderMode.java | 2 +- src/main/java/org/apache/commons/csv/QuoteMode.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index fff1f055b..09e76e3a6 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -900,7 +900,7 @@ public Builder setTrim(final boolean trim) { } /** - * Predefines formats. + * Enumerates predefines formats. * * @since 1.2 */ diff --git a/src/main/java/org/apache/commons/csv/DuplicateHeaderMode.java b/src/main/java/org/apache/commons/csv/DuplicateHeaderMode.java index 01989d664..8087f16ee 100644 --- a/src/main/java/org/apache/commons/csv/DuplicateHeaderMode.java +++ b/src/main/java/org/apache/commons/csv/DuplicateHeaderMode.java @@ -20,7 +20,7 @@ package org.apache.commons.csv; /** - * Determines how duplicate header fields should be handled + * Enumerates how duplicate header fields should be handled * if {@link CSVFormat.Builder#setHeader(Class)} is not null. * * @since 1.10.0 diff --git a/src/main/java/org/apache/commons/csv/QuoteMode.java b/src/main/java/org/apache/commons/csv/QuoteMode.java index 79bb1b34e..ae64ab486 100644 --- a/src/main/java/org/apache/commons/csv/QuoteMode.java +++ b/src/main/java/org/apache/commons/csv/QuoteMode.java @@ -19,7 +19,7 @@ package org.apache.commons.csv; /** - * Defines quoting behavior. + * Enumerates quoting behavior. * * @see CSVFormat.Builder#setQuoteMode(QuoteMode) */ From 4f51fe73c48604b945ac3e40ffa3f65e4343d8e2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 27 Mar 2026 14:48:55 -0400 Subject: [PATCH 163/245] Bump github/codeql-action from 4.34.0 to 4.34.1 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e072e3dd7..1dd2d623c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/autobuild@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index b7c1f9fb3..3156ec8b5 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c6f931105cb2c34c8f901cc885ba1e2e259cf745 # v4.34.0 + uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: sarif_file: results.sarif From 09af4ba49b06fd3af5cc810f0dc178f085f35cfc Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 30 Mar 2026 07:16:03 -0400 Subject: [PATCH 164/245] Bump Bump actions/cache from 5.0.3 to 5.0.4 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1dd2d623c..c51994f92 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 #v5.0.3 + - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 518219a1d..e4cfb933b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 #v5.0.3 + - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From e44608974671b49f464c3b3a01606593f618a4c7 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 31 Mar 2026 20:41:06 -0400 Subject: [PATCH 165/245] Bump actions/dependency-review-action from 4.8.2 to 4.9.0 --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index a04da5090..f0d8ca94e 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2 + uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 From f85eb5bac48e5d5206227ddeb4427ddba4b2ba8f Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 31 Mar 2026 21:44:18 -0400 Subject: [PATCH 166/245] Bump github/codeql-action from 4.34.1 to 4.35.1 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c51994f92..7d3074419 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/autobuild@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 3156ec8b5..85a584736 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: sarif_file: results.sarif From 89c05999855f6884b4e297399b6b29f600a49e4b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 1 Apr 2026 06:20:29 -0400 Subject: [PATCH 167/245] Bump actions/checkout from 6.0.1 to 6.0.2 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 85a584736..a0e5b9faf 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 with: persist-credentials: false From 87349e514b2a5496405f53fc4cd973b29c01fc56 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 3 Apr 2026 06:52:55 -0400 Subject: [PATCH 168/245] Run builds only on push to master and pull requests --- .github/workflows/maven.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index e4cfb933b..ebe4bc3b9 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -15,7 +15,11 @@ name: Java CI -on: [push, pull_request] +on: + push: + branches: + - 'master' + pull_request: {} permissions: contents: read From 2efa47f7bde77001c1910243c4b3b8f08ca3c9d9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 5 Apr 2026 09:31:39 -0400 Subject: [PATCH 169/245] Use static imports only for JUnit Rename internal test method --- .../commons/csv/CSVDuplicateHeaderTest.java | 17 +-- .../org/apache/commons/csv/CSVFormatTest.java | 100 +++++++++--------- 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java b/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java index cc47b999a..2f518a120 100644 --- a/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java +++ b/src/test/java/org/apache/commons/csv/CSVDuplicateHeaderTest.java @@ -19,13 +19,16 @@ package org.apache.commons.csv; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -285,11 +288,11 @@ void testCSVFormat(final DuplicateHeaderMode duplicateHeaderMode, .setHeader(headers); if (valid) { final CSVFormat format = builder.get(); - Assertions.assertEquals(duplicateHeaderMode, format.getDuplicateHeaderMode(), "DuplicateHeaderMode"); - Assertions.assertEquals(allowMissingColumnNames, format.getAllowMissingColumnNames(), "AllowMissingColumnNames"); - Assertions.assertArrayEquals(headers, format.getHeader(), "Header"); + assertEquals(duplicateHeaderMode, format.getDuplicateHeaderMode(), "DuplicateHeaderMode"); + assertEquals(allowMissingColumnNames, format.getAllowMissingColumnNames(), "AllowMissingColumnNames"); + assertArrayEquals(headers, format.getHeader(), "Header"); } else { - Assertions.assertThrows(IllegalArgumentException.class, builder::get); + assertThrows(IllegalArgumentException.class, builder::get); } } @@ -327,10 +330,10 @@ void testCSVParser(final DuplicateHeaderMode duplicateHeaderMode, try (CSVParser parser = CSVParser.parse(input, format)) { // Parser ignores null headers final List expected = Arrays.stream(headers).filter(s -> s != null).collect(Collectors.toList()); - Assertions.assertEquals(expected, parser.getHeaderNames(), "HeaderNames"); + assertEquals(expected, parser.getHeaderNames(), "HeaderNames"); } } else { - Assertions.assertThrows(IllegalArgumentException.class, () -> CSVParser.parse(input, format)); + assertThrows(IllegalArgumentException.class, () -> CSVParser.parse(input, format)); } } } diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index d1d19f755..4d428b465 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -26,6 +26,7 @@ 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.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; @@ -48,7 +49,6 @@ import java.util.Objects; import org.apache.commons.csv.CSVFormat.Builder; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** @@ -64,16 +64,16 @@ 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 void assertNotEqualsFlip(final Object right, final Object left) { + assertNotEquals(right, left); + 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) { + private void assertNotEqualsHash(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 + ")"); } @@ -198,8 +198,8 @@ void testDuplicateHeaderElementsTrueContainsEmpty3() { void testEquals() { final CSVFormat right = CSVFormat.DEFAULT; final CSVFormat left = copy(right); - Assertions.assertNotEquals(null, right); - Assertions.assertNotEquals("A String Instance", right); + assertNotEquals(null, right); + assertNotEquals("A String Instance", right); assertEquals(right, right); assertEquals(right, left); assertEquals(left, right); @@ -212,7 +212,7 @@ void testEqualsCommentStart() { final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').setCommentMarker('#').setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setCommentMarker('!').get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -221,7 +221,7 @@ void testEqualsCommentStart_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withCommentMarker('#').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withCommentMarker('!'); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -229,7 +229,7 @@ void testEqualsDelimiter() { final CSVFormat right = CSVFormat.newFormat('!'); final CSVFormat left = CSVFormat.newFormat('?'); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -237,7 +237,7 @@ 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); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -246,7 +246,7 @@ void testEqualsEscape_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withCommentMarker('#').withEscape('+').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withEscape('!'); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -262,49 +262,49 @@ void testEqualsHash() throws Exception { 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); + assertNotEqualsHash(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); + assertNotEqualsHash(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); + assertNotEqualsHash(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); + assertNotEqualsHash(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); + assertNotEqualsHash(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); + assertNotEqualsHash(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); + assertNotEqualsHash(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); + assertNotEqualsHash(name, type, a, b); break; } default: @@ -327,7 +327,7 @@ void testEqualsHeader() { .setIgnoreEmptyLines(true).setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setHeader("Three", "Two", "One").get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -337,7 +337,7 @@ void testEqualsHeader_Deprecated() { .withIgnoreEmptyLines().withIgnoreSurroundingSpaces().withQuote('"').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withHeader("Three", "Two", "One"); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -346,7 +346,7 @@ void testEqualsIgnoreEmptyLines() { .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setIgnoreEmptyLines(false).get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -356,7 +356,7 @@ void testEqualsIgnoreEmptyLines_Deprecated() { .withQuote('"').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withIgnoreEmptyLines(false); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -365,7 +365,7 @@ void testEqualsIgnoreSurroundingSpaces() { .setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setIgnoreSurroundingSpaces(false).get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -375,7 +375,7 @@ void testEqualsIgnoreSurroundingSpaces_Deprecated() { .withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withIgnoreSurroundingSpaces(false); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -383,7 +383,7 @@ void testEqualsLeftNoQuoteRightQuote() { final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get(); final CSVFormat right = left.builder().setQuote('#').get(); - assertNotEquals(left, right); + assertNotEqualsFlip(left, right); } @SuppressWarnings("deprecation") @@ -392,7 +392,7 @@ void testEqualsLeftNoQuoteRightQuote_Deprecated() { final CSVFormat left = CSVFormat.newFormat(',').withQuote(null); final CSVFormat right = left.withQuote('#'); - assertNotEquals(left, right); + assertNotEqualsFlip(left, right); } @Test @@ -418,7 +418,7 @@ void testEqualsNullString() { .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).setNullString("null").get(); final CSVFormat left = right.builder().setNullString("---").get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -428,7 +428,7 @@ void testEqualsNullString_Deprecated() { .withIgnoreSurroundingSpaces().withQuote('"').withQuoteMode(QuoteMode.ALL).withNullString("null"); final CSVFormat left = right.withNullString("---"); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -495,7 +495,7 @@ void testEqualsOne() { assertFalse(csvFormatTwo.isCommentMarkerSet()); assertNotSame(csvFormatTwo, csvFormatOne); - Assertions.assertNotEquals(csvFormatTwo, csvFormatOne); + assertNotEquals(csvFormatTwo, csvFormatOne); assertEquals('\\', (char) csvFormatOne.getEscapeCharacter()); assertNull(csvFormatOne.getQuoteMode()); @@ -554,10 +554,10 @@ void testEqualsOne() { assertNotSame(csvFormatOne, csvFormatTwo); assertNotSame(csvFormatTwo, csvFormatOne); - Assertions.assertNotEquals(csvFormatOne, csvFormatTwo); - Assertions.assertNotEquals(csvFormatTwo, csvFormatOne); + assertNotEquals(csvFormatOne, csvFormatTwo); + assertNotEquals(csvFormatTwo, csvFormatOne); - Assertions.assertNotEquals(csvFormatTwo, csvFormatOne); + assertNotEquals(csvFormatTwo, csvFormatOne); } @@ -566,7 +566,7 @@ void testEqualsQuoteChar() { final CSVFormat right = CSVFormat.newFormat('\'').builder().setQuote('"').get(); final CSVFormat left = right.builder().setQuote('!').get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -575,7 +575,7 @@ void testEqualsQuoteChar_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"'); final CSVFormat left = right.withQuote('!'); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -583,7 +583,7 @@ 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); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -592,7 +592,7 @@ void testEqualsQuotePolicy_Deprecated() { final CSVFormat right = CSVFormat.newFormat('\'').withQuote('"').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withQuoteMode(QuoteMode.MINIMAL); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -601,7 +601,7 @@ void testEqualsRecordSeparator() { .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).get(); final CSVFormat left = right.builder().setRecordSeparator(LF).get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -611,7 +611,7 @@ void testEqualsRecordSeparator_Deprecated() { .withIgnoreSurroundingSpaces().withQuote('"').withQuoteMode(QuoteMode.ALL); final CSVFormat left = right.withRecordSeparator(LF); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } void testEqualsSkipHeaderRecord() { @@ -619,7 +619,7 @@ void testEqualsSkipHeaderRecord() { .setIgnoreSurroundingSpaces(true).setQuote('"').setQuoteMode(QuoteMode.ALL).setNullString("null").setSkipHeaderRecord(true).get(); final CSVFormat left = right.builder().setSkipHeaderRecord(false).get(); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @SuppressWarnings("deprecation") @@ -629,7 +629,7 @@ void testEqualsSkipHeaderRecord_Deprecated() { .withIgnoreSurroundingSpaces().withQuote('"').withQuoteMode(QuoteMode.ALL).withNullString("null").withSkipHeaderRecord(); final CSVFormat left = right.withSkipHeaderRecord(false); - assertNotEquals(right, left); + assertNotEqualsFlip(right, left); } @Test @@ -691,7 +691,7 @@ void testEqualsWithNull() { assertNull(csvFormat.getQuoteCharacter()); assertTrue(csvFormat.isNullStringSet()); - Assertions.assertNotEquals(null, csvFormat); + assertNotEquals(null, csvFormat); } @@ -801,7 +801,7 @@ void testHashCodeAndWithIgnoreHeaderCase() { assertTrue(csvFormatTwo.getIgnoreHeaderCase()); // now different assertFalse(csvFormatTwo.getTrailingDelimiter()); - Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal + assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal assertFalse(csvFormatTwo.getAllowMissingColumnNames()); assertFalse(csvFormatTwo.getTrim()); @@ -1156,7 +1156,7 @@ void testToStringAndWithCommentMarkerTakingCharacter() { assertNotSame(csvFormat, csvFormatTwo); assertNotSame(csvFormatTwo, csvFormat); - Assertions.assertNotEquals(csvFormatTwo, csvFormat); + assertNotEquals(csvFormatTwo, csvFormat); assertNull(csvFormat.getEscapeCharacter()); assertTrue(csvFormat.isQuoteCharacterSet()); @@ -1215,9 +1215,9 @@ void testToStringAndWithCommentMarkerTakingCharacter() { assertNotSame(csvFormat, csvFormatTwo); assertNotSame(csvFormatTwo, csvFormat); - Assertions.assertNotEquals(csvFormat, csvFormatTwo); + assertNotEquals(csvFormat, csvFormatTwo); - Assertions.assertNotEquals(csvFormatTwo, csvFormat); + assertNotEquals(csvFormatTwo, csvFormat); assertEquals("Delimiter=<,> QuoteChar=<\"> CommentStart= RecordSeparator=<\r\n> EmptyLines:ignored SkipHeaderRecord:false", csvFormatTwo.toString()); @@ -1403,7 +1403,7 @@ void testWithHeaderComments() { assertNotSame(csvFormat, csvFormatTwo); assertNotSame(csvFormatTwo, csvFormat); - Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal + assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal final String string = csvFormatTwo.format(objectArray); @@ -1465,9 +1465,9 @@ void testWithHeaderComments() { assertNotSame(csvFormatTwo, csvFormat); assertNotNull(string); - Assertions.assertNotEquals(csvFormat, csvFormatTwo); // CSV-244 - should not be equal + assertNotEquals(csvFormat, csvFormatTwo); // CSV-244 - should not be equal - Assertions.assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal + assertNotEquals(csvFormatTwo, csvFormat); // CSV-244 - should not be equal assertEquals(",,,,,,,", string); } From 3ac39bbbe690adff4ddbabc59a0d3a76ae658028 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 7 Apr 2026 12:39:35 -0400 Subject: [PATCH 170/245] Bump org.apache.commons:commons-parent from 97 to 98 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 07f030ae3..1c0fd5b29 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 97 + 98 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index cadb261cf..56b8a796e 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,7 @@ Add an "Android Compatibility" section to the web site. - Bump org.apache.commons:commons-parent from 85 to 97 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 98 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.21.0. From 5093022c32c8158b4c40d5280ed959b788b0667c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 14 Apr 2026 07:48:43 -0400 Subject: [PATCH 171/245] Bump actions/cache from 5.0.4 to 5.0.5 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7d3074419..61abbca77 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4 + - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ebe4bc3b9..10c18b607 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 #v5.0.4 + - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From d92359b69e035f1fb3fbbc0cfff9fd6942c19dc6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 14 Apr 2026 07:54:51 -0400 Subject: [PATCH 172/245] Bump actions/upload-artifact from 7.0.0 to 7.0.1 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index a0e5b9faf..4ad7175c8 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -57,7 +57,7 @@ jobs: publish_results: true - name: "Upload artifact" - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: SARIF file path: results.sarif From 636a5036db6c4f2d6347e8e6141800930d24049e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 16 Apr 2026 07:10:20 -0400 Subject: [PATCH 173/245] Bump github/codeql-action from 4.35.1 to 4.35.2 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 61abbca77..b7b7fdf05 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/autobuild@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 4ad7175c8..16e37f605 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 + uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 with: sarif_file: results.sarif From f0f184853b765f377a8c6c9685c5b1bb5fbee351 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 23 Apr 2026 06:47:55 -0400 Subject: [PATCH 174/245] Bump commons-io:commons-io from 2.21.0 to 2.22.0. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 1c0fd5b29..0485c80c3 100644 --- a/pom.xml +++ b/pom.xml @@ -109,7 +109,7 @@ true 2025-07-30T14:51:35Z 1.21.0 - 2.21.0 + 2.22.0 org.apache.commons.codec.binary;version="${commons.codec.version}", diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 56b8a796e..de03faab0 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,7 +53,7 @@ [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.21.0. - Bump commons-io:commons-io from 2.20.0 to 2.21.0 #594. + Bump commons-io:commons-io from 2.20.0 to 2.22.0 #594. From 4571bc0bc4bbc83bfb6f8b7594a9bd36b1ce5a93 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 24 Apr 2026 20:40:41 -0400 Subject: [PATCH 175/245] Bump commons-codec:commons-codec from 1.21.0 to 1.22.0. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 0485c80c3..6d9a4ef20 100644 --- a/pom.xml +++ b/pom.xml @@ -108,7 +108,7 @@ false true 2025-07-30T14:51:35Z - 1.21.0 + 1.22.0 2.22.0 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index de03faab0..f8229eb75 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,7 +52,7 @@ Bump org.apache.commons:commons-parent from 85 to 98 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. - Bump commons-codec:commons-codec from 1.19.0 to 1.21.0. + Bump commons-codec:commons-codec from 1.19.0 to 1.22.0. Bump commons-io:commons-io from 2.20.0 to 2.22.0 #594. From b6ab627e062ed80e65bcebe299f779717fca2e8a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 26 Apr 2026 07:36:22 -0400 Subject: [PATCH 176/245] Bump org.apache.commons:commons-parent from 98 to 99 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6d9a4ef20..7e796568e 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 98 + 99 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f8229eb75..aacd40586 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,7 @@ Add an "Android Compatibility" section to the web site. - Bump org.apache.commons:commons-parent from 85 to 98 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 99 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.22.0. From e1ffa42ebef4907d02929b210852f466aa16d204 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 5 May 2026 11:23:19 -0400 Subject: [PATCH 177/245] Bump github/codeql-action from 4.35.2 to 4.35.3 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index b7b7fdf05..3571ff3f4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/autobuild@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 16e37f605..95dbcd027 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@95e58e9a2cdfd71adc6e0353d5c52f41a045d225 # v4.35.2 + uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 with: sarif_file: results.sarif From 6f93c7edfa0f758f757227b1d30588411fdbf669 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 12 May 2026 18:49:17 +0000 Subject: [PATCH 178/245] Bump github/codeql-action from 4.35.3 to 4.35.4 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3571ff3f4..e597a6dbb 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/autobuild@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 95dbcd027..2eed26f73 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3 + uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 with: sarif_file: results.sarif From 8b041dba39eba4975ddd884ea813b6334d39c8de Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 06:43:45 -0400 Subject: [PATCH 179/245] Bump github/codeql-action from 4.35.4 to 4.35.5 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e597a6dbb..f95d030d8 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/autobuild@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 2eed26f73..79c088cf3 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@68bde559dea0fdcac2102bfdf6230c5f70eb485e # v4.35.4 + uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: sarif_file: results.sarif From 5e2d0590ca74424d5a51defef489e374abfb921a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 07:53:21 -0400 Subject: [PATCH 180/245] [CSV-321] CSVFormat.equals()/hashCode() ignores maxRows --- .../java/org/apache/commons/csv/CSVFormat.java | 15 ++++++++------- .../org/apache/commons/csv/CSVFormatTest.java | 8 ++++++++ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 09e76e3a6..123fa2635 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -1690,11 +1690,11 @@ public boolean equals(final Object obj) { duplicateHeaderMode == other.duplicateHeaderMode && Objects.equals(escapeCharacter, other.escapeCharacter) && Arrays.equals(headerComments, other.headerComments) && Arrays.equals(headers, other.headers) && ignoreEmptyLines == other.ignoreEmptyLines && ignoreHeaderCase == other.ignoreHeaderCase && - ignoreSurroundingSpaces == other.ignoreSurroundingSpaces && lenientEof == other.lenientEof && - Objects.equals(nullString, other.nullString) && Objects.equals(quoteCharacter, other.quoteCharacter) && - quoteMode == other.quoteMode && Objects.equals(quotedNullString, other.quotedNullString) && - Objects.equals(recordSeparator, other.recordSeparator) && skipHeaderRecord == other.skipHeaderRecord && - trailingData == other.trailingData && trailingDelimiter == other.trailingDelimiter && trim == other.trim; + ignoreSurroundingSpaces == other.ignoreSurroundingSpaces && lenientEof == other.lenientEof && maxRows == other.maxRows && + Objects.equals(nullString, other.nullString) && Objects.equals(quoteCharacter, other.quoteCharacter) && quoteMode == other.quoteMode && + Objects.equals(quotedNullString, other.quotedNullString) && Objects.equals(recordSeparator, other.recordSeparator) && + skipHeaderRecord == other.skipHeaderRecord && trailingData == other.trailingData && trailingDelimiter == other.trailingDelimiter && + trim == other.trim; } private void escape(final char c, final Appendable appendable) throws IOException { @@ -2029,9 +2029,10 @@ public int hashCode() { int result = 1; result = prime * result + Arrays.hashCode(headerComments); result = prime * result + Arrays.hashCode(headers); - return prime * result + Objects.hash(allowMissingColumnNames, autoFlush, commentMarker, delimiter, duplicateHeaderMode, escapeCharacter, - ignoreEmptyLines, ignoreHeaderCase, ignoreSurroundingSpaces, lenientEof, nullString, quoteCharacter, quoteMode, quotedNullString, + result = prime * result + Objects.hash(allowMissingColumnNames, autoFlush, commentMarker, delimiter, duplicateHeaderMode, escapeCharacter, + ignoreEmptyLines, ignoreHeaderCase, ignoreSurroundingSpaces, lenientEof, maxRows, nullString, quoteCharacter, quoteMode, quotedNullString, recordSeparator, skipHeaderRecord, trailingData, trailingDelimiter, trim); + return result; } /** diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index 4d428b465..23bc9c8dc 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -395,6 +395,14 @@ void testEqualsLeftNoQuoteRightQuote_Deprecated() { assertNotEqualsFlip(left, right); } + @Test + void testEqualsMaxRows() { + final CSVFormat right = CSVFormat.DEFAULT.builder().setMaxRows(10).get(); + final CSVFormat left = CSVFormat.DEFAULT.builder().setMaxRows(1000).get(); + assertNotEqualsFlip(right, left); + assertNotEquals(right.hashCode(), left.hashCode()); + } + @Test void testEqualsNoQuotes() { final CSVFormat left = CSVFormat.newFormat(',').builder().setQuote(null).get(); From 69248ba0bed03c71454b71ec0c79805f48f5c447 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 07:58:48 -0400 Subject: [PATCH 181/245] Bump org.apache.commons:commons-parent from 99 to 100 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 7e796568e..f0578c820 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 99 + 100 commons-csv 1.14.2-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index aacd40586..34e8f8aa2 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -49,7 +49,7 @@ Add an "Android Compatibility" section to the web site. - Bump org.apache.commons:commons-parent from 85 to 99 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 100 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.22.0. From add38c3e06d1b90ebcb87ad4390a000b09850df1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 08:05:51 -0400 Subject: [PATCH 182/245] [CSV-321] CSVFormat.equals()/hashCode() ignores maxRows --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 34e8f8aa2..2bbb0946d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -46,6 +46,7 @@ Remove broken website link #577. Fix Apache RAT plugin console warnings. [Javadoc] Clarify behavior of deprecated CSVFormat#withFirstRecordAsHeader() #2413. + CSVFormat.equals()/hashCode() ignores maxRows (#600). Add an "Android Compatibility" section to the web site. From 23eb602d25a9cf0c989085e9a618dd2b3bff5b45 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 10:42:03 -0400 Subject: [PATCH 183/245] [CSV-323] ExtendedBufferedReader byte tracking leads to an incorrect CSVRecord.getBytePosition() --- .../commons/csv/ExtendedBufferedReader.java | 76 ++++++++++--------- .../org/apache/commons/csv/CSVParserTest.java | 18 +++++ 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java index 8dcda6517..889b58edc 100644 --- a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java +++ b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java @@ -37,26 +37,30 @@ /** * A special buffered reader which supports sophisticated read access. *

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

    */ final class ExtendedBufferedReader extends UnsynchronizedBufferedReader { /** The last char returned */ private int lastChar = UNDEFINED; + private int lastCharMark = UNDEFINED; /** The count of EOLs (CR/LF/CRLF) seen so far */ private long lineNumber; + private long lineNumberMark; /** The position, which is the number of characters read so far */ private long position; + private long positionMark; /** The number of bytes read so far. */ private long bytesRead; + private long bytesReadMark; /** Encoder for calculating the number of bytes for each character read. */ @@ -70,12 +74,11 @@ final class ExtendedBufferedReader extends UnsynchronizedBufferedReader { } /** - * Constructs a new instance with the specified reader, character set, - * and byte tracking option. Initializes an encoder if byte tracking is enabled - * and a character set is provided. + * Constructs a new instance with the specified reader, character set, and byte tracking option. Initializes an encoder if byte tracking is enabled and a + * character set is provided. * - * @param reader the reader supports a look-ahead option. - * @param charset the character set for encoding, or {@code null} if not applicable. + * @param reader the reader supports a look-ahead option. + * @param charset the character set for encoding, or {@code null} if not applicable. * @param trackBytes {@code true} to enable byte tracking; {@code false} to disable it. */ ExtendedBufferedReader(final Reader reader, final Charset charset, final boolean trackBytes) { @@ -86,8 +89,7 @@ final class ExtendedBufferedReader extends UnsynchronizedBufferedReader { /** * Closes the stream. * - * @throws IOException - * If an I/O error occurs + * @throws IOException If an I/O error occurs */ @Override public void close() throws IOException { @@ -105,26 +107,33 @@ long getBytesRead() { return this.bytesRead; } + private long getEncodedCharLength(final char[] buf, final int offset, final int length) throws CharacterCodingException { + int len = 0; + for (int i = offset; i < length; i++) { + len += getEncodedCharLength(buf[i]); + } + return len; + } + /** - * Gets the byte length of the given character based on the original Unicode - * specification, which defined characters as fixed-width 16-bit entities. + * Gets the byte length of the given character based on the original Unicode specification, which defined characters as fixed-width 16-bit entities. *

    * The Unicode characters are divided into two main ranges: *

      - *
    • U+0000 to U+FFFF (Basic Multilingual Plane, BMP): - *
        - *
      • Represented using a single 16-bit {@code char}.
      • - *
      • Includes UTF-8 encodings of 1-byte, 2-byte, and some 3-byte characters.
      • - *
      - *
    • - *
    • U+10000 to U+10FFFF (Supplementary Characters): - *
        - *
      • Represented as a pair of {@code char}s:
      • - *
      • The first {@code char} is from the high-surrogates range (\uD800-\uDBFF).
      • - *
      • The second {@code char} is from the low-surrogates range (\uDC00-\uDFFF).
      • - *
      • Includes UTF-8 encodings of some 3-byte characters and all 4-byte characters.
      • - *
      - *
    • + *
    • U+0000 to U+FFFF (Basic Multilingual Plane, BMP): + *
        + *
      • Represented using a single 16-bit {@code char}.
      • + *
      • Includes UTF-8 encodings of 1-byte, 2-byte, and some 3-byte characters.
      • + *
      + *
    • + *
    • U+10000 to U+10FFFF (Supplementary Characters): + *
        + *
      • Represented as a pair of {@code char}s:
      • + *
      • The first {@code char} is from the high-surrogates range (\uD800-\uDBFF).
      • + *
      • The second {@code char} is from the low-surrogates range (\uDC00-\uDFFF).
      • + *
      • Includes UTF-8 encodings of some 3-byte characters and all 4-byte characters.
      • + *
      + *
    • *
    * * @param current the current character to process. @@ -148,10 +157,9 @@ private int getEncodedCharLength(final int current) throws CharacterCodingExcept } /** - * Returns the last character that was read as an integer (0 to 65535). This will be the last character returned by - * any of the read methods. This will not include a character read using the {@link #peek()} method. If no - * character has been read then this will return {@link Constants#UNDEFINED}. If the end of the stream was reached - * on the last read then this will return {@link IOUtils#EOF}. + * Returns the last character that was read as an integer (0 to 65535). This will be the last character returned by any of the read methods. This will not + * include a character read using the {@link #peek()} method. If no character has been read then this will return {@link Constants#UNDEFINED}. If the end of + * the stream was reached on the last read then this will return {@link IOUtils#EOF}. * * @return the last character that was read */ @@ -193,8 +201,7 @@ public void mark(final int readAheadLimit) throws IOException { @Override public int read() throws IOException { final int current = super.read(); - if (current == CR || current == LF && lastChar != CR || - current == EOF && lastChar != CR && lastChar != LF && lastChar != EOF) { + if (current == CR || current == LF && lastChar != CR || current == EOF && lastChar != CR && lastChar != LF && lastChar != EOF) { lineNumber++; } if (encoder != null) { @@ -226,13 +233,15 @@ public int read(final char[] buf, final int offset, final int length) throws IOE } else if (len == EOF) { lastChar = EOF; } + if (encoder != null) { + this.bytesRead += getEncodedCharLength(buf, offset, len); + } position += len; return len; } /** - * Gets the next line, dropping the line terminator(s). This method should only be called when processing a - * comment, otherwise, information can be lost. + * Gets the next line, dropping the line terminator(s). This method should only be called when processing a comment, otherwise, information can be lost. *

    * Increments {@link #lineNumber} and updates {@link #position}. *

    @@ -272,5 +281,4 @@ public void reset() throws IOException { bytesRead = bytesReadMark; super.reset(); } - } diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index d9dd4e545..e18eee026 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -648,6 +648,24 @@ void testForEach() throws Exception { } } + @Test + void testGetBytePositionMultiCharacterDelimiter() throws IOException { + final String code = "aa[|]bb\ncc[|]dd\n"; + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); + try (CSVParser parser = CSVParser.builder() + .setReader(new StringReader(code)) + .setFormat(format) + .setCharset(StandardCharsets.UTF_8) + .setTrackBytes(true) + .get()) { + final Iterator it = parser.iterator(); + final CSVRecord first = it.next(); + final CSVRecord second = it.next(); + assertEquals(0, first.getBytePosition()); + assertEquals(8, second.getBytePosition()); + } + } + @Test void testGetHeaderComment_HeaderComment1() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) { From 7cf896b0f3da94d77ba7c4d9e76309ef0ef1273b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 11:49:48 -0400 Subject: [PATCH 184/245] [CSV-323] ExtendedBufferedReader byte tracking leads to an incorrect CSVRecord.getBytePosition() --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2bbb0946d..be2d55598 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -47,6 +47,7 @@ Fix Apache RAT plugin console warnings. [Javadoc] Clarify behavior of deprecated CSVFormat#withFirstRecordAsHeader() #2413. CSVFormat.equals()/hashCode() ignores maxRows (#600). + ExtendedBufferedReader byte tracking leads to an incorrect CSVRecord.getBytePosition() (#601). Add an "Android Compatibility" section to the web site. From 4a28ba8254ce1af6985e3dcd95c753ef1c7165ea Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 12:05:44 -0400 Subject: [PATCH 185/245] [CSV-322] CSVFormat.Builder.setQuote() does not refresh quotedNullString --- .../org/apache/commons/csv/CSVFormat.java | 2 ++ .../org/apache/commons/csv/CSVFormatTest.java | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 123fa2635..46d9d0931 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -806,6 +806,8 @@ public Builder setQuote(final Character quoteCharacter) { throw new IllegalArgumentException("The quoteCharacter cannot be a line break"); } this.quoteCharacter = quoteCharacter; + final Character quote = quoteCharacter != null ? quoteCharacter : Constants.DOUBLE_QUOTE_CHAR; + this.quotedNullString = quote + nullString + quote; return this; } diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index 23bc9c8dc..ca18754f7 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -1001,6 +1001,30 @@ void testQuoteCharSameAsDelimiterThrowsException_Deprecated() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.withQuote('!').withDelimiter('!')); } + @Test + void testQuotedNullStringTracksQuoteCharacter() throws IOException { + final StringBuilder out = new StringBuilder(); + // @formatter:off + final Builder builder = CSVFormat.DEFAULT.builder(); + final CSVFormat format = builder + .setQuoteMode(QuoteMode.ALL) + .setNullString("NULL") + .get(); + // @formatter:on + format.print(null, out, true); + assertEquals("\"NULL\"", out.toString()); + // set + out.setLength(0); + builder.setQuote('\''); + builder.get().print(null, out, true); + assertEquals("'NULL'", out.toString()); + // reset + out.setLength(0); + builder.setQuote((Character) null); + builder.get().print(null, out, true); + assertEquals("\"NULL\"", out.toString()); + } + @Test void testQuoteModeNoneShouldReturnMeaningfulExceptionMessage() { final Exception exception = assertThrows(IllegalArgumentException.class, () -> From 4c67ed89df41d4a1eb2795c1cdd4fda9ed6edb9a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 14:34:32 -0400 Subject: [PATCH 186/245] [CSV-322] CSVFormat.Builder.setQuote() does not refresh quotedNullString #2447 --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index be2d55598..a86ffcf88 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,6 +48,7 @@ [Javadoc] Clarify behavior of deprecated CSVFormat#withFirstRecordAsHeader() #2413. CSVFormat.equals()/hashCode() ignores maxRows (#600). ExtendedBufferedReader byte tracking leads to an incorrect CSVRecord.getBytePosition() (#601). + [CSV-322] CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447). Add an "Android Compatibility" section to the web site. From f25612fff9fc55e40d2e9a1c1ab37ee69dd0588e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 20 May 2026 16:23:26 -0400 Subject: [PATCH 187/245] Internal parser ctor refactoring . --- .../org/apache/commons/csv/CSVParser.java | 53 +++++++------------ 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index bce62ea54..5351f8726 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -165,10 +165,9 @@ protected Builder() { // empty } - @SuppressWarnings("resource") @Override public CSVParser get() throws IOException { - return new CSVParser(getReader(), format != null ? format : CSVFormat.DEFAULT, characterOffset, recordNumber, getCharset(), trackBytes); + return new CSVParser(this); } /** @@ -524,46 +523,30 @@ public CSVParser(final Reader reader, final CSVFormat format) throws IOException */ @Deprecated public CSVParser(final Reader reader, final CSVFormat format, final long characterOffset, final long recordNumber) throws IOException { - this(reader, format, characterOffset, recordNumber, null, false); + // @formatter:off + this(builder() + .setReader(reader) + .setFormat(Objects.requireNonNull(format, "format")) // requireNonNull for full compatibility + .setCharacterOffset(characterOffset) + .setRecordNumber(recordNumber) + .setCharset((Charset) null).setTrackBytes(false)); + // @formatter:off } /** - * Constructs a new instance using the given {@link CSVFormat}. - * - *

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

    + * Constructs a new instance from a builder. * - * @param reader - * a Reader containing CSV-formatted input. Must not be null. - * @param format - * the CSVFormat used for CSV parsing. Must not be null. - * @param characterOffset - * Lexer offset when the parser does not start parsing at the beginning of the source. - * @param recordNumber - * The next record number to assign. - * @param charset - * The character encoding to be used for the reader when enableByteTracking is true. - * @param trackBytes - * {@code true} to enable byte tracking for the parser; {@code false} to disable it. - * @throws IllegalArgumentException - * If the parameters of the format are inconsistent or if either the reader or format is null. - * @throws IOException - * If there is a problem reading the header or skipping the first record. - * @throws CSVException Thrown on invalid CSV input data. + * @param builder The source builder. + * @throws IOException if an I/O error occurs. */ - @SuppressWarnings("resource") // reader is managed by lexer. - private CSVParser(final Reader reader, final CSVFormat format, final long characterOffset, final long recordNumber, final Charset charset, - final boolean trackBytes) throws IOException { - Objects.requireNonNull(reader, "reader"); - Objects.requireNonNull(format, "format"); - this.format = format.copy(); - this.lexer = new Lexer(format, new ExtendedBufferedReader(reader, charset, trackBytes)); + @SuppressWarnings("resource") // Lexer manages ExtendedBufferedReader. + private CSVParser(final Builder builder) throws IOException { + this.format = (builder.format != null ? builder.format : CSVFormat.DEFAULT).copy(); + this.lexer = new Lexer(format, new ExtendedBufferedReader(builder.getReader(), builder.getCharset(), builder.trackBytes)); this.csvRecordIterator = new CSVRecordIterator(); this.headers = createHeaders(); - this.characterOffset = characterOffset; - this.recordNumber = recordNumber - 1; + this.characterOffset = builder.characterOffset; + this.recordNumber = builder.recordNumber - 1; } private void addRecordValue(final boolean lastRecord) { From c7c54e12ef5b0aa5a3bfef85498081eff9e899a5 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 21 May 2026 17:11:43 -0400 Subject: [PATCH 188/245] Javadoc --- .../java/org/apache/commons/csv/Lexer.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/Lexer.java b/src/main/java/org/apache/commons/csv/Lexer.java index 3d00fe0bf..e83f5465f 100644 --- a/src/main/java/org/apache/commons/csv/Lexer.java +++ b/src/main/java/org/apache/commons/csv/Lexer.java @@ -68,8 +68,8 @@ final class Lexer implements Closeable { /** * Appends the next escaped character to the token's content. * - * @param token the current token - * @throws IOException on stream access error + * @param token the current token. + * @throws IOException on stream access error. * @throws CSVException Thrown on invalid input. */ private void appendNextEscapedCharacterToToken(final Token token) throws IOException { @@ -89,7 +89,7 @@ private void appendNextEscapedCharacterToToken(final Token token) throws IOExcep * Closes resources. * * @throws IOException - * If an I/O error occurs + * If an I/O error occurs. */ @Override public void close() throws IOException { @@ -97,27 +97,27 @@ public void close() throws IOException { } /** - * Gets the number of bytes read + * Gets the number of bytes read. * - * @return the number of bytes read + * @return the number of bytes read. */ long getBytesRead() { return reader.getBytesRead(); } /** - * Returns the current character position + * Gets the current character position. * - * @return the current character position + * @return the current character position. */ long getCharacterPosition() { return reader.getPosition(); } /** - * Returns the current line number + * Gets the current line number. * - * @return the current line number + * @return the current line number. */ long getCurrentLineNumber() { return reader.getLineNumber(); @@ -136,7 +136,7 @@ boolean isCommentStart(final int ch) { } /** - * Determine whether the next characters constitute a delimiter through {@link ExtendedBufferedReader#peek(char[])}. + * Tests whether the next characters constitute a delimiter through {@link ExtendedBufferedReader#peek(char[])}. * * @param ch * the current character. @@ -214,7 +214,7 @@ boolean isQuoteChar(final int ch) { /** * Tests if the current character represents the start of a line: a CR, LF, or is at the start of the file. * - * @param ch the character to check + * @param ch the character to check. * @return true if the character is at the start of a line. */ boolean isStartOfLine(final int ch) { @@ -400,10 +400,10 @@ private Token parseEncapsulatedToken(final Token token) throws IOException { *
  • An unescaped delimiter has been reached (TOKEN)
  • * * - * @param token the current token - * @param ch the current character - * @return the filled token - * @throws IOException on stream access error + * @param token the current token. + * @param ch the current character. + * @return the filled token. + * @throws IOException on stream access error. * @throws CSVException Thrown on invalid input. */ private Token parseSimpleToken(final Token token, final int ch) throws IOException { @@ -442,7 +442,7 @@ private Token parseSimpleToken(final Token token, final int ch) throws IOExcepti /** * Greedily accepts \n, \r and \r\n This checker consumes silently the second control-character... * - * @return true if the given or next character is a line-terminator + * @return true if the given or next character is a line-terminator. */ boolean readEndOfLine(final int ch) throws IOException { // check if we have \r\n... From b29fb40acd3ecc09bb4f43d20f88ad5ee9fa8324 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 21 May 2026 17:35:06 -0400 Subject: [PATCH 189/245] Lexer.isDelimiter() accepts a partial multi-character delimiter at EOF. --- src/main/java/org/apache/commons/csv/Lexer.java | 2 ++ .../java/org/apache/commons/csv/CSVParserTest.java | 14 ++++++++++++++ .../java/org/apache/commons/csv/LexerTest.java | 12 ++++++++++++ 3 files changed, 28 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/Lexer.java b/src/main/java/org/apache/commons/csv/Lexer.java index 3d00fe0bf..e0b96b079 100644 --- a/src/main/java/org/apache/commons/csv/Lexer.java +++ b/src/main/java/org/apache/commons/csv/Lexer.java @@ -23,6 +23,7 @@ import java.io.Closeable; import java.io.IOException; +import java.util.Arrays; import org.apache.commons.io.IOUtils; @@ -272,6 +273,7 @@ Token nextToken(final Token token) throws IOException { token.type = Token.Type.COMMENT; return token; } + Arrays.fill(delimiterBuf, '\0'); // Important: make sure a new char gets consumed in each iteration while (token.type == Token.Type.INVALID) { // ignore whitespaces at beginning of a token diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index e18eee026..d7bc07e99 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -1621,6 +1621,20 @@ void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format) throw } } + /** + * Tests CSV-324. + */ + @Test + void testPartialMultiCharacterDelimiterAtEOF() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); + try (CSVParser parser = format.parse(new StringReader("a[|]b[|"))) { + final CSVRecord record = parser.nextRecord(); + assertEquals("a", record.get(0)); + assertEquals("b[|", record.get(1)); + assertEquals(2, record.size()); + } + } + @Test void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index e54e93365..511876a28 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -409,6 +409,18 @@ void testNextToken6() throws IOException { } } + /** + * Tests CSV-324. + */ + @Test + void testPartialMultiCharacterDelimiterAtEOF() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); + try (Lexer lexer = createLexer("a[|]b[|", format)) { + assertNextToken(TOKEN, "a", lexer); + assertNextToken(EOF, "b[|", lexer); + } + } + @Test void testReadEscapeBackspace() throws IOException { try (Lexer lexer = createLexer("b", CSVFormat.DEFAULT.withEscape('\b'))) { From f11278e603d7641fe46c81b5dc88bd797b725114 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 21 May 2026 17:56:23 -0400 Subject: [PATCH 190/245] [CSV-324] Lexer.isDelimiter() accepts a partial multi-character delimiter at EOF. #603 --- src/changes/changes.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index a86ffcf88..f72472eeb 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,7 +48,8 @@ [Javadoc] Clarify behavior of deprecated CSVFormat#withFirstRecordAsHeader() #2413. CSVFormat.equals()/hashCode() ignores maxRows (#600). ExtendedBufferedReader byte tracking leads to an incorrect CSVRecord.getBytePosition() (#601). - [CSV-322] CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447). + CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447). + Lexer.isDelimiter() accepts a partial multi-character delimiter at EOF (#603). Add an "Android Compatibility" section to the web site. From 64ea660f8131d3257c2c312c8396fc5b9044a628 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 21 May 2026 20:45:12 -0400 Subject: [PATCH 191/245] Sort members --- .../org/apache/commons/csv/CSVParser.java | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 5351f8726..97c65a9b3 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -473,6 +473,22 @@ public static CSVParser parse(final URL url, final Charset charset, final CSVFor private final Token reusableToken = new Token(); + /** + * Constructs a new instance from a builder. + * + * @param builder The source builder. + * @throws IOException if an I/O error occurs. + */ + @SuppressWarnings("resource") // Lexer manages ExtendedBufferedReader. + private CSVParser(final Builder builder) throws IOException { + this.format = (builder.format != null ? builder.format : CSVFormat.DEFAULT).copy(); + this.lexer = new Lexer(format, new ExtendedBufferedReader(builder.getReader(), builder.getCharset(), builder.trackBytes)); + this.csvRecordIterator = new CSVRecordIterator(); + this.headers = createHeaders(); + this.characterOffset = builder.characterOffset; + this.recordNumber = builder.recordNumber - 1; + } + /** * Constructs a new instance using the given {@link CSVFormat}. * @@ -533,22 +549,6 @@ public CSVParser(final Reader reader, final CSVFormat format, final long charact // @formatter:off } - /** - * Constructs a new instance from a builder. - * - * @param builder The source builder. - * @throws IOException if an I/O error occurs. - */ - @SuppressWarnings("resource") // Lexer manages ExtendedBufferedReader. - private CSVParser(final Builder builder) throws IOException { - this.format = (builder.format != null ? builder.format : CSVFormat.DEFAULT).copy(); - this.lexer = new Lexer(format, new ExtendedBufferedReader(builder.getReader(), builder.getCharset(), builder.trackBytes)); - this.csvRecordIterator = new CSVRecordIterator(); - this.headers = createHeaders(); - this.characterOffset = builder.characterOffset; - this.recordNumber = builder.recordNumber - 1; - } - private void addRecordValue(final boolean lastRecord) { final String input = format.trim(reusableToken.content.toString()); if (lastRecord && input.isEmpty() && format.getTrailingDelimiter()) { From 513aac23983337ddd2dddb266e43a5eff145957e Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 22 May 2026 07:24:53 -0400 Subject: [PATCH 192/245] [CSV-325] CSVParser applies characterOffset to bytePosition, which breaks getBytePosition() for multi-byte prefixes Add CSVParser.Builder.setByteOffset(long) --- .../org/apache/commons/csv/CSVParser.java | 31 +++++++++++++++++-- .../org/apache/commons/csv/CSVParserTest.java | 30 ++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 97c65a9b3..208f5a0da 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -154,6 +154,7 @@ public final class CSVParser implements Iterable, Closeable { public static class Builder extends AbstractStreamBuilder { private CSVFormat format; + private long byteOffset = -1; private long characterOffset; private long recordNumber = 1; private boolean trackBytes; @@ -171,10 +172,27 @@ public CSVParser get() throws IOException { } /** - * Sets the lexer offset when the parser does not start parsing at the beginning of the source. + * Sets the lexer byte offset when the parser does not start parsing at the beginning of the source. + *

    + * By default, the value is {@code -1}, which reuses the character offset for the byte offset. + *

    * - * @param characterOffset the lexer offset. + * @param byteOffset the lexer byte offset. * @return {@code this} instance. + * @see #setCharacterOffset(long) + * @since 1.15.0 + */ + public Builder setByteOffset(final long byteOffset) { + this.byteOffset = byteOffset; + return asThis(); + } + + /** + * Sets the lexer character offset when the parser does not start parsing at the beginning of the source. + * + * @param characterOffset the lexer character offset. + * @return {@code this} instance. + * @see #setByteOffset(long) */ public Builder setCharacterOffset(final long characterOffset) { this.characterOffset = characterOffset; @@ -465,6 +483,12 @@ public static CSVParser parse(final URL url, final Charset charset, final CSVFor */ private long recordNumber; + /** + * Lexer offset when the parser does not start parsing at the beginning of the source. Usually used in combination + * with {@link #recordNumber}. + */ + private final long byteOffset; + /** * Lexer offset when the parser does not start parsing at the beginning of the source. Usually used in combination * with {@link #recordNumber}. @@ -485,6 +509,7 @@ private CSVParser(final Builder builder) throws IOException { this.lexer = new Lexer(format, new ExtendedBufferedReader(builder.getReader(), builder.getCharset(), builder.trackBytes)); this.csvRecordIterator = new CSVRecordIterator(); this.headers = createHeaders(); + this.byteOffset = builder.byteOffset != -1 ? builder.byteOffset : builder.characterOffset; this.characterOffset = builder.characterOffset; this.recordNumber = builder.recordNumber - 1; } @@ -870,7 +895,7 @@ CSVRecord nextRecord() throws IOException { recordList.clear(); StringBuilder sb = null; final long startCharPosition = lexer.getCharacterPosition() + characterOffset; - final long startBytePosition = lexer.getBytesRead() + characterOffset; + final long startBytePosition = lexer.getBytesRead() + byteOffset; do { reusableToken.reset(); lexer.nextToken(reusableToken); diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index d7bc07e99..8b1527c42 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -666,6 +666,36 @@ void testGetBytePositionMultiCharacterDelimiter() throws IOException { } } + @Test + void testGetBytePositionWithCharacterOffsetAndMultiBytePrefix() throws Exception { + final String row0 = "é,x\n"; + final Charset charset = UTF_8; + // row0 char count is 4 + assertEquals(4, row0.length()); + // row0 byte count is 5 + final int record1ByteOffset = row0.getBytes(charset).length; + assertEquals(5, record1ByteOffset); + final String row1 = "b,c\n"; + final String rows = row0 + row1; + final long record1CharOffset = row0.length(); + final long expectedByteOffset = row0.getBytes(charset).length; + try (CSVParser parser = CSVParser.builder() + .setReader(new StringReader(row1)) + .setFormat(CSVFormat.DEFAULT) + .setCharset(charset) + .setTrackBytes(true) + .setByteOffset(record1ByteOffset) + .setCharacterOffset(record1CharOffset) + .setRecordNumber(2) // not relevant but a better use case example. + .get()) { + final CSVRecord record = parser.nextRecord(); + assertNotNull(record); + assertEquals(4, record.getCharacterPosition()); + assertEquals(record1CharOffset, record.getCharacterPosition()); + assertEquals(expectedByteOffset, record.getBytePosition()); + } + } + @Test void testGetHeaderComment_HeaderComment1() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) { From 971b629a7ad78fa053b23a45127d44dc7701e73b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 22 May 2026 07:58:11 -0400 Subject: [PATCH 193/245] [CSV-325] CSVParser applies characterOffset to bytePosition, breaking getBytePosition() for multi-byte prefixes. Add CSVParser.Builder.setByteOffset(long) (#604). --- src/changes/changes.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f72472eeb..e32ba1776 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -50,8 +50,10 @@ ExtendedBufferedReader byte tracking leads to an incorrect CSVRecord.getBytePosition() (#601). CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447). Lexer.isDelimiter() accepts a partial multi-character delimiter at EOF (#603). + CSVParser applies characterOffset to bytePosition (#604). Add an "Android Compatibility" section to the web site. + Add CSVParser.Builder.setByteOffset(long) (#604). Bump org.apache.commons:commons-parent from 85 to 100 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. From df91b6edfcf1d30e4601bb6f6ec128533ec2dbff Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 22 May 2026 07:59:58 -0400 Subject: [PATCH 194/245] The next version will be 1.15.0 --- pom.xml | 6 +++--- src/changes/changes.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index f0578c820..f362f8130 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 100 commons-csv - 1.14.2-SNAPSHOT + 1.15.0-SNAPSHOT Apache Commons CSV https://commons.apache.org/proper/commons-csv/ 2005 @@ -89,12 +89,12 @@ - 1.14.2 + 1.15.0 (Java 8 or above) RC1 1.14.1 - 1.14.3 + 1.15.1 csv org.apache.commons.csv CSV diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e32ba1776..664c922ed 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -40,7 +40,7 @@ Apache Commons CSV Release Notes - + Remove Spotbugs dependency and use exclude-filter instead #564. Remove broken website link #577. From 019456e09af622978bb5349168c5512dc4daac70 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 22 May 2026 08:39:20 -0400 Subject: [PATCH 195/245] Add comment --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index f362f8130..6d814251b 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,7 @@ com.h2database h2 + 2.2.224 test From ae6949807e894b62c57547236b8e805646a2a6b9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 27 May 2026 16:51:47 -0400 Subject: [PATCH 196/245] Bump github/codeql-action from 4.35.5 to 4.36.0 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f95d030d8..a8afcbfb7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index 79c088cf3..fd682a9a1 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 + uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 with: sarif_file: results.sarif From bbf07cbfb4c6f723105f8e82c4c805e15f96e605 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Jun 2026 10:20:17 -0400 Subject: [PATCH 197/245] Bump org.apache.commons:commons-parent from 100 to 101 --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6d814251b..57bca27b2 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 100 + 101 commons-csv 1.15.0-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 664c922ed..633de96bd 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -55,7 +55,7 @@ Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). - Bump org.apache.commons:commons-parent from 85 to 100 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 101 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.22.0. From 9f8c596a0cf3cd864960421f3222e73d586cadb9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Jun 2026 10:21:56 -0400 Subject: [PATCH 198/245] Add GH CI Java 26 Bump GH CI from Java 26-ea to 27-ea --- .github/workflows/maven.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 10c18b607..a5ff694fc 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -34,12 +34,12 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - java: [ 8, 11, 17, 21, 25 ] + java: [ 8, 11, 17, 21, 25, 36 ] experimental: [false] # Keep the same parameter order as the matrix above include: - os: ubuntu-latest - java: 26-ea + java: 27-ea experimental: true steps: From 6183c6ec5f78cd726b72c24c06e1bc0afe84df45 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 4 Jun 2026 10:22:08 -0400 Subject: [PATCH 199/245] Add GH CI Java 26 Bump GH CI from Java 26-ea to 27-ea --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a5ff694fc..f1bfba770 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -34,7 +34,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - java: [ 8, 11, 17, 21, 25, 36 ] + java: [ 8, 11, 17, 21, 25, 26 ] experimental: [false] # Keep the same parameter order as the matrix above include: From ca64eb8439b26404e2c5baa383d42ffa3436733d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Jun 2026 07:27:06 -0400 Subject: [PATCH 200/245] Better inline comments --- .../org/apache/commons/csv/CSVFormat.java | 20 +++++++++---------- .../org/apache/commons/csv/CSVParser.java | 2 +- .../org/apache/commons/csv/CSVPrinter.java | 4 ++-- .../org/apache/commons/csv/CSVRecord.java | 10 ++++------ .../org/apache/commons/csv/Constants.java | 2 +- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 46d9d0931..f6b2c5ae0 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -1479,7 +1479,7 @@ private static boolean isLineBreak(final char c) { * @return true if {@code c} is a line break character (and not null). */ private static boolean isLineBreak(final Character c) { - return c != null && isLineBreak(c.charValue()); // Explicit (un)boxing is intentional + return c != null && isLineBreak(c.charValue()); // Explicit unboxing is intentional } /** Same test as in as {@link String#trim()}. */ @@ -1700,7 +1700,7 @@ public boolean equals(final Object obj) { } private void escape(final char c, final Appendable appendable) throws IOException { - append(escapeCharacter.charValue(), appendable); // Explicit (un)boxing is intentional + append(escapeCharacter.charValue(), appendable); // Explicit unboxing is intentional append(c, appendable); } @@ -1838,7 +1838,7 @@ public DuplicateHeaderMode getDuplicateHeaderMode() { * @return the escape character, may be {@code 0} */ char getEscapeChar() { - return escapeCharacter != null ? escapeCharacter.charValue() : 0; // Explicit (un)boxing is intentional + return escapeCharacter != null ? escapeCharacter.charValue() : 0; // Explicit unboxing is intentional } /** @@ -2161,7 +2161,7 @@ private void print(final InputStream inputStream, final Appendable out, final bo } final boolean quoteCharacterSet = isQuoteCharacterSet(); if (quoteCharacterSet) { - append(getQuoteCharacter().charValue(), out); // Explicit (un)boxing is intentional + append(getQuoteCharacter().charValue(), out); // Explicit unboxing is intentional } // Stream the input to the output without reading or holding the whole value in memory. // AppendableOutputStream cannot "close" an Appendable. @@ -2169,7 +2169,7 @@ private void print(final InputStream inputStream, final Appendable out, final bo IOUtils.copy(inputStream, outputStream); } if (quoteCharacterSet) { - append(getQuoteCharacter().charValue(), out); // Explicit (un)boxing is intentional + append(getQuoteCharacter().charValue(), out); // Explicit unboxing is intentional } } @@ -2418,7 +2418,7 @@ private void printWithQuotes(final Object object, final CharSequence charSeq, fi final int len = charSeq.length(); final char[] delim = getDelimiterCharArray(); final int delimLength = delim.length; - final char quoteChar = getQuoteCharacter().charValue(); // Explicit (un)boxing is intentional + final char quoteChar = getQuoteCharacter().charValue(); // Explicit unboxing is intentional // If escape char not specified, default to the quote char // This avoids having to keep checking whether there is an escape character // at the cost of checking against quote twice @@ -2521,7 +2521,7 @@ private void printWithQuotes(final Reader reader, final Appendable appendable) t printWithEscapes(reader, appendable); return; } - final char quote = getQuoteCharacter().charValue(); // Explicit (un)boxing is intentional + final char quote = getQuoteCharacter().charValue(); // Explicit unboxing is intentional // (1) Append opening quote append(quote, appendable); // (2) Append Reader contents, doubling quotes @@ -2607,13 +2607,13 @@ boolean useRow(final long rowNum) { * @throws IllegalArgumentException Throw when any attribute is invalid or inconsistent with other attributes. */ private void validate() throws IllegalArgumentException { - if (quoteCharacter != null && contains(delimiter, quoteCharacter.charValue())) { // Explicit (un)boxing is intentional + if (quoteCharacter != null && contains(delimiter, quoteCharacter.charValue())) { // Explicit unboxing is intentional throw new IllegalArgumentException("The quoteChar character and the delimiter cannot be the same ('" + quoteCharacter + "')"); } - if (escapeCharacter != null && contains(delimiter, escapeCharacter.charValue())) { // Explicit (un)boxing is intentional + if (escapeCharacter != null && contains(delimiter, escapeCharacter.charValue())) { // Explicit unboxing is intentional throw new IllegalArgumentException("The escape character and the delimiter cannot be the same ('" + escapeCharacter + "')"); } - if (commentMarker != null && contains(delimiter, commentMarker.charValue())) { // Explicit (un)boxing is intentional + if (commentMarker != null && contains(delimiter, commentMarker.charValue())) { // Explicit unboxing is intentional throw new IllegalArgumentException("The comment start character and the delimiter cannot be the same ('" + commentMarker + "')"); } if (quoteCharacter != null && quoteCharacter.equals(commentMarker)) { diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 208f5a0da..c9b2dc44f 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -650,7 +650,7 @@ private Headers createHeaders() throws IOException { } observedMissing |= blankHeader; if (header != null) { - headerMap.put(header, Integer.valueOf(i)); // Explicit (un)boxing is intentional + headerMap.put(header, Integer.valueOf(i)); // Explicit boxing is intentional if (headerNames == null) { headerNames = new ArrayList<>(headerRecord.length); } diff --git a/src/main/java/org/apache/commons/csv/CSVPrinter.java b/src/main/java/org/apache/commons/csv/CSVPrinter.java index 087129ec5..a7048fd62 100644 --- a/src/main/java/org/apache/commons/csv/CSVPrinter.java +++ b/src/main/java/org/apache/commons/csv/CSVPrinter.java @@ -235,7 +235,7 @@ public void printComment(final String comment) throws IOException { if (!newRecord) { println(); } - appendable.append(format.getCommentMarker().charValue()); // Explicit (un)boxing is intentional + appendable.append(format.getCommentMarker().charValue()); // Explicit unboxing is intentional appendable.append(SP); for (int i = 0; i < comment.length(); i++) { final char c = comment.charAt(i); @@ -247,7 +247,7 @@ public void printComment(final String comment) throws IOException { // falls-through: break intentionally excluded. case LF: println(); - appendable.append(format.getCommentMarker().charValue()); // Explicit (un)boxing is intentional + appendable.append(format.getCommentMarker().charValue()); // Explicit unboxing is intentional appendable.append(SP); break; default: diff --git a/src/main/java/org/apache/commons/csv/CSVRecord.java b/src/main/java/org/apache/commons/csv/CSVRecord.java index f619717d0..502bf318a 100644 --- a/src/main/java/org/apache/commons/csv/CSVRecord.java +++ b/src/main/java/org/apache/commons/csv/CSVRecord.java @@ -132,13 +132,11 @@ public String get(final String name) { throw new IllegalArgumentException(String.format("Mapping for %s not found, expected one of %s", name, headerMap.keySet())); } try { - return values[index.intValue()]; // Explicit (un)boxing is intentional + return values[index.intValue()]; // Explicit unboxing is intentional } catch (final ArrayIndexOutOfBoundsException e) { + // Explicit boxing is intentional throw new IllegalArgumentException( - String.format("Index for header '%s' is %d but CSVRecord only has %d values!", name, index, Integer.valueOf(values.length))); // Explicit - // (un)boxing - // is - // intentional + String.format("Index for header '%s' is %d but CSVRecord only has %d values!", name, index, Integer.valueOf(values.length))); } } @@ -267,7 +265,7 @@ public boolean isSet(final int index) { * @return whether a given column is mapped and has a value. */ public boolean isSet(final String name) { - return isMapped(name) && getHeaderMapRaw().get(name).intValue() < values.length; // Explicit (un)boxing is intentional + return isMapped(name) && getHeaderMapRaw().get(name).intValue() < values.length; // Explicit unboxing is intentional } /** diff --git a/src/main/java/org/apache/commons/csv/Constants.java b/src/main/java/org/apache/commons/csv/Constants.java index 0b9476e1c..9dd276ecc 100644 --- a/src/main/java/org/apache/commons/csv/Constants.java +++ b/src/main/java/org/apache/commons/csv/Constants.java @@ -40,7 +40,7 @@ final class Constants { /** RFC 4180 defines line breaks as CRLF. */ static final String CRLF = "\r\n"; - static final Character DOUBLE_QUOTE_CHAR = Character.valueOf('"'); // Explicit (un)boxing is intentional. + static final Character DOUBLE_QUOTE_CHAR = Character.valueOf('"'); // Explicit boxing is intentional. static final String EMPTY = ""; From 8192d9d196a554d67d7d65b0a131001b9d1eb412 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 5 Jun 2026 07:28:04 -0400 Subject: [PATCH 201/245] Bump github/codeql-action from 4.36.0 to 4.36.2 --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/scorecards-analysis.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a8afcbfb7..4e69d1942 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -69,7 +69,7 @@ jobs: # 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@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -83,4 +83,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index fd682a9a1..bf246c140 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -64,6 +64,6 @@ jobs: retention-days: 5 - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: sarif_file: results.sarif From 297ae10f6a2d753862485b7c77fab746a1ae885d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 7 Jun 2026 10:09:01 -0400 Subject: [PATCH 202/245] Bump GH CI actions/checkout from 6.0.2 to 6.0.3 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4e69d1942..57f55cae0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -46,7 +46,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index f0d8ca94e..7bf60ad9e 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: 'Dependency Review PR' uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index f1bfba770..3ee3dec2b 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -43,7 +43,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 From 361056d668fb2c682fb26e848c58fc3f666a607d Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sun, 7 Jun 2026 10:12:54 -0400 Subject: [PATCH 203/245] Bump GH CI actions/dependency-review-action from 4.9.0 to 5.0.0 --- .github/workflows/dependency-review.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 7bf60ad9e..114f3d8a2 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -28,4 +28,4 @@ jobs: - name: 'Checkout Repository' uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: 'Dependency Review PR' - uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 + uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 From 68b4b0910be1b9c0beb52a39b906851f0c41c75c Mon Sep 17 00:00:00 2001 From: OldTruckDriver Date: Tue, 9 Jun 2026 21:15:13 +1000 Subject: [PATCH 204/245] [CSV-326] Escape Reader values with quote and escape --- src/changes/changes.xml | 1 + .../java/org/apache/commons/csv/CSVFormat.java | 7 ++++--- .../org/apache/commons/csv/CSVFormatTest.java | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 633de96bd..a3e03e372 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447). Lexer.isDelimiter() accepts a partial multi-character delimiter at EOF (#603). CSVParser applies characterOffset to bytePosition (#604). + CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back. Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index f6b2c5ae0..852a3956c 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2522,14 +2522,15 @@ private void printWithQuotes(final Reader reader, final Appendable appendable) t return; } final char quote = getQuoteCharacter().charValue(); // Explicit unboxing is intentional + final char escape = isEscapeCharacterSet() ? getEscapeChar() : quote; // (1) Append opening quote append(quote, appendable); - // (2) Append Reader contents, doubling quotes + // (2) Append Reader contents, doubling quotes and escape characters int c; while (EOF != (c = reader.read())) { append((char) c, appendable); - if (c == quote) { - append(quote, appendable); + if (c == quote || c == escape) { + append((char) c, appendable); } } // (3) Append closing quote diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index ca18754f7..c3fdeeb77 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -966,6 +966,23 @@ void testPrintWithQuotes() throws IOException { assertEquals("\"\"\"a,b,c\r\nx,y,z\"", out.toString()); } + /** + * Tests CSV-326. + */ + @Test + void testPrintWithQuotesEscapeBeforeQuote() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder() + .setEscape('\\') + .setQuote('"') + .get(); + final String value = "\\\""; + final Appendable out = new StringBuilder(); + format.print(new StringReader(value), out, true); + try (CSVParser parser = CSVParser.parse(out.toString(), format)) { + assertEquals(value, parser.getRecords().get(0).get(0)); + } + } + @Test void testQuoteCharSameAsCommentStartThrowsException() { assertThrows(IllegalArgumentException.class, () -> CSVFormat.DEFAULT.builder().setQuote('!').setCommentMarker('!').get()); From 966b38519e45c1fd85c76fbbdc47cb5bb1905238 Mon Sep 17 00:00:00 2001 From: OldTruckDriver Date: Tue, 9 Jun 2026 21:25:28 +1000 Subject: [PATCH 205/245] [CSV-327] Limit parser maxRows by produced records --- src/changes/changes.xml | 1 + .../java/org/apache/commons/csv/CSVParser.java | 6 +++++- .../org/apache/commons/csv/CSVParserTest.java | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 633de96bd..44f1a6be0 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -51,6 +51,7 @@ CSVFormat.Builder.setQuote() does not refresh quotedNullString (#2447). Lexer.isDelimiter() accepts a partial multi-character delimiter at EOF (#603). CSVParser applies characterOffset to bytePosition (#604). + CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index c9b2dc44f..83b60170e 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -237,6 +237,7 @@ public Builder setTrackBytes(final boolean trackBytes) { final class CSVRecordIterator implements Iterator { private CSVRecord current; + private long recordCount; /** * Gets the next record or null at the end of stream or max rows read. @@ -247,8 +248,11 @@ final class CSVRecordIterator implements Iterator { */ private CSVRecord getNextRecord() { CSVRecord record = null; - if (format.useRow(recordNumber + 1)) { + if (format.useRow(recordCount + 1)) { record = Uncheck.get(CSVParser.this::nextRecord); + if (record != null) { + recordCount++; + } } return record; } diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 8b1527c42..816c1c853 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -965,6 +965,23 @@ void testGetRecordsMaxRows(final long maxRows) throws IOException { } } + /** + * Tests CSV-327. + */ + @Test + void testGetRecordsMaxRowsWithRecordNumberOffset() throws IOException { + try (CSVParser parser = CSVParser.builder() + .setReader(new StringReader("a,b\nc,d\n")) + .setFormat(CSVFormat.DEFAULT.builder().setMaxRows(1).get()) + .setRecordNumber(2) + .get()) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertEquals(2, records.get(0).getRecordNumber()); + assertValuesEquals(new String[] { "a", "b" }, records.get(0)); + } + } + @Test void testGetRecordThreeBytesRead() throws Exception { final String code = "id,date,val5,val4\n" + From 1e3de1274636959d3cf70acbba14ae10128369a5 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Tue, 9 Jun 2026 17:37:44 +0530 Subject: [PATCH 206/245] clear escape delimiter buffer before peek in isEscapeDelimiter --- src/main/java/org/apache/commons/csv/Lexer.java | 1 + .../java/org/apache/commons/csv/CSVParserTest.java | 14 ++++++++++++++ .../java/org/apache/commons/csv/LexerTest.java | 12 ++++++++++++ 3 files changed, 27 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/Lexer.java b/src/main/java/org/apache/commons/csv/Lexer.java index de97868e4..238e64cee 100644 --- a/src/main/java/org/apache/commons/csv/Lexer.java +++ b/src/main/java/org/apache/commons/csv/Lexer.java @@ -191,6 +191,7 @@ boolean isEscape(final int ch) { * @throws IOException If an I/O error occurs. */ boolean isEscapeDelimiter() throws IOException { + Arrays.fill(escapeDelimiterBuf, '\0'); reader.peek(escapeDelimiterBuf); if (escapeDelimiterBuf[0] != delimiter[0]) { return false; diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 8b1527c42..5443c5e84 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -1665,6 +1665,20 @@ void testPartialMultiCharacterDelimiterAtEOF() throws IOException { } } + /** + * A truncated escaped multi-character delimiter at EOF must stay literal data and not be completed from a stale + * escape delimiter look-ahead. + */ + @Test + void testPartialEscapedMultiCharacterDelimiterAtEOF() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').get(); + try (CSVParser parser = format.parse(new StringReader("x![!|!]y![!|"))) { + final CSVRecord record = parser.nextRecord(); + assertEquals("x[|]y![!|", record.get(0)); + assertEquals(1, record.size()); + } + } + @Test void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index 511876a28..da60df07e 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -421,6 +421,18 @@ void testPartialMultiCharacterDelimiterAtEOF() throws IOException { } } + /** + * A truncated escaped multi-character delimiter at EOF must not be accepted by reusing the previous escape delimiter + * look-ahead in {@link Lexer#isEscapeDelimiter()}. + */ + @Test + void testPartialEscapedMultiCharacterDelimiterAtEOF() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").setEscape('!').get(); + try (Lexer lexer = createLexer("x![!|!]y![!|", format)) { + assertNextToken(EOF, "x[|]y![!|", lexer); + } + } + @Test void testReadEscapeBackspace() throws IOException { try (Lexer lexer = createLexer("b", CSVFormat.DEFAULT.withEscape('\b'))) { From 4f9a4037a2c1890154e1f077d66306ec54afbf60 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 11 Jun 2026 09:40:09 -0400 Subject: [PATCH 207/245] Bump org.apache.commons:commons-parent from 101 to 102. --- pom.xml | 2 +- src/changes/changes.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 57bca27b2..8cb13ed7c 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.apache.commons commons-parent - 101 + 102 commons-csv 1.15.0-SNAPSHOT diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 633de96bd..87d68ea2a 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -55,7 +55,7 @@ Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). - Bump org.apache.commons:commons-parent from 85 to 101 #573, #595. + Bump org.apache.commons:commons-parent from 85 to 102 #573, #595. [test] Bump com.opencsv:opencsv from 5.11.2 to 5.12.0 #558. Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.20.0. Bump commons-codec:commons-codec from 1.19.0 to 1.22.0. From 27126657d2117afd40e8972b8a34659abc753a65 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 11 Jun 2026 14:23:37 -0400 Subject: [PATCH 208/245] Update legacy GitHub links in CONTRIBUTING.md --- CONTRIBUTING.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb15f2518..3423e18ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,13 +48,13 @@ Getting Started --------------- + Make sure you have a [JIRA account](https://issues.apache.org/jira/). -+ Make sure you have a [GitHub account](https://github.com/signup/free). This is not essential, but makes providing patches much easier. ++ Make sure you have a [GitHub account](https://github.com/signup). This is not essential, but makes providing patches much easier. + If you're planning to implement a new feature it makes sense to discuss your changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons CSV's scope. + Submit a [Jira Ticket][jira] for your issue, assuming one does not already exist. + Clearly describe the issue including steps to reproduce when it is a bug. + Make sure you fill in the earliest version that you know has the issue. + Find the corresponding [repository on GitHub](https://github.com/apache/?query=commons-), -[fork](https://help.github.com/articles/fork-a-repo/) and check out your forked repository. If you don't have a GitHub account, you can still clone the Commons repository. +[fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) and check out your forked repository. If you don't have a GitHub account, you can still clone the Commons repository. Making Changes -------------- @@ -108,8 +108,8 @@ Additional Resources + [Contributing patches](https://commons.apache.org/patches.html) + [Apache Commons CSV JIRA project page][jira] + [Contributor License Agreement][cla] -+ [General GitHub documentation](https://help.github.com/) -+ [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/) ++ [General GitHub documentation](https://docs.github.com/) ++ [GitHub pull request documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request) + [Apache Commons Twitter Account](https://twitter.com/ApacheCommons) [cla]:https://www.apache.org/licenses/#clas From 6887303cbca84216a3324e103504d9dd91660ea8 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 11 Jun 2026 15:33:31 -0400 Subject: [PATCH 209/245] [CSV-326] Escape Reader values with quote and escape (#606). --- src/changes/changes.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 8ea12d983..2475f2b9b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,6 +53,8 @@ CSVParser applies characterOffset to bytePosition (#604). CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back. CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. + Escape Reader values with quote and escape (#606). +. Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). From 037e2e0cd161c9d4f485aae8e49879d6cf2048ab Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 11 Jun 2026 15:59:34 -0400 Subject: [PATCH 210/245] Fix typo. --- src/changes/changes.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2475f2b9b..cb4a17848 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,8 +53,7 @@ CSVParser applies characterOffset to bytePosition (#604). CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back. CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. - Escape Reader values with quote and escape (#606). -. + Escape Reader values with quote and escape (#606). Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). From 19b29139dfdb58426bf1330567e6d6c750abe81c Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 11 Jun 2026 16:00:26 -0400 Subject: [PATCH 211/245] Clear escape delimiter buffer before peek in isEscapeDelimiter (#608). --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index cb4a17848..0786cc365 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,6 +54,7 @@ CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back. CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. Escape Reader values with quote and escape (#606). + Clear escape delimiter buffer before peek in isEscapeDelimiter (#608). Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). From b5940a642eef0de550733887fc5b78451d4a8eed Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Sat, 13 Jun 2026 12:30:53 +0530 Subject: [PATCH 212/245] escape quote char in printWithEscapes when QuoteMode is NONE --- .../java/org/apache/commons/csv/CSVFormat.java | 8 ++++++-- .../org/apache/commons/csv/CSVPrinterTest.java | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 852a3956c..03211e689 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2324,12 +2324,14 @@ private void printWithEscapes(final CharSequence charSeq, final Appendable appen final char[] delimArray = getDelimiterCharArray(); final int delimLength = delimArray.length; final char escape = getEscapeChar(); + final boolean quoteSet = isQuoteCharacterSet(); + final char quote = quoteSet ? getQuoteCharacter().charValue() : 0; while (pos < end) { char c = charSeq.charAt(pos); final boolean isDelimiterStart = isDelimiter(c, charSeq, pos, delimArray, delimLength); final boolean isCr = c == Constants.CR; final boolean isLf = c == Constants.LF; - if (isCr || isLf || c == escape || isDelimiterStart) { + if (isCr || isLf || c == escape || quoteSet && c == quote || isDelimiterStart) { // write out segment up until this char if (pos > start) { appendable.append(charSeq, start, pos); @@ -2368,6 +2370,8 @@ private void printWithEscapes(final Reader reader, final Appendable appendable) final char[] delimArray = getDelimiterCharArray(); final int delimLength = delimArray.length; final char escape = getEscapeChar(); + final boolean quoteSet = isQuoteCharacterSet(); + final char quote = quoteSet ? getQuoteCharacter().charValue() : 0; final StringBuilder builder = new StringBuilder(IOUtils.DEFAULT_BUFFER_SIZE); int c; final char[] lookAheadBuffer = new char[delimLength - 1]; @@ -2379,7 +2383,7 @@ private void printWithEscapes(final Reader reader, final Appendable appendable) final boolean isDelimiterStart = isDelimiter((char) c, test, pos, delimArray, delimLength); final boolean isCr = c == Constants.CR; final boolean isLf = c == Constants.LF; - if (isCr || isLf || c == escape || isDelimiterStart) { + if (isCr || isLf || c == escape || quoteSet && c == quote || isDelimiterStart) { // write out segment up until this char if (pos > start) { append(builder.substring(start, pos), appendable); diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index 1ff791010..7d1993e01 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -423,6 +423,23 @@ void testDelimeterStringQuoteNone() throws IOException { } } + @Test + void testQuoteCharEscapedWithQuoteModeNone() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setQuote('"').setEscape('?').setQuoteMode(QuoteMode.NONE).get(); + final StringWriter sw = new StringWriter(); + try (CSVPrinter printer = new CSVPrinter(sw, format)) { + printer.printRecord("\"abc", "x\"y"); + } + assertEquals("?\"abc,x?\"y\r\n", sw.toString()); + // The emitted record must read back as the original values. + try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertEquals("\"abc", records.get(0).get(0)); + assertEquals("x\"y", records.get(0).get(1)); + } + } + @Test void testDelimiterEscaped() throws IOException { final StringWriter sw = new StringWriter(); From 27a439ae0aba41221d296bca7bb5e00379bc25a8 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 13 Jun 2026 08:33:49 -0400 Subject: [PATCH 213/245] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../java/org/apache/commons/csv/CSVPrinterTest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index 7d1993e01..79ce987bd 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -429,14 +429,17 @@ void testQuoteCharEscapedWithQuoteModeNone() throws IOException { final StringWriter sw = new StringWriter(); try (CSVPrinter printer = new CSVPrinter(sw, format)) { printer.printRecord("\"abc", "x\"y"); + printer.printRecord(new StringReader("\"abc"), new StringReader("x\"y")); } - assertEquals("?\"abc,x?\"y\r\n", sw.toString()); - // The emitted record must read back as the original values. + assertEquals("?\"abc,x?\"y" + RECORD_SEPARATOR + "?\"abc,x?\"y" + RECORD_SEPARATOR, sw.toString()); + // The emitted records must read back as the original values. try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { final List records = parser.getRecords(); - assertEquals(1, records.size()); - assertEquals("\"abc", records.get(0).get(0)); - assertEquals("x\"y", records.get(0).get(1)); + assertEquals(2, records.size()); + for (final CSVRecord record : records) { + assertEquals("\"abc", record.get(0)); + assertEquals("x\"y", record.get(1)); + } } } From d729b442e4bbdf6c603e3e64955d27352744cc29 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 13 Jun 2026 12:37:26 +0000 Subject: [PATCH 214/245] Sort members --- .../org/apache/commons/csv/CSVParserTest.java | 28 ++++++------- .../apache/commons/csv/CSVPrinterTest.java | 40 +++++++++---------- .../org/apache/commons/csv/LexerTest.java | 24 +++++------ 3 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index cccbef4e6..dca37fc5a 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -1668,20 +1668,6 @@ void testParsingPrintedEmptyFirstColumn(final CSVFormat.Predefined format) throw } } - /** - * Tests CSV-324. - */ - @Test - void testPartialMultiCharacterDelimiterAtEOF() throws IOException { - final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); - try (CSVParser parser = format.parse(new StringReader("a[|]b[|"))) { - final CSVRecord record = parser.nextRecord(); - assertEquals("a", record.get(0)); - assertEquals("b[|", record.get(1)); - assertEquals(2, record.size()); - } - } - /** * A truncated escaped multi-character delimiter at EOF must stay literal data and not be completed from a stale * escape delimiter look-ahead. @@ -1696,6 +1682,20 @@ void testPartialEscapedMultiCharacterDelimiterAtEOF() throws IOException { } } + /** + * Tests CSV-324. + */ + @Test + void testPartialMultiCharacterDelimiterAtEOF() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); + try (CSVParser parser = format.parse(new StringReader("a[|]b[|"))) { + final CSVRecord record = parser.nextRecord(); + assertEquals("a", record.get(0)); + assertEquals("b[|", record.get(1)); + assertEquals(2, record.size()); + } + } + @Test void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index 79ce987bd..b58782210 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -423,26 +423,6 @@ void testDelimeterStringQuoteNone() throws IOException { } } - @Test - void testQuoteCharEscapedWithQuoteModeNone() throws IOException { - final CSVFormat format = CSVFormat.DEFAULT.builder().setQuote('"').setEscape('?').setQuoteMode(QuoteMode.NONE).get(); - final StringWriter sw = new StringWriter(); - try (CSVPrinter printer = new CSVPrinter(sw, format)) { - printer.printRecord("\"abc", "x\"y"); - printer.printRecord(new StringReader("\"abc"), new StringReader("x\"y")); - } - assertEquals("?\"abc,x?\"y" + RECORD_SEPARATOR + "?\"abc,x?\"y" + RECORD_SEPARATOR, sw.toString()); - // The emitted records must read back as the original values. - try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { - final List records = parser.getRecords(); - assertEquals(2, records.size()); - for (final CSVRecord record : records) { - assertEquals("\"abc", record.get(0)); - assertEquals("x\"y", record.get(1)); - } - } - } - @Test void testDelimiterEscaped() throws IOException { final StringWriter sw = new StringWriter(); @@ -1818,6 +1798,26 @@ void testQuoteAll() throws IOException { } } + @Test + void testQuoteCharEscapedWithQuoteModeNone() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setQuote('"').setEscape('?').setQuoteMode(QuoteMode.NONE).get(); + final StringWriter sw = new StringWriter(); + try (CSVPrinter printer = new CSVPrinter(sw, format)) { + printer.printRecord("\"abc", "x\"y"); + printer.printRecord(new StringReader("\"abc"), new StringReader("x\"y")); + } + assertEquals("?\"abc,x?\"y" + RECORD_SEPARATOR + "?\"abc,x?\"y" + RECORD_SEPARATOR, sw.toString()); + // The emitted records must read back as the original values. + try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { + final List records = parser.getRecords(); + assertEquals(2, records.size()); + for (final CSVRecord record : records) { + assertEquals("\"abc", record.get(0)); + assertEquals("x\"y", record.get(1)); + } + } + } + @Test void testQuoteCommaFirstChar() throws IOException { final StringWriter sw = new StringWriter(); diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index da60df07e..244079df6 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -409,18 +409,6 @@ void testNextToken6() throws IOException { } } - /** - * Tests CSV-324. - */ - @Test - void testPartialMultiCharacterDelimiterAtEOF() throws IOException { - final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); - try (Lexer lexer = createLexer("a[|]b[|", format)) { - assertNextToken(TOKEN, "a", lexer); - assertNextToken(EOF, "b[|", lexer); - } - } - /** * A truncated escaped multi-character delimiter at EOF must not be accepted by reusing the previous escape delimiter * look-ahead in {@link Lexer#isEscapeDelimiter()}. @@ -433,6 +421,18 @@ void testPartialEscapedMultiCharacterDelimiterAtEOF() throws IOException { } } + /** + * Tests CSV-324. + */ + @Test + void testPartialMultiCharacterDelimiterAtEOF() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); + try (Lexer lexer = createLexer("a[|]b[|", format)) { + assertNextToken(TOKEN, "a", lexer); + assertNextToken(EOF, "b[|", lexer); + } + } + @Test void testReadEscapeBackspace() throws IOException { try (Lexer lexer = createLexer("b", CSVFormat.DEFAULT.withEscape('\b'))) { From d4d4154454b43c46aff65ed75c721605eafb142b Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 13 Jun 2026 12:43:32 +0000 Subject: [PATCH 215/245] Refactor some magic strings in CSVPrinterTest.testQuoteCharEscapedWithQuoteModeNone() --- .../java/org/apache/commons/csv/CSVPrinterTest.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index b58782210..16901c4e2 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -1802,9 +1802,11 @@ void testQuoteAll() throws IOException { void testQuoteCharEscapedWithQuoteModeNone() throws IOException { final CSVFormat format = CSVFormat.DEFAULT.builder().setQuote('"').setEscape('?').setQuoteMode(QuoteMode.NONE).get(); final StringWriter sw = new StringWriter(); + final String col1 = "\"abc"; + final String col2 = "x\"y"; try (CSVPrinter printer = new CSVPrinter(sw, format)) { - printer.printRecord("\"abc", "x\"y"); - printer.printRecord(new StringReader("\"abc"), new StringReader("x\"y")); + printer.printRecord(col1, col2); + printer.printRecord(new StringReader(col1), new StringReader(col2)); } assertEquals("?\"abc,x?\"y" + RECORD_SEPARATOR + "?\"abc,x?\"y" + RECORD_SEPARATOR, sw.toString()); // The emitted records must read back as the original values. @@ -1812,8 +1814,8 @@ void testQuoteCharEscapedWithQuoteModeNone() throws IOException { final List records = parser.getRecords(); assertEquals(2, records.size()); for (final CSVRecord record : records) { - assertEquals("\"abc", record.get(0)); - assertEquals("x\"y", record.get(1)); + assertEquals(col1, record.get(0)); + assertEquals(col2, record.get(1)); } } } From 411d3a37c923361f2ccca1c26862e6e4d7fd4742 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 13 Jun 2026 12:45:52 +0000 Subject: [PATCH 216/245] Escape quote char in printWithEscapes when QuoteMode is NONE (#609). --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 0786cc365..41b1a038c 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -55,6 +55,7 @@ CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. Escape Reader values with quote and escape (#606). Clear escape delimiter buffer before peek in isEscapeDelimiter (#608). + Escape quote char in printWithEscapes when QuoteMode is NONE (#609). Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). From a99f2609299a72b08a3e43c2968822555528da4e Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Mon, 15 Jun 2026 21:31:34 +0530 Subject: [PATCH 217/245] quote value starting with comment marker in minimal quote mode --- .../java/org/apache/commons/csv/CSVFormat.java | 5 +++-- .../org/apache/commons/csv/CSVPrinterTest.java | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 03211e689..4f60eff93 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2454,10 +2454,11 @@ private void printWithQuotes(final Object object, final CharSequence charSeq, fi } } else { char c = charSeq.charAt(pos); - if (c <= Constants.COMMENT) { + if (c <= Constants.COMMENT || isCommentMarkerSet() && c == commentMarker.charValue()) { // Some other chars at the start of a value caused the parser to fail, so for now // encapsulate if we start in anything less than '#'. We are being conservative - // by including the default comment char too. + // by including the default comment char and any configured comment marker too, + // which the parser would otherwise read back as a comment line. quote = true; } else { while (pos < len) { diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index 16901c4e2..e00accfb0 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -1829,6 +1829,24 @@ void testQuoteCommaFirstChar() throws IOException { } } + @Test + void testQuoteCommentMarkerFirstChar() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setCommentMarker(';').get(); + final StringWriter sw = new StringWriter(); + final String col1 = ";comment-like"; + try (CSVPrinter printer = new CSVPrinter(sw, format)) { + printer.printRecord(col1, "b"); + } + assertEquals("\";comment-like\",b" + RECORD_SEPARATOR, sw.toString()); + // A value starting with the comment marker must read back as data, not a dropped comment line. + try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertEquals(col1, records.get(0).get(0)); + assertEquals("b", records.get(0).get(1)); + } + } + @Test void testQuoteNonNumeric() throws IOException { final StringWriter sw = new StringWriter(); From 3c2291cf5e40c5b9a19f3a6b3165fb27c8de5321 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Tue, 16 Jun 2026 14:35:39 +0530 Subject: [PATCH 218/245] expand comment marker test to contrast printed comment with quoted value --- .../org/apache/commons/csv/CSVPrinterTest.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index e00accfb0..f4f3c85b1 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -1835,15 +1835,24 @@ void testQuoteCommentMarkerFirstChar() throws IOException { final StringWriter sw = new StringWriter(); final String col1 = ";comment-like"; try (CSVPrinter printer = new CSVPrinter(sw, format)) { + // A real comment is written with the marker, unquoted. + printer.printComment("a real comment"); + // A value starting with the marker is quoted, so it does not read back as a comment. printer.printRecord(col1, "b"); + // The marker past the first character does not start a comment, so only the leading-marker value is quoted. + printer.printRecord("a;b", ";c"); } - assertEquals("\";comment-like\",b" + RECORD_SEPARATOR, sw.toString()); - // A value starting with the comment marker must read back as data, not a dropped comment line. + assertEquals("; a real comment" + RECORD_SEPARATOR + + "\";comment-like\",b" + RECORD_SEPARATOR + + "a;b,\";c\"" + RECORD_SEPARATOR, sw.toString()); + // The comment is dropped on read; both data records survive intact. try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { final List records = parser.getRecords(); - assertEquals(1, records.size()); + assertEquals(2, records.size()); assertEquals(col1, records.get(0).get(0)); assertEquals("b", records.get(0).get(1)); + assertEquals("a;b", records.get(1).get(0)); + assertEquals(";c", records.get(1).get(1)); } } From e21d66e410cdafca2e822361de5eb6b2596291f2 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 16 Jun 2026 21:20:03 +0000 Subject: [PATCH 219/245] Quote value starting with comment marker in minimal quote mode (#610). Extract to local variable. --- src/changes/changes.xml | 1 + src/test/java/org/apache/commons/csv/CSVPrinterTest.java | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 41b1a038c..431da6b5f 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -56,6 +56,7 @@ Escape Reader values with quote and escape (#606). Clear escape delimiter buffer before peek in isEscapeDelimiter (#608). Escape quote char in printWithEscapes when QuoteMode is NONE (#609). + Quote value starting with comment marker in minimal quote mode (#610).. Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index f4f3c85b1..e68d4c243 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -1842,11 +1842,12 @@ void testQuoteCommentMarkerFirstChar() throws IOException { // The marker past the first character does not start a comment, so only the leading-marker value is quoted. printer.printRecord("a;b", ";c"); } + final String string = sw.toString(); assertEquals("; a real comment" + RECORD_SEPARATOR + "\";comment-like\",b" + RECORD_SEPARATOR + - "a;b,\";c\"" + RECORD_SEPARATOR, sw.toString()); + "a;b,\";c\"" + RECORD_SEPARATOR, string); // The comment is dropped on read; both data records survive intact. - try (CSVParser parser = CSVParser.parse(sw.toString(), format)) { + try (CSVParser parser = CSVParser.parse(string, format)) { final List records = parser.getRecords(); assertEquals(2, records.size()); assertEquals(col1, records.get(0).get(0)); From 110e830616e44844a0a57256401093a151ae0e66 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Wed, 17 Jun 2026 16:38:10 +0530 Subject: [PATCH 220/245] clear delimiter buffer before each peek in isDelimiter --- src/main/java/org/apache/commons/csv/Lexer.java | 2 +- src/test/java/org/apache/commons/csv/LexerTest.java | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/Lexer.java b/src/main/java/org/apache/commons/csv/Lexer.java index 238e64cee..93a584663 100644 --- a/src/main/java/org/apache/commons/csv/Lexer.java +++ b/src/main/java/org/apache/commons/csv/Lexer.java @@ -153,6 +153,7 @@ boolean isDelimiter(final int ch) throws IOException { isLastTokenDelimiter = true; return true; } + Arrays.fill(delimiterBuf, '\0'); reader.peek(delimiterBuf); for (int i = 0; i < delimiterBuf.length; i++) { if (delimiterBuf[i] != delimiter[i + 1]) { @@ -274,7 +275,6 @@ Token nextToken(final Token token) throws IOException { token.type = Token.Type.COMMENT; return token; } - Arrays.fill(delimiterBuf, '\0'); // Important: make sure a new char gets consumed in each iteration while (token.type == Token.Type.INVALID) { // ignore whitespaces at beginning of a token diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index 244079df6..e5f831fb2 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -433,6 +433,19 @@ void testPartialMultiCharacterDelimiterAtEOF() throws IOException { } } + /** + * A truncated multi-character delimiter at EOF must not be accepted by reusing the look-ahead buffer left dirty by an + * earlier non-matching peek in the same token (CSV-324 only cleared the buffer once per token). + */ + @Test + void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); + // The "[a]" peek leaves ']' in the look-ahead buffer; the trailing "[|" must not match "[|]". + try (Lexer lexer = createLexer("x[a][|", format)) { + assertNextToken(EOF, "x[a][|", lexer); + } + } + @Test void testReadEscapeBackspace() throws IOException { try (Lexer lexer = createLexer("b", CSVFormat.DEFAULT.withEscape('\b'))) { From 61f521350b34c5605bfd68760cdce120a5da4ed7 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Wed, 17 Jun 2026 17:07:51 +0530 Subject: [PATCH 221/245] add public-api parser test for partial delimiter false-match at eof --- .../org/apache/commons/csv/CSVParserTest.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index dca37fc5a..c1ca3d7a4 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -1696,6 +1696,21 @@ void testPartialMultiCharacterDelimiterAtEOF() throws IOException { } } + /** + * A truncated multi-character delimiter at EOF must not be completed from the look-ahead buffer left dirty by an + * earlier non-matching peek in the same token. + */ + @Test + void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); + // The "[a]" peek leaves ']' in the look-ahead buffer; the trailing "[|" must not match "[|]". + try (CSVParser parser = format.parse(new StringReader("x[a][|"))) { + final CSVRecord record = parser.nextRecord(); + assertEquals("x[a][|", record.get(0)); + assertEquals(1, record.size()); + } + } + @Test void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); From ed8dbf25ad73856cfa10cba4f5e9855fdcae0d88 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 17 Jun 2026 12:08:58 +0000 Subject: [PATCH 222/245] Clear escape delimiter buffer before peek in Lexer.isEscapeDelimiter() (#608, #611). Refactor magic strings in tests --- src/changes/changes.xml | 2 +- src/test/java/org/apache/commons/csv/CSVParserTest.java | 5 +++-- src/test/java/org/apache/commons/csv/LexerTest.java | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 431da6b5f..66073c9dd 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -54,7 +54,7 @@ CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back. CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. Escape Reader values with quote and escape (#606). - Clear escape delimiter buffer before peek in isEscapeDelimiter (#608). + Clear escape delimiter buffer before peek in Lexer.isEscapeDelimiter() (#608, #611). Escape quote char in printWithEscapes when QuoteMode is NONE (#609). Quote value starting with comment marker in minimal quote mode (#610).. diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index c1ca3d7a4..5bece571f 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -1704,9 +1704,10 @@ void testPartialMultiCharacterDelimiterAtEOF() throws IOException { void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); // The "[a]" peek leaves ']' in the look-ahead buffer; the trailing "[|" must not match "[|]". - try (CSVParser parser = format.parse(new StringReader("x[a][|"))) { + final String recordString = "x[a][|"; + try (CSVParser parser = format.parse(new StringReader(recordString))) { final CSVRecord record = parser.nextRecord(); - assertEquals("x[a][|", record.get(0)); + assertEquals(recordString, record.get(0)); assertEquals(1, record.size()); } } diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index e5f831fb2..db1ab3a6d 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -441,8 +441,9 @@ void testPartialMultiCharacterDelimiterAtEOF() throws IOException { void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter("[|]").get(); // The "[a]" peek leaves ']' in the look-ahead buffer; the trailing "[|" must not match "[|]". - try (Lexer lexer = createLexer("x[a][|", format)) { - assertNextToken(EOF, "x[a][|", lexer); + final String recordString = "x[a][|"; + try (Lexer lexer = createLexer(recordString, format)) { + assertNextToken(EOF, recordString, lexer); } } From a6ee67ecf0d4b9208ffc640f433d8b40c258e1f3 Mon Sep 17 00:00:00 2001 From: OldTruckDriver Date: Fri, 19 Jun 2026 01:32:16 +1000 Subject: [PATCH 223/245] [CSV-328] Fix quoted null string after disabling quote setNullString(String) rebuilt quotedNullString by concatenating the nullable quoteCharacter field directly, so calling setQuote(null) before setNullString(...) produced a literal "nullNULLnull". Extract a shared setQuotedNullString() helper that applies the default-quote fallback, so both builder orders produce the same state. Reviewed-by: OpenAI Codex Reviewed-by: Anthropic Claude Code --- src/changes/changes.xml | 1 + src/main/java/org/apache/commons/csv/CSVFormat.java | 7 +++++-- src/test/java/org/apache/commons/csv/CSVFormatTest.java | 5 +++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 66073c9dd..64f936554 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,6 +53,7 @@ CSVParser applies characterOffset to bytePosition (#604). CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back. CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. + CSVFormat.Builder.setNullString(String) can build an invalid quoted null string after setQuote(null). Escape Reader values with quote and escape (#606). Clear escape delimiter buffer before peek in Lexer.isEscapeDelimiter() (#608, #611). Escape quote char in printWithEscapes when QuoteMode is NONE (#609). diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 4f60eff93..9c403d9e1 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -780,8 +780,7 @@ public Builder setMaxRows(final long maxRows) { */ public Builder setNullString(final String nullString) { this.nullString = nullString; - this.quotedNullString = quoteCharacter + nullString + quoteCharacter; - return this; + return setQuotedNullString(); } /** @@ -806,6 +805,10 @@ public Builder setQuote(final Character quoteCharacter) { throw new IllegalArgumentException("The quoteCharacter cannot be a line break"); } this.quoteCharacter = quoteCharacter; + return setQuotedNullString(); + } + + private Builder setQuotedNullString() { final Character quote = quoteCharacter != null ? quoteCharacter : Constants.DOUBLE_QUOTE_CHAR; this.quotedNullString = quote + nullString + quote; return this; diff --git a/src/test/java/org/apache/commons/csv/CSVFormatTest.java b/src/test/java/org/apache/commons/csv/CSVFormatTest.java index c3fdeeb77..ed20898de 100644 --- a/src/test/java/org/apache/commons/csv/CSVFormatTest.java +++ b/src/test/java/org/apache/commons/csv/CSVFormatTest.java @@ -1040,6 +1040,11 @@ void testQuotedNullStringTracksQuoteCharacter() throws IOException { builder.setQuote((Character) null); builder.get().print(null, out, true); assertEquals("\"NULL\"", out.toString()); + // reset, reverse setter order + out.setLength(0); + builder.setNullString(null).setQuote((Character) null).setNullString("NULL"); + builder.get().print(null, out, true); + assertEquals("\"NULL\"", out.toString()); } @Test From 1d89cd5f0aa454ef3853dfc7528242399ef26b74 Mon Sep 17 00:00:00 2001 From: OldTruckDriver Date: Fri, 19 Jun 2026 02:05:55 +1000 Subject: [PATCH 224/245] [CSV-329] Fix byte tracking for supplementary delimiters ExtendedBufferedReader.read(char[], int, int) updated lastChar before computing the encoded byte length, so a surrogate pair in the delimiter lookahead buffer was paired against the post-update lastChar and threw CharacterCodingException. Count bytes before updating lastChar, and pair each char against the preceding char in the buffer seeded from lastChar so pairs split across reads still count. Add parser and ExtendedBufferedReader regression tests. Reviewed-by: OpenAI Codex Reviewed-by: Anthropic Claude Code --- src/changes/changes.xml | 1 + .../commons/csv/ExtendedBufferedReader.java | 20 +++++++++------ .../org/apache/commons/csv/CSVParserTest.java | 25 +++++++++++++++++++ .../csv/ExtendedBufferedReaderTest.java | 14 +++++++++++ 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 66073c9dd..f6a474dbf 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,6 +53,7 @@ CSVParser applies characterOffset to bytePosition (#604). CSVPrinter Reader printing with quote and escape can emit CSV that its parser cannot read back. CSVParser applies maxRows to record numbers instead of rows produced when setRecordNumber(...) is used. + CSVParser with trackBytes enabled throws on multi-character delimiters containing supplementary Unicode characters. Escape Reader values with quote and escape (#606). Clear escape delimiter buffer before peek in Lexer.isEscapeDelimiter() (#608, #611). Escape quote char in printWithEscapes when QuoteMode is NONE (#609). diff --git a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java index 889b58edc..5b519a08c 100644 --- a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java +++ b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java @@ -108,9 +108,11 @@ long getBytesRead() { } private long getEncodedCharLength(final char[] buf, final int offset, final int length) throws CharacterCodingException { - int len = 0; - for (int i = offset; i < length; i++) { - len += getEncodedCharLength(buf[i]); + long len = 0; + int previous = lastChar; + for (int i = offset; i < offset + length; i++) { + len += getEncodedCharLength(previous, buf[i]); + previous = buf[i]; } return len; } @@ -141,8 +143,12 @@ private long getEncodedCharLength(final char[] buf, final int offset, final int * @throws CharacterCodingException if the character cannot be encoded. */ private int getEncodedCharLength(final int current) throws CharacterCodingException { + return getEncodedCharLength(lastChar, current); + } + + private int getEncodedCharLength(final int previous, final int current) throws CharacterCodingException { final char cChar = (char) current; - final char lChar = (char) lastChar; + final char lChar = (char) previous; if (!Character.isSurrogate(cChar)) { return encoder.encode(CharBuffer.wrap(new char[] { cChar })).limit(); } @@ -218,6 +224,9 @@ public int read(final char[] buf, final int offset, final int length) throws IOE return 0; } final int len = super.read(buf, offset, length); + if (encoder != null && len > 0) { + this.bytesRead += getEncodedCharLength(buf, offset, len); + } if (len > 0) { for (int i = offset; i < offset + len; i++) { final char ch = buf[i]; @@ -233,9 +242,6 @@ public int read(final char[] buf, final int offset, final int length) throws IOE } else if (len == EOF) { lastChar = EOF; } - if (encoder != null) { - this.bytesRead += getEncodedCharLength(buf, offset, len); - } position += len; return len; } diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 5bece571f..29ca0cf1f 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -666,6 +666,31 @@ void testGetBytePositionMultiCharacterDelimiter() throws IOException { } } + /** + * Tests CSV-329. + */ + @Test + void testGetBytePositionMultiCharacterDelimiterWithSupplementaryCharacter() throws IOException { + final String delimiter = "x😀"; + final String code = "ax😀b\ncx😀d\n"; + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(delimiter).get(); + try (CSVParser parser = CSVParser.builder() + .setReader(new StringReader(code)) + .setFormat(format) + .setCharset(UTF_8) + .setTrackBytes(true) + .get()) { + final CSVRecord first = parser.nextRecord(); + final CSVRecord second = parser.nextRecord(); + assertNotNull(first); + assertNotNull(second); + assertValuesEquals(new String[] { "a", "b" }, first); + assertValuesEquals(new String[] { "c", "d" }, second); + assertEquals(0, first.getBytePosition()); + assertEquals("ax😀b\n".getBytes(UTF_8).length, second.getBytePosition()); + } + } + @Test void testGetBytePositionWithCharacterOffsetAndMultiBytePrefix() throws Exception { final String row0 = "é,x\n"; diff --git a/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java b/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java index 056b8a9c9..b8d9b9f19 100644 --- a/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java +++ b/src/test/java/org/apache/commons/csv/ExtendedBufferedReaderTest.java @@ -26,6 +26,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; @@ -104,6 +105,19 @@ void testReadingInDifferentBuffer() throws Exception { } } + @Test + void testReadingSupplementaryCharacterTracksBytes() throws Exception { + final String input = "😀"; + final char[] buffer = new char[input.length()]; + try (ExtendedBufferedReader reader = new ExtendedBufferedReader(new StringReader(input), StandardCharsets.UTF_8, true)) { + assertEquals(input.length(), reader.read(buffer, 0, buffer.length)); + assertArrayEquals(input.toCharArray(), buffer); + assertEquals(input.getBytes(StandardCharsets.UTF_8).length, reader.getBytesRead()); + assertEquals(input.length(), reader.getPosition()); + assertEquals(input.charAt(input.length() - 1), reader.getLastChar()); + } + } + @Test void testReadLine() throws Exception { try (ExtendedBufferedReader br = createBufferedReader("")) { From d8e12423b47109c76196bbae454726a114cf7c07 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jun 2026 07:28:18 -0400 Subject: [PATCH 225/245] Bump actions/checkout from 6.0.3 to 7.0.0. --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/dependency-review.yml | 2 +- .github/workflows/maven.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 57f55cae0..08c673ee0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -46,7 +46,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 114f3d8a2..7bc02bdd2 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -26,6 +26,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: 'Dependency Review PR' uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3ee3dec2b..3cb743cbf 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -43,7 +43,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 From a1cf4f2a73065281ca7c22841c2f3ec0c00098c1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jun 2026 11:44:21 +0000 Subject: [PATCH 226/245] Refactor delimiter in test Rename local variable --- src/test/java/org/apache/commons/csv/CSVParserTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 29ca0cf1f..aa4a639dd 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -672,10 +672,10 @@ void testGetBytePositionMultiCharacterDelimiter() throws IOException { @Test void testGetBytePositionMultiCharacterDelimiterWithSupplementaryCharacter() throws IOException { final String delimiter = "x😀"; - final String code = "ax😀b\ncx😀d\n"; + final String data = "a" + delimiter + "b\nc" + delimiter + "d\n"; final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(delimiter).get(); try (CSVParser parser = CSVParser.builder() - .setReader(new StringReader(code)) + .setReader(new StringReader(data)) .setFormat(format) .setCharset(UTF_8) .setTrackBytes(true) @@ -687,7 +687,7 @@ void testGetBytePositionMultiCharacterDelimiterWithSupplementaryCharacter() thro assertValuesEquals(new String[] { "a", "b" }, first); assertValuesEquals(new String[] { "c", "d" }, second); assertEquals(0, first.getBytePosition()); - assertEquals("ax😀b\n".getBytes(UTF_8).length, second.getBytePosition()); + assertEquals("a" + delimiter + "b\n".getBytes(UTF_8).length, second.getBytePosition()); } } From caa1c8d0ed1a05f4a75f9a4fc6e5e2dc6fa5bf51 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jun 2026 18:51:44 +0000 Subject: [PATCH 227/245] Revert "Refactor delimiter in test" This reverts commit a1cf4f2a73065281ca7c22841c2f3ec0c00098c1. --- src/test/java/org/apache/commons/csv/CSVParserTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index aa4a639dd..29ca0cf1f 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -672,10 +672,10 @@ void testGetBytePositionMultiCharacterDelimiter() throws IOException { @Test void testGetBytePositionMultiCharacterDelimiterWithSupplementaryCharacter() throws IOException { final String delimiter = "x😀"; - final String data = "a" + delimiter + "b\nc" + delimiter + "d\n"; + final String code = "ax😀b\ncx😀d\n"; final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(delimiter).get(); try (CSVParser parser = CSVParser.builder() - .setReader(new StringReader(data)) + .setReader(new StringReader(code)) .setFormat(format) .setCharset(UTF_8) .setTrackBytes(true) @@ -687,7 +687,7 @@ void testGetBytePositionMultiCharacterDelimiterWithSupplementaryCharacter() thro assertValuesEquals(new String[] { "a", "b" }, first); assertValuesEquals(new String[] { "c", "d" }, second); assertEquals(0, first.getBytePosition()); - assertEquals("a" + delimiter + "b\n".getBytes(UTF_8).length, second.getBytePosition()); + assertEquals("ax😀b\n".getBytes(UTF_8).length, second.getBytePosition()); } } From 61aa0555d60c68120914b4952232f8c6bfc72ed3 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Fri, 19 Jun 2026 23:39:51 +0530 Subject: [PATCH 228/245] escape leading comment marker in printWithEscapes --- .../org/apache/commons/csv/CSVFormat.java | 14 ++++- .../apache/commons/csv/CSVPrinterTest.java | 51 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index 9c403d9e1..eaa8c8ffe 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -2329,12 +2329,16 @@ private void printWithEscapes(final CharSequence charSeq, final Appendable appen final char escape = getEscapeChar(); final boolean quoteSet = isQuoteCharacterSet(); final char quote = quoteSet ? getQuoteCharacter().charValue() : 0; + final boolean commentMarkerSet = isCommentMarkerSet(); + final char commentChar = commentMarkerSet ? commentMarker.charValue() : 0; // Explicit unboxing is intentional while (pos < end) { char c = charSeq.charAt(pos); final boolean isDelimiterStart = isDelimiter(c, charSeq, pos, delimArray, delimLength); final boolean isCr = c == Constants.CR; final boolean isLf = c == Constants.LF; - if (isCr || isLf || c == escape || quoteSet && c == quote || isDelimiterStart) { + // A leading comment marker would be read back as a comment, so escape it. + final boolean isComment = commentMarkerSet && pos == 0 && c == commentChar; + if (isCr || isLf || c == escape || quoteSet && c == quote || isDelimiterStart || isComment) { // write out segment up until this char if (pos > start) { appendable.append(charSeq, start, pos); @@ -2375,8 +2379,11 @@ private void printWithEscapes(final Reader reader, final Appendable appendable) final char escape = getEscapeChar(); final boolean quoteSet = isQuoteCharacterSet(); final char quote = quoteSet ? getQuoteCharacter().charValue() : 0; + final boolean commentMarkerSet = isCommentMarkerSet(); + final char commentChar = commentMarkerSet ? commentMarker.charValue() : 0; // Explicit unboxing is intentional final StringBuilder builder = new StringBuilder(IOUtils.DEFAULT_BUFFER_SIZE); int c; + boolean firstChar = true; final char[] lookAheadBuffer = new char[delimLength - 1]; while (EOF != (c = bufferedReader.read())) { builder.append((char) c); @@ -2386,7 +2393,10 @@ private void printWithEscapes(final Reader reader, final Appendable appendable) final boolean isDelimiterStart = isDelimiter((char) c, test, pos, delimArray, delimLength); final boolean isCr = c == Constants.CR; final boolean isLf = c == Constants.LF; - if (isCr || isLf || c == escape || quoteSet && c == quote || isDelimiterStart) { + // A leading comment marker would be read back as a comment, so escape it. + final boolean isComment = commentMarkerSet && firstChar && c == commentChar; + firstChar = false; + if (isCr || isLf || c == escape || quoteSet && c == quote || isDelimiterStart || isComment) { // write out segment up until this char if (pos > start) { append(builder.substring(start, pos), appendable); diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java index e68d4c243..9ae80c1e5 100644 --- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java +++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java @@ -569,6 +569,57 @@ void testEscapeBackslash5() throws IOException { assertEquals("\\\\", sw.toString()); } + @Test + void testEscapeCommentMarkerFirstChar() throws IOException { + // No quoting available in escape mode, so a leading comment marker must be escaped or the + // record reads back as a comment and is dropped. Mirrors the quoting fix for QuoteMode.MINIMAL. + final CSVFormat format = CSVFormat.DEFAULT.builder().setQuote(null).setEscape('\\').setCommentMarker(';').get(); + final StringWriter sw = new StringWriter(); + final String col1 = ";comment-like"; + try (CSVPrinter printer = new CSVPrinter(sw, format)) { + printer.printRecord(col1, "b"); + printer.printRecord(new StringReader(col1), new StringReader("b")); + // The marker past the first character does not start a comment and is left alone. + printer.printRecord("a;b", ";c"); + } + final String string = sw.toString(); + assertEquals("\\;comment-like,b" + RECORD_SEPARATOR + + "\\;comment-like,b" + RECORD_SEPARATOR + + "a;b,\\;c" + RECORD_SEPARATOR, string); + // The emitted records must read back as the original values, none parsed as a comment. + try (CSVParser parser = CSVParser.parse(string, format)) { + final List records = parser.getRecords(); + assertEquals(3, records.size()); + assertEquals(col1, records.get(0).get(0)); + assertEquals("b", records.get(0).get(1)); + assertEquals(col1, records.get(1).get(0)); + assertEquals("b", records.get(1).get(1)); + assertEquals("a;b", records.get(2).get(0)); + assertEquals(";c", records.get(2).get(1)); + } + } + + @Test + void testEscapeCommentMarkerFirstCharWithQuoteModeNone() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setEscape('\\').setQuoteMode(QuoteMode.NONE).setCommentMarker(';').get(); + final StringWriter sw = new StringWriter(); + final String col1 = ";bar"; + try (CSVPrinter printer = new CSVPrinter(sw, format)) { + printer.printRecord(col1, "b"); + printer.printRecord(new StringReader(col1), new StringReader("b")); + } + final String string = sw.toString(); + assertEquals("\\;bar,b" + RECORD_SEPARATOR + "\\;bar,b" + RECORD_SEPARATOR, string); + try (CSVParser parser = CSVParser.parse(string, format)) { + final List records = parser.getRecords(); + assertEquals(2, records.size()); + for (final CSVRecord record : records) { + assertEquals(col1, record.get(0)); + assertEquals("b", record.get(1)); + } + } + } + @Test void testEscapeNull1() throws IOException { final StringWriter sw = new StringWriter(); From b112daacc74664c925b28d413b660dc47faddcef Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 19 Jun 2026 21:14:05 +0000 Subject: [PATCH 229/245] Escape leading comment marker in printWithEscapes (#614). --- src/changes/changes.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 006de7711..f172a96fe 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -58,7 +58,8 @@ Escape Reader values with quote and escape (#606). Clear escape delimiter buffer before peek in Lexer.isEscapeDelimiter() (#608, #611). Escape quote char in printWithEscapes when QuoteMode is NONE (#609). - Quote value starting with comment marker in minimal quote mode (#610).. + Quote value starting with comment marker in minimal quote mode (#610). + Escape leading comment marker in printWithEscapes (#614). Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). From 274b4ceba4e418726a5c9e7043bf9d460b0429c5 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Sat, 20 Jun 2026 20:33:44 +0530 Subject: [PATCH 230/245] skip byte counting at EOF in ExtendedBufferedReader.read --- .../commons/csv/ExtendedBufferedReader.java | 2 +- .../org/apache/commons/csv/CSVParserTest.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java index 5b519a08c..20c1ef544 100644 --- a/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java +++ b/src/main/java/org/apache/commons/csv/ExtendedBufferedReader.java @@ -210,7 +210,7 @@ public int read() throws IOException { if (current == CR || current == LF && lastChar != CR || current == EOF && lastChar != CR && lastChar != LF && lastChar != EOF) { lineNumber++; } - if (encoder != null) { + if (encoder != null && current != EOF) { this.bytesRead += getEncodedCharLength(current); } lastChar = current; diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 29ca0cf1f..1332fa582 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -691,6 +691,27 @@ void testGetBytePositionMultiCharacterDelimiterWithSupplementaryCharacter() thro } } + @Test + void testGetBytePositionWithSingleByteCharset() throws IOException { + // A single-byte charset cannot encode U+FFFF, the char value of the EOF sentinel. + // Byte counting must skip the EOF read so a valid file parses without throwing. + final String code = "a,b\nc,d\n"; + try (CSVParser parser = CSVParser.builder() + .setReader(new StringReader(code)) + .setFormat(CSVFormat.DEFAULT) + .setCharset(StandardCharsets.ISO_8859_1) + .setTrackBytes(true) + .get()) { + final CSVRecord first = parser.nextRecord(); + final CSVRecord second = parser.nextRecord(); + assertNotNull(first); + assertNotNull(second); + assertNull(parser.nextRecord()); + assertEquals(0, first.getBytePosition()); + assertEquals(4, second.getBytePosition()); + } + } + @Test void testGetBytePositionWithCharacterOffsetAndMultiBytePrefix() throws Exception { final String row0 = "é,x\n"; From 0633c989c9ff892d99bacd3289a3ff8d4cb0fbd6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Sat, 20 Jun 2026 15:11:11 +0000 Subject: [PATCH 231/245] Skip byte counting at EOF in ExtendedBufferedReader.read (#615). Sort members. --- src/changes/changes.xml | 1 + .../org/apache/commons/csv/CSVParserTest.java | 42 +++++++++---------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index f172a96fe..867a20507 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -60,6 +60,7 @@ Escape quote char in printWithEscapes when QuoteMode is NONE (#609). Quote value starting with comment marker in minimal quote mode (#610). Escape leading comment marker in printWithEscapes (#614). + Skip byte counting at EOF in ExtendedBufferedReader.read (#615). Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 1332fa582..309a073cf 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -691,27 +691,6 @@ void testGetBytePositionMultiCharacterDelimiterWithSupplementaryCharacter() thro } } - @Test - void testGetBytePositionWithSingleByteCharset() throws IOException { - // A single-byte charset cannot encode U+FFFF, the char value of the EOF sentinel. - // Byte counting must skip the EOF read so a valid file parses without throwing. - final String code = "a,b\nc,d\n"; - try (CSVParser parser = CSVParser.builder() - .setReader(new StringReader(code)) - .setFormat(CSVFormat.DEFAULT) - .setCharset(StandardCharsets.ISO_8859_1) - .setTrackBytes(true) - .get()) { - final CSVRecord first = parser.nextRecord(); - final CSVRecord second = parser.nextRecord(); - assertNotNull(first); - assertNotNull(second); - assertNull(parser.nextRecord()); - assertEquals(0, first.getBytePosition()); - assertEquals(4, second.getBytePosition()); - } - } - @Test void testGetBytePositionWithCharacterOffsetAndMultiBytePrefix() throws Exception { final String row0 = "é,x\n"; @@ -742,6 +721,27 @@ void testGetBytePositionWithCharacterOffsetAndMultiBytePrefix() throws Exception } } + @Test + void testGetBytePositionWithSingleByteCharset() throws IOException { + // A single-byte charset cannot encode U+FFFF, the char value of the EOF sentinel. + // Byte counting must skip the EOF read so a valid file parses without throwing. + final String code = "a,b\nc,d\n"; + try (CSVParser parser = CSVParser.builder() + .setReader(new StringReader(code)) + .setFormat(CSVFormat.DEFAULT) + .setCharset(StandardCharsets.ISO_8859_1) + .setTrackBytes(true) + .get()) { + final CSVRecord first = parser.nextRecord(); + final CSVRecord second = parser.nextRecord(); + assertNotNull(first); + assertNotNull(second); + assertNull(parser.nextRecord()); + assertEquals(0, first.getBytePosition()); + assertEquals(4, second.getBytePosition()); + } + } + @Test void testGetHeaderComment_HeaderComment1() throws IOException { try (CSVParser parser = CSVParser.parse(CSV_INPUT_HEADER_COMMENT, FORMAT_AUTO_HEADER)) { From 609a228e35adf9d73275a6b88e065de091c94be6 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Mon, 22 Jun 2026 02:01:19 +0530 Subject: [PATCH 232/245] keep quoted empty trailing field with trailingDelimiter --- .../java/org/apache/commons/csv/CSVParser.java | 4 +++- .../org/apache/commons/csv/CSVParserTest.java | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/CSVParser.java b/src/main/java/org/apache/commons/csv/CSVParser.java index 83b60170e..141eba732 100644 --- a/src/main/java/org/apache/commons/csv/CSVParser.java +++ b/src/main/java/org/apache/commons/csv/CSVParser.java @@ -580,7 +580,9 @@ public CSVParser(final Reader reader, final CSVFormat format, final long charact private void addRecordValue(final boolean lastRecord) { final String input = format.trim(reusableToken.content.toString()); - if (lastRecord && input.isEmpty() && format.getTrailingDelimiter()) { + // Only drop the empty field produced by an actual trailing delimiter. A quoted empty + // field ("") is a real value, not a trailing delimiter, so it must be kept. + if (lastRecord && input.isEmpty() && format.getTrailingDelimiter() && !reusableToken.isQuoted) { return; } recordList.add(handleNull(input)); diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 309a073cf..051548757 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -1949,6 +1949,23 @@ void testTrailingDelimiter() throws Exception { } } + @Test + void testTrailingDelimiterKeepsQuotedEmptyLastField() throws Exception { + final CSVFormat format = CSVFormat.DEFAULT.builder().setTrailingDelimiter(true).get(); + try (CSVParser parser = CSVParser.parse("a,b,\"\"", format)) { + final CSVRecord record = parser.iterator().next(); + assertEquals(3, record.size()); + assertEquals("a", record.get(0)); + assertEquals("b", record.get(1)); + assertEquals("", record.get(2)); + } + // An unquoted trailing delimiter still drops the empty field. + try (CSVParser parser = CSVParser.parse("a,b,", format)) { + final CSVRecord record = parser.iterator().next(); + assertEquals(2, record.size()); + } + } + @Test void testTrim() throws Exception { final Reader in = new StringReader("a,a,a\n\" 1 \",\" 2 \",\" 3 \"\nx,y,z"); From 53360c47dbdd5d6ba4fe5e8008f8bb3510200b33 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 22 Jun 2026 07:32:06 -0400 Subject: [PATCH 233/245] Bump actions/setup-java from 5.2.0 to 5.3.0 --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3cb743cbf..a6154ddb1 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -53,7 +53,7 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 with: distribution: ${{ runner.os == 'macOS' && matrix.java == '8' && 'zulu' || 'temurin' }} java-version: ${{ matrix.java }} From fc4c0e3b43c3cba69f023d336629d2696e250294 Mon Sep 17 00:00:00 2001 From: rootvector2 Date: Mon, 22 Jun 2026 18:06:33 +0530 Subject: [PATCH 234/245] document trailing delimiter parse behavior and contrast with trailing data --- .../org/apache/commons/csv/CSVFormat.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java index eaa8c8ffe..7145d23d3 100644 --- a/src/main/java/org/apache/commons/csv/CSVFormat.java +++ b/src/main/java/org/apache/commons/csv/CSVFormat.java @@ -883,6 +883,16 @@ public Builder setTrailingData(final boolean trailingData) { /** * Sets whether to add a trailing delimiter. * + *

    + * When writing, a delimiter is appended after the last value of each record. When reading, the empty field + * that such a trailing delimiter produces is dropped so the output round-trips back to the original record; + * a quoted empty trailing field ({@code ""}) is a real value rather than a trailing delimiter and is kept. + *

    + *

    + * This is unrelated to {@link #setTrailingData(boolean) trailing data}, which controls whether characters + * after the closing quote of an encapsulated value are tolerated when reading. + *

    + * * @param trailingDelimiter whether to add a trailing delimiter. * @return This instance. */ @@ -2012,6 +2022,16 @@ public boolean getTrailingData() { /** * Gets whether to add a trailing delimiter. * + *

    + * When writing, a delimiter is appended after the last value of each record. When reading, the empty field + * that such a trailing delimiter produces is dropped so the output round-trips back to the original record; + * a quoted empty trailing field ({@code ""}) is a real value rather than a trailing delimiter and is kept. + *

    + *

    + * This is unrelated to {@link #getTrailingData() trailing data}, which controls whether characters after the + * closing quote of an encapsulated value are tolerated when reading. + *

    + * * @return whether to add a trailing delimiter. * @since 1.3 */ From e729d17d5089d794c07e41dd6c9d374f9ea09e85 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 22 Jun 2026 13:49:46 +0000 Subject: [PATCH 235/245] Keep quoted empty trailing field with trailingDelimiter (#616). --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 867a20507..0d0175ccc 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -61,6 +61,7 @@ Quote value starting with comment marker in minimal quote mode (#610). Escape leading comment marker in printWithEscapes (#614). Skip byte counting at EOF in ExtendedBufferedReader.read (#615). + Keep quoted empty trailing field with trailingDelimiter (#616). Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). From afbf34ad92cbf741b9dfad84699e890d8695a6f9 Mon Sep 17 00:00:00 2001 From: Naveed Khan Date: Thu, 25 Jun 2026 23:12:11 +0530 Subject: [PATCH 236/245] evaluate isDelimiter once in nextToken whitespace skip --- .../java/org/apache/commons/csv/Lexer.java | 11 +++++++++-- .../org/apache/commons/csv/LexerTest.java | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/apache/commons/csv/Lexer.java b/src/main/java/org/apache/commons/csv/Lexer.java index 93a584663..fe964480a 100644 --- a/src/main/java/org/apache/commons/csv/Lexer.java +++ b/src/main/java/org/apache/commons/csv/Lexer.java @@ -277,15 +277,22 @@ Token nextToken(final Token token) throws IOException { } // Important: make sure a new char gets consumed in each iteration while (token.type == Token.Type.INVALID) { + // isDelimiter consumes the trailing characters of a multi-character delimiter as a side effect, so it must + // only be evaluated once per character. Remember a match found while skipping whitespace below. + boolean delimiter = false; // ignore whitespaces at beginning of a token if (ignoreSurroundingSpaces) { - while (Character.isWhitespace((char) c) && !isDelimiter(c) && !eol) { + while (Character.isWhitespace((char) c) && !eol) { + if (isDelimiter(c)) { + delimiter = true; + break; + } c = reader.read(); eol = readEndOfLine(c); } } // ok, start of token reached: encapsulated, or token - if (isDelimiter(c)) { + if (delimiter || isDelimiter(c)) { // empty token return TOKEN("") token.type = Token.Type.TOKEN; } else if (eol) { diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index db1ab3a6d..445f710a1 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -447,6 +447,25 @@ void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { } } + /** + * With {@code ignoreSurroundingSpaces} enabled and a multi-character delimiter whose first character is whitespace, + * the side-effecting {@link Lexer#isDelimiter(int)} must only be evaluated once per character, otherwise the + * delimiter is consumed in the whitespace-skip loop and the empty field at the boundary is dropped. + */ + @Test + void testEmptyTokenBeforeWhitespacePrefixedMultiCharacterDelimiter() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(" |").setIgnoreSurroundingSpaces(true).get(); + try (Lexer lexer = createLexer(" |a", format)) { + assertNextToken(TOKEN, "", lexer); + assertNextToken(EOF, "a", lexer); + } + try (Lexer lexer = createLexer("a | |b", format)) { + assertNextToken(TOKEN, "a", lexer); + assertNextToken(TOKEN, "", lexer); + assertNextToken(EOF, "b", lexer); + } + } + @Test void testReadEscapeBackspace() throws IOException { try (Lexer lexer = createLexer("b", CSVFormat.DEFAULT.withEscape('\b'))) { From c9362f76baa32534e82334a27220b698db49788c Mon Sep 17 00:00:00 2001 From: Naveed Khan Date: Fri, 26 Jun 2026 02:45:35 +0530 Subject: [PATCH 237/245] add public-api test for whitespace-prefixed multi-char delimiter exercises the empty-field-dropped regression through CSVParser, not just the lexer. --- .../org/apache/commons/csv/CSVParserTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 051548757..565e132eb 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -1758,6 +1758,26 @@ void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { } } + /** + * With {@code ignoreSurroundingSpaces} enabled and a multi-character delimiter whose first character is whitespace, + * the empty field at the delimiter boundary must survive. The delimiter look-ahead is consumed while skipping + * leading whitespace, so re-evaluating it would drop the empty field and merge the following field's value. + */ + @Test + void testEmptyFieldBeforeWhitespacePrefixedMultiCharacterDelimiter() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(" |").setIgnoreSurroundingSpaces(true).get(); + try (CSVParser parser = CSVParser.parse(" |a", format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertValuesEquals(new String[] { "", "a" }, records.get(0)); + } + try (CSVParser parser = CSVParser.parse("a | |b", format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertValuesEquals(new String[] { "a", "", "b" }, records.get(0)); + } + } + @Test void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); From c4113ceb3acfba0634133e47d35c40d141e18525 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 25 Jun 2026 22:11:14 +0000 Subject: [PATCH 238/245] Evaluate isDelimiter once in nextToken whitespace skip (#618). --- src/changes/changes.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 0d0175ccc..93952e9f1 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -62,6 +62,7 @@ Escape leading comment marker in printWithEscapes (#614). Skip byte counting at EOF in ExtendedBufferedReader.read (#615). Keep quoted empty trailing field with trailingDelimiter (#616). + Evaluate isDelimiter once in nextToken whitespace skip (#618).. Add an "Android Compatibility" section to the web site. Add CSVParser.Builder.setByteOffset(long) (#604). From e36e7f3a1d0fbe29f2ff602f041d3a3d4195b84a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 25 Jun 2026 22:11:53 +0000 Subject: [PATCH 239/245] Sort members --- .../org/apache/commons/csv/CSVParserTest.java | 40 +++++++++---------- .../org/apache/commons/csv/LexerTest.java | 38 +++++++++--------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 565e132eb..3bea08fac 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -465,6 +465,26 @@ void testDuplicateHeadersNotAllowed() { () -> CSVParser.parse("a,b,a\n1,2,3\nx,y,z", CSVFormat.DEFAULT.withHeader().withAllowDuplicateHeaderNames(false))); } + /** + * With {@code ignoreSurroundingSpaces} enabled and a multi-character delimiter whose first character is whitespace, + * the empty field at the delimiter boundary must survive. The delimiter look-ahead is consumed while skipping + * leading whitespace, so re-evaluating it would drop the empty field and merge the following field's value. + */ + @Test + void testEmptyFieldBeforeWhitespacePrefixedMultiCharacterDelimiter() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(" |").setIgnoreSurroundingSpaces(true).get(); + try (CSVParser parser = CSVParser.parse(" |a", format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertValuesEquals(new String[] { "", "a" }, records.get(0)); + } + try (CSVParser parser = CSVParser.parse("a | |b", format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertValuesEquals(new String[] { "a", "", "b" }, records.get(0)); + } + } + @Test void testEmptyFile() throws Exception { try (CSVParser parser = CSVParser.parse(Paths.get("src/test/resources/org/apache/commons/csv/empty.txt"), StandardCharsets.UTF_8, @@ -1758,26 +1778,6 @@ void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { } } - /** - * With {@code ignoreSurroundingSpaces} enabled and a multi-character delimiter whose first character is whitespace, - * the empty field at the delimiter boundary must survive. The delimiter look-ahead is consumed while skipping - * leading whitespace, so re-evaluating it would drop the empty field and merge the following field's value. - */ - @Test - void testEmptyFieldBeforeWhitespacePrefixedMultiCharacterDelimiter() throws IOException { - final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(" |").setIgnoreSurroundingSpaces(true).get(); - try (CSVParser parser = CSVParser.parse(" |a", format)) { - final List records = parser.getRecords(); - assertEquals(1, records.size()); - assertValuesEquals(new String[] { "", "a" }, records.get(0)); - } - try (CSVParser parser = CSVParser.parse("a | |b", format)) { - final List records = parser.getRecords(); - assertEquals(1, records.size()); - assertValuesEquals(new String[] { "a", "", "b" }, records.get(0)); - } - } - @Test void testProvidedHeader() throws Exception { final Reader in = new StringReader("a,b,c\n1,2,3\nx,y,z"); diff --git a/src/test/java/org/apache/commons/csv/LexerTest.java b/src/test/java/org/apache/commons/csv/LexerTest.java index 445f710a1..a76f6e513 100644 --- a/src/test/java/org/apache/commons/csv/LexerTest.java +++ b/src/test/java/org/apache/commons/csv/LexerTest.java @@ -216,6 +216,25 @@ void testDelimiterIsWhitespace() throws IOException { } } + /** + * With {@code ignoreSurroundingSpaces} enabled and a multi-character delimiter whose first character is whitespace, + * the side-effecting {@link Lexer#isDelimiter(int)} must only be evaluated once per character, otherwise the + * delimiter is consumed in the whitespace-skip loop and the empty field at the boundary is dropped. + */ + @Test + void testEmptyTokenBeforeWhitespacePrefixedMultiCharacterDelimiter() throws IOException { + final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(" |").setIgnoreSurroundingSpaces(true).get(); + try (Lexer lexer = createLexer(" |a", format)) { + assertNextToken(TOKEN, "", lexer); + assertNextToken(EOF, "a", lexer); + } + try (Lexer lexer = createLexer("a | |b", format)) { + assertNextToken(TOKEN, "a", lexer); + assertNextToken(TOKEN, "", lexer); + assertNextToken(EOF, "b", lexer); + } + } + @Test void testEOFWithoutClosingQuote() throws Exception { final String code = "a,\"b"; @@ -447,25 +466,6 @@ void testPartialMultiCharacterDelimiterAtEOFAfterMismatch() throws IOException { } } - /** - * With {@code ignoreSurroundingSpaces} enabled and a multi-character delimiter whose first character is whitespace, - * the side-effecting {@link Lexer#isDelimiter(int)} must only be evaluated once per character, otherwise the - * delimiter is consumed in the whitespace-skip loop and the empty field at the boundary is dropped. - */ - @Test - void testEmptyTokenBeforeWhitespacePrefixedMultiCharacterDelimiter() throws IOException { - final CSVFormat format = CSVFormat.DEFAULT.builder().setDelimiter(" |").setIgnoreSurroundingSpaces(true).get(); - try (Lexer lexer = createLexer(" |a", format)) { - assertNextToken(TOKEN, "", lexer); - assertNextToken(EOF, "a", lexer); - } - try (Lexer lexer = createLexer("a | |b", format)) { - assertNextToken(TOKEN, "a", lexer); - assertNextToken(TOKEN, "", lexer); - assertNextToken(EOF, "b", lexer); - } - } - @Test void testReadEscapeBackspace() throws IOException { try (Lexer lexer = createLexer("b", CSVFormat.DEFAULT.withEscape('\b'))) { From 26a53751934e52f84663e5e90956db99f0eefc49 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 25 Jun 2026 22:13:08 +0000 Subject: [PATCH 240/245] Add test more assertions to CSVParserTest.testEmptyFieldBeforeWhitespacePrefixedMultiCharacterDelimiter() --- src/test/java/org/apache/commons/csv/CSVParserTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/org/apache/commons/csv/CSVParserTest.java b/src/test/java/org/apache/commons/csv/CSVParserTest.java index 3bea08fac..6d9bdd9e8 100644 --- a/src/test/java/org/apache/commons/csv/CSVParserTest.java +++ b/src/test/java/org/apache/commons/csv/CSVParserTest.java @@ -483,6 +483,11 @@ void testEmptyFieldBeforeWhitespacePrefixedMultiCharacterDelimiter() throws IOEx assertEquals(1, records.size()); assertValuesEquals(new String[] { "a", "", "b" }, records.get(0)); } + try (CSVParser parser = CSVParser.parse("a | |b |", format)) { + final List records = parser.getRecords(); + assertEquals(1, records.size()); + assertValuesEquals(new String[] { "a", "", "b", "" }, records.get(0)); + } } @Test From b346046e10a5833e5f6143fd0162155bb51ccc87 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Thu, 25 Jun 2026 18:23:59 -0400 Subject: [PATCH 241/245] Bump actions/cache from 5.0.5 to 6.0.0. --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 08c673ee0..20f1ee2cb 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 + - uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index a6154ddb1..139df406d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae #v5.0.5 + - uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 930bc7919db7ebb81dc566e9e278ce2bed3acf42 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 29 Jun 2026 07:29:52 -0400 Subject: [PATCH 242/245] Bump actions/cache from 6.0.0 to 6.1.0 --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/maven.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 20f1ee2cb..cca38e512 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -49,7 +49,7 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 139df406d..2637840b1 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -46,7 +46,7 @@ jobs: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - - uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0 + - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 #v6.1.0 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} From 6471196a31d9ea92942a634732e5350ef5253fcf Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 30 Jun 2026 13:58:31 +0000 Subject: [PATCH 243/245] Javadoc --- src/main/java/org/apache/commons/csv/CSVRecord.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/apache/commons/csv/CSVRecord.java b/src/main/java/org/apache/commons/csv/CSVRecord.java index 502bf318a..8dab14d90 100644 --- a/src/main/java/org/apache/commons/csv/CSVRecord.java +++ b/src/main/java/org/apache/commons/csv/CSVRecord.java @@ -281,7 +281,7 @@ public Iterator iterator() { /** * Puts all values of this record into the given Map. * - * @param the map type. + * @param The map type. * @param map The Map to populate. * @return the given map. * @since 1.9.0 From f7efa29cd9c4d9d1c1cafdae4469cf254bf22f42 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Tue, 30 Jun 2026 20:50:12 -0400 Subject: [PATCH 244/245] Bump actions/setup-java from 5.3.0 to 5.4.0 --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 2637840b1..17ba7dd38 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -53,7 +53,7 @@ jobs: restore-keys: | ${{ runner.os }}-maven- - name: Set up JDK ${{ matrix.java }} - uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 + uses: actions/setup-java@1bcf9fb12cf4aa7d266a90ae39939e61372fe520 # v5.4.0 with: distribution: ${{ runner.os == 'macOS' && matrix.java == '8' && 'zulu' || 'temurin' }} java-version: ${{ matrix.java }} From 4434d93b92ff3f7b0754e65eba53721dd95c59f1 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Wed, 1 Jul 2026 07:31:54 -0400 Subject: [PATCH 245/245] Bump actions/checkout from 6.0.2 to 7.0.0 --- .github/workflows/scorecards-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml index bf246c140..e1868cb46 100644 --- a/.github/workflows/scorecards-analysis.yml +++ b/.github/workflows/scorecards-analysis.yml @@ -40,7 +40,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # 7.0.0 with: persist-credentials: false

    E({I_^w! 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 Apache Commons Team + + +

  • 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 literal 20042 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 diff --git a/src/site/resources/images/logo.xcf b/src/site/resources/images/logo.xcf deleted file mode 100644 index 98ff21ec1d5a71964d0a7159d4f5987f93de64f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141911 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