diff --git a/.asf.yaml b/.asf.yaml
index 5ea25ac8897..33a8dd8c4ff 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
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 00079caf1bc..90ec55f742e 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"
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 7578b4da036..9ff35c83e79 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -23,8 +23,8 @@ 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 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.
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index fcc16fe390a..4246d5e4de3 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -42,6 +42,7 @@ jobs:
security-events: write
strategy:
+ max-parallel: 20
fail-fast: false
matrix:
language: [ 'java' ]
@@ -50,10 +51,10 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+ - uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
@@ -62,7 +63,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@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.
@@ -73,7 +74,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@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -87,4 +88,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5
+ uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index 1e043924237..7bc02bdd23d 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@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: 'Dependency Review PR'
- uses: actions/dependency-review-action@595b5aeba73380359d98a5e087f648dbb0edce1b # v4.7.3
+ uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index 7d0f0892434..916b676cc14 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -37,9 +37,10 @@ jobs:
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental }}
strategy:
+ max-parallel: 20
matrix:
- os: [ubuntu-latest, windows-latest, macos-13]
- java: [ 8, 11, 17, 21 ]
+ os: [ubuntu-latest, windows-latest, macos-latest]
+ java: [ 8, 11, 17, 21, 25, 26 ]
experimental: [false]
# Keep the same parameter order as the matrix above
include:
@@ -48,41 +49,31 @@ jobs:
java: 21
experimental: false
deploy: true
- # Experimental builds: Java 25-ea
+ # Experimental builds: Java 27-ea
- os: ubuntu-latest
- java: 25
+ java: 27-ea
experimental: true
- os: windows-latest
- java: 25
+ java: 27-ea
experimental: true
- os: macos-latest
- java: 25
- experimental: true
- # Experimental builds: Java 26-ea
- - os: ubuntu-latest
- java: 26-ea
- experimental: true
- - os: windows-latest
- java: 26-ea
- experimental: true
- - os: macos-latest
- java: 26-ea
+ java: 27-ea
experimental: true
fail-fast: false
steps:
- - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
+ - uses: actions/cache@2c8a9bd7457de244a408f35966fab2fb45fda9c8 # v6.0.0
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Set up JDK ${{ matrix.java }}
- uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
+ uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
- distribution: 'temurin'
+ distribution: ${{ runner.os == 'macOS' && matrix.java == '8' && 'zulu' || 'temurin' }}
java-version: ${{ matrix.java }}
# these values cause the plugin to set up the Maven settings.xml file
server-id: apache.snapshots.https # Value of the distributionManagement/repository/id field of the pom.xml
diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index cf4d6ba87b0..53acdc68101 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -42,12 +42,12 @@ jobs:
steps:
- name: "Checkout code"
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
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
@@ -59,13 +59,13 @@ jobs:
publish_results: true
- name: "Upload artifact"
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@303c0aef88fc2fe5ff6d63d3b1596bfd83dfa1f9 # 3.29.5
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
with:
sarif_file: results.sarif
diff --git a/.gitignore b/.gitignore
index f43fea02686..91824e5be73 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
-### https://raw.github.com/github/gitignore/14b7566ce157ce95b07006466bacee160f242284/maven.gitignore
-
target/
pom.xml.tag
pom.xml.releaseBackup
@@ -7,16 +5,19 @@ pom.xml.versionsBackup
pom.xml.next
release.properties
-
site-content
/.classpath
/.project
/.settings/
-### Ignore IntelliJ files
+# Ignore IntelliJ files
/.idea/
*.iml
/bin/
-### Ignore Visual Studio code files
+# Ignore Visual Studio code files
/.vscode/
+
+# NetBeans files
+nb-configuration.xml
+nbactions.xml
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f708680735d..babb08bb394 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 IO'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
--------------
@@ -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.
@@ -108,9 +108,8 @@ Additional Resources
+ [Contributing patches](https://commons.apache.org/patches.html)
+ [Apache Commons IO 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/)
-+ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
++ [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)
[cla]:https://www.apache.org/licenses/#clas
[jira]:https://issues.apache.org/jira/browse/IO
diff --git a/NOTICE.txt b/NOTICE.txt
index 2a4682551b1..b9fb860712d 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,5 @@
Apache Commons IO
-Copyright 2002-2025 The Apache Software Foundation
+Copyright 2002-2026 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (https://www.apache.org/).
diff --git a/README.md b/README.md
index bb31ce854a6..8e4ae6db426 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ Apache Commons IO
[](https://github.com/apache/commons-io/actions/workflows/maven.yml)
[](https://search.maven.org/artifact/commons-io/commons-io)
-[](https://javadoc.io/doc/commons-io/commons-io/2.20.0)
+[](https://javadoc.io/doc/commons-io/commons-io/2.22.0)
[](https://github.com/apache/commons-io/actions/workflows/codeql-analysis.yml)
[](https://api.securityscorecards.dev/projects/github.com/apache/commons-io)
@@ -69,7 +69,7 @@ Alternatively, you can pull it from the central Maven repositories:
commons-iocommons-io
- 2.20.0
+ 2.22.0
```
@@ -90,7 +90,7 @@ There are some guidelines which will make applying PRs easier for us:
+ Respect the existing code style for each file.
+ 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.
++ Before you push a PR, run `mvn` (without arguments). 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 -Pjacoco`
If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas).
@@ -112,7 +112,6 @@ Additional Resources
+ [Apache Commons Homepage](https://commons.apache.org/)
+ [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/IO)
+ [Apache Commons Slack Channel](https://the-asf.slack.com/archives/C60NVB8AD)
-+ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
Apache Commons Components
-------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 1f30f8b0f5a..904a8f55302 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -1,5 +1,281 @@
+Apache Commons IO 2.22.0 Release Notes
+--------------------------------------
+
+The Apache Commons IO team is pleased to announce the release of Apache Commons IO 2.22.0.
+
+Introduction
+------------
+
+The Apache Commons IO library contains utility classes, stream implementations, file filters,
+file comparators, endian transformation classes, and much more.
+
+This is a feature and maintenance release. Java 8 or later is required.
+
+New features
+------------
+
+o Add and use IOUtils.closeQuietlySuppress(Closeable, Throwable) #818. Thanks to Gary Gregory, Piotr P. Karwasz.
+o Add ProxyWriter.setReference(Writer). Thanks to Gary Gregory.
+o Add ProxyWriter.unwrap(). Thanks to Gary Gregory.
+o Add ProxyReader.setReference(Reader). Thanks to Gary Gregory.
+o Add ProxyReader.unrwap(). Thanks to Gary Gregory.
+o IO-883: ByteArraySeekableByteChannel should optionally configure a read-only channel. Thanks to Konrad Windszus, Gary Gregory, Makarand Hinge.
+o IO-883: Add ByteArraySeekableByteChannel.Builder and builder(). Thanks to Gary Gregory.
+o IO-883: Add AbstractStreamBuilder.getByteArray(). Thanks to Gary Gregory.
+o CloseShieldInputStream now supports a custom close shield as a function #836. Thanks to Gary Gregory.
+o Add FlushShieldOutputStream to workaround issues in generic code that ends up calling third parties like like org.tukaani.xz.LZMAOutputStream.flush(). Thanks to Gary Gregory.
+o Add filter channels. Thanks to Gary Gregory.
+
+Fixed Bugs
+----------
+
+o Fix Apache RAT plugin console warnings. Thanks to Gary Gregory.
+o ByteArraySeekableByteChannel.position(long) and truncate(long) shouldn't throw an IllegalArgumentException for a new positive position that's too large #817. Thanks to Gary Gregory, Piotr P. Karwasz.
+o Fix malformed Javadoc comments. Thanks to Gary Gregory.
+o ReadAheadInputStream.close() doesn't always close its filtered input stream. Thanks to Stanislav Fort, Gary Gregory.
+o ReadAheadInputStream now restores the current thread's interrupt flag when catching InterruptedException. Thanks to Gary Gregory.
+o FileAlterationMonitor.stop(long) now restores the current thread's interrupt flag when catching InterruptedException. Thanks to Gary Gregory.
+o FileCleaningTracker now restores the current thread's interrupt flag when catching InterruptedException. Thanks to Gary Gregory.
+o ThreadMonitor.run() now restores the current thread's interrupt flag when catching InterruptedException. Thanks to Gary Gregory.
+o ThrottledInputStream.throttle() now restores the current thread's interrupt flag when catching InterruptedException. Thanks to Gary Gregory.
+o ThrottledInputStream.throttle() doesn't preserve the original InterruptedException as the cause of its InterruptedIOException. Thanks to Gary Gregory.
+o All thread names are now prefixed with "commons-io-". Thanks to Gary Gregory.
+o IO-639: ReversedLinesFileReader does not read first line if its empty #829. Thanks to Kishor, Mashrur Mia.
+o IO-886: Fixed incorrect regular expression in PathUtils.RelativeSortedPaths.extractKey(String, String). Thanks to Peter De Maeyer.
+o Fix typos in Javadoc of FileUtils and related test classes #833. Thanks to Martin Wiesner.
+o IO-887: WriterOutputStream from a builder fails on malformed or unmappable input bytes. Thanks to Daniel Vega, Gary Gregory.
+o BoundedReader now extends ProxyReader. Thanks to Gary Gregory.
+o AbstractStreamBuilder.setOpenOptions(OpenOption...) now makes a defensive copy of its input array. Thanks to Gary Gregory.
+o IO-885: Path visits follow links #832. Thanks to Peter De Maeyer, Gary Gregory.
+o BOMInputStream fail-fast and tracks its ByteOrderMark as a final #835. Thanks to Gary Gregory.
+o Refactor UnixLineEndingInputStream and WindowsLineEndingInputStream for duplication. Thanks to Gary Gregory.
+o IO-857: [Javadoc] PathUtils.cleanDirectory() methods vs FileUtils. Thanks to Peter De Maeyer, Gary Gregory.
+o Fix JaCoCo report generation (code coverage). Thanks to Gary Gregory.
+o AbstractStreamBuilder.setBufferSizeDefault(int) now resets to default for input less than or equal to zero. Thanks to Gary Gregory.
+
+Changes
+-------
+
+o Bump org.apache.commons:commons-parent from 91 to 98 #816. Thanks to Gary Gregory, Dependabot.
+o Bump commons-codec:commons-codec from 1.19.0 to 1.21.0 #812. Thanks to Gary Gregory, Dependabot.
+o Bump commons.bytebuddy.version from 1.17.8 to 1.18.8 #814, #820, #838. Thanks to Gary Gregory, Dependabot.
+o Bump commons-lang3 from 3.19.0 to 3.20.0. Thanks to Gary Gregory, Dependabot.
+
+
+Commons IO 2.7 and up requires Java 8 or above.
+Commons IO 2.6 requires Java 7 or above.
+Commons IO 2.3 through 2.5 requires Java 6 or above.
+Commons IO 2.2 requires Java 5 or above.
+Commons IO 1.4 requires Java 1.3 or above.
+
+Historical list of changes: https://commons.apache.org/proper/commons-io/changes.html
+
+For complete information on Apache Commons IO, including instructions on how to submit bug reports,
+patches, or suggestions for improvement, see the Apache Commons IO website:
+
+https://commons.apache.org/proper/commons-io/
+
+Download page: https://commons.apache.org/proper/commons-io/download_io.cgi
+
+Have fun!
+-Apache Commons Team
+
+------------------------------------------------------------------------------
+
+
+Apache Commons IO 2.22.0 Release Notes
+--------------------------------------
+
+The Apache Commons IO team is pleased to announce the release of Apache Commons IO 2.22.0.
+
+Introduction
+------------
+
+The Apache Commons IO library contains utility classes, stream implementations, file filters,
+file comparators, endian transformation classes, and much more.
+
+This is a feature and maintenance release. Java 8 or later is required.
+
+New features
+------------
+
+o Add and use IOUtils.closeQuietlySuppress(Closeable, Throwable) #818. Thanks to Gary Gregory, Piotr P. Karwasz.
+
+Fixed Bugs
+----------
+
+o Fix Apache RAT plugin console warnings. Thanks to Gary Gregory.
+o ByteArraySeekableByteChannel.position(long) and truncate(long) shouldn't throw an IllegalArgumentException for a new positive position that's too large #817. Thanks to Gary Gregory, Piotr P. Karwasz.
+o Fix malformed Javadoc comments. Thanks to Gary Gregory.
+o ReadAheadInputStream.close() doesn't always close its filtered input stream. Thanks to Stanislav Fort, Gary Gregory.
+
+Changes
+-------
+
+o Bump org.apache.commons:commons-parent from 91 to 96 #816. Thanks to Gary Gregory, Dependabot.
+o Bump commons-codec:commons-codec from 1.19.0 to 1.20.0 #812. Thanks to Gary Gregory, Dependabot.
+o Bump commons.bytebuddy.version from 1.17.8 to 1.18.4 #814, #820. Thanks to Gary Gregory, Dependabot.
+o Bump commons-lang3 from 3.19.0 to 3.20.0. Thanks to Gary Gregory, Dependabot.
+
+
+Commons IO 2.7 and up requires Java 8 or above.
+Commons IO 2.6 requires Java 7 or above.
+Commons IO 2.3 through 2.5 requires Java 6 or above.
+Commons IO 2.2 requires Java 5 or above.
+Commons IO 1.4 requires Java 1.3 or above.
+
+Historical list of changes: https://commons.apache.org/proper/commons-io/changes.html
+
+For complete information on Apache Commons IO, including instructions on how to submit bug reports,
+patches, or suggestions for improvement, see the Apache Commons IO website:
+
+https://commons.apache.org/proper/commons-io/
+
+Download page: https://commons.apache.org/proper/commons-io/download_io.cgi
+
+Have fun!
+-Apache Commons Team
+
+------------------------------------------------------------------------------
+
+Apache Commons IO 2.22.0 Release Notes
+--------------------------------------
+
+The Apache Commons IO team is pleased to announce the release of Apache Commons IO 2.22.0.
+
+Introduction
+------------
+
+The Apache Commons IO library contains utility classes, stream implementations, file filters,
+file comparators, endian transformation classes, and much more.
+
+This is a feature and maintenance release. Java 8 or later is required.
+
+New features
+------------
+
+o Add and use IOUtils.closeQuietly(Closeable, Throwable) #818. Thanks to Gary Gregory.
+
+Fixed Bugs
+----------
+
+o Fix Apache RAT plugin console warnings. Thanks to Gary Gregory.
+o ByteArraySeekableByteChannel.position(long) and truncate(long) shouldn't throw an IllegalArgumentException for a new positive position that's too large #817. Thanks to Gary Gregory, Piotr P. Karwasz.
+o Fix malformed Javadoc comments. Thanks to Gary Gregory.
+o ReadAheadInputStream.close() doesn't always close its filtered input stream. Thanks to Stanislav Fort, Gary Gregory.
+
+Changes
+-------
+
+o Bump org.apache.commons:commons-parent from 91 to 95 #816. Thanks to Gary Gregory, Dependabot.
+o Bump commons-codec:commons-codec from 1.19.0 to 1.20.0 #812. Thanks to Gary Gregory, Dependabot.
+o Bump commons.bytebuddy.version from 1.17.8 to 1.18.3 #814, #820. Thanks to Gary Gregory, Dependabot.
+o Bump commons-lang3 from 3.19.0 to 3.20.0. Thanks to Gary Gregory, Dependabot.
+
+
+Commons IO 2.7 and up requires Java 8 or above.
+Commons IO 2.6 requires Java 7 or above.
+Commons IO 2.3 through 2.5 requires Java 6 or above.
+Commons IO 2.2 requires Java 5 or above.
+Commons IO 1.4 requires Java 1.3 or above.
+
+Historical list of changes: https://commons.apache.org/proper/commons-io/changes.html
+
+For complete information on Apache Commons IO, including instructions on how to submit bug reports,
+patches, or suggestions for improvement, see the Apache Commons IO website:
+
+https://commons.apache.org/proper/commons-io/
+
+Download page: https://commons.apache.org/proper/commons-io/download_io.cgi
+
+Have fun!
+-Apache Commons Team
+
+------------------------------------------------------------------------------
+
+
+Apache Commons IO 2.21.0 Release Notes
+--------------------------------------
+
+The Apache Commons IO team is pleased to announce the release of Apache Commons IO 2.21.0.
+
+Introduction
+------------
+
+The Apache Commons IO library contains utility classes, stream implementations, file filters,
+file comparators, endian transformation classes, and much more.
+
+Version 2.21.0: Java 8 or later is required.
+
+New features
+------------
+
+o FileUtils#byteCountToDisplaySize() supports Zettabyte, Yottabyte, Ronnabyte and Quettabyte #763. Thanks to strangelookingnerd, Gary Gregory.
+o Add org.apache.commons.io.FileUtils.ONE_RB #763. Thanks to strangelookingnerd, Gary Gregory.
+o Add org.apache.commons.io.FileUtils.ONE_QB #763. Thanks to strangelookingnerd, Gary Gregory.
+o Add org.apache.commons.io.output.ProxyOutputStream.writeRepeat(byte[], int, int, long). Thanks to Gary Gregory.
+o Add org.apache.commons.io.output.ProxyOutputStream.writeRepeat(byte[], long). Thanks to Gary Gregory.
+o Add org.apache.commons.io.output.ProxyOutputStream.writeRepeat(int, long). Thanks to Gary Gregory.
+o Add length unit support in FileSystem limits. Thanks to Piotr P. Karwasz.
+o Add IOUtils.toByteArray(InputStream, int, int) for safer chunked reading with size validation. Thanks to Piotr P. Karwasz.
+o Add org.apache.commons.io.file.PathUtils.getPath(String, String). Thanks to Gary Gregory.
+o Add org.apache.commons.io.channels.ByteArraySeekableByteChannel. Thanks to Gary Gregory.
+o Add IOIterable.asIterable(). Thanks to Gary Gregory.
+o Add NIO channel support to `AbstractStreamBuilder`. Thanks to Piotr P. Karwasz.
+o Add CloseShieldChannel to close-shielded NIO Channels #786. Thanks to Piotr P. Karwasz.
+o Added IOUtils.checkFromIndexSize as a Java 8 backport of Objects.checkFromIndexSize #790. Thanks to Piotr P. Karwasz.
+
+Fixed Bugs
+----------
+
+o When testing on Java 21 and up, enable -XX:+EnableDynamicAgentLoading. Thanks to Gary Gregory.
+o When testing on Java 24 and up, don't fail FileUtilsListFilesTest for a different behavior in the JRE. Thanks to Gary Gregory.
+o ValidatingObjectInputStream does not validate dynamic proxy interfaces. Thanks to Stanislav Fort, Gary Gregory.
+o BoundedInputStream.getRemaining() now reports Long.MAX_VALUE instead of 0 when no limit is set. Thanks to Piotr P. Karwasz.
+o BoundedInputStream.available() correctly accounts for the maximum read limit. Thanks to Piotr P. Karwasz.
+o Deprecate IOUtils.readFully(InputStream, int) in favor of toByteArray(InputStream, int). Thanks to Gary Gregory, Piotr P. Karwasz.
+o IOUtils.toByteArray(InputStream) now throws IOException on byte array overflow. Thanks to Piotr P. Karwasz.
+o Javadoc general improvements. Thanks to Gary Gregory, Piotr P. Karwasz.
+o IOUtils.toByteArray() now throws EOFException when not enough data is available #796. Thanks to Piotr P. Karwasz.
+o Fix IOUtils.skip() usage in concurrent scenarios. Thanks to Piotr P. Karwasz.
+o [javadoc] Fix XmlStreamReader Javadoc to indicate the correct class that is built #806. Thanks to J Hawkins.
+
+Changes
+-------
+
+o Bump org.apache.commons:commons-parent from 85 to 91 #774, #783, #808. Thanks to Gary Gregory, Dependabot.
+o [test] Bump commons-codec:commons-codec from 1.18.0 to 1.19.0. Thanks to Gary Gregory.
+o [test] Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #769. Thanks to Gary Gregory, Dependabot.
+o [test] Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0. Thanks to Gary Gregory.
+
+Removed
+-------
+
+o Inline private constant field ProxyInputStream.exceptionHandler #780. Thanks to Piotr P. Karwasz.
+Commons IO 2.7 and up requires Java 8 or above.
+Commons IO 2.6 requires Java 7 or above.
+Commons IO 2.3 through 2.5 requires Java 6 or above.
+Commons IO 2.2 requires Java 5 or above.
+Commons IO 1.4 requires Java 1.3 or above.
+
+Historical list of changes: https://commons.apache.org/proper/commons-io/changes.html
+
+For complete information on Apache Commons IO, including instructions on how to submit bug reports,
+patches, or suggestions for improvement, see the Apache Commons IO website:
+
+https://commons.apache.org/proper/commons-io/
+
+Download page: https://commons.apache.org/proper/commons-io/download_io.cgi
+
+Have fun!
+-Apache Commons Team
+
+------------------------------------------------------------------------------
+
+
Apache Commons IO 2.20.0 Release Notes
+--------------------------------------
The Apache Commons IO team is pleased to announce the release of Apache Commons IO 2.20.0.
@@ -78,6 +354,7 @@ Have fun!
Apache Commons IO 2.19.0 Release Notes
+--------------------------------------
Introduction
------------
@@ -173,6 +450,7 @@ Have fun!
Apache Commons IO 2.18.0 Release Notes
+--------------------------------------
Introduction
------------
@@ -251,6 +529,7 @@ Apache Commons Team
Apache Commons IO 2.17.0 Release Notes
+--------------------------------------
Introduction
------------
@@ -341,6 +620,7 @@ Have fun!
Apache Commons IO 2.16.1 Release Notes
+--------------------------------------
Introduction
------------
@@ -393,6 +673,7 @@ Have fun!
Apache Commons IO 2.16.1 Release Notes
+--------------------------------------
Introduction
------------
@@ -444,6 +725,7 @@ Have fun!
Apache Commons IO 2.16.0 Release Notes
+--------------------------------------
Introduction
------------
diff --git a/pom.xml b/pom.xml
index c356baf502a..727b999d69d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,12 +19,12 @@
org.apache.commonscommons-parent
- 88
+ 1024.0.0commons-iocommons-io
- 2.21.0-SNAPSHOT
+ 2.23.0-SNAPSHOTApache Commons IO2002
@@ -32,10 +32,6 @@ The Apache Commons IO library contains utility classes, stream implementations,
file comparators, endian transformation classes, and much more.
https://commons.apache.org/proper/commons-io/
-
- jira
- https://issues.apache.org/jira/browse/IO
- apache.website
@@ -43,16 +39,6 @@ file comparators, endian transformation classes, and much more.
scm:svn:https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-io/
-
- scm:git:https://gitbox.apache.org/repos/asf/commons-io.git
- scm:git:https://gitbox.apache.org/repos/asf/commons-io.git
- https://gitbox.apache.org/repos/asf?p=commons-io.git
- rel/commons-io-2.21.0
-
-
- GitHub
- https://github.com/apache/commons-io/actions
- org.junit.jupiter
@@ -93,13 +79,13 @@ file comparators, endian transformation classes, and much more.
org.apache.commonscommons-lang3
- 3.19.0
+ 3.20.0testcommons-codeccommons-codec
- 1.19.0
+ 1.22.0test
@@ -115,11 +101,11 @@ file comparators, endian transformation classes, and much more.
ioorg.apache.commons.ioRC1
- 2.20.0
- 2.21.0
- 2.21.1
+ 2.22.0
+ 2.23.0
+ 2.23.1
- 2025-07-18T21:12:04Z
+ 2026-04-23T10:25:32Z(requires Java 8)IO12310477
@@ -146,11 +132,10 @@ file comparators, endian transformation classes, and much more.
https://svn.apache.org/repos/infra/websites/production/commons/content/proper/commons-io/site-content
- 1.17.7
+ 1.18.8falsetrue
- ${env.JACOCO_SKIP}true0.980.90
@@ -170,11 +155,11 @@ file comparators, endian transformation classes, and much more.
org.apache.ratapache-rat-plugin
-
- src/test/resources/**/*.bin
- src/test/resources/dir-equals-tests/**
- test/**
-
+
+ src/test/resources/**/*.bin
+ src/test/resources/dir-equals-tests/**
+ test/**
+
@@ -219,7 +204,7 @@ file comparators, endian transformation classes, and much more.
false
- ${argLine} -Xmx25M ${EnableDynamicAgentLoading}
+ @{argLine} -Xmx25M ${EnableDynamicAgentLoading}**/*Test*.class
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index fb68216e20a..1b3449f0765 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -45,7 +45,77 @@ The type attribute can be add,update,fix,remove.
Apache Commons IO Release Notes
-
+
+
+ ThresholdingOutputStream.isThresholdExceeded() now reflects the threshold-reached state, and a failed thresholdReached() no longer leaves the stream unable to fire the event again.
+ Clean BufferedFileChannelInputStream's direct ByteBuffer only once #854.
+ BufferedFileChannelInputStream now clears its direct memory byte buffer on close (#855).
+ MemoryMappedFileInputStream now clears its direct memory byte buffer on close (#855).
+ FileChannels.contentEquals(ReadableByteChannel, ReadableByteChannel, int) now clears its direct memory byte buffer on close (#855).
+ BufferedFileChannelInputStream now clears its direct memory byte buffer on close (#855).
+ MemoryMappedFileInputStream now clears its direct memory byte buffer on close (#855).
+ Clarify PeekableInputStream.peek() behavior in Javadoc (#856).
+ DeferredFileOutputStream now clears and deletes its temporary storage by default (#858).
+ Update generic type of RandomAccessFileMode.accept(Path, IOConsumer) from IOConsumer<RandomAccessFile> to IOConsumer<IORandomAccessFile>.
+ Harden tests for NPEs on failures, happy path unchanged.
+ Fix BoundedReader.skip(long) accounting and bounds handling (#860).
+ DeferredFileOutputStream better NPE message and new file permission tests (#862).
+
+ Add IOConsumer.accept(IOConsumer, T) (#846).
+ Add UnsynchronizedBufferedReader.unwrap() (#850).
+ Add UnsynchronizedBufferedReader.getPosition() (#851).
+ Add Buffers clear() methods (#853).
+ Add DeferredFileOutputStream.Builder.setDeleteTempFileOnClose(boolean) (#858).
+ Add PathUtils.clear[IfExists](Path) (#858).
+ Add PathUtils.deleteIfExists(Path) (#858).
+
+ Bump org.apache.commons:commons-parent from 98 to 102 (#849).
+ [test] Bump commons-codec:commons-codec from 1.21.0 to 1.22.0.
+
+
+
+ Fix Apache RAT plugin console warnings.
+ ByteArraySeekableByteChannel.position(long) and truncate(long) shouldn't throw an IllegalArgumentException for a new positive position that's too large #817.
+ Fix malformed Javadoc comments.
+ ReadAheadInputStream.close() doesn't always close its filtered input stream.
+ ReadAheadInputStream now restores the current thread's interrupt flag when catching InterruptedException.
+ FileAlterationMonitor.stop(long) now restores the current thread's interrupt flag when catching InterruptedException.
+ FileCleaningTracker now restores the current thread's interrupt flag when catching InterruptedException.
+ ThreadMonitor.run() now restores the current thread's interrupt flag when catching InterruptedException.
+ ThrottledInputStream.throttle() now restores the current thread's interrupt flag when catching InterruptedException.
+ ThrottledInputStream.throttle() doesn't preserve the original InterruptedException as the cause of its InterruptedIOException.
+ All thread names are now prefixed with "commons-io-".
+ ReversedLinesFileReader does not read first line if its empty #829.
+ Fixed incorrect regular expression in PathUtils.RelativeSortedPaths.extractKey(String, String).
+ Fix typos in Javadoc of FileUtils and related test classes #833.
+ WriterOutputStream from a builder fails on malformed or unmappable input bytes.
+ BoundedReader now extends ProxyReader.
+ AbstractStreamBuilder.setOpenOptions(OpenOption...) now makes a defensive copy of its input array.
+ Path visits follow links #832.
+ BOMInputStream fail-fast and tracks its ByteOrderMark as a final #835.
+ Refactor UnixLineEndingInputStream and WindowsLineEndingInputStream for duplication.
+ [Javadoc] PathUtils.cleanDirectory() methods vs FileUtils.
+ Fix JaCoCo report generation (code coverage).
+ AbstractStreamBuilder.setBufferSizeDefault(int) now resets to default for input less than or equal to zero.
+
+ Add and use IOUtils.closeQuietlySuppress(Closeable, Throwable) #818.
+ Add ProxyWriter.setReference(Writer).
+ Add ProxyWriter.unwrap().
+ Add ProxyReader.setReference(Reader).
+ Add ProxyReader.unrwap().
+ ByteArraySeekableByteChannel should optionally configure a read-only channel.
+ Add ByteArraySeekableByteChannel.Builder and builder().
+ Add AbstractStreamBuilder.getByteArray().
+ CloseShieldInputStream now supports a custom close shield as a function #836.
+ Add FlushShieldOutputStream to workaround issues in generic code that ends up calling third parties like like org.tukaani.xz.LZMAOutputStream.flush().
+ Add filter channels.
+
+ Bump org.apache.commons:commons-parent from 91 to 98 #816.
+ Bump commons-codec:commons-codec from 1.19.0 to 1.21.0 #812.
+ Bump commons.bytebuddy.version from 1.17.8 to 1.18.8 #814, #820, #838.
+ Bump commons-lang3 from 3.19.0 to 3.20.0.
+
+ When testing on Java 21 and up, enable -XX:+EnableDynamicAgentLoading.When testing on Java 24 and up, don't fail FileUtilsListFilesTest for a different behavior in the JRE.
@@ -55,6 +125,9 @@ The type attribute can be add,update,fix,remove.
Deprecate IOUtils.readFully(InputStream, int) in favor of toByteArray(InputStream, int).IOUtils.toByteArray(InputStream) now throws IOException on byte array overflow.Javadoc general improvements.
+ IOUtils.toByteArray() now throws EOFException when not enough data is available #796.
+ Fix IOUtils.skip() usage in concurrent scenarios.
+ [javadoc] Fix XmlStreamReader Javadoc to indicate the correct class that is built #806.FileUtils#byteCountToDisplaySize() supports Zettabyte, Yottabyte, Ronnabyte and Quettabyte #763.Add org.apache.commons.io.FileUtils.ONE_RB #763.
@@ -71,9 +144,9 @@ The type attribute can be add,update,fix,remove.
Add CloseShieldChannel to close-shielded NIO Channels #786.Added IOUtils.checkFromIndexSize as a Java 8 backport of Objects.checkFromIndexSize #790.
- Bump org.apache.commons:commons-parent from 85 to 88 #774, #783.
+ Bump org.apache.commons:commons-parent from 85 to 91 #774, #783, #808.[test] Bump commons-codec:commons-codec from 1.18.0 to 1.19.0.
- [test] Bump commons.bytebuddy.version from 1.17.6 to 1.17.7 #769.
+ [test] Bump commons.bytebuddy.version from 1.17.6 to 1.17.8 #769.[test] Bump org.apache.commons:commons-lang3 from 3.18.0 to 3.19.0.Inline private constant field ProxyInputStream.exceptionHandler #780.
@@ -1340,7 +1413,7 @@ The type attribute can be add,update,fix,remove.
Fixed error of copying directories between different file systems #203.
- Fix Typos in JavaDoc, Comments and Tests #201.
+ Fix Typos in Javadoc, Comments and Tests #201.
FileUtils.checksumCRC32 and FileUtils.checksum are not thread safe.
diff --git a/src/changes/release-notes.vm b/src/changes/release-notes.vm
index c28de3c8729..aa5a3663420 100644
--- a/src/changes/release-notes.vm
+++ b/src/changes/release-notes.vm
@@ -16,6 +16,7 @@
## under the License.
Apache Commons IO ${version} Release Notes
+--------------------------------------
The ${developmentTeam} is pleased to announce the release of ${project.name} ${version}.
diff --git a/src/conf/maven-pmd-plugin.xml b/src/conf/maven-pmd-plugin.xml
index 215ac295ede..9d51e182ff9 100644
--- a/src/conf/maven-pmd-plugin.xml
+++ b/src/conf/maven-pmd-plugin.xml
@@ -78,7 +78,6 @@ under the License.
-
diff --git a/src/main/java/org/apache/commons/io/Buffers.java b/src/main/java/org/apache/commons/io/Buffers.java
new file mode 100644
index 00000000000..cd4e2a2b179
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/Buffers.java
@@ -0,0 +1,299 @@
+/*
+ * 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.io;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.LongBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.ShortBuffer;
+import java.util.Arrays;
+
+/**
+ * Helps use {@link Buffer} instances.
+ *
+ * @since 2.23.0
+ */
+public final class Buffers {
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer, or null.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ * @throws UnsupportedOperationException Thrown if the given buffer is not one of {@link CharBuffer}, {@link ByteBuffer}, {@link DoubleBuffer},
+ * {@link FloatBuffer}, {@link IntBuffer}, {@link LongBuffer}, {@link ShortBuffer}, or null.
+ */
+ public static Buffer clear(final Buffer buffer) {
+ if (buffer instanceof CharBuffer) {
+ return clear((CharBuffer) buffer);
+ }
+ if (buffer instanceof ByteBuffer) {
+ return clear((ByteBuffer) buffer);
+ }
+ if (buffer instanceof DoubleBuffer) {
+ return clear((DoubleBuffer) buffer);
+ }
+ if (buffer instanceof FloatBuffer) {
+ return clear((FloatBuffer) buffer);
+ }
+ if (buffer instanceof IntBuffer) {
+ return clear((IntBuffer) buffer);
+ }
+ if (buffer instanceof LongBuffer) {
+ return clear((LongBuffer) buffer);
+ }
+ if (buffer instanceof ShortBuffer) {
+ return clear((ShortBuffer) buffer);
+ }
+ if (buffer == null) {
+ return null;
+ }
+ throw new UnsupportedOperationException(buffer.getClass().getCanonicalName());
+ }
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ */
+ public static ByteBuffer clear(final ByteBuffer buffer) {
+ if (buffer == null) {
+ return null;
+ }
+ if (clearBuffer(buffer).hasArray()) {
+ Arrays.fill(buffer.array(), (byte) 0);
+ } else {
+ final byte[] zeros = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
+ while (buffer.hasRemaining()) {
+ buffer.put(zeros, 0, Math.min(buffer.remaining(), zeros.length));
+ }
+ }
+ return clearBuffer(buffer);
+ }
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ */
+ public static CharBuffer clear(final CharBuffer buffer) {
+ if (buffer == null) {
+ return null;
+ }
+ if (clearBuffer(buffer).hasArray()) {
+ Arrays.fill(buffer.array(), (char) 0);
+ } else {
+ final char[] zeros = new char[IOUtils.DEFAULT_BUFFER_SIZE];
+ while (buffer.hasRemaining()) {
+ buffer.put(zeros, 0, Math.min(buffer.remaining(), zeros.length));
+ }
+ }
+ return clearBuffer(buffer);
+ }
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ */
+ public static DoubleBuffer clear(final DoubleBuffer buffer) {
+ if (buffer == null) {
+ return null;
+ }
+ if (clearBuffer(buffer).hasArray()) {
+ Arrays.fill(buffer.array(), 0);
+ } else {
+ final double[] zeros = new double[IOUtils.DEFAULT_BUFFER_SIZE];
+ while (buffer.hasRemaining()) {
+ buffer.put(zeros, 0, Math.min(buffer.remaining(), zeros.length));
+ }
+ }
+ return clearBuffer(buffer);
+ }
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ */
+ public static FloatBuffer clear(final FloatBuffer buffer) {
+ if (buffer == null) {
+ return null;
+ }
+ if (clearBuffer(buffer).hasArray()) {
+ Arrays.fill(buffer.array(), 0);
+ } else {
+ final float[] zeros = new float[IOUtils.DEFAULT_BUFFER_SIZE];
+ while (buffer.hasRemaining()) {
+ buffer.put(zeros, 0, Math.min(buffer.remaining(), zeros.length));
+ }
+ }
+ return clearBuffer(buffer);
+ }
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ */
+ public static IntBuffer clear(final IntBuffer buffer) {
+ if (buffer == null) {
+ return null;
+ }
+ if (clearBuffer(buffer).hasArray()) {
+ Arrays.fill(buffer.array(), 0);
+ } else {
+ final int[] zeros = new int[IOUtils.DEFAULT_BUFFER_SIZE];
+ while (buffer.hasRemaining()) {
+ buffer.put(zeros, 0, Math.min(buffer.remaining(), zeros.length));
+ }
+ }
+ return clearBuffer(buffer);
+ }
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ */
+ public static LongBuffer clear(final LongBuffer buffer) {
+ if (buffer == null) {
+ return null;
+ }
+ if (clearBuffer(buffer).hasArray()) {
+ Arrays.fill(buffer.array(), 0);
+ } else {
+ final long[] zeros = new long[IOUtils.DEFAULT_BUFFER_SIZE];
+ while (buffer.hasRemaining()) {
+ buffer.put(zeros, 0, Math.min(buffer.remaining(), zeros.length));
+ }
+ }
+ return clearBuffer(buffer);
+ }
+
+ /**
+ * Clears this buffer by filling it with zeros, the position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ * @throws ReadOnlyBufferException If the buffer is read-only.
+ */
+ public static ShortBuffer clear(final ShortBuffer buffer) {
+ if (buffer == null) {
+ return null;
+ }
+ if (clearBuffer(buffer).hasArray()) {
+ Arrays.fill(buffer.array(), (short) 0);
+ } else {
+ final short[] zeros = new short[IOUtils.DEFAULT_BUFFER_SIZE];
+ while (buffer.hasRemaining()) {
+ buffer.put(zeros, 0, Math.min(buffer.remaining(), zeros.length));
+ }
+ }
+ return clearBuffer(buffer);
+ }
+
+ /**
+ * A better typed version of {@link Buffer#clear()}.
+ *
+ * Clears this buffer. The position is set to zero, the limit is set to the capacity, and the mark is discarded.
+ *
+ *
+ * Invoke this method before using a sequence of channel-read or put operations to fill this buffer. For example:
+ *
+ *
+ *
+ * buf.clear(); // Prepare buffer for reading
+ * in.read(buf); // Read data
+ *
+ *
+ *
+ * This method does not actually erase the data in the buffer, but it is named as if it did because it will most often be used in situations in which that
+ * might as well be the case.
+ *
+ *
+ * @param A Buffer subclass.
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ */
+ private static B clearBuffer(final B buffer) {
+ buffer.clear();
+ return buffer;
+ }
+
+ /**
+ * Clears the given direct buffer by filling it with zeros and resetting the position to zero. The limit is set to the capacity of the buffer.
+ *
+ * If the given buffer is a not direct buffer, nothing happens to that buffer.
+ *
+ *
+ * @param A Buffer subclass.
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ */
+ public static B clearDirect(final B buffer) {
+ if (buffer != null && buffer.isDirect()) {
+ clear(buffer);
+ }
+ return buffer;
+ }
+
+ /**
+ * Clears the given writable buffer by filling it with zeros and resetting the position to zero. The limit is set to the capacity of the buffer.
+ *
+ * If the buffer is read-only, then nothing happens to that buffer.
+ *
+ *
+ * @param A Buffer subclass.
+ * @param buffer The buffer to clear, may be null.
+ * @return The given buffer.
+ */
+ public static B clearWritable(final B buffer) {
+ if (buffer != null && !buffer.isReadOnly()) {
+ clear(buffer);
+ }
+ return buffer;
+ }
+
+ /**
+ * No instances.
+ */
+ private Buffers() {
+ // empty.
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/ByteBuffers.java b/src/main/java/org/apache/commons/io/ByteBuffers.java
index 91efd8ed3e2..d5126f01534 100644
--- a/src/main/java/org/apache/commons/io/ByteBuffers.java
+++ b/src/main/java/org/apache/commons/io/ByteBuffers.java
@@ -68,8 +68,11 @@ public static ByteBuffer littleEndian(final int capacity) {
return littleEndian(ByteBuffer.allocate(capacity));
}
+ /**
+ * No instances.
+ */
private ByteBuffers() {
- // empty, no instance.
+ // empty.
}
}
diff --git a/src/main/java/org/apache/commons/io/ByteOrderMark.java b/src/main/java/org/apache/commons/io/ByteOrderMark.java
index 0067f7d2d6f..b9209cb316f 100644
--- a/src/main/java/org/apache/commons/io/ByteOrderMark.java
+++ b/src/main/java/org/apache/commons/io/ByteOrderMark.java
@@ -40,7 +40,7 @@
*
* @see org.apache.commons.io.input.BOMInputStream
* @see Wikipedia: Byte Order Mark
- * @see W3C: Autodetection of Character Encodings
+ * @see W3C: Autodetection of Character Encodings
* (Non-Normative)
* @since 2.0
*/
@@ -128,10 +128,10 @@ public class ByteOrderMark implements Serializable {
/**
* Constructs a new instance.
*
- * @param charsetName The name of the charset the BOM represents
- * @param bytes The BOM's bytes
- * @throws IllegalArgumentException if the charsetName is zero length
- * @throws IllegalArgumentException if the bytes are zero length
+ * @param charsetName The name of the charset the BOM represents.
+ * @param bytes The BOM's bytes.
+ * @throws IllegalArgumentException if the charsetName is zero length.
+ * @throws IllegalArgumentException if the bytes are zero length.
*/
public ByteOrderMark(final String charsetName, final int... bytes) {
Objects.requireNonNull(charsetName, "charsetName");
@@ -149,9 +149,9 @@ public ByteOrderMark(final String charsetName, final int... bytes) {
/**
* Indicates if this instance's bytes equals another.
*
- * @param obj The object to compare to
+ * @param obj The object to compare to.
* @return true if the bom's bytes are equal, otherwise
- * false
+ * false.
*/
@Override
public boolean equals(final Object obj) {
@@ -173,8 +173,8 @@ public boolean equals(final Object obj) {
/**
* Gets the byte at the specified position.
*
- * @param pos The position
- * @return The specified byte
+ * @param pos The position.
+ * @return The specified byte.
*/
public int get(final int pos) {
return bytes[pos];
@@ -183,7 +183,7 @@ public int get(final int pos) {
/**
* Gets a copy of the BOM's bytes.
*
- * @return a copy of the BOM's bytes
+ * @return a copy of the BOM's bytes.
*/
public byte[] getBytes() {
final byte[] copy = IOUtils.byteArray(bytes.length);
@@ -196,7 +196,7 @@ public byte[] getBytes() {
/**
* Gets the name of the {@link java.nio.charset.Charset} the BOM represents.
*
- * @return the character set name
+ * @return the character set name.
*/
public String getCharsetName() {
return charsetName;
@@ -224,7 +224,7 @@ public int hashCode() {
/**
* Gets the length of the BOM's bytes.
*
- * @return the length of the BOM's bytes
+ * @return the length of the BOM's bytes.
*/
public int length() {
return bytes.length;
@@ -260,7 +260,7 @@ public boolean matches(final int[] test) {
/**
* Converts this instance to a String representation of the BOM.
*
- * @return the length of the BOM's bytes
+ * @return the length of the BOM's bytes.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/ByteOrderParser.java b/src/main/java/org/apache/commons/io/ByteOrderParser.java
index 33a263e4966..6684c04c23f 100644
--- a/src/main/java/org/apache/commons/io/ByteOrderParser.java
+++ b/src/main/java/org/apache/commons/io/ByteOrderParser.java
@@ -41,8 +41,8 @@ public final class ByteOrderParser {
*
*
* @param value
- * the {@link String} containing the ByteOrder representation to be parsed
- * @return the ByteOrder represented by the string argument
+ * the {@link String} containing the ByteOrder representation to be parsed.
+ * @return the ByteOrder represented by the string argument.
* @throws IllegalArgumentException
* if the {@link String} containing the ByteOrder representation to be parsed is unknown.
*/
diff --git a/src/main/java/org/apache/commons/io/Charsets.java b/src/main/java/org/apache/commons/io/Charsets.java
index ef6a6264f77..0c5fa748a73 100644
--- a/src/main/java/org/apache/commons/io/Charsets.java
+++ b/src/main/java/org/apache/commons/io/Charsets.java
@@ -34,21 +34,38 @@
* documentation for your implementation to see if any other encodings are supported.
*
*
- *
- *
{@code US-ASCII}
- * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.
- *
{@code ISO-8859-1}
- * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
{@code UTF-16}
- * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order
- * accepted on input, big-endian used on output.)
- *
+ *
+ *
Standard Charsets
+ *
+ *
Charset
+ *
Description
+ *
+ *
+ *
{@code US-ASCII}
+ *
Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.
+ *
+ *
+ *
{@code ISO-8859-1}
+ *
ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.
+ *
+ *
+ *
{@code UTF-8}
+ *
Eight-bit Unicode Transformation Format.
+ *
+ *
+ *
{@code UTF-16BE}
+ *
Sixteen-bit Unicode Transformation Format, big-endian byte order.
+ *
+ *
+ *
{@code UTF-16LE}
+ *
Sixteen-bit Unicode Transformation Format, little-endian byte order.
+ *
+ *
+ *
{@code UTF-16}
+ *
Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order
+ * accepted on input, big-endian used on output.)
+ *
+ *
*
* @see Standard charsets
* @since 2.3
@@ -80,7 +97,7 @@ public class Charsets {
*
*
* @see Standard charsets
- * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ * @deprecated Use {@link java.nio.charset.StandardCharsets#ISO_8859_1}.
*/
@Deprecated
public static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
@@ -94,7 +111,7 @@ public class Charsets {
*
*
* @see Standard charsets
- * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ * @deprecated Use {@link java.nio.charset.StandardCharsets#US_ASCII}.
*/
@Deprecated
public static final Charset US_ASCII = StandardCharsets.US_ASCII;
@@ -109,7 +126,7 @@ public class Charsets {
*
*
* @see Standard charsets
- * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_16}.
*/
@Deprecated
public static final Charset UTF_16 = StandardCharsets.UTF_16;
@@ -123,7 +140,7 @@ public class Charsets {
*
*
* @see Standard charsets
- * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_16BE}.
*/
@Deprecated
public static final Charset UTF_16BE = StandardCharsets.UTF_16BE;
@@ -137,7 +154,7 @@ public class Charsets {
*
*
* @see Standard charsets
- * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_16LE}.
*/
@Deprecated
public static final Charset UTF_16LE = StandardCharsets.UTF_16LE;
@@ -151,7 +168,7 @@ public class Charsets {
*
*
* @see Standard charsets
- * @deprecated Use Java 7's {@link java.nio.charset.StandardCharsets}
+ * @deprecated Use {@link java.nio.charset.StandardCharsets#UTF_8}.
*/
@Deprecated
public static final Charset UTF_8 = StandardCharsets.UTF_8;
@@ -210,7 +227,7 @@ public static SortedMap requiredCharsets() {
*
* @param charset
* A charset or null.
- * @return the given Charset or the default Charset if the given Charset is null
+ * @return the given Charset or the default Charset if the given Charset is null.
* @see Charset#defaultCharset()
*/
public static Charset toCharset(final Charset charset) {
@@ -277,7 +294,7 @@ public static Charset toCharsetDefault(final String charsetName, final Charset d
/**
* Construct a new instance.
*
- * @deprecated Will be private in 4.0
+ * @deprecated Will be private in 3.0.
*/
@Deprecated
public Charsets() {
diff --git a/src/main/java/org/apache/commons/io/CopyUtils.java b/src/main/java/org/apache/commons/io/CopyUtils.java
index ad426952e4e..ed816826305 100644
--- a/src/main/java/org/apache/commons/io/CopyUtils.java
+++ b/src/main/java/org/apache/commons/io/CopyUtils.java
@@ -29,6 +29,8 @@
import java.io.Writer;
import java.nio.charset.Charset;
+import org.apache.commons.io.IOUtils.ScratchChars;
+
/**
* This class provides static utility methods for buffered
* copying between sources ({@link InputStream}, {@link Reader},
@@ -44,7 +46,7 @@
* released when the associated Stream is garbage-collected. It is not a good
* idea to rely on this mechanism. For a good overview of the distinction
* between "memory management" and "resource management", see
- * this
+ * this
* UnixReview article.
*
* For byte-to-char methods, a {@code copy} variant allows the encoding
@@ -115,9 +117,10 @@ public class CopyUtils {
/**
* Copies bytes from a {@code byte[]} to an {@link OutputStream}.
- * @param input the byte array to read from
- * @param output the {@link OutputStream} to write to
- * @throws IOException In case of an I/O problem
+ *
+ * @param input the byte array to read from.
+ * @param output the {@link OutputStream} to write to.
+ * @throws IOException In case of an I/O problem.
*/
public static void copy(final byte[] input, final OutputStream output) throws IOException {
output.write(input);
@@ -128,10 +131,10 @@ public static void copy(final byte[] input, final OutputStream output) throws IO
* {@link Writer}.
* The platform's default encoding is used for the byte-to-char conversion.
*
- * @param input the byte array to read from
- * @param output the {@link Writer} to write to
- * @throws IOException In case of an I/O problem
- * @deprecated Use {@link #copy(byte[], Writer, String)} instead
+ * @param input the byte array to read from.
+ * @param output the {@link Writer} to write to.
+ * @throws IOException In case of an I/O problem.
+ * @deprecated Use {@link #copy(byte[], Writer, String)} instead.
*/
@Deprecated
public static void copy(final byte[] input, final Writer output) throws IOException {
@@ -143,12 +146,12 @@ public static void copy(final byte[] input, final Writer output) throws IOExcept
* Copies and convert bytes from a {@code byte[]} to chars on a
* {@link Writer}, using the specified encoding.
*
- * @param input the byte array to read from
- * @param output the {@link Writer} to write to
+ * @param input the byte array to read from.
+ * @param output the {@link Writer} to write to.
* @param encoding The name of a supported character encoding. See the
- * IANA
+ * IANA
* Charset Registry for a list of valid encoding types.
- * @throws IOException In case of an I/O problem
+ * @throws IOException In case of an I/O problem.
*/
public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException {
final ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
@@ -159,10 +162,10 @@ public static void copy(final byte[] input, final Writer output, final String en
* Copies bytes from an {@link InputStream} to an
* {@link OutputStream}.
*
- * @param input the {@link InputStream} to read from
- * @param output the {@link OutputStream} to write to
- * @return the number of bytes copied
- * @throws IOException In case of an I/O problem
+ * @param input the {@link InputStream} to read from.
+ * @param output the {@link OutputStream} to write to.
+ * @return the number of bytes copied.
+ * @throws IOException In case of an I/O problem.
*/
public static int copy(final InputStream input, final OutputStream output) throws IOException {
final byte[] buffer = IOUtils.byteArray();
@@ -179,13 +182,13 @@ public static int copy(final InputStream input, final OutputStream output) throw
* Copies and convert bytes from an {@link InputStream} to chars on a
* {@link Writer}.
*
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion.
+ * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion.
*
*
- * @param input the {@link InputStream} to read from
- * @param output the {@link Writer} to write to
- * @throws IOException In case of an I/O problem
- * @deprecated Use {@link #copy(InputStream, Writer, String)} instead
+ * @param input the {@link InputStream} to read from.
+ * @param output the {@link Writer} to write to.
+ * @throws IOException In case of an I/O problem.
+ * @deprecated Use {@link #copy(InputStream, Writer, String)} instead.
*/
@Deprecated
public static void copy(
@@ -201,12 +204,12 @@ public static void copy(
* Copies and convert bytes from an {@link InputStream} to chars on a
* {@link Writer}, using the specified encoding.
*
- * @param input the {@link InputStream} to read from
- * @param output the {@link Writer} to write to
+ * @param input the {@link InputStream} to read from.
+ * @param output the {@link Writer} to write to.
* @param encoding The name of a supported character encoding. See the
- * IANA
+ * IANA
* Charset Registry for a list of valid encoding types.
- * @throws IOException In case of an I/O problem
+ * @throws IOException In case of an I/O problem.
*/
public static void copy(
final InputStream input,
@@ -221,13 +224,13 @@ public static void copy(
* Serialize chars from a {@link Reader} to bytes on an
* {@link OutputStream}, and flush the {@link OutputStream}.
*
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion.
+ * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion.
*
*
- * @param input the {@link Reader} to read from
- * @param output the {@link OutputStream} to write to
- * @throws IOException In case of an I/O problem
- * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead
+ * @param input the {@link Reader} to read from.
+ * @param output the {@link OutputStream} to write to.
+ * @throws IOException In case of an I/O problem.
+ * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead.
*/
@Deprecated
public static void copy(
@@ -246,12 +249,12 @@ public static void copy(
* Serialize chars from a {@link Reader} to bytes on an
* {@link OutputStream}, and flush the {@link OutputStream}.
*
- * @param input the {@link Reader} to read from
- * @param output the {@link OutputStream} to write to
+ * @param input the {@link Reader} to read from.
+ * @param output the {@link OutputStream} to write to.
* @param encoding The name of a supported character encoding. See the
- * IANA
+ * IANA
* Charset Registry for a list of valid encoding types.
- * @throws IOException In case of an I/O problem
+ * @throws IOException In case of an I/O problem.
* @since 2.5
*/
public static void copy(
@@ -269,23 +272,25 @@ public static void copy(
/**
* Copies chars from a {@link Reader} to a {@link Writer}.
*
- * @param input the {@link Reader} to read from
- * @param output the {@link Writer} to write to
- * @return the number of characters copied
- * @throws IOException In case of an I/O problem
+ * @param input the {@link Reader} to read from.
+ * @param output the {@link Writer} to write to.
+ * @return the number of characters copied.
+ * @throws IOException In case of an I/O problem.
*/
public static int copy(
final Reader input,
final Writer output)
throws IOException {
- final char[] buffer = IOUtils.getScratchCharArray();
- int count = 0;
- int n;
- while (EOF != (n = input.read(buffer))) {
- output.write(buffer, 0, n);
- count += n;
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ final char[] buffer = scratch.array();
+ int count = 0;
+ int n;
+ while (EOF != (n = input.read(buffer))) {
+ output.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
}
- return count;
}
/**
@@ -293,13 +298,13 @@ public static int copy(
* {@link OutputStream}, and
* flush the {@link OutputStream}.
*
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion.
+ * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion.
*
*
- * @param input the {@link String} to read from
- * @param output the {@link OutputStream} to write to
- * @throws IOException In case of an I/O problem
- * @deprecated Use {@link #copy(String, OutputStream, String)} instead
+ * @param input the {@link String} to read from.
+ * @param output the {@link OutputStream} to write to.
+ * @throws IOException In case of an I/O problem.
+ * @deprecated Use {@link #copy(String, OutputStream, String)} instead.
*/
@Deprecated
public static void copy(
@@ -320,12 +325,12 @@ public static void copy(
* {@link OutputStream}, and
* flush the {@link OutputStream}.
*
- * @param input the {@link String} to read from
- * @param output the {@link OutputStream} to write to
+ * @param input the {@link String} to read from.
+ * @param output the {@link OutputStream} to write to.
* @param encoding The name of a supported character encoding. See the
- * IANA
+ * IANA
* Charset Registry for a list of valid encoding types.
- * @throws IOException In case of an I/O problem
+ * @throws IOException In case of an I/O problem.
* @since 2.5
*/
public static void copy(
@@ -344,9 +349,9 @@ public static void copy(
/**
* Copies chars from a {@link String} to a {@link Writer}.
*
- * @param input the {@link String} to read from
- * @param output the {@link Writer} to write to
- * @throws IOException In case of an I/O problem
+ * @param input the {@link String} to read from.
+ * @param output the {@link Writer} to write to.
+ * @throws IOException In case of an I/O problem.
*/
public static void copy(final String input, final Writer output)
throws IOException {
diff --git a/src/main/java/org/apache/commons/io/DirectoryWalker.java b/src/main/java/org/apache/commons/io/DirectoryWalker.java
index ac3d8bd5fd7..1d2a7678fd4 100644
--- a/src/main/java/org/apache/commons/io/DirectoryWalker.java
+++ b/src/main/java/org/apache/commons/io/DirectoryWalker.java
@@ -167,7 +167,7 @@
*
*
The decision logic on whether to cancel processing or not.
*
Constructing and throwing a {@link CancelException}.
- *
Custom cancel processing in the {@code handleCancelled()} method.
+ *
Custom cancel processing in the {@code handleCancelled()} method.
*
*
* Two possible scenarios are envisaged for cancellation:
@@ -196,14 +196,14 @@
*
* public class FooDirectoryWalker extends DirectoryWalker {
*
- * private volatile boolean cancelled = false;
+ * private volatile boolean canceled = false;
*
* public void cancel() {
- * cancelled = true;
+ * canceled = true;
* }
*
* protected boolean handleIsCancelled(File file, int depth, Collection results) {
- * return cancelled;
+ * return canceled;
* }
*
* protected void handleCancelled(File startDirectory, Collection results, CancelException cancel) {
@@ -265,6 +265,7 @@ public static class CancelException extends IOException {
/** The file being processed when the exception was thrown. */
private final File file;
+
/** The file depth when the exception was thrown. */
private final int depth;
@@ -272,8 +273,8 @@ public static class CancelException extends IOException {
* Constructs a {@link CancelException} with
* the file and depth when cancellation occurred.
*
- * @param file the file when the operation was cancelled, may be null
- * @param depth the depth when the operation was cancelled, may be null
+ * @param file the file when the operation was canceled, may be null.
+ * @param depth the depth when the operation was canceled, may be null.
*/
public CancelException(final File file, final int depth) {
this("Operation Cancelled", file, depth);
@@ -284,9 +285,9 @@ public CancelException(final File file, final int depth) {
* an appropriate message and the file and depth when
* cancellation occurred.
*
- * @param message the detail message
- * @param file the file when the operation was cancelled
- * @param depth the depth when the operation was cancelled
+ * @param message the detail message.
+ * @param file the file when the operation was canceled.
+ * @param depth the depth when the operation was canceled.
*/
public CancelException(final String message, final File file, final int depth) {
super(message);
@@ -295,23 +296,24 @@ public CancelException(final String message, final File file, final int depth) {
}
/**
- * Returns the depth when the operation was cancelled.
+ * Returns the depth when the operation was canceled.
*
- * @return the depth when the operation was cancelled
+ * @return the depth when the operation was canceled.
*/
public int getDepth() {
return depth;
}
/**
- * Returns the file when the operation was cancelled.
+ * Returns the file when the operation was canceled.
*
- * @return the file when the operation was cancelled
+ * @return the file when the operation was canceled.
*/
public File getFile() {
return file;
}
}
+
/**
* The file filter to use to filter files and directories.
*/
@@ -338,9 +340,9 @@ protected DirectoryWalker() {
* filtering should occur and all files and directories will be visited.
*
*
- * @param filter the filter to apply, null means visit all files
+ * @param filter the filter to apply, null means visit all files.
* @param depthLimit controls how deep the hierarchy is
- * navigated to (less than 0 means unlimited)
+ * navigated to (less than 0 means unlimited).
*/
protected DirectoryWalker(final FileFilter filter, final int depthLimit) {
this.filter = filter;
@@ -357,10 +359,10 @@ protected DirectoryWalker(final FileFilter filter, final int depthLimit) {
* A {@code null} filter means that no filtering should occur.
*
*
- * @param directoryFilter the filter to apply to directories, null means visit all directories
- * @param fileFilter the filter to apply to files, null means visit all files
+ * @param directoryFilter the filter to apply to directories, null means visit all directories.
+ * @param fileFilter the filter to apply to files, null means visit all files.
* @param depthLimit controls how deep the hierarchy is
- * navigated to (less than 0 means unlimited)
+ * navigated to (less than 0 means unlimited).
*/
protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter, final int depthLimit) {
if (directoryFilter == null && fileFilter == null) {
@@ -376,7 +378,7 @@ protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter,
}
/**
- * Checks whether the walk has been cancelled by calling {@link #handleIsCancelled},
+ * Checks whether the walk has been canceled by calling {@link #handleIsCancelled},
* throwing a {@link CancelException} if it has.
*
* Writers of subclasses should not normally call this method as it is called
@@ -385,10 +387,10 @@ protected DirectoryWalker(IOFileFilter directoryFilter, IOFileFilter fileFilter,
* you may wish to check for cancellation by calling this method.
*
*
- * @param file the current file being processed
- * @param depth the current file level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param file the current file being processed.
+ * @param depth the current file level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
protected final void checkIfCancelled(final File file, final int depth, final Collection results) throws
IOException {
@@ -403,11 +405,11 @@ protected final void checkIfCancelled(final File file, final int depth, final Co
* This implementation returns the files unchanged
*
*
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
+ * @param directory the current directory being processed.
+ * @param depth the current directory level (starting directory = 0).
* @param files the files (possibly filtered) in the directory, may be {@code null}
- * @return the filtered list of files
- * @throws IOException if an I/O Error occurs
+ * @return the filtered list of files.
+ * @throws IOException if an I/O Error occurs.
* @since 2.0
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
@@ -417,18 +419,18 @@ protected File[] filterDirectoryContents(final File directory, final int depth,
}
/**
- * Overridable callback method invoked when the operation is cancelled.
+ * Overridable callback method invoked when the operation is canceled.
* The file being processed when the cancellation occurred can be
* obtained from the exception.
*
* This implementation just re-throws the {@link CancelException}.
*
*
- * @param startDirectory the directory that the walk started from
- * @param results the collection of result objects, may be updated
+ * @param startDirectory the directory that the walk started from.
+ * @param results the collection of result objects, may be updated.
* @param cancel the exception throw to cancel further processing
* containing details at the point of cancellation.
- * @throws IOException if an I/O Error occurs
+ * @throws IOException if an I/O Error occurs.
*/
protected void handleCancelled(final File startDirectory, final Collection results,
final CancelException cancel) throws IOException {
@@ -447,11 +449,11 @@ protected void handleCancelled(final File startDirectory, final Collection re
* This implementation does nothing and returns true.
*
*
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @return true to process this directory, false to skip this directory
- * @throws IOException if an I/O Error occurs
+ * @param directory the current directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @return true to process this directory, false to skip this directory.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected boolean handleDirectory(final File directory, final int depth, final Collection results) throws
@@ -466,10 +468,10 @@ protected boolean handleDirectory(final File directory, final int depth, final C
* This implementation does nothing.
*
*
- * @param directory the directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleDirectoryEnd(final File directory, final int depth, final Collection results) throws
@@ -483,10 +485,10 @@ protected void handleDirectoryEnd(final File directory, final int depth, final C
* This implementation does nothing.
*
*
- * @param directory the current directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the current directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleDirectoryStart(final File directory, final int depth, final Collection results) throws
@@ -500,8 +502,8 @@ protected void handleDirectoryStart(final File directory, final int depth, final
* This implementation does nothing.
*
*
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleEnd(final Collection results) throws IOException {
@@ -514,10 +516,10 @@ protected void handleEnd(final Collection results) throws IOException {
* This implementation does nothing.
*
*
- * @param file the current file being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param file the current file being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleFile(final File file, final int depth, final Collection results) throws IOException {
@@ -526,7 +528,7 @@ protected void handleFile(final File file, final int depth, final Collection
/**
* Overridable callback method invoked to determine if the entire walk
- * operation should be immediately cancelled.
+ * operation should be immediately canceled.
*
* This method should be implemented by those subclasses that want to
* provide a public {@code cancel()} method available from another
@@ -534,13 +536,13 @@ protected void handleFile(final File file, final int depth, final Collection
*
* If this method returns true, then the directory walk is immediately
- * cancelled. The next callback method will be {@link #handleCancelled}.
+ * canceled. The next callback method will be {@link #handleCancelled}.
*
*
* This implementation returns false.
*
*
- * @param file the file or directory being processed
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @return true if the walk has been cancelled
- * @throws IOException if an I/O Error occurs
+ * @param file the file or directory being processed.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @return true if the walk has been canceled.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected boolean handleIsCancelled(
final File file, final int depth, final Collection results) throws IOException {
// do nothing - overridable by subclass
- return false; // not cancelled
+ return false; // not canceled
}
/**
@@ -575,10 +577,10 @@ protected boolean handleIsCancelled(
* This implementation does nothing.
*
*
- * @param directory the restricted directory
- * @param depth the current directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the restricted directory.
+ * @param depth the current directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleRestricted(final File directory, final int depth, final Collection results) throws
@@ -592,9 +594,9 @@ protected void handleRestricted(final File directory, final int depth, final Col
* This implementation does nothing.
*
*
- * @param startDirectory the directory to start from
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param startDirectory the directory to start from.
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
protected void handleStart(final File startDirectory, final Collection results) throws IOException {
@@ -613,10 +615,10 @@ protected void handleStart(final File startDirectory, final Collection result
* The event methods have the prefix {@code handle}.
*
*
- * @param startDirectory the directory to start from, not null
- * @param results the collection of result objects, may be updated
- * @throws NullPointerException if the start directory is null
- * @throws IOException if an I/O Error occurs
+ * @param startDirectory the directory to start from, not null.
+ * @param results the collection of result objects, may be updated.
+ * @throws NullPointerException if the start directory is null.
+ * @throws IOException if an I/O Error occurs.
*/
protected final void walk(final File startDirectory, final Collection results) throws IOException {
Objects.requireNonNull(startDirectory, "startDirectory");
@@ -632,10 +634,10 @@ protected final void walk(final File startDirectory, final Collection results
/**
* Main recursive method to examine the directory hierarchy.
*
- * @param directory the directory to examine, not null
- * @param depth the directory level (starting directory = 0)
- * @param results the collection of result objects, may be updated
- * @throws IOException if an I/O Error occurs
+ * @param directory the directory to examine, not null.
+ * @param depth the directory level (starting directory = 0).
+ * @param results the collection of result objects, may be updated.
+ * @throws IOException if an I/O Error occurs.
*/
private void walk(final File directory, final int depth, final Collection results) throws IOException {
checkIfCancelled(directory, depth, results);
diff --git a/src/main/java/org/apache/commons/io/EndianUtils.java b/src/main/java/org/apache/commons/io/EndianUtils.java
index 6b4d58eeba3..b6cb2ebd83a 100644
--- a/src/main/java/org/apache/commons/io/EndianUtils.java
+++ b/src/main/java/org/apache/commons/io/EndianUtils.java
@@ -50,9 +50,10 @@ public class EndianUtils {
/**
* Reads the next byte from the input stream.
- * @param input the stream
- * @return the byte
- * @throws IOException if the end of file is reached
+ *
+ * @param input the stream.
+ * @return the byte.
+ * @throws IOException if the end of file is reached.
*/
private static int read(final InputStream input) throws IOException {
final int value = input.read();
@@ -65,10 +66,10 @@ private static int read(final InputStream input) throws IOException {
/**
* Reads a little-endian {@code double} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static double readSwappedDouble(final byte[] data, final int offset) {
return Double.longBitsToDouble(readSwappedLong(data, offset));
@@ -77,9 +78,9 @@ public static double readSwappedDouble(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code double} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static double readSwappedDouble(final InputStream input) throws IOException {
return Double.longBitsToDouble(readSwappedLong(input));
@@ -88,10 +89,10 @@ public static double readSwappedDouble(final InputStream input) throws IOExcepti
/**
* Reads a little-endian {@code float} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static float readSwappedFloat(final byte[] data, final int offset) {
return Float.intBitsToFloat(readSwappedInteger(data, offset));
@@ -100,9 +101,9 @@ public static float readSwappedFloat(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code float} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static float readSwappedFloat(final InputStream input) throws IOException {
return Float.intBitsToFloat(readSwappedInteger(input));
@@ -111,14 +112,15 @@ public static float readSwappedFloat(final InputStream input) throws IOException
/**
* Reads a little-endian {@code int} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static int readSwappedInteger(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE);
- return ((data[offset + 0] & 0xff) << 0) +
+ return
+ ((data[offset + 0] & 0xff) << 0) +
((data[offset + 1] & 0xff) << 8) +
((data[offset + 2] & 0xff) << 16) +
((data[offset + 3] & 0xff) << 24);
@@ -127,25 +129,29 @@ public static int readSwappedInteger(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code int} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static int readSwappedInteger(final InputStream input) throws IOException {
final int value1 = read(input);
final int value2 = read(input);
final int value3 = read(input);
final int value4 = read(input);
- return ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16) + ((value4 & 0xff) << 24);
+ return
+ ((value1 & 0xff) << 0) +
+ ((value2 & 0xff) << 8) +
+ ((value3 & 0xff) << 16) +
+ ((value4 & 0xff) << 24);
}
/**
* Reads a little-endian {@code long} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static long readSwappedLong(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Long.SIZE / Byte.SIZE);
@@ -157,9 +163,9 @@ public static long readSwappedLong(final byte[] data, final int offset) {
/**
* Reads a little-endian {@code long} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static long readSwappedLong(final InputStream input) throws IOException {
final byte[] bytes = new byte[8];
@@ -172,41 +178,47 @@ public static long readSwappedLong(final InputStream input) throws IOException {
/**
* Reads a little-endian {@code short} value from a byte array at a given offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes.
*/
public static short readSwappedShort(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE);
- return (short) (((data[offset + 0] & 0xff) << 0) + ((data[offset + 1] & 0xff) << 8));
+ return (short) (
+ ((data[offset + 0] & 0xff) << 0) +
+ ((data[offset + 1] & 0xff) << 8)
+ );
}
/**
* Reads a little-endian {@code short} value from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static short readSwappedShort(final InputStream input) throws IOException {
- return (short) (((read(input) & 0xff) << 0) + ((read(input) & 0xff) << 8));
+ return (short) (
+ ((read(input) & 0xff) << 0) +
+ ((read(input) & 0xff) << 8)
+ );
}
/**
* Reads a little-endian unsigned integer (32-bit) value from a byte array at a given
* offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static long readSwappedUnsignedInteger(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE);
final long low = ((data[offset + 0] & 0xff) << 0) +
- ((data[offset + 1] & 0xff) << 8) +
- ((data[offset + 2] & 0xff) << 16);
+ ((data[offset + 1] & 0xff) << 8) +
+ ((data[offset + 2] & 0xff) << 16);
final long high = data[offset + 3] & 0xff;
return (high << 24) + (0xffffffffL & low);
}
@@ -214,16 +226,18 @@ public static long readSwappedUnsignedInteger(final byte[] data, final int offse
/**
* Reads a little-endian unsigned integer (32-bit) from an InputStream.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static long readSwappedUnsignedInteger(final InputStream input) throws IOException {
final int value1 = read(input);
final int value2 = read(input);
final int value3 = read(input);
final int value4 = read(input);
- final long low = ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8) + ((value3 & 0xff) << 16);
+ final long low = ((value1 & 0xff) << 0) +
+ ((value2 & 0xff) << 8) +
+ ((value3 & 0xff) << 16);
final long high = value4 & 0xff;
return (high << 24) + (0xffffffffL & low);
}
@@ -232,28 +246,30 @@ public static long readSwappedUnsignedInteger(final InputStream input) throws IO
* Reads an unsigned short (16-bit) value from a byte array in little-endian order at a given
* offset.
*
- * @param data source byte array
- * @param offset starting offset in the byte array
- * @return the value read
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes
+ * @param data source byte array.
+ * @param offset starting offset in the byte array.
+ * @return the value read.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes.
*/
public static int readSwappedUnsignedShort(final byte[] data, final int offset) {
validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE);
- return ((data[offset + 0] & 0xff) << 0) + ((data[offset + 1] & 0xff) << 8);
+ return ((data[offset + 0] & 0xff) << 0) +
+ ((data[offset + 1] & 0xff) << 8);
}
/**
* Reads an unsigned short (16-bit) from an InputStream in little-endian order.
*
- * @param input source InputStream
- * @return the value just read
- * @throws IOException in case of an I/O problem
+ * @param input source InputStream.
+ * @return the value just read.
+ * @throws IOException in case of an I/O problem.
*/
public static int readSwappedUnsignedShort(final InputStream input) throws IOException {
final int value1 = read(input);
final int value2 = read(input);
- return ((value1 & 0xff) << 0) + ((value2 & 0xff) << 8);
+ return ((value1 & 0xff) << 0) +
+ ((value2 & 0xff) << 8);
}
/**
@@ -263,8 +279,8 @@ public static int readSwappedUnsignedShort(final InputStream input) throws IOExc
* This can be useful if you have a number that was read from the
* underlying source in the wrong endianness.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static double swapDouble(final double value) {
return Double.longBitsToDouble(swapLong(Double.doubleToLongBits(value)));
@@ -273,8 +289,8 @@ public static double swapDouble(final double value) {
/**
* Converts a {@code float} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static float swapFloat(final float value) {
return Float.intBitsToFloat(swapInteger(Float.floatToIntBits(value)));
@@ -283,8 +299,8 @@ public static float swapFloat(final float value) {
/**
* Converts an {@code int} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static int swapInteger(final int value) {
return
@@ -297,8 +313,8 @@ public static int swapInteger(final int value) {
/**
* Converts a {@code long} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static long swapLong(final long value) {
return
@@ -315,21 +331,23 @@ public static long swapLong(final long value) {
/**
* Converts a {@code short} value from big-endian to little-endian and vice versa.
*
- * @param value value to convert
- * @return the converted value
+ * @param value value to convert.
+ * @return the converted value.
*/
public static short swapShort(final short value) {
- return (short) (((value >> 0 & 0xff) << 8) +
- ((value >> 8 & 0xff) << 0));
+ return (short) (
+ ((value >> 0 & 0xff) << 8) +
+ ((value >> 8 & 0xff) << 0)
+ );
}
/**
* Validates if the provided byte array has enough data.
*
- * @param data the input byte array
- * @param offset the input offset
- * @param byteNeeded the needed number of bytes
- * @throws IllegalArgumentException if the byte array does not have enough data
+ * @param data the input byte array.
+ * @param offset the input offset.
+ * @param byteNeeded the needed number of bytes.
+ * @throws IllegalArgumentException if the byte array does not have enough data.
*/
private static void validateByteArrayOffset(final byte[] data, final int offset, final int byteNeeded) {
if (data.length < offset + byteNeeded) {
@@ -340,10 +358,10 @@ private static void validateByteArrayOffset(final byte[] data, final int offset,
/**
* Writes the 8 bytes of a {@code double} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static void writeSwappedDouble(final byte[] data, final int offset, final double value) {
writeSwappedLong(data, offset, Double.doubleToLongBits(value));
@@ -352,9 +370,9 @@ public static void writeSwappedDouble(final byte[] data, final int offset, final
/**
* Writes the 8 bytes of a {@code double} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedDouble(final OutputStream output, final double value) throws IOException {
writeSwappedLong(output, Double.doubleToLongBits(value));
@@ -363,10 +381,10 @@ public static void writeSwappedDouble(final OutputStream output, final double va
/**
* Writes the 4 bytes of a {@code float} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static void writeSwappedFloat(final byte[] data, final int offset, final float value) {
writeSwappedInteger(data, offset, Float.floatToIntBits(value));
@@ -375,9 +393,9 @@ public static void writeSwappedFloat(final byte[] data, final int offset, final
/**
* Writes the 4 bytes of a {@code float} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedFloat(final OutputStream output, final float value) throws IOException {
writeSwappedInteger(output, Float.floatToIntBits(value));
@@ -386,10 +404,10 @@ public static void writeSwappedFloat(final OutputStream output, final float valu
/**
* Writes the 4 bytes of an {@code int} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 4 bytes.
*/
public static void writeSwappedInteger(final byte[] data, final int offset, final int value) {
validateByteArrayOffset(data, offset, Integer.SIZE / Byte.SIZE);
@@ -402,9 +420,9 @@ public static void writeSwappedInteger(final byte[] data, final int offset, fina
/**
* Writes the 4 bytes of an {@code int} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedInteger(final OutputStream output, final int value) throws IOException {
output.write((byte) (value >> 0 & 0xff));
@@ -416,10 +434,10 @@ public static void writeSwappedInteger(final OutputStream output, final int valu
/**
* Writes the 8 bytes of a {@code long} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 8 bytes.
*/
public static void writeSwappedLong(final byte[] data, final int offset, final long value) {
validateByteArrayOffset(data, offset, Long.SIZE / Byte.SIZE);
@@ -436,9 +454,9 @@ public static void writeSwappedLong(final byte[] data, final int offset, final l
/**
* Writes the 8 bytes of a {@code long} to an output stream in little-endian order.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedLong(final OutputStream output, final long value) throws IOException {
output.write((byte) (value >> 0 & 0xff));
@@ -454,10 +472,10 @@ public static void writeSwappedLong(final OutputStream output, final long value)
/**
* Writes the 2 bytes of a {@code short} to a byte array at a given offset in little-endian order.
*
- * @param data target byte array
- * @param offset starting offset in the byte array
- * @param value value to write
- * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes
+ * @param data target byte array.
+ * @param offset starting offset in the byte array.
+ * @param value value to write.
+ * @throws IllegalArgumentException if the part of the byte array starting at offset does not have at least 2 bytes.
*/
public static void writeSwappedShort(final byte[] data, final int offset, final short value) {
validateByteArrayOffset(data, offset, Short.SIZE / Byte.SIZE);
@@ -468,9 +486,9 @@ public static void writeSwappedShort(final byte[] data, final int offset, final
/**
* Writes the 2 bytes of a {@code short} to an output stream using little-endian encoding.
*
- * @param output target OutputStream
- * @param value value to write
- * @throws IOException in case of an I/O problem
+ * @param output target OutputStream.
+ * @param value value to write.
+ * @throws IOException in case of an I/O problem.
*/
public static void writeSwappedShort(final OutputStream output, final short value) throws IOException {
output.write((byte) (value >> 0 & 0xff));
diff --git a/src/main/java/org/apache/commons/io/FileCleaner.java b/src/main/java/org/apache/commons/io/FileCleaner.java
index 5ffdd7db219..3ca1d1ad735 100644
--- a/src/main/java/org/apache/commons/io/FileCleaner.java
+++ b/src/main/java/org/apache/commons/io/FileCleaner.java
@@ -25,12 +25,14 @@
* This utility creates a background thread to handle file deletion.
* Each file to be deleted is registered with a handler object.
* When the handler object is garbage collected, the file is deleted.
+ *
*
* In an environment with multiple class loaders (a servlet container, for
* example), you should consider stopping the background thread if it is no
* longer needed. This is done by invoking the method
* {@link #exitWhenFinished}, typically in
* {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)} or similar.
+ *
*
* @deprecated Use {@link FileCleaningTracker}
*/
@@ -51,18 +53,22 @@ public class FileCleaner {
* with multiple class loaders (such as an application server), you should be
* aware that the file cleaner thread will continue running even if the class
* loader it was started from terminates. This can constitute a memory leak.
+ *
*
* For example, suppose that you have developed a web application, which
- * contains the commons-io jar file in your WEB-INF/lib directory. In other
+ * contains the Commons IO jar file in your WEB-INF/lib directory. In other
* words, the FileCleaner class is loaded through the class loader of your
* web application. If the web application is terminated, but the servlet
* container is still running, then the file cleaner thread will still exist,
* posing a memory leak.
+ *
*
* This method allows the thread to be terminated. Simply call this method
* in the resource cleanup code, such as
* {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)}.
* One called, no new objects can be tracked by the file cleaner.
+ *
+ *
* @deprecated Use {@link FileCleaningTracker#exitWhenFinished()}.
*/
@Deprecated
@@ -76,7 +82,7 @@ public static synchronized void exitWhenFinished() {
* {@link FileCleaningTracker} class while maintain compatibility with the
* deprecated {@link FileCleaner}.
*
- * @return the singleton instance
+ * @return the singleton instance.
*/
public static FileCleaningTracker getInstance() {
return INSTANCE;
@@ -86,7 +92,7 @@ public static FileCleaningTracker getInstance() {
* Gets the number of files currently being tracked, and therefore
* awaiting deletion.
*
- * @return the number of files being tracked
+ * @return the number of files being tracked.
* @deprecated Use {@link FileCleaningTracker#getTrackCount()}.
*/
@Deprecated
@@ -99,9 +105,9 @@ public static int getTrackCount() {
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the file is null.
* @deprecated Use {@link FileCleaningTracker#track(File, Object)}.
*/
@Deprecated
@@ -114,10 +120,10 @@ public static void track(final File file, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the file is null.
* @deprecated Use {@link FileCleaningTracker#track(File, Object, FileDeleteStrategy)}.
*/
@Deprecated
@@ -130,9 +136,9 @@ public static void track(final File file, final Object marker, final FileDeleteS
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the path is null.
* @deprecated Use {@link FileCleaningTracker#track(String, Object)}.
*/
@Deprecated
@@ -145,10 +151,10 @@ public static void track(final String path, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the path is null.
* @deprecated Use {@link FileCleaningTracker#track(String, Object, FileDeleteStrategy)}.
*/
@Deprecated
diff --git a/src/main/java/org/apache/commons/io/FileCleaningTracker.java b/src/main/java/org/apache/commons/io/FileCleaningTracker.java
index 98edebc518e..be2746b66be 100644
--- a/src/main/java/org/apache/commons/io/FileCleaningTracker.java
+++ b/src/main/java/org/apache/commons/io/FileCleaningTracker.java
@@ -21,14 +21,14 @@
import java.lang.ref.ReferenceQueue;
import java.nio.file.Path;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
- * Keeps track of files awaiting deletion, and deletes them when an associated
+ * Tracks files awaiting deletion, and deletes them when an associated
* marker object is reclaimed by the garbage collector.
*
* This utility creates a background thread to handle file deletion.
@@ -51,9 +51,10 @@ public class FileCleaningTracker {
* The reaper thread.
*/
private final class Reaper extends Thread {
+
/** Constructs a new Reaper */
Reaper() {
- super("File Reaper");
+ super("commons-io-FileCleaningTracker-Reaper");
setPriority(MAX_PRIORITY);
setDaemon(true);
}
@@ -65,16 +66,18 @@ private final class Reaper extends Thread {
@Override
public void run() {
// thread exits when exitWhenFinished is true and there are no more tracked objects
- while (!exitWhenFinished || !trackers.isEmpty()) {
+ while (!(exitWhenFinished && trackers.isEmpty())) {
try {
// Wait for a tracker to remove.
- final Tracker tracker = (Tracker) q.remove(); // cannot return null
+ final Tracker tracker = (Tracker) refQueue.remove(); // cannot return null
trackers.remove(tracker);
if (!tracker.delete()) {
deleteFailures.add(tracker.getPath());
}
tracker.clear();
} catch (final InterruptedException e) {
+ // interrupted removing from the queue.
+ interrupt();
continue;
}
}
@@ -99,15 +102,14 @@ private static final class Tracker extends PhantomReference
*
* For example, suppose that you have developed a web application, which
- * contains the commons-io jar file in your WEB-INF/lib directory. In other
+ * contains the Commons IO JAR file in your WEB-INF/lib directory. In other
* words, the FileCleaner class is loaded through the class loader of your
* web application. If the web application is terminated, but the servlet
* container is still running, then the file cleaner thread will still exist,
* posing a memory leak.
+ *
*
* This method allows the thread to be terminated. Simply call this method
* in the resource cleanup code, such as
* {@code javax.servlet.ServletContextListener.contextDestroyed(javax.servlet.ServletContextEvent)}.
* Once called, no new objects can be tracked by the file cleaner.
+ *
*/
public synchronized void exitWhenFinished() {
- // synchronized block protects reaper
+ // synchronized method guards reaper
exitWhenFinished = true;
if (reaper != null) {
synchronized (reaper) {
@@ -218,7 +223,7 @@ public synchronized void exitWhenFinished() {
/**
* Gets a copy of the file paths that failed to delete.
*
- * @return a copy of the file paths that failed to delete
+ * @return a copy of the file paths that failed to delete.
* @since 2.0
*/
public List getDeleteFailures() {
@@ -229,7 +234,7 @@ public List getDeleteFailures() {
* Gets the number of files currently being tracked, and therefore
* awaiting deletion.
*
- * @return the number of files being tracked
+ * @return the number of files being tracked.
*/
public int getTrackCount() {
return trackers.size();
@@ -240,9 +245,9 @@ public int getTrackCount() {
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the file is null.
*/
public void track(final File file, final Object marker) {
track(file, marker, null);
@@ -253,10 +258,10 @@ public void track(final File file, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the file is null.
*/
public void track(final File file, final Object marker, final FileDeleteStrategy deleteStrategy) {
Objects.requireNonNull(file, "file");
@@ -268,9 +273,9 @@ public void track(final File file, final Object marker, final FileDeleteStrategy
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the file is null.
* @since 2.14.0
*/
public void track(final Path file, final Object marker) {
@@ -282,10 +287,10 @@ public void track(final Path file, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param file the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the file is null
+ * @param file the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException if the file is null.
* @since 2.14.0
*/
public void track(final Path file, final Object marker, final FileDeleteStrategy deleteStrategy) {
@@ -298,9 +303,9 @@ public void track(final Path file, final Object marker, final FileDeleteStrategy
* when the marker instance is garbage collected.
* The {@link FileDeleteStrategy#NORMAL normal} deletion strategy will be used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @throws NullPointerException if the path is null.
*/
public void track(final String path, final Object marker) {
track(path, marker, null);
@@ -311,13 +316,12 @@ public void track(final String path, final Object marker) {
* when the marker instance is garbage collected.
* The specified deletion strategy is used.
*
- * @param path the full path to the file to be tracked, not null
- * @param marker the marker object used to track the file, not null
- * @param deleteStrategy the strategy to delete the file, null means normal
- * @throws NullPointerException if the path is null
+ * @param path the full path to the file to be tracked, not null.
+ * @param marker the marker object used to track the file, not null.
+ * @param deleteStrategy the strategy to delete the file, null means normal.
+ * @throws NullPointerException Thrown if the path is null.
*/
public void track(final String path, final Object marker, final FileDeleteStrategy deleteStrategy) {
- Objects.requireNonNull(path, "path");
addTracker(path, marker, deleteStrategy);
}
diff --git a/src/main/java/org/apache/commons/io/FileDeleteStrategy.java b/src/main/java/org/apache/commons/io/FileDeleteStrategy.java
index 62cf28c1631..a73ea719a75 100644
--- a/src/main/java/org/apache/commons/io/FileDeleteStrategy.java
+++ b/src/main/java/org/apache/commons/io/FileDeleteStrategy.java
@@ -37,7 +37,7 @@ public class FileDeleteStrategy {
/**
* Force file deletion strategy.
*/
- static class ForceFileDeleteStrategy extends FileDeleteStrategy {
+ static final class ForceFileDeleteStrategy extends FileDeleteStrategy {
/** Default Constructor */
ForceFileDeleteStrategy() {
@@ -51,10 +51,10 @@ static class ForceFileDeleteStrategy extends FileDeleteStrategy {
* if the file exists.
*
*
- * @param fileToDelete the file to delete, not null
+ * @param fileToDelete the file to delete, not null.
* @return Always returns {@code true}
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
+ * @throws NullPointerException if the file is null.
+ * @throws IOException if an error occurs during file deletion.
*/
@Override
protected boolean doDelete(final File fileToDelete) throws IOException {
@@ -81,7 +81,7 @@ protected boolean doDelete(final File fileToDelete) throws IOException {
/**
* Restricted constructor.
*
- * @param name the name by which the strategy is known
+ * @param name the name by which the strategy is known.
*/
protected FileDeleteStrategy(final String name) {
this.name = name;
@@ -94,9 +94,9 @@ protected FileDeleteStrategy(final String name) {
* Subclass writers should override {@link #doDelete(File)}, not this method.
*
*
- * @param fileToDelete the file to delete, not null
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
+ * @param fileToDelete the file to delete, not null.
+ * @throws NullPointerException if the file is null.
+ * @throws IOException if an error occurs during file deletion.
*/
public void delete(final File fileToDelete) throws IOException {
if (fileToDelete.exists() && !doDelete(fileToDelete)) {
@@ -112,8 +112,8 @@ public void delete(final File fileToDelete) throws IOException {
* Subclass writers should override {@link #doDelete(File)}, not this method.
*
*
- * @param fileToDelete the file to delete, null returns true
- * @return true if the file was deleted, or there was no such file
+ * @param fileToDelete the file to delete, null returns true.
+ * @return true if the file was deleted, or there was no such file.
*/
public boolean deleteQuietly(final File fileToDelete) {
if (fileToDelete == null || !fileToDelete.exists()) {
@@ -139,10 +139,10 @@ public boolean deleteQuietly(final File fileToDelete) {
* This implementation uses {@link FileUtils#delete(File)}.
*
*
- * @param file the file to delete, exists, not null
- * @return true if the file was deleted
- * @throws NullPointerException if the file is null
- * @throws IOException if an error occurs during file deletion
+ * @param file the file to delete, exists, not null.
+ * @return true if the file was deleted.
+ * @throws NullPointerException if the file is null.
+ * @throws IOException if an error occurs during file deletion.
*/
protected boolean doDelete(final File file) throws IOException {
FileUtils.delete(file);
@@ -152,7 +152,7 @@ protected boolean doDelete(final File file) throws IOException {
/**
* Gets a string describing the delete strategy.
*
- * @return a string describing the delete strategy
+ * @return a string describing the delete strategy.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/FileExistsException.java b/src/main/java/org/apache/commons/io/FileExistsException.java
index 1f733cf11ae..0b18ff8cac2 100644
--- a/src/main/java/org/apache/commons/io/FileExistsException.java
+++ b/src/main/java/org/apache/commons/io/FileExistsException.java
@@ -20,7 +20,7 @@
import java.io.IOException;
/**
- * Indicates that a file already exists.
+ * Signals that a file already exists.
*
* @since 2.0
*/
@@ -40,7 +40,7 @@ public FileExistsException() {
/**
* Constructs an instance with the specified file.
*
- * @param file The file that exists
+ * @param file The file that exists.
*/
public FileExistsException(final File file) {
super("File " + file + " exists");
@@ -49,7 +49,7 @@ public FileExistsException(final File file) {
/**
* Constructs an instance with the specified message.
*
- * @param message The error message
+ * @param message The error message.
*/
public FileExistsException(final String message) {
super(message);
diff --git a/src/main/java/org/apache/commons/io/FileSystem.java b/src/main/java/org/apache/commons/io/FileSystem.java
index 4169e1a53b1..11d3673f213 100644
--- a/src/main/java/org/apache/commons/io/FileSystem.java
+++ b/src/main/java/org/apache/commons/io/FileSystem.java
@@ -32,11 +32,10 @@
import java.util.Objects;
/**
- * Abstracts an OS' file system details, currently supporting the single use case of converting a file name String to a
- * legal file name with {@link #toLegalFileName(String, char)}.
+ * Enumerates file system details for operating systems, currently supporting the single use case of converting a file name String to a legal file name with
+ * {@link #toLegalFileName(String, char)}.
*
- * The starting point of any operation is {@link #getCurrent()} which gets you the enum for the file system that matches
- * the OS hosting the running JVM.
+ * The starting point of any operation is {@link #getCurrent()} which gets you the enum for the file system that matches the OS hosting the running JVM.
*
*
* @since 2.7
@@ -118,6 +117,7 @@ public enum FileSystem {
* Implementations measure length and can truncate to a specified limit.
*/
enum NameLengthStrategy {
+
/** Length measured as encoded bytes. */
BYTES {
@Override
@@ -266,7 +266,7 @@ final boolean isWithinLimit(final CharSequence value, final int limit, final Cha
/**
* Gets the current file system.
*
- * @return the current file system
+ * @return the current file system.
*/
private static FileSystem current() {
if (IS_OS_LINUX) {
@@ -284,7 +284,7 @@ private static FileSystem current() {
/**
* Gets the current file system.
*
- * @return the current file system
+ * @return the current file system.
*/
public static FileSystem getCurrent() {
return CURRENT;
@@ -294,8 +294,8 @@ public static FileSystem getCurrent() {
* Decides if the operating system matches.
*
* @param osNamePrefix
- * the prefix for the os name
- * @return true if matches, or false if not or can't determine
+ * the prefix for the operating system name.
+ * @return true if matches, or false if not or can't determine.
*/
private static boolean getOsMatchesName(final String osNamePrefix) {
return isOsNameMatch(getSystemProperty("os.name"), osNamePrefix);
@@ -309,8 +309,8 @@ private static boolean getOsMatchesName(final String osNamePrefix) {
*
*
* @param property
- * the system property name
- * @return the system property value or {@code null} if a security problem occurs
+ * the system property name.
+ * @return the system property value or {@code null} if a security problem occurs.
*/
private static String getSystemProperty(final String property) {
try {
@@ -345,10 +345,10 @@ private static int indexOfFirstDot(final CharSequence cs) {
*
*
* @param osName
- * the actual OS name
+ * the actual OS name.
* @param osNamePrefix
- * the prefix for the expected OS name
- * @return true if matches, or false if not or can't determine
+ * the prefix for the expected OS name.
+ * @return true if matches, or false if not or can't determine.
*/
private static boolean isOsNameMatch(final String osName, final String osNamePrefix) {
if (osName == null) {
diff --git a/src/main/java/org/apache/commons/io/FileSystemUtils.java b/src/main/java/org/apache/commons/io/FileSystemUtils.java
index 4c0af0d3671..7455dca8d09 100644
--- a/src/main/java/org/apache/commons/io/FileSystemUtils.java
+++ b/src/main/java/org/apache/commons/io/FileSystemUtils.java
@@ -53,12 +53,12 @@ public class FileSystemUtils {
* FileSystemUtils.freeSpace("/volume"); // *nix
*
*
- * @param path the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume
+ * @param path the path to get free space for, not null, not empty on Unix.
+ * @return the amount of free drive space on the drive or volume.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 1.1, enhanced OS support in 1.2 and 1.3
- * @deprecated Use freeSpaceKb(String) Deprecated from 1.3, may be removed in 2.0
+ * @deprecated Use freeSpaceKb(String) Deprecated from 1.3, may be removed in 2.0.
*/
@Deprecated
public static long freeSpace(final String path) throws IOException {
@@ -75,7 +75,7 @@ public static long freeSpace(final String path) throws IOException {
* freeSpaceKb(FileUtils.current().getAbsolutePath())
*
*
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 2.0
@@ -97,7 +97,7 @@ public static long freeSpaceKb() throws IOException {
*
*
* @param timeout ignored.
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 2.0
@@ -116,8 +116,8 @@ public static long freeSpaceKb(final long timeout) throws IOException {
* FileSystemUtils.freeSpaceKb("/volume"); // *nix
*
*
- * @param path the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @param path the path to get free space for, not null, not empty on Unix.
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 1.2, enhanced OS support in 1.3
@@ -136,9 +136,9 @@ public static long freeSpaceKb(final String path) throws IOException {
* FileSystemUtils.freeSpaceKb("/volume"); // *nix
*
*
- * @param path the path to get free space for, not null, not empty on Unix
+ * @param path the path to get free space for, not null, not empty on Unix.
* @param timeout ignored.
- * @return the amount of free drive space on the drive or volume in kilobytes
+ * @return the amount of free drive space on the drive or volume in kilobytes.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
* @since 2.0
@@ -157,8 +157,8 @@ public static long freeSpaceKb(final String path, final long timeout) throws IOE
* FileSystemUtils.freeSpace("/volume"); // *nix
*
*
- * @param pathStr the path to get free space for, not null, not empty on Unix
- * @return the amount of free drive space on the drive or volume
+ * @param pathStr the path to get free space for, not null, not empty on Unix.
+ * @return the amount of free drive space on the drive or volume.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException if the path is invalid.
*/
diff --git a/src/main/java/org/apache/commons/io/FileUtils.java b/src/main/java/org/apache/commons/io/FileUtils.java
index 203fe84bfc5..11afd3f5d62 100644
--- a/src/main/java/org/apache/commons/io/FileUtils.java
+++ b/src/main/java/org/apache/commons/io/FileUtils.java
@@ -93,16 +93,16 @@
* Facilities are provided in the following areas:
*
*
- *
writing to a file
- *
reading from a file
- *
make a directory including parent directories
- *
copying files and directories
- *
deleting files and directories
- *
converting to and from a URL
- *
listing files and directories by filter and extension
- *
comparing file content
- *
file last changed date
- *
calculating a checksum
+ *
writing to a file
+ *
reading from a file
+ *
make a directory including parent directories
+ *
copying files and directories
+ *
deleting files and directories
+ *
converting to and from a URL
+ *
listing files and directories by filter and extension
+ *
comparing file content
+ *
file last changed date
+ *
calculating a checksum
*
*
* Note that a specific charset should be specified whenever possible. Relying on the platform default means that the
@@ -112,7 +112,7 @@
* {@link SecurityException} are not documented in the Javadoc.
*
*/
public class FileUtils {
@@ -230,8 +230,8 @@ public class FileUtils {
* Similarly for the 1MB and 1KB boundaries.
*
*
- * @param size the number of bytes
- * @return a human-readable display value (includes units - QB, RB, YB, ZB, EB, PB, TB, GB, MB, KB or bytes)
+ * @param size the number of bytes.
+ * @return a human-readable display value (includes units - QB, RB, YB, ZB, EB, PB, TB, GB, MB, KB or bytes).
* @throws NullPointerException if the given {@link BigInteger} is {@code null}.
* @see IO-226 - should the rounding be changed?
* @since 2.4
@@ -276,8 +276,8 @@ public static String byteCountToDisplaySize(final BigInteger size) {
* Similarly for the 1MB and 1KB boundaries.
*
*
- * @param size the number of bytes
- * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes)
+ * @param size the number of bytes.
+ * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes).
* @see IO-226 - should the rounding be changed?
*/
// See https://issues.apache.org/jira/browse/IO-226 - should the rounding be changed?
@@ -295,8 +295,8 @@ public static String byteCountToDisplaySize(final long size) {
* Similarly for the 1MB and 1KB boundaries.
*
*
- * @param size the number of bytes
- * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes)
+ * @param size the number of bytes.
+ * @return a human-readable display value (includes units - EB, PB, TB, GB, MB, KB or bytes).
* @see IO-226 - should the rounding be changed?
* @since 2.12.0
*/
@@ -357,11 +357,11 @@ private static File checkIsFile(final File file, final String name) {
*
* @param file the file to checksum, must not be {@code null}
* @param checksum the checksum object to be used, must not be {@code null}
- * @return the checksum specified, updated with the content of the file
+ * @return the checksum specified, updated with the content of the file.
* @throws NullPointerException if the given {@link File} is {@code null}.
* @throws NullPointerException if the given {@link Checksum} is {@code null}.
* @throws IllegalArgumentException if the given {@link File} is not a file.
- * @throws FileNotFoundException if the file does not exist
+ * @throws FileNotFoundException if the file does not exist.
* @throws IOException if an IO error occurs reading the file.
* @since 1.3
*/
@@ -379,7 +379,7 @@ public static Checksum checksum(final File file, final Checksum checksum) throws
* The value of the checksum is returned.
*
* @param file the file to checksum, must not be {@code null}
- * @return the checksum value
+ * @return the checksum value.
* @throws NullPointerException if the {@code file} is {@code null}.
* @throws IllegalArgumentException if the {@code file} does not exist or is not a file.
* @throws IOException if an IO error occurs reading the file.
@@ -392,7 +392,7 @@ public static long checksumCRC32(final File file) throws IOException {
/**
* Cleans a directory without deleting it.
*
- * @param directory directory to clean
+ * @param directory directory to clean.
* @throws NullPointerException if the given {@link File} is {@code null}.
* @throws IllegalArgumentException if the {@code directory} does not exist or is not a directory.
* @throws IOException if an I/O error occurs.
@@ -422,9 +422,9 @@ private static void cleanDirectoryOnExit(final File directory) throws IOExceptio
* resorting to byte-by-byte comparison of the contents.
*
*
- * @param file1 the first file
- * @param file2 the second file
- * @return true if the content of the files are equal or they both don't exist, false otherwise
+ * @param file1 the first file.
+ * @param file2 the second file.
+ * @return true if the content of the files are equal or they both don't exist, false otherwise.
* @throws IllegalArgumentException when an input is not a file.
* @throws IOException If an I/O error occurs.
* @see PathUtils#fileContentEquals(Path,Path)
@@ -464,12 +464,12 @@ public static boolean contentEquals(final File file1, final File file2) throws I
* before resorting to line-by-line comparison of the contents.
*
*
- * @param file1 the first file
- * @param file2 the second file
+ * @param file1 the first file.
+ * @param file2 the second file.
* @param charsetName the name of the requested charset.
- * May be null, in which case the platform default is used
+ * May be null, in which case the platform default is used.
* @return true if the content of the files are equal or neither exists,
- * false otherwise
+ * false otherwise.
* @throws IllegalArgumentException when an input is not a file.
* @throws IOException in case of an I/O error.
* @throws UnsupportedCharsetException If the named charset is unavailable (unchecked exception).
@@ -509,7 +509,7 @@ public static boolean contentEqualsIgnoreEOL(final File file1, final File file2,
* representation. This is to account for the difference between
* File.listFiles() and FileUtils.listFiles().
*
- * @param files a Collection containing {@link File} instances
+ * @param files a Collection containing {@link File} instances.
* @return an array of {@link File}
*/
public static File[] convertFileCollectionToFileArray(final Collection files) {
@@ -545,9 +545,9 @@ public static File[] convertFileCollectionToFileArray(final Collection fil
* @param destDir the new directory, must not be {@code null}.
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory,
- * the source and the destination directory are the same
+ * the source and the destination directory are the same.
* @throws FileNotFoundException if the source does not exist.
- * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
+ * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed.
* @since 1.1
*/
public static void copyDirectory(final File srcDir, final File destDir) throws IOException {
@@ -573,9 +573,9 @@ public static void copyDirectory(final File srcDir, final File destDir) throws I
* @param destDir the new directory, must not be {@code null}.
* @param preserveFileDate true if the file date of the copy should be the same as the original.
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or
- * the source and the destination directory are the same
+ * the source and the destination directory are the same.
* @throws FileNotFoundException if the source does not exist.
- * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
+ * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed.
* @since 1.1
*/
public static void copyDirectory(final File srcDir, final File destDir, final boolean preserveFileDate)
@@ -623,9 +623,9 @@ public static void copyDirectory(final File srcDir, final File destDir, final bo
* @param filter the filter to apply, null means copy all directories and files should be the same as the original.
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or
- * the source and the destination directory are the same
+ * the source and the destination directory are the same.
* @throws FileNotFoundException if the source does not exist.
- * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
+ * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed.
* @since 1.4
*/
public static void copyDirectory(final File srcDir, final File destDir, final FileFilter filter)
@@ -675,7 +675,7 @@ public static void copyDirectory(final File srcDir, final File destDir, final Fi
* @param preserveFileDate true if the file date of the copy should be the same as the original.
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory,
- * the source and the destination directory are the same, or the destination is not writable
+ * the source and the destination directory are the same, or the destination is not writable.
* @throws FileNotFoundException if the source does not exist.
* @throws IOException if an error occurs or setting the last-modified time didn't succeed.
* @since 1.4
@@ -722,14 +722,14 @@ public static void copyDirectory(final File srcDir, final File destDir, final Fi
*
* @param srcDir an existing directory to copy, must not be {@code null}
* @param destDir the new directory, must not be {@code null}
- * @param fileFilter the filter to apply, null means copy all directories and files
- * @param preserveFileDate true if the file date of the copy should be the same as the original
+ * @param fileFilter the filter to apply, null means copy all directories and files.
+ * @param preserveFileDate true if the file date of the copy should be the same as the original.
* @param copyOptions options specifying how the copy should be done, for example {@link StandardCopyOption}.
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
* @throws IllegalArgumentException if {@code srcDir} exists but is not a directory, or
- * the source and the destination directory are the same
+ * the source and the destination directory are the same.
* @throws FileNotFoundException if the source does not exist.
- * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
+ * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed.
* @since 2.8.0
*/
public static void copyDirectory(final File srcDir, final File destDir, final FileFilter fileFilter, final boolean preserveFileDate,
@@ -775,7 +775,7 @@ public static void copyDirectory(final File srcDir, final File destDir, final Fi
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
* @throws IllegalArgumentException if the source or destination is invalid.
* @throws FileNotFoundException if the source does not exist.
- * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed
+ * @throws IOException if an error occurs, the destination is not writable, or setting the last-modified time didn't succeed.
* @since 1.2
*/
public static void copyDirectoryToDirectory(final File sourceDir, final File destinationDir) throws IOException {
@@ -831,7 +831,7 @@ public static void copyFile(final File srcFile, final File destFile) throws IOEx
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
* @throws IOException if source or destination is invalid.
* @throws IOException if an error occurs or setting the last-modified time didn't succeed.
- * @throws IOException if the output file length is not the same as the input file length after the copy completes
+ * @throws IOException if the output file length is not the same as the input file length after the copy completes.
* @see #copyFile(File, File, boolean, CopyOption...)
*/
public static void copyFile(final File srcFile, final File destFile, final boolean preserveFileDate) throws IOException {
@@ -864,10 +864,10 @@ public static void copyFile(final File srcFile, final File destFile, final boole
* @param copyOptions options specifying how the copy should be done, for example {@link StandardCopyOption}.
* @throws NullPointerException if any of the given {@link File}s are {@code null}.
* @throws FileNotFoundException if the source does not exist.
- * @throws IllegalArgumentException if {@code srcFile} or {@code destFile} is not a file
+ * @throws IllegalArgumentException if {@code srcFile} or {@code destFile} is not a file.
* @throws IOException if the output file length is not the same as the input file length after the copy completes.
* @throws IOException if an I/O error occurs, setting the last-modified time didn't succeed,
- * or the destination is not writable
+ * or the destination is not writable.
* @see #copyFileToDirectory(File, File, boolean)
* @since 2.8.0
*/
@@ -917,7 +917,7 @@ public static void copyFile(final File srcFile, final File destFile, final CopyO
*
* @param input the {@link File} to read.
* @param output the {@link OutputStream} to write.
- * @return the number of bytes copied
+ * @return the number of bytes copied.
* @throws NullPointerException if the File is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
* @throws IOException if an I/O error occurs.
@@ -995,13 +995,13 @@ public static void copyFileToDirectory(final File sourceFile, final File destina
* See {@link #copyToFile(InputStream, File)} for a method that does not close the input stream.
*
*
- * @param source the {@link InputStream} to copy bytes from, must not be {@code null}, will be closed
+ * @param source the {@link InputStream} to copy bytes from, must not be {@code null}, will be closed.
* @param destination the non-directory {@link File} to write bytes to
* (possibly overwriting), must not be {@code null}
- * @throws IOException if {@code destination} is a directory
- * @throws IOException if {@code destination} cannot be written
- * @throws IOException if {@code destination} needs creating but can't be
- * @throws IOException if an IO error occurs during copying
+ * @throws IOException if {@code destination} is a directory.
+ * @throws IOException if {@code destination} cannot be written.
+ * @throws IOException if {@code destination} needs creating but can't be.
+ * @throws IOException if an IO error occurs during copying.
* @since 2.0
*/
public static void copyInputStreamToFile(final InputStream source, final File destination) throws IOException {
@@ -1116,11 +1116,11 @@ public static void copyToFile(final InputStream inputStream, final File file) th
* @param source the {@link URL} to copy bytes from, must not be {@code null}
* @param destination the non-directory {@link File} to write bytes to
* (possibly overwriting), must not be {@code null}
- * @throws IOException if {@code source} URL cannot be opened
- * @throws IOException if {@code destination} is a directory
- * @throws IOException if {@code destination} cannot be written
- * @throws IOException if {@code destination} needs creating but can't be
- * @throws IOException if an IO error occurs during copying
+ * @throws IOException if {@code source} URL cannot be opened.
+ * @throws IOException if {@code destination} is a directory.
+ * @throws IOException if {@code destination} cannot be written.
+ * @throws IOException if {@code destination} needs creating but can't be.
+ * @throws IOException if an IO error occurs during copying.
*/
public static void copyURLToFile(final URL source, final File destination) throws IOException {
final Path path = destination.toPath();
@@ -1140,11 +1140,11 @@ public static void copyURLToFile(final URL source, final File destination) throw
* be established to the {@code source}
* @param readTimeoutMillis the number of milliseconds until this method will time out if no data could be read from
* the {@code source}
- * @throws IOException if {@code source} URL cannot be opened
- * @throws IOException if {@code destination} is a directory
- * @throws IOException if {@code destination} cannot be written
- * @throws IOException if {@code destination} needs creating but can't be
- * @throws IOException if an IO error occurs during copying
+ * @throws IOException if {@code source} URL cannot be opened.
+ * @throws IOException if {@code destination} is a directory.
+ * @throws IOException if {@code destination} cannot be written.
+ * @throws IOException if {@code destination} needs creating but can't be.
+ * @throws IOException if an IO error occurs during copying.
* @since 2.0
*/
public static void copyURLToFile(final URL source, final File destination, final int connectionTimeoutMillis, final int readTimeoutMillis)
@@ -1235,7 +1235,7 @@ static String decodeUrl(final String url) {
*
* @param file The file to delete.
* @return the given file.
- * @throws NullPointerException if the parameter is {@code null}
+ * @throws NullPointerException if the parameter is {@code null}.
* @throws IOException if the file cannot be deleted.
* @see File#delete()
* @since 2.9.0
@@ -1249,10 +1249,10 @@ public static File delete(final File file) throws IOException {
/**
* Deletes a directory recursively.
*
- * @param directory directory to delete
- * @throws IOException in case deletion is unsuccessful
- * @throws NullPointerException if the parameter is {@code null}
- * @throws IllegalArgumentException if {@code directory} is not a directory
+ * @param directory directory to delete.
+ * @throws IOException in case deletion is unsuccessful.
+ * @throws NullPointerException if the parameter is {@code null}.
+ * @throws IllegalArgumentException if {@code directory} is not a directory.
*/
public static void deleteDirectory(final File directory) throws IOException {
Objects.requireNonNull(directory, "directory");
@@ -1269,8 +1269,8 @@ public static void deleteDirectory(final File directory) throws IOException {
* Requests a directory for deletion recursively when the virtual machine terminates.
*
* @param directory directory to delete, must not be {@code null}
- * @throws NullPointerException if the directory is {@code null}
- * @throws IOException in case deletion is unsuccessful
+ * @throws NullPointerException if the directory is {@code null}.
+ * @throws IOException in case deletion is unsuccessful.
*/
private static void deleteDirectoryOnExit(final File directory) throws IOException {
if (!directory.exists()) {
@@ -1292,9 +1292,9 @@ private static void deleteDirectoryOnExit(final File directory) throws IOExcepti
*
No exceptions are thrown when a file or directory cannot be deleted.
*
*
- * @param file file or directory to delete, can be {@code null}
+ * @param file file or directory to delete, can be {@code null}.
* @return {@code true} if the file or directory was deleted, otherwise
- * {@code false}
+ * {@code false}.
* @since 1.4
*/
public static boolean deleteQuietly(final File file) {
@@ -1360,7 +1360,7 @@ public static boolean directoryContains(final File directory, final File child)
* @param preserveDirDate preserve the directories last modified dates.
* @param copyOptions options specifying how the copy should be done, see {@link StandardCopyOption}.
* @throws IOException if the directory was not created along with all its parent directories.
- * @throws IllegalArgumentException if {@code destDir} is not writable
+ * @throws IllegalArgumentException if {@code destDir} is not writable.
* @throws SecurityException See {@link File#mkdirs()}.
*/
private static void doCopyDirectory(final File srcDir, final File destDir, final FileFilter fileFilter, final List exclusionList,
@@ -1540,9 +1540,9 @@ private static File getParentFile(final File file) {
}
/**
- * Gets a {@link File} representing the system temporary directory.
+ * Gets a {@link File} representing the system temporary directory based on the Java system property {@code java.io.tmpdir}.
*
- * @return the system temporary directory as a File
+ * @return the system temporary directory as a File.
* @since 2.0
*/
public static File getTempDirectory() {
@@ -1550,14 +1550,13 @@ public static File getTempDirectory() {
}
/**
- * Getsv the path to the system temporary directory.
- *
- * WARNING: this method relies on the Java system property 'java.io.tmpdir'
- * which may or may not have a trailing file separator.
- * This can affect code that uses String processing to manipulate pathnames rather
- * than the standard libary methods in classes such as {@link File}
+ * Gets the path to the system temporary directory.
+ *
+ * WARNING: This method reads the Java system property {@code java.io.tmpdir}, which may or may not have a trailing file separator. This can affect code
+ * that uses String processing to manipulate pathnames rather than the standard library methods in classes such as {@link File}.
+ *
*
- * @return the path to the system temporary directory as a String
+ * @return the path to the system temporary directory as a String.
* @since 2.0
*/
public static String getTempDirectoryPath() {
@@ -1565,7 +1564,7 @@ public static String getTempDirectoryPath() {
}
/**
- * Gets a {@link File} representing the user's home directory.
+ * Gets a {@link File} representing the user's home directory based on the Java system property {@code user.home}.
*
* @return the user's home directory.
* @since 2.0
@@ -1575,7 +1574,7 @@ public static File getUserDirectory() {
}
/**
- * Gets the path to the user's home directory.
+ * Gets the path to the user's home directory based on the Java system property {@code user.home}.
*
* @return the path to the user's home directory.
* @since 2.0
@@ -1589,7 +1588,7 @@ public static String getUserDirectoryPath() {
* null-safe delegate to {@link Files#isDirectory(Path path, LinkOption... options)}.
*
* @param file the path to the file.
- * @param options options indicating how symbolic links are handled
+ * @param options options indicating how symbolic links are handled.
* @return {@code true} if the file is a directory; {@code false} if
* the path is null, the file does not exist, is not a directory, or it cannot
* be determined if the file is a directory or not.
@@ -1632,7 +1631,7 @@ public static boolean isEmptyDirectory(final File directory) throws IOException
* @param chronoLocalDate the date reference.
* @return true if the {@link File} exists and has been modified after the given
* {@link ChronoLocalDate} at the current time.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @throws NullPointerException if the file or local date is {@code null}.
* @since 2.8.0
*/
@@ -1656,7 +1655,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoL
* @param localTime the time reference.
* @return true if the {@link File} exists and has been modified after the given
* {@link ChronoLocalDate} at the given time.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @throws NullPointerException if the file, local date or zone ID is {@code null}.
* @since 2.8.0
*/
@@ -1670,13 +1669,13 @@ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoL
* Tests if the specified {@link File} is newer than the specified {@link ChronoLocalDate} at the specified
* {@link OffsetTime}.
*
- * @param file the {@link File} of which the modification date must be compared
- * @param chronoLocalDate the date reference
- * @param offsetTime the time reference
+ * @param file the {@link File} of which the modification date must be compared.
+ * @param chronoLocalDate the date reference.
+ * @param offsetTime the time reference.
* @return true if the {@link File} exists and has been modified after the given {@link ChronoLocalDate} at the given
* {@link OffsetTime}.
- * @throws UncheckedIOException if an I/O error occurs
- * @throws NullPointerException if the file, local date or zone ID is {@code null}
+ * @throws UncheckedIOException if an I/O error occurs.
+ * @throws NullPointerException if the file, local date or zone ID is {@code null}.
* @since 2.12.0
*/
public static boolean isFileNewer(final File file, final ChronoLocalDate chronoLocalDate, final OffsetTime offsetTime) {
@@ -1700,7 +1699,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDate chronoL
* @param chronoLocalDateTime the date reference.
* @return true if the {@link File} exists and has been modified after the given
* {@link ChronoLocalDateTime} at the system-default time zone.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @throws NullPointerException if the file or local date time is {@code null}.
* @since 2.8.0
*/
@@ -1717,7 +1716,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDateTime>
* @param zoneId the time zone.
* @return true if the {@link File} exists and has been modified after the given
* {@link ChronoLocalDateTime} at the given {@link ZoneId}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @throws NullPointerException if the file, local date time or zone ID is {@code null}.
* @since 2.8.0
*/
@@ -1735,7 +1734,7 @@ public static boolean isFileNewer(final File file, final ChronoLocalDateTime>
* @return true if the {@link File} exists and has been modified after the given
* {@link ChronoZonedDateTime}.
* @throws NullPointerException if the file or zoned date time is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @since 2.8.0
*/
public static boolean isFileNewer(final File file, final ChronoZonedDateTime> chronoZonedDateTime) {
@@ -1751,7 +1750,7 @@ public static boolean isFileNewer(final File file, final ChronoZonedDateTime>
* @param date the date reference.
* @return true if the {@link File} exists and has been modified
* after the given {@link Date}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @throws NullPointerException if the file or date is {@code null}.
*/
public static boolean isFileNewer(final File file, final Date date) {
@@ -1795,7 +1794,7 @@ public static boolean isFileNewer(final File file, final FileTime fileTime) thro
* @param instant the date reference.
* @return true if the {@link File} exists and has been modified after the given {@link Instant}.
* @throws NullPointerException if the file or instant is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @since 2.8.0
*/
public static boolean isFileNewer(final File file, final Instant instant) {
@@ -1810,7 +1809,7 @@ public static boolean isFileNewer(final File file, final Instant instant) {
* @param timeMillis the time reference measured in milliseconds since the
* epoch (00:00:00 GMT, January 1, 1970).
* @return true if the {@link File} exists and has been modified after the given time reference.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @throws NullPointerException if the file is {@code null}.
*/
public static boolean isFileNewer(final File file, final long timeMillis) {
@@ -1821,11 +1820,11 @@ public static boolean isFileNewer(final File file, final long timeMillis) {
/**
* Tests if the specified {@link File} is newer than the specified {@link OffsetDateTime}.
*
- * @param file the {@link File} of which the modification date must be compared
- * @param offsetDateTime the date reference
+ * @param file the {@link File} of which the modification date must be compared.
+ * @param offsetDateTime the date reference.
* @return true if the {@link File} exists and has been modified before the given {@link OffsetDateTime}.
- * @throws UncheckedIOException if an I/O error occurs
- * @throws NullPointerException if the file or zoned date time is {@code null}
+ * @throws UncheckedIOException if an I/O error occurs.
+ * @throws NullPointerException if the file or zoned date time is {@code null}.
* @since 2.12.0
*/
public static boolean isFileNewer(final File file, final OffsetDateTime offsetDateTime) {
@@ -1850,7 +1849,7 @@ public static boolean isFileNewer(final File file, final OffsetDateTime offsetDa
* @return true if the {@link File} exists and has been modified before the given
* {@link ChronoLocalDate} at the current time.
* @throws NullPointerException if the file or local date is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @see ZoneId#systemDefault()
* @see LocalTime#now()
* @since 2.8.0
@@ -1875,7 +1874,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoL
* @param localTime the time reference.
* @return true if the {@link File} exists and has been modified before the
* given {@link ChronoLocalDate} at the specified time.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @throws NullPointerException if the file, local date or local time is {@code null}.
* @see ZoneId#systemDefault()
* @since 2.8.0
@@ -1890,13 +1889,13 @@ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoL
* Tests if the specified {@link File} is older than the specified {@link ChronoLocalDate} at the specified
* {@link OffsetTime}.
*
- * @param file the {@link File} of which the modification date must be compared
- * @param chronoLocalDate the date reference
- * @param offsetTime the time reference
+ * @param file the {@link File} of which the modification date must be compared.
+ * @param chronoLocalDate the date reference.
+ * @param offsetTime the time reference.
* @return true if the {@link File} exists and has been modified after the given {@link ChronoLocalDate} at the given
* {@link OffsetTime}.
- * @throws NullPointerException if the file, local date or zone ID is {@code null}
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws NullPointerException if the file, local date or zone ID is {@code null}.
+ * @throws UncheckedIOException if an I/O error occurs.
* @since 2.12.0
*/
public static boolean isFileOlder(final File file, final ChronoLocalDate chronoLocalDate, final OffsetTime offsetTime) {
@@ -1921,7 +1920,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDate chronoL
* @return true if the {@link File} exists and has been modified before the given
* {@link ChronoLocalDateTime} at the system-default time zone.
* @throws NullPointerException if the file or local date time is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @see ZoneId#systemDefault()
* @since 2.8.0
*/
@@ -1939,7 +1938,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDateTime>
* @return true if the {@link File} exists and has been modified before the given
* {@link ChronoLocalDateTime} at the given {@link ZoneId}.
* @throws NullPointerException if the file, local date time or zone ID is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @since 2.8.0
*/
public static boolean isFileOlder(final File file, final ChronoLocalDateTime> chronoLocalDateTime, final ZoneId zoneId) {
@@ -1956,7 +1955,7 @@ public static boolean isFileOlder(final File file, final ChronoLocalDateTime>
* @return true if the {@link File} exists and has been modified before the given
* {@link ChronoZonedDateTime}.
* @throws NullPointerException if the file or zoned date time is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
* @since 2.8.0
*/
public static boolean isFileOlder(final File file, final ChronoZonedDateTime> chronoZonedDateTime) {
@@ -1971,7 +1970,7 @@ public static boolean isFileOlder(final File file, final ChronoZonedDateTime>
* @param date the date reference.
* @return true if the {@link File} exists and has been modified before the given {@link Date}.
* @throws NullPointerException if the file or date is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
*/
public static boolean isFileOlder(final File file, final Date date) {
Objects.requireNonNull(date, "date");
@@ -1986,7 +1985,7 @@ public static boolean isFileOlder(final File file, final Date date) {
* @return true if the {@link File} exists and has been modified before the reference {@link File}.
* @throws NullPointerException if the file or reference file is {@code null}.
* @throws FileNotFoundException if the reference file doesn't exist.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
*/
public static boolean isFileOlder(final File file, final File reference) throws FileNotFoundException {
return Uncheck.getAsBoolean(() -> PathUtils.isOlder(file.toPath(), reference.toPath()));
@@ -2029,7 +2028,7 @@ public static boolean isFileOlder(final File file, final Instant instant) {
* epoch (00:00:00 GMT, January 1, 1970).
* @return true if the {@link File} exists and has been modified before the given time reference.
* @throws NullPointerException if the file is {@code null}.
- * @throws UncheckedIOException if an I/O error occurs
+ * @throws UncheckedIOException if an I/O error occurs.
*/
public static boolean isFileOlder(final File file, final long timeMillis) {
Objects.requireNonNull(file, PROTOCOL_FILE);
@@ -2039,8 +2038,8 @@ public static boolean isFileOlder(final File file, final long timeMillis) {
/**
* Tests if the specified {@link File} is older than the specified {@link OffsetDateTime}.
*
- * @param file the {@link File} of which the modification date must be compared
- * @param offsetDateTime the date reference
+ * @param file the {@link File} of which the modification date must be compared.
+ * @param offsetDateTime the date reference.
* @return true if the {@link File} exists and has been modified before the given {@link OffsetDateTime}.
* @throws NullPointerException if the file or zoned date time is {@code null}
* @since 2.12.0
@@ -2065,7 +2064,7 @@ private static boolean isFileProtocol(final URL url) {
* null-safe delegate to {@link Files#isRegularFile(Path path, LinkOption... options)}.
*
* @param file the path to the file.
- * @param options options indicating how symbolic links are handled
+ * @param options options indicating how symbolic links are handled.
* @return {@code true} if the file is a regular file; {@code false} if
* the path is null, the file does not exist, is not a regular file, or it cannot
* be determined if the file is a regular file or not.
@@ -2290,7 +2289,7 @@ public static LineIterator lineIterator(final File file, final String charsetNam
inputStream = Files.newInputStream(file.toPath());
return IOUtils.lineIterator(inputStream, charsetName);
} catch (final IOException | RuntimeException ex) {
- IOUtils.closeQuietly(inputStream, ex::addSuppressed);
+ IOUtils.closeQuietlySuppress(inputStream, ex);
throw ex;
}
}
@@ -2693,9 +2692,9 @@ public static FileInputStream openInputStream(final File file) throws IOExceptio
*
*
* @param file the file to open for output, must not be {@code null}.
- * @return a new {@link FileOutputStream} for the specified file
+ * @return a new {@link FileOutputStream} for the specified file.
* @throws NullPointerException if the file object is {@code null}.
- * @throws IllegalArgumentException if the file object is a directory
+ * @throws IllegalArgumentException if the file object is a directory.
* @throws IllegalArgumentException if the file is not writable.
* @throws IOException if the directories could not be created.
* @since 1.3
@@ -2755,7 +2754,7 @@ public static byte[] readFileToByteArray(final File file) throws IOException {
}
/**
- * Reads the contents of a file into a String using the virtual machine's {@link Charset#defaultCharset() default charset}. The
+ * Reads the contents of a file into a String using the virtual machine's {@linkplain Charset#defaultCharset() default charset}. The
* file is always closed.
*
* @param file the file to read, must not be {@code null}.
@@ -2804,7 +2803,7 @@ public static String readFileToString(final File file, final String charsetName)
}
/**
- * Reads the contents of a file line by line to a List of Strings using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Reads the contents of a file line by line to a List of Strings using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
* The file is always closed.
*
* @param file the file to read, must not be {@code null}.
@@ -3212,7 +3211,7 @@ public static boolean waitFor(final File file, final int seconds) {
}
/**
- * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param file the file to write.
* @param data the content to write to the file.
@@ -3226,7 +3225,7 @@ public static void write(final File file, final CharSequence data) throws IOExce
}
/**
- * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes a CharSequence to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param file the file to write.
* @param data the content to write to the file.
@@ -3271,11 +3270,11 @@ public static void write(final File file, final CharSequence data, final Charset
/**
* Writes a CharSequence to a file creating the file if it does not exist.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @param charsetName the name of the requested charset, {@code null} means platform default
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
+ * @throws IOException in case of an I/O error.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM.
* @since 2.0
*/
public static void write(final File file, final CharSequence data, final String charsetName) throws IOException {
@@ -3285,13 +3284,13 @@ public static void write(final File file, final CharSequence data, final String
/**
* Writes a CharSequence to a file creating the file if it does not exist.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @param charsetName the name of the requested charset, {@code null} means platform default
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
* @param append if {@code true}, then the data will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
- * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
+ * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM.
* @since 2.1
*/
public static void write(final File file, final CharSequence data, final String charsetName, final boolean append) throws IOException {
@@ -3304,9 +3303,9 @@ public static void write(final File file, final CharSequence data, final String
* Writes a byte array to a file creating the file if it does not exist.
* The parent directories of the file will be created if they do not exist.
*
- * @param file the file to write to
- * @param data the content to write to the file
- * @throws IOException in case of an I/O error
+ * @param file the file to write to.
+ * @param data the content to write to the file.
+ * @throws IOException in case of an I/O error.
* @since 1.1
*/
public static void writeByteArrayToFile(final File file, final byte[] data) throws IOException {
@@ -3316,11 +3315,11 @@ public static void writeByteArrayToFile(final File file, final byte[] data) thro
/**
* Writes a byte array to a file creating the file if it does not exist.
*
- * @param file the file to write to
- * @param data the content to write to the file
+ * @param file the file to write to.
+ * @param data the content to write to the file.
* @param append if {@code true}, then bytes will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
* @since 2.1
*/
public static void writeByteArrayToFile(final File file, final byte[] data, final boolean append) throws IOException {
@@ -3332,11 +3331,11 @@ public static void writeByteArrayToFile(final File file, final byte[] data, fina
* at offset {@code off} to a file, creating the file if it does
* not exist.
*
- * @param file the file to write to
- * @param data the content to write to the file
- * @param off the start offset in the data
- * @param len the number of bytes to write
- * @throws IOException in case of an I/O error
+ * @param file the file to write to.
+ * @param data the content to write to the file.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
+ * @throws IOException in case of an I/O error.
* @since 2.5
*/
public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len) throws IOException {
@@ -3348,13 +3347,13 @@ public static void writeByteArrayToFile(final File file, final byte[] data, fina
* at offset {@code off} to a file, creating the file if it does
* not exist.
*
- * @param file the file to write to
- * @param data the content to write to the file
- * @param off the start offset in the data
- * @param len the number of bytes to write
+ * @param file the file to write to.
+ * @param data the content to write to the file.
+ * @param off the start offset in the data.
+ * @param len the number of bytes to write.
* @param append if {@code true}, then bytes will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
* @since 2.5
*/
public static void writeByteArrayToFile(final File file, final byte[] data, final int off, final int len, final boolean append) throws IOException {
@@ -3368,9 +3367,9 @@ public static void writeByteArrayToFile(final File file, final byte[] data, fina
* the specified {@link File} line by line.
* The default VM encoding and the default line ending will be used.
*
- * @param file the file to write to
- * @param lines the lines to write, {@code null} entries produce blank lines
- * @throws IOException in case of an I/O error
+ * @param file the file to write to.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
+ * @throws IOException in case of an I/O error.
* @since 1.3
*/
public static void writeLines(final File file, final Collection> lines) throws IOException {
@@ -3382,11 +3381,11 @@ public static void writeLines(final File file, final Collection> lines) throws
* the specified {@link File} line by line.
* The default VM encoding and the default line ending will be used.
*
- * @param file the file to write to
- * @param lines the lines to write, {@code null} entries produce blank lines
+ * @param file the file to write to.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
* @param append if {@code true}, then the lines will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
* @since 2.1
*/
public static void writeLines(final File file, final Collection> lines, final boolean append) throws IOException {
@@ -3398,10 +3397,10 @@ public static void writeLines(final File file, final Collection> lines, final
* the specified {@link File} line by line.
* The default VM encoding and the specified line ending will be used.
*
- * @param file the file to write to
- * @param lines the lines to write, {@code null} entries produce blank lines
- * @param lineEnding the line separator to use, {@code null} is system default
- * @throws IOException in case of an I/O error
+ * @param file the file to write to.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
+ * @param lineEnding the line separator to use, {@code null} is system default.
+ * @throws IOException in case of an I/O error.
* @since 1.3
*/
public static void writeLines(final File file, final Collection> lines, final String lineEnding) throws IOException {
@@ -3413,12 +3412,12 @@ public static void writeLines(final File file, final Collection> lines, final
* the specified {@link File} line by line.
* The default VM encoding and the specified line ending will be used.
*
- * @param file the file to write to
- * @param lines the lines to write, {@code null} entries produce blank lines
- * @param lineEnding the line separator to use, {@code null} is system default
+ * @param file the file to write to.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
+ * @param lineEnding the line separator to use, {@code null} is system default.
* @param append if {@code true}, then the lines will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
* @since 2.1
*/
public static void writeLines(final File file, final Collection> lines, final String lineEnding, final boolean append) throws IOException {
@@ -3431,11 +3430,11 @@ public static void writeLines(final File file, final Collection> lines, final
* The specified character encoding and the default line ending will be used.
* The parent directories of the file will be created if they do not exist.
*
- * @param file the file to write to
- * @param charsetName the name of the requested charset, {@code null} means platform default
- * @param lines the lines to write, {@code null} entries produce blank lines
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ * @param file the file to write to.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
+ * @throws IOException in case of an I/O error.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM.
* @since 1.1
*/
public static void writeLines(final File file, final String charsetName, final Collection> lines) throws IOException {
@@ -3447,13 +3446,13 @@ public static void writeLines(final File file, final String charsetName, final C
* the specified {@link File} line by line, optionally appending.
* The specified character encoding and the default line ending will be used.
*
- * @param file the file to write to
- * @param charsetName the name of the requested charset, {@code null} means platform default
- * @param lines the lines to write, {@code null} entries produce blank lines
+ * @param file the file to write to.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
* @param append if {@code true}, then the lines will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM.
* @since 2.1
*/
public static void writeLines(final File file, final String charsetName, final Collection> lines, final boolean append) throws IOException {
@@ -3466,12 +3465,12 @@ public static void writeLines(final File file, final String charsetName, final C
* The specified character encoding and the line ending will be used.
* The parent directories of the file will be created if they do not exist.
*
- * @param file the file to write to
- * @param charsetName the name of the requested charset, {@code null} means platform default
- * @param lines the lines to write, {@code null} entries produce blank lines
- * @param lineEnding the line separator to use, {@code null} is system default
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ * @param file the file to write to.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
+ * @param lineEnding the line separator to use, {@code null} is system default.
+ * @throws IOException in case of an I/O error.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM.
* @since 1.1
*/
public static void writeLines(final File file, final String charsetName, final Collection> lines, final String lineEnding) throws IOException {
@@ -3483,14 +3482,14 @@ public static void writeLines(final File file, final String charsetName, final C
* the specified {@link File} line by line.
* The specified character encoding and the line ending will be used.
*
- * @param file the file to write to
- * @param charsetName the name of the requested charset, {@code null} means platform default
- * @param lines the lines to write, {@code null} entries produce blank lines
- * @param lineEnding the line separator to use, {@code null} is system default
+ * @param file the file to write to.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
+ * @param lines the lines to write, {@code null} entries produce blank lines.
+ * @param lineEnding the line separator to use, {@code null} is system default.
* @param append if {@code true}, then the lines will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM.
* @since 2.1
*/
public static void writeLines(final File file, final String charsetName, final Collection> lines, final String lineEnding, final boolean append)
@@ -3501,12 +3500,12 @@ public static void writeLines(final File file, final String charsetName, final C
}
/**
- * Writes a String to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes a String to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @throws IOException in case of an I/O error
- * @deprecated Use {@link #writeStringToFile(File, String, Charset)} instead (and specify the appropriate encoding)
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @throws IOException in case of an I/O error.
+ * @deprecated Use {@link #writeStringToFile(File, String, Charset)} instead (and specify the appropriate encoding).
*/
@Deprecated
public static void writeStringToFile(final File file, final String data) throws IOException {
@@ -3514,14 +3513,14 @@ public static void writeStringToFile(final File file, final String data) throws
}
/**
- * Writes a String to a file creating the file if it does not exist using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes a String to a file creating the file if it does not exist using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @param append if {@code true}, then the String will be added to the end of the file rather than overwriting
- * @throws IOException in case of an I/O error
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @param append if {@code true}, then the String will be added to the end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
* @since 2.1
- * @deprecated Use {@link #writeStringToFile(File, String, Charset, boolean)} instead (and specify the appropriate encoding)
+ * @deprecated Use {@link #writeStringToFile(File, String, Charset, boolean)} instead (and specify the appropriate encoding).
*/
@Deprecated
public static void writeStringToFile(final File file, final String data, final boolean append) throws IOException {
@@ -3532,11 +3531,11 @@ public static void writeStringToFile(final File file, final String data, final b
* Writes a String to a file creating the file if it does not exist.
* The parent directories of the file will be created if they do not exist.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @param charset the charset to use, {@code null} means platform default
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @param charset the charset to use, {@code null} means platform default.
+ * @throws IOException in case of an I/O error.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM.
* @since 2.4
*/
public static void writeStringToFile(final File file, final String data, final Charset charset) throws IOException {
@@ -3547,12 +3546,12 @@ public static void writeStringToFile(final File file, final String data, final C
* Writes a String to a file, creating the file if it does not exist.
* The parent directories of the file are created if they do not exist.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @param charset the charset to use, {@code null} means platform default
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @param charset the charset to use, {@code null} means platform default.
* @param append if {@code true}, then the String will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
* @since 2.3
*/
public static void writeStringToFile(final File file, final String data, final Charset charset, final boolean append) throws IOException {
@@ -3565,11 +3564,11 @@ public static void writeStringToFile(final File file, final String data, final C
* Writes a String to a file, creating the file if it does not exist.
* The parent directories of the file are created if they do not exist.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @param charsetName the name of the requested charset, {@code null} means platform default
- * @throws IOException in case of an I/O error
- * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
+ * @throws IOException in case of an I/O error.
+ * @throws java.io.UnsupportedEncodingException if the encoding is not supported by the VM.
*/
public static void writeStringToFile(final File file, final String data, final String charsetName) throws IOException {
writeStringToFile(file, data, charsetName, false);
@@ -3579,13 +3578,13 @@ public static void writeStringToFile(final File file, final String data, final S
* Writes a String to a file, creating the file if it does not exist.
* The parent directories of the file are created if they do not exist.
*
- * @param file the file to write
- * @param data the content to write to the file
- * @param charsetName the name of the requested charset, {@code null} means platform default
+ * @param file the file to write.
+ * @param data the content to write to the file.
+ * @param charsetName the name of the requested charset, {@code null} means platform default.
* @param append if {@code true}, then the String will be added to the
- * end of the file rather than overwriting
- * @throws IOException in case of an I/O error
- * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM
+ * end of the file rather than overwriting.
+ * @throws IOException in case of an I/O error.
+ * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported by the VM.
* @since 2.1
*/
public static void writeStringToFile(final File file, final String data, final String charsetName, final boolean append) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/FilenameUtils.java b/src/main/java/org/apache/commons/io/FilenameUtils.java
index ec836e29421..f8ddc7515e0 100644
--- a/src/main/java/org/apache/commons/io/FilenameUtils.java
+++ b/src/main/java/org/apache/commons/io/FilenameUtils.java
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.commons.io;
import java.io.File;
@@ -28,30 +29,25 @@
import java.util.stream.Stream;
/**
- * General file name and file path manipulation utilities. The methods in this class
- * operate on strings that represent relative or absolute paths. Nothing in this class
- * ever accesses the file system, or depends on whether a path points to a file that exists.
+ * General file name and file path manipulation utilities. The methods in this class operate on strings that represent relative or absolute paths. Nothing in
+ * this class ever accesses the file system, or depends on whether a path points to a file that exists.
*
- * When dealing with file names, you can hit problems when moving from a Windows
- * based development machine to a Unix based production machine.
- * This class aims to help avoid those problems.
+ * When dealing with file names, you can hit problems when moving from a Windows based development machine to a Unix based production machine. This class aims
+ * to help avoid those problems.
*
*
- * NOTE: You may be able to avoid using this class entirely simply by
- * using JDK {@link File File} objects and the two argument constructor
+ * NOTE: You may be able to avoid using this class entirely simply by using JDK {@link File File} objects and the two argument constructor
* {@link File#File(java.io.File, String) File(File,String)}.
*
*
- * Most methods in this class are designed to work the same on both Unix and Windows.
- * Those that don't include 'System', 'Unix', or 'Windows' in their name.
+ * Most methods in this class are designed to work the same on both Unix and Windows. Those that don't include 'System', 'Unix', or 'Windows' in their name.
*
*
- * Most methods recognize both separators (forward and backslashes), and both
- * sets of prefixes. See the Javadoc of each method for details.
+ * Most methods recognize both separators (forward and backslashes), and both sets of prefixes. See the Javadoc of each method for details.
*
*
- * This class defines six components within a path (sometimes called a file name or a full file name).
- * Given an absolute Windows path such as C:\dev\project\file.txt they are:
+ * This class defines six components within a path (sometimes called a file name or a full file name). Given an absolute Windows path such as
+ * C:\dev\project\file.txt they are:
*
*
*
the full file name, or just file name - C:\dev\project\file.txt
@@ -98,18 +94,14 @@
*
the base name - file
*
the extension - txt
*
- *
- *
*
- * This class works best if directory names end with a separator.
- * If you omit the last separator, it is impossible to determine if the last component
- * corresponds to a file or a directory. This class treats final components
- * that do not end with a separator as files, not directories.
+ * This class works best if directory names end with a separator. If you omit the last separator, it is impossible to determine if the last component
+ * corresponds to a file or a directory. This class treats final components that do not end with a separator as files, not directories.
*
*
- * This class only supports Unix and Windows style names.
- * Prefixes are matched as follows:
+ * This class only supports Unix and Windows style names. Prefixes are matched as follows:
*
- * Both prefix styles are matched, irrespective of the machine that you are
- * currently running on.
+ * Both prefix styles are matched, irrespective of the machine that you are currently running on.
*
*
* @since 1.1
@@ -143,12 +134,14 @@ public class FilenameUtils {
/**
* The extension separator character.
+ *
* @since 1.4
*/
public static final char EXTENSION_SEPARATOR = '.';
/**
* The extension separator String.
+ *
* @since 1.4
*/
public static final String EXTENSION_SEPARATOR_STR = Character.toString(EXTENSION_SEPARATOR);
@@ -190,24 +183,20 @@ public class FilenameUtils {
/**
* Concatenates a fileName to a base path using normal command line style rules.
*
- * The effect is equivalent to resultant directory after changing
- * directory to the first argument, followed by changing directory to
- * the second argument.
+ * The effect is equivalent to resultant directory after changing directory to the first argument, followed by changing directory to the second argument.
*
*
- * The first argument is the base path, the second is the path to concatenate.
- * The returned path is always normalized via {@link #normalize(String)},
- * thus {@code ..} is handled.
+ * The first argument is the base path, the second is the path to concatenate. The returned path is always normalized via {@link #normalize(String)}, thus
+ * {@code ..} is handled.
*
*
- * If {@code pathToAdd} is absolute (has an absolute prefix), then
- * it will be normalized and returned.
- * Otherwise, the paths will be joined, normalized and returned.
+ * If {@code pathToAdd} is absolute (has an absolute prefix), then it will be normalized and returned. Otherwise, the paths will be joined, normalized and
+ * returned.
*
*
- * The output will be the same on both Unix and Windows except
- * for the separator character.
+ * The output will be the same on both Unix and Windows except for the separator character.
*
+ *
*
* /foo/ + bar --> /foo/bar
* /foo + bar --> /foo/bar
@@ -222,19 +211,17 @@ public class FilenameUtils {
* /foo/c.txt + bar --> /foo/c.txt/bar [2]
*
*
- * [1] Note that the Windows relative drive prefix is unreliable when
- * used with this method.
+ * [1] Note that the Windows relative drive prefix is unreliable when used with this method.
*
*
- * [2] Note that the first parameter must be a path. If it ends with a name, then
- * the name will be built into the concatenated path. If this might be a problem,
- * use {@link #getFullPath(String)} on the base path argument.
+ * [2] Note that the first parameter must be a path. If it ends with a name, then the name will be built into the concatenated path. If this might be a
+ * problem, use {@link #getFullPath(String)} on the base path argument.
*
*
- * @param basePath the base path to attach to, always treated as a path
- * @param fullFileNameToAdd the file name (or path) to attach to the base
- * @return the concatenated path, or null if invalid
- * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000})
+ * @param basePath the base path to attach to, always treated as a path.
+ * @param fullFileNameToAdd the file name (or path) to attach to the base.
+ * @return the concatenated path, or null if invalid.
+ * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}).
*/
public static String concat(final String basePath, final String fullFileNameToAdd) {
final int prefix = getPrefixLength(fullFileNameToAdd);
@@ -259,13 +246,11 @@ public static String concat(final String basePath, final String fullFileNameToAd
}
/**
- * Determines whether the {@code parent} directory contains the {@code child} (a file or directory).
- * This does not read from the file system, and there is no guarantee or expectation that
- * these paths actually exist.
+ * Determines whether the {@code parent} directory contains the {@code child} (a file or directory). This does not read from the file system, and there is
+ * no guarantee or expectation that these paths actually exist.
*
* The files names are expected to be normalized.
*
- *
* Edge cases:
*
*
A {@code directory} must not be null: if null, throw IllegalArgumentException
@@ -274,35 +259,29 @@ public static String concat(final String basePath, final String fullFileNameToAd
*
*
* @param canonicalParent the path string to consider as the parent.
- * @param canonicalChild the path string to consider as the child.
+ * @param canonicalChild the path string to consider as the child.
* @return true if the candidate leaf is under the specified composite. False otherwise.
* @since 2.2
* @see FileUtils#directoryContains(File, File)
*/
public static boolean directoryContains(final String canonicalParent, final String canonicalChild) {
- if (isEmpty(canonicalParent) || isEmpty(canonicalChild)) {
+ if (isEmpty(canonicalParent) || isEmpty(canonicalChild) || IOCase.SYSTEM.checkEquals(canonicalParent, canonicalChild)) {
return false;
}
-
- if (IOCase.SYSTEM.checkEquals(canonicalParent, canonicalChild)) {
- return false;
- }
-
final char separator = toSeparator(canonicalParent.charAt(0) == UNIX_NAME_SEPARATOR);
final String parentWithEndSeparator = canonicalParent.charAt(canonicalParent.length() - 1) == separator ? canonicalParent : canonicalParent + separator;
-
return IOCase.SYSTEM.checkStartsWith(canonicalChild, parentWithEndSeparator);
}
/**
* Does the work of getting the path.
*
- * @param fileName the file name
- * @param includeSeparator true to include the end separator
- * @return the path
- * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000})
+ * @param fileName the file name.
+ * @param includeEndSeparator true to include the end separator.
+ * @return the path.
+ * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}).
*/
- private static String doGetFullPath(final String fileName, final boolean includeSeparator) {
+ private static String doGetFullPath(final String fileName, final boolean includeEndSeparator) {
if (fileName == null) {
return null;
}
@@ -311,8 +290,8 @@ private static String doGetFullPath(final String fileName, final boolean include
return null;
}
if (prefix >= fileName.length()) {
- if (includeSeparator) {
- return getPrefix(fileName); // add end slash if necessary
+ if (includeEndSeparator) {
+ return getPrefix(fileName); // add end slash if necessary
}
return fileName;
}
@@ -320,7 +299,7 @@ private static String doGetFullPath(final String fileName, final boolean include
if (index < 0) {
return fileName.substring(0, prefix);
}
- int end = index + (includeSeparator ? 1 : 0);
+ int end = index + (includeEndSeparator ? 1 : 0);
if (end == 0) {
end++;
}
@@ -330,10 +309,10 @@ private static String doGetFullPath(final String fileName, final boolean include
/**
* Does the work of getting the path.
*
- * @param fileName the file name
- * @param separatorAdd 0 to omit the end separator, 1 to return it
- * @return the path
- * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000})
+ * @param fileName the file name.
+ * @param separatorAdd 0 to omit the end separator, 1 to return it.
+ * @return the path.
+ * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}).
*/
private static String doGetPath(final String fileName, final int separatorAdd) {
if (fileName == null) {
@@ -354,19 +333,17 @@ private static String doGetPath(final String fileName, final int separatorAdd) {
/**
* Internal method to perform the normalization.
*
- * @param fileName the file name
- * @param separator The separator character to use
- * @param keepSeparator true to keep the final separator
- * @return the normalized fileName
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name.
+ * @param separator The separator character to use.
+ * @param keepSeparator true to keep the final separator.
+ * @return the normalized fileName.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
private static String doNormalize(final String fileName, final char separator, final boolean keepSeparator) {
if (fileName == null) {
return null;
}
-
requireNonNullChars(fileName);
-
int size = fileName.length();
if (size == 0) {
return fileName;
@@ -375,10 +352,8 @@ private static String doNormalize(final String fileName, final char separator, f
if (prefix < 0) {
return null;
}
-
- final char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy
+ final char[] array = new char[size + 2]; // +1 for possible extra slash, +2 for arraycopy
fileName.getChars(0, fileName.length(), array, 0);
-
// fix separators throughout
final char otherSeparator = flipSeparator(separator);
for (int i = 0; i < array.length; i++) {
@@ -386,14 +361,12 @@ private static String doNormalize(final String fileName, final char separator, f
array[i] = separator;
}
}
-
// add extra separator on the end to simplify code below
boolean lastIsDirectory = true;
if (array[size - 1] != separator) {
array[size++] = separator;
lastIsDirectory = false;
}
-
// adjoining slashes
// If we get here, prefix can only be 0 or greater, size 1 or greater
// If prefix is 0, set loop start to 1 to prevent index errors
@@ -404,11 +377,9 @@ private static String doNormalize(final String fileName, final char separator, f
i--;
}
}
-
// period slash
for (int i = prefix + 1; i < size; i++) {
- if (array[i] == separator && array[i - 1] == '.' &&
- (i == prefix + 1 || array[i - 2] == separator)) {
+ if (array[i] == separator && array[i - 1] == '.' && (i == prefix + 1 || array[i - 2] == separator)) {
if (i == size - 1) {
lastIsDirectory = true;
}
@@ -417,12 +388,9 @@ private static String doNormalize(final String fileName, final char separator, f
i--;
}
}
-
// double period slash
- outer:
- for (int i = prefix + 2; i < size; i++) {
- if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' &&
- (i == prefix + 2 || array[i - 3] == separator)) {
+ outer: for (int i = prefix + 2; i < size; i++) {
+ if (array[i] == separator && array[i - 1] == '.' && array[i - 2] == '.' && (i == prefix + 2 || array[i - 3] == separator)) {
if (i == prefix + 2) {
return null;
}
@@ -430,7 +398,7 @@ private static String doNormalize(final String fileName, final char separator, f
lastIsDirectory = true;
}
int j;
- for (j = i - 4 ; j >= prefix; j--) {
+ for (j = i - 4; j >= prefix; j--) {
if (array[j] == separator) {
// remove b/../ from a/b/../c
System.arraycopy(array, i + 1, array, j + 1, size - i);
@@ -445,29 +413,24 @@ private static String doNormalize(final String fileName, final char separator, f
i = prefix + 1;
}
}
-
- if (size <= 0) { // should never be less than 0
+ if (size <= 0) { // should never be less than 0
return EMPTY_STRING;
}
- if (size <= prefix) { // should never be less than prefix
- return new String(array, 0, size);
+ if (size <= prefix || lastIsDirectory && keepSeparator) {
+ return new String(array, 0, size); // keep trailing separator
}
- if (lastIsDirectory && keepSeparator) {
- return new String(array, 0, size); // keep trailing separator
- }
- return new String(array, 0, size - 1); // lose trailing separator
+ return new String(array, 0, size - 1); // lose trailing separator
}
/**
* Checks whether two file names are exactly equal.
*
- * No processing is performed on the file names other than comparison.
- * This is merely a null-safe case-sensitive string equality.
+ * No processing is performed on the file names other than comparison. This is merely a null-safe case-sensitive string equality.
*
*
- * @param fileName1 the first file name, may be null
- * @param fileName2 the second file name, may be null
- * @return true if the file names are equal, null equals null
+ * @param fileName1 the first file name, may be null.
+ * @param fileName2 the second file name, may be null.
+ * @return true if the file names are equal, null equals null.
* @see IOCase#SENSITIVE
*/
public static boolean equals(final String fileName1, final String fileName2) {
@@ -475,18 +438,16 @@ public static boolean equals(final String fileName1, final String fileName2) {
}
/**
- * Checks whether two file names are equal, optionally normalizing and providing
- * control over the case-sensitivity.
- *
- * @param fileName1 the first file name, may be null
- * @param fileName2 the second file name, may be null
- * @param normalize whether to normalize the file names
- * @param ioCase what case sensitivity rule to use, null means case-sensitive
- * @return true if the file names are equal, null equals null
+ * Checks whether two file names are equal, optionally normalizing and providing control over the case-sensitivity.
+ *
+ * @param fileName1 the first file name, may be null.
+ * @param fileName2 the second file name, may be null.
+ * @param normalize whether to normalize the file names.
+ * @param ioCase what case sensitivity rule to use, null means case-sensitive.
+ * @return true if the file names are equal, null equals null.
* @since 1.3
*/
public static boolean equals(String fileName1, String fileName2, final boolean normalize, final IOCase ioCase) {
-
if (fileName1 == null || fileName2 == null) {
return fileName1 == null && fileName2 == null;
}
@@ -506,13 +467,12 @@ public static boolean equals(String fileName1, String fileName2, final boolean n
/**
* Checks whether two file names are equal after both have been normalized.
*
- * Both file names are first passed to {@link #normalize(String)}.
- * The check is then performed in a case-sensitive manner.
+ * Both file names are first passed to {@link #normalize(String)}. The check is then performed in a case-sensitive manner.
*
*
- * @param fileName1 the first file name, may be null
- * @param fileName2 the second file name, may be null
- * @return true if the file names are equal, null equals null
+ * @param fileName1 the first file name, may be null.
+ * @param fileName2 the second file name, may be null.
+ * @return true if the file names are equal, null equals null.
* @see IOCase#SENSITIVE
*/
public static boolean equalsNormalized(final String fileName1, final String fileName2) {
@@ -520,17 +480,14 @@ public static boolean equalsNormalized(final String fileName1, final String file
}
/**
- * Checks whether two file names are equal using the case rules of the system
- * after both have been normalized.
+ * Checks whether two file names are equal using the case rules of the system after both have been normalized.
*
- * Both file names are first passed to {@link #normalize(String)}.
- * The check is then performed case-sensitively on Unix and
- * case-insensitively on Windows.
+ * Both file names are first passed to {@link #normalize(String)}. The check is then performed case-sensitively on Unix and case-insensitively on Windows.
*
*
- * @param fileName1 the first file name, may be null
- * @param fileName2 the second file name, may be null
- * @return true if the file names are equal, null equals null
+ * @param fileName1 the first file name, may be null.
+ * @param fileName2 the second file name, may be null.
+ * @return true if the file names are equal, null equals null.
* @see IOCase#SYSTEM
*/
public static boolean equalsNormalizedOnSystem(final String fileName1, final String fileName2) {
@@ -540,13 +497,12 @@ public static boolean equalsNormalizedOnSystem(final String fileName1, final Str
/**
* Checks whether two file names are equal using the case rules of the system.
*
- * No processing is performed on the file names other than comparison.
- * The check is case-sensitive on Unix and case-insensitive on Windows.
+ * No processing is performed on the file names other than comparison. The check is case-sensitive on Unix and case-insensitive on Windows.
*
*
- * @param fileName1 the first file name, may be null
- * @param fileName2 the second file name, may be null
- * @return true if the file names are equal, null equals null
+ * @param fileName1 the first file name, may be null.
+ * @param fileName2 the second file name, may be null.
+ * @return true if the file names are equal, null equals null.
* @see IOCase#SYSTEM
*/
public static boolean equalsOnSystem(final String fileName1, final String fileName2) {
@@ -572,7 +528,7 @@ static char flipSeparator(final char ch) {
/**
* Special handling for NTFS ADS: Don't accept colon in the file name.
*
- * @param fileName a file name
+ * @param fileName a file name.
* @return ADS offsets.
*/
private static int getAdsCriticalOffset(final String fileName) {
@@ -594,9 +550,9 @@ private static int getAdsCriticalOffset(final String fileName) {
/**
* Gets the base name, minus the full path and extension, from a full file name.
*
- * This method will handle a path in either Unix or Windows format.
- * The text after the last forward or backslash and before the last period is returned.
+ * This method will handle a path in either Unix or Windows format. The text after the last forward or backslash and before the last period is returned.
*
+ *
*
* a/b/c.txt --> c
* a\b\c.txt --> c
@@ -609,9 +565,9 @@ private static int getAdsCriticalOffset(final String fileName) {
* The output will be the same irrespective of the machine that the code is running on.
*
*
- * @param fileName the file name, null returns null
- * @return the name of the file without the path, or an empty string if none exists
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the name of the file without the path, or an empty string if none exists.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static String getBaseName(final String fileName) {
return removeExtension(getName(fileName));
@@ -620,9 +576,9 @@ public static String getBaseName(final String fileName) {
/**
* Gets the extension of a file name.
*
- * This method returns the textual part of the file name after the last period.
- * There must be no directory separator after the period.
+ * This method returns the textual part of the file name after the last period. There must be no directory separator after the period.
*
- * The output will be the same irrespective of the machine that the code is running on, with the
- * exception of a possible {@link IllegalArgumentException} on Windows (see below).
+ * The output will be the same irrespective of the machine that the code is running on, with the exception of a possible {@link IllegalArgumentException} on
+ * Windows (see below).
*
*
- * Note: This method used to have a hidden problem for names like "foo.exe:bar.txt".
- * In this case, the name wouldn't be the name of a file, but the identifier of an
- * alternate data stream (bar.txt) on the file foo.exe. The method used to return
- * ".txt" here, which would be misleading. Commons IO 2.7 and later throw
- * an {@link IllegalArgumentException} for names like this.
+ * Note: This method used to have a hidden problem for names like "foo.exe:bar.txt". In this case, the name wouldn't be the name of a file,
+ * but the identifier of an alternate data stream (bar.txt) on the file foo.exe. The method used to return ".txt" here, which would be misleading. Commons
+ * IO 2.7 and later throw an {@link IllegalArgumentException} for names like this.
*
*
* @param fileName the file name to retrieve the extension of.
- * @return the extension of the file or an empty string if none exists or {@code null}
- * if the file name is {@code null}.
- * @throws IllegalArgumentException Windows only: the file name parameter is, in fact,
- * the identifier of an Alternate Data Stream, for example "foo.exe:bar.txt".
+ * @return the extension of the file or an empty string if none exists or {@code null} if the file name is {@code null}.
+ * @throws IllegalArgumentException Windows only: the file name parameter is, in fact, the identifier of an Alternate Data Stream, for
+ * example "foo.exe:bar.txt".
*/
public static String getExtension(final String fileName) throws IllegalArgumentException {
if (fileName == null) {
@@ -661,10 +614,10 @@ public static String getExtension(final String fileName) throws IllegalArgumentE
/**
* Gets the full path (prefix + path) from a full file name.
*
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before and
- * including the last forward or backslash.
+ * This method will handle a file in either Unix or Windows format. The method is entirely text based, and returns the text before and including the last
+ * forward or backslash.
*
+ *
*
* C:\a\b\c.txt --> C:\a\b\
* ~/a/b/c.txt --> ~/a/b/
@@ -682,22 +635,21 @@ public static String getExtension(final String fileName) throws IllegalArgumentE
* The output will be the same irrespective of the machine that the code is running on.
*
*
- * @param fileName the file name, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the path of the file, an empty string if none exists, null if invalid.
+ * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}).
*/
public static String getFullPath(final String fileName) {
return doGetFullPath(fileName, true);
}
/**
- * Gets the full path (prefix + path) from a full file name,
- * excluding the final directory separator.
+ * Gets the full path (prefix + path) from a full file name, excluding the final directory separator.
*
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before the
- * last forward or backslash.
+ * This method will handle a file in either Unix or Windows format. The method is entirely text based, and returns the text before the last forward or
+ * backslash.
*
+ *
*
* C:\a\b\c.txt --> C:\a\b
* ~/a/b/c.txt --> ~/a/b
@@ -715,9 +667,9 @@ public static String getFullPath(final String fileName) {
* The output will be the same irrespective of the machine that the code is running on.
*
*
- * @param fileName the file name, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the path of the file, an empty string if none exists, null if invalid.
+ * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}).
*/
public static String getFullPathNoEndSeparator(final String fileName) {
return doGetFullPath(fileName, false);
@@ -726,9 +678,9 @@ public static String getFullPathNoEndSeparator(final String fileName) {
/**
* Gets the name minus the path from a full file name.
*
- * This method will handle a file in either Unix or Windows format.
- * The text after the last forward or backslash is returned.
+ * This method will handle a file in either Unix or Windows format. The text after the last forward or backslash is returned.
*
+ *
*
* a/b/c.txt --> c.txt
* a\b\c.txt --> c.txt
@@ -740,9 +692,9 @@ public static String getFullPathNoEndSeparator(final String fileName) {
* The output will be the same irrespective of the machine that the code is running on.
*
*
- * @param fileName the file name, null returns null
- * @return the name of the file without the path, or an empty string if none exists
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the name of the file without the path, or an empty string if none exists.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static String getName(final String fileName) {
if (fileName == null) {
@@ -754,10 +706,10 @@ public static String getName(final String fileName) {
/**
* Gets the path from a full file name, which excludes the prefix and the name.
*
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before and
- * including the last forward or backslash.
+ * This method will handle a file in either Unix or Windows format. The method is entirely text based, and returns the text before and including the last
+ * forward or backslash.
*
+ *
*
* C:\a\b\c.txt --> a\b\
* ~/a/b/c.txt --> a/b/
@@ -769,26 +721,24 @@ public static String getName(final String fileName) {
* The output will be the same irrespective of the machine that the code is running on.
*
*
- * This method drops the prefix from the result.
- * See {@link #getFullPath(String)} for the method that retains the prefix.
+ * This method drops the prefix from the result. See {@link #getFullPath(String)} for the method that retains the prefix.
*
*
- * @param fileName the file name, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the path of the file, an empty string if none exists, null if invalid.
+ * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}).
*/
public static String getPath(final String fileName) {
return doGetPath(fileName, 1);
}
/**
- * Gets the path (which excludes the prefix) from a full file name, and
- * also excluding the final directory separator.
+ * Gets the path (which excludes the prefix) from a full file name, and also excluding the final directory separator.
*
- * This method will handle a file in either Unix or Windows format.
- * The method is entirely text based, and returns the text before the
- * last forward or backslash.
+ * This method will handle a file in either Unix or Windows format. The method is entirely text based, and returns the text before the last forward or
+ * backslash.
*
+ *
*
* C:\a\b\c.txt --> a\b
* ~/a/b/c.txt --> a/b
@@ -800,13 +750,12 @@ public static String getPath(final String fileName) {
* The output will be the same irrespective of the machine that the code is running on.
*
*
- * This method drops the prefix from the result.
- * See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix.
+ * This method drops the prefix from the result. See {@link #getFullPathNoEndSeparator(String)} for the method that retains the prefix.
*
*
- * @param fileName the file name, null returns null
- * @return the path of the file, an empty string if none exists, null if invalid
- * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the path of the file, an empty string if none exists, null if invalid.
+ * @throws IllegalArgumentException if the result path contains the null character ({@code U+0000}).
*/
public static String getPathNoEndSeparator(final String fileName) {
return doGetPath(fileName, 0);
@@ -815,9 +764,9 @@ public static String getPathNoEndSeparator(final String fileName) {
/**
* Gets the prefix such as {@code C:/} or {@code ~/} from a full file name,
*
- * This method will handle a file in either Unix or Windows format.
- * The prefix includes the first slash in the full file name where applicable.
+ * This method will handle a file in either Unix or Windows format. The prefix includes the first slash in the full file name where applicable.
*
+ *
*
* Windows:
* a\b\c.txt --> "" --> relative
@@ -835,13 +784,12 @@ public static String getPathNoEndSeparator(final String fileName) {
* ~user --> "~user/" --> named user (slash added)
*
*
- * The output will be the same irrespective of the machine that the code is running on.
- * ie. both Unix and Windows prefixes are matched regardless.
+ * The output will be the same irrespective of the machine that the code is running on. ie. both Unix and Windows prefixes are matched regardless.
*
*
- * @param fileName the file name, null returns null
- * @return the prefix of the file, null if invalid
- * @throws IllegalArgumentException if the result contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the prefix of the file, null if invalid.
+ * @throws IllegalArgumentException if the result contains the null character ({@code U+0000}).
*/
public static String getPrefix(final String fileName) {
if (fileName == null) {
@@ -864,10 +812,10 @@ public static String getPrefix(final String fileName) {
* This method will handle a file in either Unix or Windows format.
*
*
- * The prefix length includes the first slash in the full file name
- * if applicable. Thus, it is possible that the length returned is greater
- * than the length of the input string.
+ * The prefix length includes the first slash in the full file name if applicable. Thus, it is possible that the length returned is greater than the length
+ * of the input string.
*
+ *
*
* Windows:
* a\b\c.txt --> 0 --> relative
@@ -889,17 +837,15 @@ public static String getPrefix(final String fileName) {
* C: --> 0 --> valid file name as only null character and / are reserved characters
*
*
- * The output will be the same irrespective of the machine that the code is running on.
- * ie. both Unix and Windows prefixes are matched regardless.
+ * The output will be the same irrespective of the machine that the code is running on. ie. both Unix and Windows prefixes are matched regardless.
*
*
- * Note that a leading // (or \\) is used to indicate a UNC name on Windows.
- * These must be followed by a server name, so double-slashes are not collapsed
- * to a single slash at the start of the file name.
+ * Note that a leading // (or \\) is used to indicate a UNC name on Windows. These must be followed by a server name, so double-slashes are not collapsed to
+ * a single slash at the start of the file name.
*
*
- * @param fileName the file name to find the prefix in, null returns -1
- * @return the length of the prefix, -1 if invalid or null
+ * @param fileName the file name to find the prefix in, null returns -1.
+ * @return the length of the prefix, -1 if invalid or null.
*/
public static int getPrefixLength(final String fileName) {
if (fileName == null) {
@@ -915,7 +861,7 @@ public static int getPrefixLength(final String fileName) {
}
if (len == 1) {
if (ch0 == '~') {
- return 2; // return a length greater than the input
+ return 2; // return a length greater than the input
}
return isSeparator(ch0) ? 1 : 0;
}
@@ -923,7 +869,7 @@ public static int getPrefixLength(final String fileName) {
int posUnix = fileName.indexOf(UNIX_NAME_SEPARATOR, 1);
int posWin = fileName.indexOf(WINDOWS_NAME_SEPARATOR, 1);
if (posUnix == NOT_FOUND && posWin == NOT_FOUND) {
- return len + 1; // return a length greater than the input
+ return len + 1; // return a length greater than the input
}
posUnix = posUnix == NOT_FOUND ? posWin : posUnix;
posWin = posWin == NOT_FOUND ? posUnix : posWin;
@@ -945,7 +891,6 @@ public static int getPrefixLength(final String fileName) {
return 1;
}
return NOT_FOUND;
-
}
if (!isSeparator(ch0) || !isSeparator(ch1)) {
return isSeparator(ch0) ? 1 : 0;
@@ -965,24 +910,23 @@ public static int getPrefixLength(final String fileName) {
/**
* Returns the index of the last extension separator character, which is a period.
*
- * This method also checks that there is no directory separator after the last period. To do this it uses
- * {@link #indexOfLastSeparator(String)} which will handle a file in either Unix or Windows format.
+ * This method also checks that there is no directory separator after the last period. To do this it uses {@link #indexOfLastSeparator(String)} which will
+ * handle a file in either Unix or Windows format.
*
*
- * The output will be the same irrespective of the machine that the code is running on, with the
- * exception of a possible {@link IllegalArgumentException} on Windows (see below).
+ * The output will be the same irrespective of the machine that the code is running on, with the exception of a possible {@link IllegalArgumentException} on
+ * Windows (see below).
*
- * Note: This method used to have a hidden problem for names like "foo.exe:bar.txt".
- * In this case, the name wouldn't be the name of a file, but the identifier of an
- * alternate data stream (bar.txt) on the file foo.exe. The method used to return
- * ".txt" here, which would be misleading. Commons IO 2.7, and later versions, are throwing
- * an {@link IllegalArgumentException} for names like this.
- *
- * @param fileName
- * the file name to find the last extension separator in, null returns -1
- * @return the index of the last extension separator character, or -1 if there is no such character
- * @throws IllegalArgumentException Windows only: the file name parameter is, in fact,
- * the identifier of an Alternate Data Stream, for example "foo.exe:bar.txt".
+ *
+ * Note: This method used to have a hidden problem for names like "foo.exe:bar.txt". In this case, the name wouldn't be the name of a file,
+ * but the identifier of an alternate data stream (bar.txt) on the file foo.exe. The method used to return ".txt" here, which would be misleading. Commons
+ * IO 2.7, and later versions, are throwing an {@link IllegalArgumentException} for names like this.
+ *
+ *
+ * @param fileName the file name to find the last extension separator in, null returns -1.
+ * @return the index of the last extension separator character, or -1 if there is no such character.
+ * @throws IllegalArgumentException Windows only: the file name parameter is, in fact, the identifier of an Alternate Data Stream, for
+ * example "foo.exe:bar.txt".
*/
public static int indexOfExtension(final String fileName) throws IllegalArgumentException {
if (fileName == null) {
@@ -1003,14 +947,14 @@ public static int indexOfExtension(final String fileName) throws IllegalArgument
/**
* Returns the index of the last directory separator character.
*
- * This method will handle a file in either Unix or Windows format.
- * The position of the last forward or backslash is returned.
+ * This method will handle a file in either Unix or Windows format. The position of the last forward or backslash is returned.
+ *
*
* The output will be the same irrespective of the machine that the code is running on.
+ *
*
- * @param fileName the file name to find the last path separator in, null returns -1
- * @return the index of the last separator character, or -1 if there
- * is no such character
+ * @param fileName the file name to find the last path separator in, null returns -1.
+ * @return the index of the last separator character, or -1 if there is no such character.
*/
public static int indexOfLastSeparator(final String fileName) {
if (fileName == null) {
@@ -1028,21 +972,20 @@ private static boolean isEmpty(final String string) {
/**
* Checks whether the extension of the file name is one of those specified.
*
- * This method obtains the extension as the textual part of the file name
- * after the last period. There must be no directory separator after the period.
- * The extension check is case-sensitive on all platforms.
- *
- * @param fileName the file name, null returns false
- * @param extensions the extensions to check for, null checks for no extension
- * @return true if the file name is one of the extensions
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * This method obtains the extension as the textual part of the file name after the last period. There must be no directory separator after the period. The
+ * extension check is case-sensitive on all platforms.
+ *
+ *
+ * @param fileName the file name, null returns false.
+ * @param extensions the extensions to check for, null checks for no extension.
+ * @return true if the file name is one of the extensions.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static boolean isExtension(final String fileName, final Collection extensions) {
if (fileName == null) {
return false;
}
requireNonNullChars(fileName);
-
if (extensions == null || extensions.isEmpty()) {
return indexOfExtension(fileName) == NOT_FOUND;
}
@@ -1052,21 +995,20 @@ public static boolean isExtension(final String fileName, final Collection
- * This method obtains the extension as the textual part of the file name
- * after the last period. There must be no directory separator after the period.
- * The extension check is case-sensitive on all platforms.
- *
- * @param fileName the file name, null returns false
- * @param extension the extension to check for, null or empty checks for no extension
- * @return true if the file name has the specified extension
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * This method obtains the extension as the textual part of the file name after the last period. There must be no directory separator after the period. The
+ * extension check is case-sensitive on all platforms.
+ *
+ *
+ * @param fileName the file name, null returns false.
+ * @param extension the extension to check for, null or empty checks for no extension.
+ * @return true if the file name has the specified extension.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static boolean isExtension(final String fileName, final String extension) {
if (fileName == null) {
return false;
}
requireNonNullChars(fileName);
-
if (isEmpty(extension)) {
return indexOfExtension(fileName) == NOT_FOUND;
}
@@ -1076,21 +1018,20 @@ public static boolean isExtension(final String fileName, final String extension)
/**
* Checks whether the extension of the file name is one of those specified.
*
- * This method obtains the extension as the textual part of the file name
- * after the last period. There must be no directory separator after the period.
- * The extension check is case-sensitive on all platforms.
- *
- * @param fileName the file name, null returns false
- * @param extensions the extensions to check for, null checks for no extension
- * @return true if the file name is one of the extensions
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * This method obtains the extension as the textual part of the file name after the last period. There must be no directory separator after the period. The
+ * extension check is case-sensitive on all platforms.
+ *
+ *
+ * @param fileName the file name, null returns false.
+ * @param extensions the extensions to check for, null checks for no extension.
+ * @return true if the file name is one of the extensions.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static boolean isExtension(final String fileName, final String... extensions) {
if (fileName == null) {
return false;
}
requireNonNullChars(fileName);
-
if (extensions == null || extensions.length == 0) {
return indexOfExtension(fileName) == NOT_FOUND;
}
@@ -1101,8 +1042,8 @@ public static boolean isExtension(final String fileName, final String... extensi
/**
* Checks whether a given string represents a valid IPv4 address.
*
- * @param name the name to validate
- * @return true if the given name is a valid IPv4 address
+ * @param name the name to validate.
+ * @return true if the given name is a valid IPv4 address.
*/
// mostly copied from org.apache.commons.validator.routines.InetAddressValidator#isValidInet4Address
private static boolean isIPv4Address(final String name) {
@@ -1110,21 +1051,14 @@ private static boolean isIPv4Address(final String name) {
if (!m.matches() || m.groupCount() != 4) {
return false;
}
-
// verify that address subgroups are legal
for (int i = 1; i <= 4; i++) {
final String ipSegment = m.group(i);
final int iIpSegment = Integer.parseInt(ipSegment);
- if (iIpSegment > IPV4_MAX_OCTET_VALUE) {
- return false;
- }
-
- if (ipSegment.length() > 1 && ipSegment.startsWith("0")) {
+ if (iIpSegment > IPV4_MAX_OCTET_VALUE || ipSegment.length() > 1 && ipSegment.startsWith("0")) {
return false;
}
-
}
-
return true;
}
@@ -1132,16 +1066,15 @@ private static boolean isIPv4Address(final String name) {
/**
* Checks whether a given string represents a valid IPv6 address.
*
- * @param inet6Address the name to validate
- * @return true if the given name is a valid IPv6 address
+ * @param inet6Address the name to validate.
+ * @return true if the given name is a valid IPv6 address.
*/
private static boolean isIPv6Address(final String inet6Address) {
final boolean containsCompressedZeroes = inet6Address.contains("::");
if (containsCompressedZeroes && inet6Address.indexOf("::") != inet6Address.lastIndexOf("::")) {
return false;
}
- if (inet6Address.startsWith(":") && !inet6Address.startsWith("::")
- || inet6Address.endsWith(":") && !inet6Address.endsWith("::")) {
+ if (inet6Address.startsWith(":") && !inet6Address.startsWith("::") || inet6Address.endsWith(":") && !inet6Address.endsWith("::")) {
return false;
}
String[] octets = inet6Address.split(":");
@@ -1196,12 +1129,11 @@ private static boolean isIPv6Address(final String inet6Address) {
}
/**
- * Checks whether a given string is a valid host name according to
- * RFC 3986 - not accepting IP addresses.
+ * Checks whether a given string is a valid host name according to RFC 3986 - not accepting IP addresses.
*
* @see "https://tools.ietf.org/html/rfc3986#section-3.2.2"
- * @param name the hostname to validate
- * @return true if the given name is a valid host name
+ * @param name the hostname to validate.
+ * @return true if the given name is a valid host name.
*/
private static boolean isRFC3986HostName(final String name) {
final String[] parts = name.split("\\.", -1);
@@ -1220,8 +1152,8 @@ private static boolean isRFC3986HostName(final String name) {
/**
* Checks if the character is a separator.
*
- * @param ch the character to check
- * @return true if it is a separator character
+ * @param ch the character to check.
+ * @return true if it is a separator character.
*/
private static boolean isSeparator(final char ch) {
return ch == UNIX_NAME_SEPARATOR || ch == WINDOWS_NAME_SEPARATOR;
@@ -1230,23 +1162,21 @@ private static boolean isSeparator(final char ch) {
/**
* Determines if Windows file system is in use.
*
- * @return true if the system is Windows
+ * @return true if the system is Windows.
*/
static boolean isSystemWindows() {
return SYSTEM_NAME_SEPARATOR == WINDOWS_NAME_SEPARATOR;
}
/**
- * Checks whether a given string is a valid host name according to
- * RFC 3986.
- *
- *
Accepted are IP addresses (v4 and v6) as well as what the
- * RFC calls a "reg-name". Percent encoded names don't seem to be
- * valid names in UNC paths.
+ * Checks whether a given string is a valid host name according to RFC 3986.
+ *
+ * Accepted are IP addresses (v4 and v6) as well as what the RFC calls a "reg-name". Percent encoded names don't seem to be valid names in UNC paths.
+ *
*
* @see "https://tools.ietf.org/html/rfc3986#section-3.2.2"
- * @param name the hostname to validate
- * @return true if the given name is a valid host name
+ * @param name the hostname to validate.
+ * @return true if the given name is a valid host name.
*/
private static boolean isValidHostName(final String name) {
return isIPv6Address(name) || isRFC3986HostName(name);
@@ -1255,18 +1185,20 @@ private static boolean isValidHostName(final String name) {
/**
* Normalizes a path, removing double and single period path steps.
*
- * This method normalizes a path to a standard format.
- * The input may contain separators in either Unix or Windows format.
- * The output will contain separators in the format of the system.
- *
- * A trailing slash will be retained.
- * A double slash will be merged to a single slash (but UNC names are handled).
- * A single period path segment will be removed.
- * A double period will cause that path segment and the one before to be removed.
- * If the double period has no parent path segment, {@code null} is returned.
+ * This method normalizes a path to a standard format. The input may contain separators in either Unix or Windows format. The output will contain separators
+ * in the format of the system.
+ *
+ *
+ *
A trailing slash will be retained.
+ *
A double slash will be merged to a single slash (but UNC names are handled).
+ *
A single period path segment will be removed.
+ *
A double period will cause that path segment and the one before to be removed.
+ *
If the double period has no parent path segment, {@code null} is returned.
+ *
*
- * The output will be the same on both Unix and Windows except
- * for the separator character.
+ * The output will be the same on both Unix and Windows except for the separator character.
+ *
* (Note the file separator will be correct for Windows/Unix.)
+ *
*
- * @param fileName the file name to normalize, null returns null
- * @return the normalized fileName, or null if invalid
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name to normalize, null returns null.
+ * @return the normalized fileName, or null if invalid.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static String normalize(final String fileName) {
return doNormalize(fileName, SYSTEM_NAME_SEPARATOR, true);
@@ -1299,19 +1233,20 @@ public static String normalize(final String fileName) {
/**
* Normalizes a path, removing double and single period path steps.
*
- * This method normalizes a path to a standard format.
- * The input may contain separators in either Unix or Windows format.
- * The output will contain separators in the format specified.
- *
- * A trailing slash will be retained.
- * A double slash will be merged to a single slash (but UNC names are handled).
- * A single period path segment will be removed.
- * A double period will cause that path segment and the one before to be removed.
- * If the double period has no parent path segment to work with, {@code null}
- * is returned.
+ * This method normalizes a path to a standard format. The input may contain separators in either Unix or Windows format. The output will contain separators
+ * in the format specified.
+ *
+ *
+ *
A trailing slash will be retained.
+ *
A double slash will be merged to a single slash (but UNC names are handled).
+ *
A single period path segment will be removed.
+ *
A double period will cause that path segment and the one before to be removed.
+ *
If the double period has no parent path segment to work with, {@code null} is returned.
+ *
*
- * The output will be the same on both Unix and Windows except
- * for the separator character.
+ * The output will be the same on both Unix and Windows except for the separator character.
+ *
- * The output will be the same on both Unix and Windows including
- * the separator character.
- *
- * @param fileName the file name to normalize, null returns null
- * @param unixSeparator {@code true} if a Unix separator should
- * be used or {@code false} if a Windows separator should be used.
- * @return the normalized fileName, or null if invalid
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ *
+ * The output will be the same on both Unix and Windows including the separator character.
+ *
+ *
+ * @param fileName the file name to normalize, null returns null.
+ * @param unixSeparator {@code true} if a Unix separator should be used or {@code false} if a Windows separator should be used.
+ * @return the normalized fileName, or null if invalid.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
* @since 2.0
*/
public static String normalize(final String fileName, final boolean unixSeparator) {
@@ -1346,22 +1281,22 @@ public static String normalize(final String fileName, final boolean unixSeparato
}
/**
- * Normalizes a path, removing double and single period path steps,
- * and removing any final directory separator.
- *
- * This method normalizes a path to a standard format.
- * The input may contain separators in either Unix or Windows format.
- * The output will contain separators in the format of the system.
+ * Normalizes a path, removing double and single period path steps, and removing any final directory separator.
*
- * A trailing slash will be removed.
- * A double slash will be merged to a single slash (but UNC names are handled).
- * A single period path segment will be removed.
- * A double period will cause that path segment and the one before to be removed.
- * If the double period has no parent path segment to work with, {@code null}
- * is returned.
+ * This method normalizes a path to a standard format. The input may contain separators in either Unix or Windows format. The output will contain separators
+ * in the format of the system.
+ *
+ *
+ *
A trailing slash will be removed.
+ *
A double slash will be merged to a single slash (but UNC names are handled).
+ *
A single period path segment will be removed.
+ *
A double period will cause that path segment and the one before to be removed.
+ *
If the double period has no parent path segment to work with, {@code null} is returned.
+ *
*
- * The output will be the same on both Unix and Windows except
- * for the separator character.
+ * The output will be the same on both Unix and Windows except for the separator character.
+ *
+ *
* (Note the file separator returned will be correct for Windows/Unix)
*
- * @param fileName the file name to normalize, null returns null
- * @return the normalized fileName, or null if invalid
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name to normalize, null returns null.
+ * @return the normalized fileName, or null if invalid.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static String normalizeNoEndSeparator(final String fileName) {
return doNormalize(fileName, SYSTEM_NAME_SEPARATOR, false);
}
/**
- * Normalizes a path, removing double and single period path steps,
- * and removing any final directory separator.
- *
- * This method normalizes a path to a standard format.
- * The input may contain separators in either Unix or Windows format.
- * The output will contain separators in the format specified.
+ * Normalizes a path, removing double and single period path steps, and removing any final directory separator.
*
- * A trailing slash will be removed.
- * A double slash will be merged to a single slash (but UNC names are handled).
- * A single period path segment will be removed.
- * A double period will cause that path segment and the one before to be removed.
- * If the double period has no parent path segment to work with, {@code null}
- * is returned.
+ * This method normalizes a path to a standard format. The input may contain separators in either Unix or Windows format. The output will contain separators
+ * in the format specified.
+ *
+ *
+ *
A trailing slash will be removed.
+ *
A double slash will be merged to a single slash (but UNC names are handled).
+ *
A single period path segment will be removed.
+ *
A double period will cause that path segment and the one before to be removed.
+ *
If the double period has no parent path segment to work with, {@code null} is returned.
+ *
*
- * The output will be the same on both Unix and Windows including
- * the separator character.
+ * The output will be the same on both Unix and Windows including the separator character.
+ *
*
*
- * @param fileName the file name to normalize, null returns null
- * @param unixSeparator {@code true} if a Unix separator should
- * be used or {@code false} if a Windows separator should be used.
- * @return the normalized fileName, or null if invalid
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name to normalize, null returns null.
+ * @param unixSeparator {@code true} if a Unix separator should be used or {@code false} if a Windows separator should be used.
+ * @return the normalized fileName, or null if invalid.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
* @since 2.0
*/
public static String normalizeNoEndSeparator(final String fileName, final boolean unixSeparator) {
- return doNormalize(fileName, toSeparator(unixSeparator), false);
+ return doNormalize(fileName, toSeparator(unixSeparator), false);
}
/**
* Removes the extension from a fileName.
*
- * This method returns the textual part of the file name before the last period.
- * There must be no directory separator after the period.
+ * This method returns the textual part of the file name before the last period. There must be no directory separator after the period.
+ *
*
* The output will be the same irrespective of the machine that the code is running on.
*
- * @param fileName the file name, null returns null
- * @return the file name minus the extension
- * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000})
+ * @param fileName the file name, null returns null.
+ * @return the file name minus the extension.
+ * @throws IllegalArgumentException if the file name contains the null character ({@code U+0000}).
*/
public static String removeExtension(final String fileName) {
if (fileName == null) {
return null;
}
requireNonNullChars(fileName);
-
final int index = indexOfExtension(fileName);
if (index == NOT_FOUND) {
return fileName;
@@ -1473,18 +1406,17 @@ public static String removeExtension(final String fileName) {
}
/**
- * Checks the input for null characters ({@code U+0000}), a sign of unsanitized data being passed to file level functions.
+ * Checks the input for null characters ({@code U+0000}), a sign of unsanitized data being passed to file level functions. This may be used to defend
+ * against poison byte attacks.
*
- * This may be used to defend against poison byte attacks.
- *
- * @param path the path to check
- * @return The input
- * @throws IllegalArgumentException if path contains the null character ({@code U+0000})
+ * @param path the path to check.
+ * @return The input.
+ * @throws IllegalArgumentException if path contains the null character ({@code U+0000}).
*/
private static String requireNonNullChars(final String path) {
if (path.indexOf(0) >= 0) {
throw new IllegalArgumentException(
- "Null character present in file/path name. There are no known legitimate use cases for such data, but several injection attacks may use it");
+ "Null character present in file/path name; there are no legitimate use cases, but several injection attacks may use it");
}
return path;
}
@@ -1520,21 +1452,17 @@ public static String separatorsToWindows(final String path) {
}
/**
- * Splits a string into a number of tokens.
- * The text is split by '?' and '*'.
- * Where multiple '*' occur consecutively they are collapsed into a single '*'.
+ * Splits a string into a number of tokens. The text is split by '?' and '*'. Where multiple '*' occur consecutively they are collapsed into a single '*'.
*
- * @param text the text to split
- * @return the array of tokens, never null
+ * @param text the text to split.
+ * @return the array of tokens, never null.
*/
static String[] splitOnTokens(final String text) {
// used by wildcardMatch
// package level so a unit test may run on this
-
if (text.indexOf('?') == NOT_FOUND && text.indexOf('*') == NOT_FOUND) {
return new String[] { text };
}
-
final char[] array = text.toCharArray();
final ArrayList list = new ArrayList<>();
final StringBuilder buffer = new StringBuilder();
@@ -1558,7 +1486,6 @@ static String[] splitOnTokens(final String text) {
if (buffer.length() != 0) {
list.add(buffer.toString());
}
-
return list.toArray(EMPTY_STRING_ARRAY);
}
@@ -1573,13 +1500,12 @@ private static char toSeparator(final boolean unixSeparator) {
}
/**
- * Checks a fileName to see if it matches the specified wildcard matcher,
- * always testing case-sensitive.
+ * Checks a fileName to see if it matches the specified wildcard matcher, always testing case-sensitive.
*
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple (zero or more) wildcard characters.
- * This is the same as often found on DOS/Unix command lines.
- * The check is case-sensitive always.
+ * The wildcard matcher uses the characters '?' and '*' to represent a single or multiple (zero or more) wildcard characters. This is the same as often
+ * found on DOS/Unix command lines. The check is case-sensitive always.
+ *
* The sequence "*?" does not work properly at present in match strings.
+ *
*
- * @param fileName the file name to match on
- * @param wildcardMatcher the wildcard string to match against
- * @return true if the file name matches the wildcard string
+ * @param fileName the file name to match on, may be null.
+ * @param wildcardMatcher the wildcard string to match against, may be null.
+ * @return true if the file name matches the wildcard string.
* @see IOCase#SENSITIVE
*/
public static boolean wildcardMatch(final String fileName, final String wildcardMatcher) {
@@ -1599,17 +1527,16 @@ public static boolean wildcardMatch(final String fileName, final String wildcard
}
/**
- * Checks a fileName to see if it matches the specified wildcard matcher
- * allowing control over case-sensitivity.
+ * Checks a fileName to see if it matches the specified wildcard matcher allowing control over case-sensitivity.
*
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple (zero or more) wildcard characters.
- * The sequence "*?" does not work properly at present in match strings.
+ * The wildcard matcher uses the characters '?' and '*' to represent a single or multiple (zero or more) wildcard characters. The sequence "*?" does not
+ * work properly at present in match strings.
+ *
*
- * @param fileName the file name to match on
- * @param wildcardMatcher the wildcard string to match against
- * @param ioCase what case sensitivity rule to use, null means case-sensitive
- * @return true if the file name matches the wildcard string
+ * @param fileName the file name to match on, may be null.
+ * @param wildcardMatcher the wildcard string to match against, may be null.
+ * @param ioCase what case sensitivity rule to use, null means case-sensitive.
+ * @return true if the file name matches the wildcard string.
* @since 1.3
*/
public static boolean wildcardMatch(final String fileName, final String wildcardMatcher, IOCase ioCase) {
@@ -1625,7 +1552,6 @@ public static boolean wildcardMatch(final String fileName, final String wildcard
int textIdx = 0;
int wcsIdx = 0;
final Deque backtrack = new ArrayDeque<>(wcs.length);
-
// loop around a backtrack stack, to handle complex * matching
do {
if (!backtrack.isEmpty()) {
@@ -1634,10 +1560,8 @@ public static boolean wildcardMatch(final String fileName, final String wildcard
textIdx = array[1];
anyChars = true;
}
-
// loop whilst tokens and text left to process
while (wcsIdx < wcs.length) {
-
if (wcs[wcsIdx].equals("?")) {
// ? so move to next text char
textIdx++;
@@ -1645,14 +1569,12 @@ public static boolean wildcardMatch(final String fileName, final String wildcard
break;
}
anyChars = false;
-
} else if (wcs[wcsIdx].equals("*")) {
// set any chars status
anyChars = true;
if (wcsIdx == wcs.length - 1) {
textIdx = fileName.length();
}
-
} else {
// matching text token
if (anyChars) {
@@ -1664,40 +1586,34 @@ public static boolean wildcardMatch(final String fileName, final String wildcard
}
final int repeat = ioCase.checkIndexOf(fileName, textIdx + 1, wcs[wcsIdx]);
if (repeat >= 0) {
- backtrack.push(new int[] {wcsIdx, repeat});
+ backtrack.push(new int[] { wcsIdx, repeat });
}
} else if (!ioCase.checkRegionMatches(fileName, textIdx, wcs[wcsIdx])) {
// matching from current position
// couldn't match token
break;
}
-
// matched text token, move text index to end of matched token
textIdx += wcs[wcsIdx].length();
anyChars = false;
}
-
wcsIdx++;
}
-
// full match
if (wcsIdx == wcs.length && textIdx == fileName.length()) {
return true;
}
-
} while (!backtrack.isEmpty());
-
return false;
}
/**
- * Checks a fileName to see if it matches the specified wildcard matcher
- * using the case rules of the system.
+ * Checks a fileName to see if it matches the specified wildcard matcher using the case rules of the system.
*
- * The wildcard matcher uses the characters '?' and '*' to represent a
- * single or multiple (zero or more) wildcard characters.
- * This is the same as often found on DOS/Unix command lines.
- * The check is case-sensitive on Unix and case-insensitive on Windows.
+ * The wildcard matcher uses the characters '?' and '*' to represent a single or multiple (zero or more) wildcard characters. This is the same as often
+ * found on DOS/Unix command lines. The check is case-sensitive on Unix and case-insensitive on Windows.
+ *
* The sequence "*?" does not work properly at present in match strings.
+ *
*
- * @param fileName the file name to match on
- * @param wildcardMatcher the wildcard string to match against
- * @return true if the file name matches the wildcard string
+ * @param fileName the file name to match on.
+ * @param wildcardMatcher the wildcard string to match against.
+ * @return true if the file name matches the wildcard string.
* @see IOCase#SYSTEM
*/
public static boolean wildcardMatchOnSystem(final String fileName, final String wildcardMatcher) {
diff --git a/src/main/java/org/apache/commons/io/HexDump.java b/src/main/java/org/apache/commons/io/HexDump.java
index cb7efa7b2f2..38f52fdd325 100644
--- a/src/main/java/org/apache/commons/io/HexDump.java
+++ b/src/main/java/org/apache/commons/io/HexDump.java
@@ -62,11 +62,11 @@ public class HexDump {
* characters (if any) that those bytes represent printed per each line
* of output.
*
- * @param data the byte array to be dumped
- * @param appendable the Appendable to which the data is to be written
+ * @param data the byte array to be dumped.
+ * @param appendable the Appendable to which the data is to be written.
* @throws IOException is thrown if anything goes wrong writing
- * the data to appendable
- * @throws NullPointerException if the output appendable is null
+ * the data to appendable.
+ * @throws NullPointerException if the output appendable is null.
* @since 2.12.0
*/
public static void dump(final byte[] data, final Appendable appendable)
@@ -89,16 +89,16 @@ public static void dump(final byte[] data, final Appendable appendable)
* the first byte on that line is located.
*
*
- * @param data the byte array to be dumped
- * @param offset offset of the byte array within a larger entity
- * @param appendable the Appendable to which the data is to be written
- * @param index initial index into the byte array
- * @param length number of bytes to dump from the array
+ * @param data the byte array to be dumped.
+ * @param offset offset of the byte array within a larger entity.
+ * @param appendable the Appendable to which the data is to be written.
+ * @param index initial index into the byte array.
+ * @param length number of bytes to dump from the array.
* @throws IOException is thrown if anything goes wrong writing
- * the data to appendable
+ * the data to appendable.
* @throws ArrayIndexOutOfBoundsException if the index or length is
- * outside the data array's bounds
- * @throws NullPointerException if the output appendable is null
+ * outside the data array's bounds.
+ * @throws NullPointerException if the output appendable is null.
* @since 2.12.0
*/
public static void dump(final byte[] data, final long offset,
@@ -169,19 +169,19 @@ public static void dump(final byte[] data, final long offset,
* data array are dumped.
*
*
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
*
- * @param data the byte array to be dumped
- * @param offset offset of the byte array within a larger entity
+ * @param data the byte array to be dumped.
+ * @param offset offset of the byte array within a larger entity.
* @param stream the OutputStream to which the data is to be
- * written
- * @param index initial index into the byte array
+ * written.
+ * @param index initial index into the byte array.
* @throws IOException is thrown if anything goes wrong writing
- * the data to stream
+ * the data to stream.
* @throws ArrayIndexOutOfBoundsException if the index is
- * outside the data array's bounds
- * @throws NullPointerException if the output stream is null
+ * outside the data array's bounds.
+ * @throws NullPointerException if the output stream is null.
*/
@SuppressWarnings("resource") // Caller closes stream
public static void dump(final byte[] data, final long offset,
@@ -197,8 +197,8 @@ public static void dump(final byte[] data, final long offset,
/**
* Dumps a byte value into a StringBuilder.
*
- * @param builder the StringBuilder to dump the value in
- * @param value the byte value to be dumped
+ * @param builder the StringBuilder to dump the value in.
+ * @param value the byte value to be dumped.
* @return StringBuilder containing the dumped value.
*/
private static StringBuilder dump(final StringBuilder builder, final byte value) {
@@ -211,8 +211,8 @@ private static StringBuilder dump(final StringBuilder builder, final byte value)
/**
* Dumps a long value into a StringBuilder.
*
- * @param builder the StringBuilder to dump the value in
- * @param value the long value to be dumped
+ * @param builder the StringBuilder to dump the value in.
+ * @param value the long value to be dumped.
* @return StringBuilder containing the dumped value.
*/
private static StringBuilder dump(final StringBuilder builder, final long value) {
diff --git a/src/main/java/org/apache/commons/io/IOCase.java b/src/main/java/org/apache/commons/io/IOCase.java
index 7fee424f489..9a4d168fc3a 100644
--- a/src/main/java/org/apache/commons/io/IOCase.java
+++ b/src/main/java/org/apache/commons/io/IOCase.java
@@ -21,7 +21,7 @@
import java.util.stream.Stream;
/**
- * Enumeration of IO case sensitivity.
+ * Enumerates IO case sensitivity types.
*
* Different filing systems have different rules for case-sensitivity.
* Windows is case-insensitive, Unix is case-sensitive.
@@ -72,9 +72,9 @@ public enum IOCase {
/**
* Looks up an IOCase by name.
*
- * @param name the name to find
- * @return the IOCase object
- * @throws IllegalArgumentException if the name is invalid
+ * @param name the name to find.
+ * @return the IOCase object.
+ * @throws IllegalArgumentException if the name is invalid.
*/
public static IOCase forName(final String name) {
return Stream.of(values()).filter(ioCase -> ioCase.getName().equals(name)).findFirst()
@@ -95,7 +95,7 @@ public static boolean isCaseSensitive(final IOCase ioCase) {
/**
* Returns the given value if not-null, the defaultValue if null.
*
- * @param value the value to test.
+ * @param value the value to test, may be null.
* @param defaultValue the default value.
* @return the given value if not-null, the defaultValue if null.
* @since 2.12.0
@@ -236,7 +236,7 @@ public boolean checkStartsWith(final String str, final String start) {
/**
* Gets the name of the constant.
*
- * @return the name of the constant
+ * @return the name of the constant.
*/
public String getName() {
return name;
diff --git a/src/main/java/org/apache/commons/io/IOExceptionList.java b/src/main/java/org/apache/commons/io/IOExceptionList.java
index 740bedb6789..256cebd1360 100644
--- a/src/main/java/org/apache/commons/io/IOExceptionList.java
+++ b/src/main/java/org/apache/commons/io/IOExceptionList.java
@@ -126,7 +126,7 @@ public List getCauseList() {
* Works around Throwable and Generics, may fail at runtime depending on the argument value.
*
* @param type of exception to return.
- * @param clazz the target type
+ * @param clazz the target type.
* @return The list of causes.
*/
public List getCauseList(final Class clazz) {
diff --git a/src/main/java/org/apache/commons/io/IOExceptionWithCause.java b/src/main/java/org/apache/commons/io/IOExceptionWithCause.java
index af25e8b0a40..b5dbba671bb 100644
--- a/src/main/java/org/apache/commons/io/IOExceptionWithCause.java
+++ b/src/main/java/org/apache/commons/io/IOExceptionWithCause.java
@@ -20,10 +20,10 @@
import java.io.IOException;
/**
- * Subclasses IOException with the {@link Throwable} constructors missing before Java 6.
+ * Subclasses {@link IOException} with the {@link Throwable} constructors missing before Java 6.
*
* @since 1.4
- * @deprecated (since 2.5) use {@link IOException} instead
+ * @deprecated (since 2.5) use {@link IOException} instead.
*/
@Deprecated
public class IOExceptionWithCause extends IOException {
@@ -41,7 +41,7 @@ public class IOExceptionWithCause extends IOException {
*
*
* @param message
- * the message (see {@link #getMessage()})
+ * the message (see {@link #getMessage()}).
* @param cause
* the cause (see {@link #getCause()}). A {@code null} value is allowed.
*/
diff --git a/src/main/java/org/apache/commons/io/IOIndexedException.java b/src/main/java/org/apache/commons/io/IOIndexedException.java
index fcb84334ff6..958d8307317 100644
--- a/src/main/java/org/apache/commons/io/IOIndexedException.java
+++ b/src/main/java/org/apache/commons/io/IOIndexedException.java
@@ -27,6 +27,7 @@
public class IOIndexedException extends IOException {
private static final long serialVersionUID = 1L;
+
/**
* Converts input to a suitable String for exception message.
*
diff --git a/src/main/java/org/apache/commons/io/IORandomAccessFile.java b/src/main/java/org/apache/commons/io/IORandomAccessFile.java
index 9b4aea52dec..f3a679dd41b 100644
--- a/src/main/java/org/apache/commons/io/IORandomAccessFile.java
+++ b/src/main/java/org/apache/commons/io/IORandomAccessFile.java
@@ -19,6 +19,7 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Objects;
@@ -37,7 +38,7 @@ public final class IORandomAccessFile extends RandomAccessFile {
/**
* Constructs a new instance by calling {@link RandomAccessFile#RandomAccessFile(File, String)}.
*
- * @param file the file object
+ * @param file the file object.
* @param mode the access mode, as described in {@link RandomAccessFile#RandomAccessFile(File, String)}.
* @throws FileNotFoundException Thrown by {@link RandomAccessFile#RandomAccessFile(File, String)}.
* @see RandomAccessFile#RandomAccessFile(File, String)
@@ -51,7 +52,7 @@ public IORandomAccessFile(final File file, final String mode) throws FileNotFoun
/**
* Constructs a new instance by calling {@link RandomAccessFile#RandomAccessFile(String, String)}.
*
- * @param name the file object
+ * @param name the system-dependent file name.
* @param mode the access mode, as described in {@link RandomAccessFile#RandomAccessFile(String, String)}.
* @throws FileNotFoundException Thrown by {@link RandomAccessFile#RandomAccessFile(String, String)}.
* @see RandomAccessFile#RandomAccessFile(String, String)
@@ -62,6 +63,26 @@ public IORandomAccessFile(final String name, final String mode) throws FileNotFo
this.mode = mode;
}
+ /**
+ * Clears the contents of this existing file by filling it with NUL ({@code 0)} bytes.
+ *
+ * @return {@code this} instance.
+ * @throws FileNotFoundException See {@link #IORandomAccessFile(File, String)}.
+ * @throws IOException Thrown if an I/O error occurs.
+ */
+ public IORandomAccessFile clear() throws IOException {
+ final long length = length();
+ final byte[] zeroBuffer = IOUtils.byteArray();
+ long bytesWritten = 0;
+ while (bytesWritten < length) {
+ final long remaining = length - bytesWritten;
+ final int toWrite = (int) Math.min(zeroBuffer.length, remaining);
+ write(zeroBuffer, 0, toWrite);
+ bytesWritten += toWrite;
+ }
+ return this;
+ }
+
/**
* Gets the file passed to {@link #IORandomAccessFile(File, String)}.
*
@@ -81,7 +102,7 @@ public String getMode() {
}
/**
- * Returns the pathname string of this abstract pathname. This is just the string returned by the {@link File#toString()} method.
+ * Returns the path name string of this abstract pathname. This is just the string returned by the {@link File#toString()} method.
*
* @return The string form of the File's abstract pathname.
* @see File#toString()
@@ -90,5 +111,4 @@ public String getMode() {
public String toString() {
return Objects.toString(file);
}
-
}
diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java
index a882d4d87cb..d4b9af073d0 100644
--- a/src/main/java/org/apache/commons/io/IOUtils.java
+++ b/src/main/java/org/apache/commons/io/IOUtils.java
@@ -81,25 +81,20 @@
* This class provides static utility methods for input/output operations.
*
*
- *
closeQuietly - these methods close a stream ignoring nulls and exceptions
- *
toXxx/read - these methods read data from a stream
- *
write - these methods write data to a stream
- *
copy - these methods copy all the data from one stream to another
- *
contentEquals - these methods compare the content of two streams
+ *
closeQuietly - these methods close a stream ignoring nulls and exceptions
+ *
toXxx/read - these methods read data from a stream
+ *
write - these methods write data to a stream
+ *
copy - these methods copy all the data from one stream to another
+ *
contentEquals - these methods compare the content of two streams
*
*
- * The byte-to-char methods and char-to-byte methods involve a conversion step.
- * Two methods are provided in each case, one that uses the platform default
- * encoding and the other which allows you to specify an encoding. You are
- * encouraged to always specify an encoding because relying on the platform
- * default can lead to unexpected results, for example when moving from
- * development to production.
+ * The byte-to-char methods and char-to-byte methods involve a conversion step. Two methods are provided in each case, one that uses the platform default
+ * encoding and the other which allows you to specify an encoding. You are encouraged to always specify an encoding because relying on the platform default can
+ * lead to unexpected results, for example when moving from development to production.
*
*
- * All the methods in this class that read a stream are buffered internally.
- * This means that there is no cause to use a {@link BufferedInputStream}
- * or {@link BufferedReader}. The default buffer size of 4K has been shown
- * to be efficient in tests.
+ * All the methods in this class that read a stream are buffered internally. This means that there is no cause to use a {@link BufferedInputStream} or
+ * {@link BufferedReader}. The default buffer size of 4K has been shown to be efficient in tests.
*
*
* The various copy methods all delegate the actual copying to one of the following methods:
@@ -110,18 +105,14 @@
*
*
- * For example, {@link #copy(InputStream, OutputStream)} calls {@link #copyLarge(InputStream, OutputStream)}
- * which calls {@link #copy(InputStream, OutputStream, int)} which creates the buffer and calls
- * {@link #copyLarge(InputStream, OutputStream, byte[])}.
+ * For example, {@link #copy(InputStream, OutputStream)} calls {@link #copyLarge(InputStream, OutputStream)} which calls
+ * {@link #copy(InputStream, OutputStream, int)} which creates the buffer and calls {@link #copyLarge(InputStream, OutputStream, byte[])}.
*
- * Applications can re-use buffers by using the underlying methods directly.
- * This may improve performance for applications that need to do a lot of copying.
+ * Applications can re-use buffers by using the underlying methods directly. This may improve performance for applications that need to do a lot of copying.
*
*
- * Wherever possible, the methods in this class do not flush or close
- * the stream. This is to avoid making non-portable assumptions about the
- * streams' origin and further use. Thus the caller is still responsible for
- * closing streams after use.
+ * Wherever possible, the methods in this class do not flush or close the stream. This is to avoid making non-portable assumptions about the streams'
+ * origin and further use. Thus the caller is still responsible for closing streams after use.
*
*
* Provenance: Excalibur.
@@ -132,6 +123,142 @@ public class IOUtils {
// Writer. Each method should take at least one of these as a parameter,
// or return one of them.
+ /**
+ * Holder for per-thread internal scratch buffer.
+ *
+ * Buffers are created lazily and reused within the same thread to reduce allocation overhead. In the rare case of reentrant access, a temporary buffer is
+ * allocated to avoid data corruption.
+ *
+ */
+ static final class ScratchBytes implements AutoCloseable {
+
+ /**
+ * Wraps an internal byte array. [0] boolean in use. [1] byte[] buffer.
+ */
+ private static final ThreadLocal LOCAL = ThreadLocal.withInitial(() -> new Object[] { false, byteArray() });
+
+ private static final ScratchBytes INSTANCE = new ScratchBytes(null);
+
+ /**
+ * Gets the internal byte array buffer.
+ *
+ * @return the internal byte array buffer.
+ */
+ static ScratchBytes get() {
+ final Object[] holder = LOCAL.get();
+ // If already in use, return a new array
+ if ((boolean) holder[0]) {
+ return new ScratchBytes(byteArray());
+ }
+ holder[0] = true;
+ return INSTANCE;
+ }
+
+ /**
+ * The buffer, or null if using the thread-local buffer.
+ */
+ private final byte[] buffer;
+
+ private ScratchBytes(final byte[] buffer) {
+ this.buffer = buffer;
+ }
+
+ byte[] array() {
+ return buffer != null ? buffer : (byte[]) LOCAL.get()[1];
+ }
+
+ /**
+ * If the buffer is the internal array, clear and release it for reuse.
+ */
+ @Override
+ public void close() {
+ if (buffer == null) {
+ final Object[] holder = LOCAL.get();
+ Arrays.fill((byte[]) holder[1], (byte) 0);
+ holder[0] = false;
+ }
+ }
+ }
+
+ /**
+ * Holder for per-thread internal scratch buffer.
+ *
+ * Buffers are created lazily and reused within the same thread to reduce allocation overhead. In the rare case of reentrant access, a temporary buffer is
+ * allocated to avoid data corruption.
+ *
+ */
+ static final class ScratchChars implements AutoCloseable {
+
+ /**
+ * Wraps an internal char array. [0] boolean in use. [1] char[] buffer.
+ */
+ private static final ThreadLocal LOCAL = ThreadLocal.withInitial(() -> new Object[] { false, charArray() });
+
+ private static final ScratchChars INSTANCE = new ScratchChars(null);
+
+ /**
+ * Gets the internal char array buffer.
+ *
+ * @return the internal char array buffer.
+ */
+ static ScratchChars get() {
+ final Object[] holder = LOCAL.get();
+ // If already in use, return a new array
+ if ((boolean) holder[0]) {
+ return new ScratchChars(charArray());
+ }
+ holder[0] = true;
+ return INSTANCE;
+ }
+
+ /**
+ * The buffer, or null if using the thread-local buffer.
+ */
+ private final char[] buffer;
+
+ private ScratchChars(final char[] buffer) {
+ this.buffer = buffer;
+ }
+
+ char[] array() {
+ return buffer != null ? buffer : (char[]) LOCAL.get()[1];
+ }
+
+ /**
+ * If the buffer is the internal array, clear and release it for reuse.
+ */
+ @Override
+ public void close() {
+ if (buffer == null) {
+ final Object[] holder = LOCAL.get();
+ Arrays.fill((char[]) holder[1], (char) 0);
+ holder[0] = false;
+ }
+ }
+ }
+
/**
* CR char '{@value}'.
*
@@ -162,12 +289,13 @@ public class IOUtils {
/**
* A singleton empty byte array.
*
- * @since 2.9.0
+ * @since 2.9.0
*/
public static final byte[] EMPTY_BYTE_ARRAY = {};
/**
* Represents the end-of-file (or stream) value {@value}.
+ *
* @since 2.5 (made public)
*/
public static final int EOF = -1;
@@ -201,26 +329,6 @@ public class IOUtils {
*/
public static final String LINE_SEPARATOR_WINDOWS = StandardLineSeparator.CRLF.getString();
- /**
- * Internal byte array buffer, intended for both reading and writing.
- */
- private static final ThreadLocal SCRATCH_BYTE_BUFFER_RW = ThreadLocal.withInitial(IOUtils::byteArray);
-
- /**
- * Internal byte array buffer, intended for write only operations.
- */
- private static final byte[] SCRATCH_BYTE_BUFFER_WO = byteArray();
-
- /**
- * Internal char array buffer, intended for both reading and writing.
- */
- private static final ThreadLocal SCRATCH_CHAR_BUFFER_RW = ThreadLocal.withInitial(IOUtils::charArray);
-
- /**
- * Internal char array buffer, intended for write only operations.
- */
- private static final char[] SCRATCH_CHAR_BUFFER_WO = charArray();
-
/**
* The maximum size of an array in many Java VMs.
*
@@ -232,8 +340,7 @@ public class IOUtils {
public static final int SOFT_MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
/**
- * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a
- * BufferedInputStream from the given InputStream.
+ * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a BufferedInputStream from the given InputStream.
*
* @param inputStream the InputStream to wrap or return (not null).
* @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream.
@@ -245,16 +352,14 @@ public static BufferedInputStream buffer(final InputStream inputStream) {
// reject null early on rather than waiting for IO operation to fail
// not checked by BufferedInputStream
Objects.requireNonNull(inputStream, "inputStream");
- return inputStream instanceof BufferedInputStream ?
- (BufferedInputStream) inputStream : new BufferedInputStream(inputStream);
+ return inputStream instanceof BufferedInputStream ? (BufferedInputStream) inputStream : new BufferedInputStream(inputStream);
}
/**
- * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a
- * BufferedInputStream from the given InputStream.
+ * Returns the given InputStream if it is already a {@link BufferedInputStream}, otherwise creates a BufferedInputStream from the given InputStream.
*
* @param inputStream the InputStream to wrap or return (not null).
- * @param size the buffer size, if a new BufferedInputStream is created.
+ * @param size the buffer size, if a new BufferedInputStream is created.
* @return the given InputStream or a new {@link BufferedInputStream} for the given InputStream.
* @throws NullPointerException if the input parameter is null.
* @since 2.5
@@ -264,16 +369,14 @@ public static BufferedInputStream buffer(final InputStream inputStream, final in
// reject null early on rather than waiting for IO operation to fail
// not checked by BufferedInputStream
Objects.requireNonNull(inputStream, "inputStream");
- return inputStream instanceof BufferedInputStream ?
- (BufferedInputStream) inputStream : new BufferedInputStream(inputStream, size);
+ return inputStream instanceof BufferedInputStream ? (BufferedInputStream) inputStream : new BufferedInputStream(inputStream, size);
}
/**
- * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a
- * BufferedOutputStream from the given OutputStream.
+ * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a BufferedOutputStream from the given OutputStream.
*
* @param outputStream the OutputStream to wrap or return (not null).
- * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream
+ * @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream.
* @throws NullPointerException if the input parameter is null.
* @since 2.5
*/
@@ -282,16 +385,14 @@ public static BufferedOutputStream buffer(final OutputStream outputStream) {
// reject null early on rather than waiting for IO operation to fail
// not checked by BufferedInputStream
Objects.requireNonNull(outputStream, "outputStream");
- return outputStream instanceof BufferedOutputStream ?
- (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream);
+ return outputStream instanceof BufferedOutputStream ? (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream);
}
/**
- * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a
- * BufferedOutputStream from the given OutputStream.
+ * Returns the given OutputStream if it is already a {@link BufferedOutputStream}, otherwise creates a BufferedOutputStream from the given OutputStream.
*
* @param outputStream the OutputStream to wrap or return (not null).
- * @param size the buffer size, if a new BufferedOutputStream is created.
+ * @param size the buffer size, if a new BufferedOutputStream is created.
* @return the given OutputStream or a new {@link BufferedOutputStream} for the given OutputStream.
* @throws NullPointerException if the input parameter is null.
* @since 2.5
@@ -301,13 +402,11 @@ public static BufferedOutputStream buffer(final OutputStream outputStream, final
// reject null early on rather than waiting for IO operation to fail
// not checked by BufferedInputStream
Objects.requireNonNull(outputStream, "outputStream");
- return outputStream instanceof BufferedOutputStream ?
- (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream, size);
+ return outputStream instanceof BufferedOutputStream ? (BufferedOutputStream) outputStream : new BufferedOutputStream(outputStream, size);
}
/**
- * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from
- * the given reader.
+ * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader.
*
* @param reader the reader to wrap or return (not null).
* @return the given reader or a new {@link BufferedReader} for the given reader.
@@ -319,11 +418,10 @@ public static BufferedReader buffer(final Reader reader) {
}
/**
- * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the
- * given reader.
+ * Returns the given reader if it is already a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader.
*
* @param reader the reader to wrap or return (not null).
- * @param size the buffer size, if a new BufferedReader is created.
+ * @param size the buffer size, if a new BufferedReader is created.
* @return the given reader or a new {@link BufferedReader} for the given reader.
* @throws NullPointerException if the input parameter is null.
* @since 2.5
@@ -333,8 +431,7 @@ public static BufferedReader buffer(final Reader reader, final int size) {
}
/**
- * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the
- * given Writer.
+ * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the given Writer.
*
* @param writer the Writer to wrap or return (not null).
* @return the given Writer or a new {@link BufferedWriter} for the given Writer.
@@ -346,11 +443,10 @@ public static BufferedWriter buffer(final Writer writer) {
}
/**
- * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the
- * given Writer.
+ * Returns the given Writer if it is already a {@link BufferedWriter}, otherwise creates a BufferedWriter from the given Writer.
*
* @param writer the Writer to wrap or return (not null).
- * @param size the buffer size, if a new BufferedWriter is created.
+ * @param size the buffer size, if a new BufferedWriter is created.
* @return the given Writer or a new {@link BufferedWriter} for the given Writer.
* @throws NullPointerException if the input parameter is null.
* @since 2.5
@@ -370,9 +466,7 @@ public static byte[] byteArray() {
}
/**
- * Returns a new byte array of the given size.
- *
- * TODO Consider guarding or warning against large allocations.
+ * Returns a new byte array of the given size. TODO Consider guarding or warning against large allocations.
*
* @param size array size.
* @return a new byte array of the given size.
@@ -394,9 +488,7 @@ private static char[] charArray() {
}
/**
- * Returns a new char array of the given size.
- *
- * TODO Consider guarding or warning against large allocations.
+ * Returns a new char array of the given size. TODO Consider guarding or warning against large allocations.
*
* @param size array size.
* @return a new char array of the given size.
@@ -408,19 +500,23 @@ private static char[] charArray(final int size) {
/**
* Validates that the sub-range {@code [off, off + len)} is within the bounds of the given array.
- *
- *
The range is valid if all of the following hold:
+ *
+ * The range is valid if all of the following hold:
+ *
*
- *
{@code off >= 0}
- *
{@code len >= 0}
- *
{@code off + len <= array.length}
+ *
{@code off >= 0}
+ *
{@code len >= 0}
+ *
{@code off + len <= array.length}
*
+ *
+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
+ *
+ *
+ * Typical usage in {@link InputStream#read(byte[], int, int)} and {@link OutputStream#write(byte[], int, int)} implementations:
+ *
*
- *
If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- *
- *
Typical usage in {@link InputStream#read(byte[], int, int)} and {@link OutputStream#write(byte[], int, int)} implementations:
- *
- *
+ *
+ *
* public int read(byte[] b, int off, int len) throws IOException {
* IOUtils.checkFromIndexSize(b, off, len);
* if (len == 0) {
@@ -438,13 +534,14 @@ private static char[] charArray(final int size) {
* ensureOpen();
* // perform write...
* }
- *
+ *
+ *
*
- * @param array the array against which the range is validated
- * @param off the starting offset into the array (inclusive)
- * @param len the number of elements to access
- * @throws NullPointerException if {@code array} is {@code null}
- * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}
+ * @param array the array against which the range is validated.
+ * @param off the starting offset into the array (inclusive).
+ * @param len the number of elements to access.
+ * @throws NullPointerException if {@code array} is {@code null}.
+ * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}.
* @see InputStream#read(byte[], int, int)
* @see OutputStream#write(byte[], int, int)
* @since 2.21.0
@@ -455,19 +552,23 @@ public static void checkFromIndexSize(final byte[] array, final int off, final i
/**
* Validates that the sub-range {@code [off, off + len)} is within the bounds of the given array.
- *
- *
The range is valid if all of the following hold:
+ *
+ * The range is valid if all of the following hold:
+ *
*
- *
{@code off >= 0}
- *
{@code len >= 0}
- *
{@code off + len <= array.length}
+ *
{@code off >= 0}
+ *
{@code len >= 0}
+ *
{@code off + len <= array.length}
*
+ *
+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
+ *
+ *
+ * Typical usage in {@link Reader#read(char[], int, int)} and {@link Writer#write(char[], int, int)} implementations:
+ *
*
- *
If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- *
- *
Typical usage in {@link Reader#read(char[], int, int)} and {@link Writer#write(char[], int, int)} implementations:
- *
- *
+ *
+ *
* public int read(char[] cbuf, int off, int len) throws IOException {
* ensureOpen();
* IOUtils.checkFromIndexSize(cbuf, off, len);
@@ -485,13 +586,14 @@ public static void checkFromIndexSize(final byte[] array, final int off, final i
* }
* // perform write...
* }
- *
+ *
+ *
*
- * @param array the array against which the range is validated
- * @param off the starting offset into the array (inclusive)
- * @param len the number of characters to access
- * @throws NullPointerException if {@code array} is {@code null}
- * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}
+ * @param array the array against which the range is validated.
+ * @param off the starting offset into the array (inclusive).
+ * @param len the number of characters to access.
+ * @throws NullPointerException if {@code array} is {@code null}.
+ * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code array}.
* @see Reader#read(char[], int, int)
* @see Writer#write(char[], int, int)
* @since 2.21.0
@@ -500,21 +602,31 @@ public static void checkFromIndexSize(final char[] array, final int off, final i
checkFromIndexSize(off, len, Objects.requireNonNull(array, "char array").length);
}
+ static void checkFromIndexSize(final int off, final int len, final int arrayLength) {
+ if ((off | len | arrayLength) < 0 || arrayLength - len < off) {
+ throw new IndexOutOfBoundsException(String.format("Range [%s, %The range is valid if all of the following hold:
+ *
+ * The range is valid if all of the following hold:
+ *
*
- *
{@code off >= 0}
- *
{@code len >= 0}
- *
{@code off + len <= str.length()}
+ *
{@code off >= 0}
+ *
{@code len >= 0}
+ *
{@code off + len <= str.length()}
*
+ *
+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
+ *
If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- *
- *
Typical usage in {@link Writer#write(String, int, int)} implementations:
- *
- *
+ *
+ *
* public void write(String str, int off, int len) throws IOException {
* IOUtils.checkFromIndexSize(str, off, len);
* if (len == 0) {
@@ -522,13 +634,14 @@ public static void checkFromIndexSize(final char[] array, final int off, final i
* }
* // perform write...
* }
- *
+ *
+ *
*
- * @param str the string against which the range is validated
- * @param off the starting offset into the string (inclusive)
- * @param len the number of characters to write
- * @throws NullPointerException if {@code str} is {@code null}
- * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code str}
+ * @param str the string against which the range is validated.
+ * @param off the starting offset into the string (inclusive).
+ * @param len the number of characters to write.
+ * @throws NullPointerException if {@code str} is {@code null}.
+ * @throws IndexOutOfBoundsException if the range {@code [off, off + len)} is out of bounds for {@code str}.
* @see Writer#write(String, int, int)
* @since 2.21.0
*/
@@ -536,40 +649,40 @@ public static void checkFromIndexSize(final String str, final int off, final int
checkFromIndexSize(off, len, Objects.requireNonNull(str, "str").length());
}
- static void checkFromIndexSize(final int off, final int len, final int arrayLength) {
- if ((off | len | arrayLength) < 0 || arrayLength - len < off) {
- throw new IndexOutOfBoundsException(String.format("Range [%s, %The sub-sequence is valid if all of the following hold:
+ *
+ * The sub-sequence is valid if all of the following hold:
+ *
*
- *
{@code fromIndex >= 0}
- *
{@code fromIndex <= toIndex}
- *
{@code toIndex <= seq.length()}
+ *
{@code fromIndex >= 0}
+ *
{@code fromIndex <= toIndex}
+ *
{@code toIndex <= seq.length()}
*
+ *
+ * If {@code seq} is {@code null}, it is treated as the literal string {@code "null"} (length {@code 4}).
+ *
+ *
+ * If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
+ *
If {@code seq} is {@code null}, it is treated as the literal string {@code "null"} (length {@code 4}).
- *
- *
If the range is invalid, throws {@link IndexOutOfBoundsException} with a descriptive message.
- *
- *
Typical usage in {@link Appendable#append(CharSequence, int, int)} implementations:
- *
- *
+ *
+ *
* public Appendable append(CharSequence csq, int start, int end) throws IOException {
* IOUtils.checkFromToIndex(csq, start, end);
* // perform append...
* return this;
* }
- *
+ *
+ *
*
- * @param seq the character sequence to validate (may be {@code null}, treated as {@code "null"})
- * @param fromIndex the starting index (inclusive)
- * @param toIndex the ending index (exclusive)
- * @throws IndexOutOfBoundsException if the range {@code [fromIndex, toIndex)} is out of bounds for {@code seq}
+ * @param seq the character sequence to validate (may be {@code null}, treated as {@code "null"}).
+ * @param fromIndex the starting index (inclusive).
+ * @param toIndex the ending index (exclusive).
+ * @throws IndexOutOfBoundsException if the range {@code [fromIndex, toIndex)} is out of bounds for {@code seq}.
* @see Appendable#append(CharSequence, int, int)
* @since 2.21.0
*/
@@ -589,13 +702,12 @@ static void checkFromToIndex(final int fromIndex, final int toIndex, final int l
*
Removes the current thread's value for thread-local variables.
*
Sets static scratch arrays to 0s.
*
+ *
* @see IO#clear()
*/
static void clear() {
- SCRATCH_BYTE_BUFFER_RW.remove();
- SCRATCH_CHAR_BUFFER_RW.remove();
- Arrays.fill(SCRATCH_BYTE_BUFFER_WO, (byte) 0);
- Arrays.fill(SCRATCH_CHAR_BUFFER_WO, (char) 0);
+ ScratchBytes.LOCAL.remove();
+ ScratchChars.LOCAL.remove();
}
/**
@@ -626,8 +738,8 @@ public static void close(final Closeable... closeables) throws IOExceptionList {
* Closes the given {@link Closeable} as a null-safe operation.
*
* @param closeable The resource to close, may be null.
- * @param consumer Consume the IOException thrown by {@link Closeable#close()}.
- * @throws IOException if an I/O error occurs.
+ * @param consumer Consume the IOException thrown by {@link Closeable#close()}.
+ * @throws IOException As thrown by the consumer.
* @since 2.7
*/
public static void close(final Closeable closeable, final IOConsumer consumer) throws IOException {
@@ -635,13 +747,9 @@ public static void close(final Closeable closeable, final IOConsumer) null);
}
/**
* Closes a {@link Closeable} unconditionally.
- *
*
- * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in
- * finally blocks.
+ * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
* Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
*
- * This is typically used in finally blocks to ensure that the closeable is closed
- * even if an Exception was thrown before the normal close statement was reached.
- *
- * It should not be used to replace the close statement(s)
- * which should be present for the non-exceptional case.
- *
- * It is only intended to simplify tidying up where normal processing has already failed
- * and reporting close failure as well is not necessary or useful.
+ * This is typically used in finally blocks to ensure that the closeable is closed even if an Exception was thrown before the normal close statement was
+ * reached.
+ *
+ *
+ * It should not be used to replace the close statement(s) which should be present for the non-exceptional case.
+ *
+ * It is only intended to simplify tidying up where normal processing has already failed and reporting close failure as well is not necessary or useful.
*
* Also consider using a try-with-resources statement where appropriate.
*
+ *
* @param closeables the objects to close, may be null or already closed.
* @see #closeQuietly(Closeable)
* @since 2.5
@@ -767,7 +877,7 @@ public static void closeQuietly(final Closeable... closeables) {
* Closes the given {@link Closeable} as a null-safe operation while consuming IOException by the given {@code consumer}.
*
* @param closeable The resource to close, may be null.
- * @param consumer Consumes the Exception thrown by {@link Closeable#close()}.
+ * @param consumer Consumes the Exception thrown by {@link Closeable#close()}.
* @since 2.7
*/
public static void closeQuietly(final Closeable closeable, final Consumer consumer) {
@@ -785,24 +895,24 @@ public static void closeQuietly(final Closeable closeable, final Consumer
- * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * byte[] data = new byte[1024];
- * InputStream in = null;
- * try {
- * in = new FileInputStream("foo.txt");
- * in.read(data);
- * in.close(); //close errors are handled
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(in);
- * }
+ * byte[] data = new byte[1024];
+ * InputStream in = null;
+ * try {
+ * in = new FileInputStream("foo.txt");
+ * in.read(data);
+ * in.close(); // close errors are handled
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(in);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -834,20 +944,19 @@ public static void closeQuietly(final Iterable closeables) {
/**
* Closes an {@link OutputStream} unconditionally.
*
- * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
* byte[] data = "Hello, World".getBytes();
- *
* OutputStream out = null;
* try {
* out = new FileOutputStream("foo.txt");
* out.write(data);
- * out.close(); //close errors are handled
+ * out.close(); // close errors are handled
* } catch (IOException e) {
* // error handling
* } finally {
@@ -868,24 +977,24 @@ public static void closeQuietly(final OutputStream output) {
/**
* Closes an {@link Reader} unconditionally.
*
- * Equivalent to {@link Reader#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Reader#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
*
* Example code:
*
+ *
*
- * char[] data = new char[1024];
- * Reader in = null;
- * try {
- * in = new FileReader("foo.txt");
- * in.read(data);
- * in.close(); //close errors are handled
- * } catch (Exception e) {
- * // error handling
- * } finally {
- * IOUtils.closeQuietly(in);
- * }
+ * char[] data = new char[1024];
+ * Reader in = null;
+ * try {
+ * in = new FileReader("foo.txt");
+ * in.read(data);
+ * in.close(); // close errors are handled
+ * } catch (Exception e) {
+ * // error handling
+ * } finally {
+ * IOUtils.closeQuietly(in);
+ * }
*
*
* Also consider using a try-with-resources statement where appropriate.
@@ -901,23 +1010,22 @@ public static void closeQuietly(final Reader reader) {
/**
* Closes a {@link Selector} unconditionally.
*
- * Equivalent to {@link Selector#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Selector#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
* Also consider using a try-with-resources statement where appropriate.
@@ -934,23 +1042,23 @@ public static void closeQuietly(final Selector selector) {
/**
* Closes a {@link ServerSocket} unconditionally.
*
- * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
* Also consider using a try-with-resources statement where appropriate.
@@ -967,23 +1075,23 @@ public static void closeQuietly(final ServerSocket serverSocket) {
/**
* Closes a {@link Socket} unconditionally.
*
- * Equivalent to {@link Socket#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Socket#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
* Also consider using a try-with-resources statement where appropriate.
@@ -1016,23 +1124,23 @@ public static void closeQuietly(final Stream closeables) {
/**
* Closes an {@link Writer} unconditionally.
*
- * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
- * This is typically used in finally blocks.
+ * Equivalent to {@link Writer#close()}, except any exceptions will be ignored. This is typically used in finally blocks.
*
* Also consider using a try-with-resources statement where appropriate.
@@ -1045,6 +1153,37 @@ public static void closeQuietly(final Writer writer) {
closeQ(writer);
}
+ /**
+ * Closes a {@link Closeable} unconditionally and adds any exception thrown by the {@code close()} to the given Throwable.
+ *
+ * Also consider using a try-with-resources statement where appropriate.
+ *
+ *
+ * @param The Throwable type.
+ * @param closeable The object to close, may be null or already closed.
+ * @param throwable Add the exception throw by the closeable to the given Throwable.
+ * @return The given Throwable.
+ * @since 2.22.0
+ * @see Throwable#addSuppressed(Throwable)
+ */
+ public static T closeQuietlySuppress(final Closeable closeable, final T throwable) {
+ closeQuietly(closeable, throwable::addSuppressed);
+ return throwable;
+ }
+
/**
* Consumes bytes from a {@link InputStream} and ignores them.
*
@@ -1054,7 +1193,7 @@ public static void closeQuietly(final Writer writer) {
* @param input the {@link InputStream} to read.
* @return the number of bytes copied. or {@code 0} if {@code input is null}.
* @throws NullPointerException if the InputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.8.0
*/
public static long consume(final InputStream input) throws IOException {
@@ -1070,7 +1209,7 @@ public static long consume(final InputStream input) throws IOException {
* @param input the {@link Reader} to read.
* @return the number of bytes copied. or {@code 0} if {@code input is null}.
* @throws NullPointerException if the Reader is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.12.0
*/
public static long consume(final Reader input) throws IOException {
@@ -1078,18 +1217,15 @@ public static long consume(final Reader input) throws IOException {
}
/**
- * Compares the contents of two Streams to determine if they are equal or
- * not.
+ * Compares the contents of two Streams to determine if they are equal or not.
*
- * This method buffers the input internally using
- * {@link BufferedInputStream} if they are not already buffered.
+ * This method buffers the input internally using {@link BufferedInputStream} if they are not already buffered.
*
*
* @param input1 the first stream.
* @param input2 the second stream.
- * @return true if the content of the streams are equal or they both don't.
- * exist, false otherwise.
- * @throws IOException if an I/O error occurs.
+ * @return true if the content of the streams are equal or they both don't. exist, false otherwise.
+ * @throws IOException if an I/O error occurs.
*/
@SuppressWarnings("resource") // Caller closes input streams
public static boolean contentEquals(final InputStream input1, final InputStream input2) throws IOException {
@@ -1107,10 +1243,7 @@ public static boolean contentEquals(final InputStream input1, final InputStream
// TODO Consider making public
private static boolean contentEquals(final Iterator> iterator1, final Iterator> iterator2) {
while (iterator1.hasNext()) {
- if (!iterator2.hasNext()) {
- return false;
- }
- if (!Objects.equals(iterator1.next(), iterator2.next())) {
+ if (!iterator2.hasNext() || !Objects.equals(iterator1.next(), iterator2.next())) {
return false;
}
}
@@ -1127,7 +1260,7 @@ private static boolean contentEquals(final Iterator> iterator1, final Iterator
* @param input2 the second reader.
* @return true if the content of the readers are equal or they both don't exist, false otherwise.
* @throws NullPointerException if either input is null.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 1.1
*/
public static boolean contentEquals(final Reader input1, final Reader input2) throws IOException {
@@ -1137,39 +1270,38 @@ public static boolean contentEquals(final Reader input1, final Reader input2) th
if (input1 == null || input2 == null) {
return false;
}
-
- // reuse one
- final char[] array1 = getScratchCharArray();
- // but allocate another
- final char[] array2 = charArray();
- int pos1;
- int pos2;
- int count1;
- int count2;
- while (true) {
- pos1 = 0;
- pos2 = 0;
- for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) {
- if (pos1 == index) {
- do {
- count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1);
- } while (count1 == 0);
- if (count1 == EOF) {
- return pos2 == index && input2.read() == EOF;
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ final char[] array1 = scratch.array();
+ final char[] array2 = charArray();
+ int pos1;
+ int pos2;
+ int count1;
+ int count2;
+ while (true) {
+ pos1 = 0;
+ pos2 = 0;
+ for (int index = 0; index < DEFAULT_BUFFER_SIZE; index++) {
+ if (pos1 == index) {
+ do {
+ count1 = input1.read(array1, pos1, DEFAULT_BUFFER_SIZE - pos1);
+ } while (count1 == 0);
+ if (count1 == EOF) {
+ return pos2 == index && input2.read() == EOF;
+ }
+ pos1 += count1;
}
- pos1 += count1;
- }
- if (pos2 == index) {
- do {
- count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2);
- } while (count2 == 0);
- if (count2 == EOF) {
- return pos1 == index && input1.read() == EOF;
+ if (pos2 == index) {
+ do {
+ count2 = input2.read(array2, pos2, DEFAULT_BUFFER_SIZE - pos2);
+ } while (count2 == 0);
+ if (count2 == EOF) {
+ return pos1 == index && input1.read() == EOF;
+ }
+ pos2 += count2;
+ }
+ if (array1[index] != array2[index]) {
+ return false;
}
- pos2 += count2;
- }
- if (array1[index] != array2[index]) {
- return false;
}
}
}
@@ -1198,16 +1330,14 @@ private static boolean contentEqualsIgnoreEOL(final BufferedReader reader1, fina
}
/**
- * Compares the contents of two Readers to determine if they are equal or
- * not, ignoring EOL characters.
+ * Compares the contents of two Readers to determine if they are equal or not, ignoring EOL characters.
*
- * This method buffers the input internally using
- * {@link BufferedReader} if they are not already buffered.
+ * This method buffers the input internally using {@link BufferedReader} if they are not already buffered.
*
*
* @param reader1 the first reader.
* @param reader2 the second reader.
- * @return true if the content of the readers are equal (ignoring EOL differences), false otherwise.
+ * @return true if the content of the readers are equal (ignoring EOL differences), false otherwise.
* @throws NullPointerException if either input is null.
* @throws UncheckedIOException if an I/O error occurs.
* @since 2.2
@@ -1229,17 +1359,16 @@ public static boolean contentEqualsIgnoreEOL(final Reader reader1, final Reader
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Large streams (over 2GB) will return a bytes copied value of {@code -1} after the copy has completed since
- * the correct number of bytes cannot be returned as an int. For large streams use the
- * {@link #copyLarge(InputStream, OutputStream)} method.
+ * Large streams (over 2GB) will return a bytes copied value of {@code -1} after the copy has completed since the correct number of bytes cannot be returned
+ * as an int. For large streams use the {@link #copyLarge(InputStream, OutputStream)} method.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write.
* @return the number of bytes copied, or -1 if greater than {@link Integer#MAX_VALUE}.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 1.1
*/
public static int copy(final InputStream inputStream, final OutputStream outputStream) throws IOException {
@@ -1248,19 +1377,18 @@ public static int copy(final InputStream inputStream, final OutputStream outputS
}
/**
- * Copies bytes from an {@link InputStream} to an {@link OutputStream} using an internal buffer of the
- * given size.
+ * Copies bytes from an {@link InputStream} to an {@link OutputStream} using an internal buffer of the given size.
*
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write to.
- * @param bufferSize the bufferSize used to copy from the input to the output.
+ * @param bufferSize the bufferSize used to copy from the input to the output.
* @return the number of bytes copied.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.5
*/
public static long copy(final InputStream inputStream, final OutputStream outputStream, final int bufferSize) throws IOException {
@@ -1268,17 +1396,15 @@ public static long copy(final InputStream inputStream, final OutputStream output
}
/**
- * Copies bytes from an {@link InputStream} to chars on a
- * {@link Writer} using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Copies bytes from an {@link InputStream} to chars on a {@link Writer} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* This method uses {@link InputStreamReader}.
*
*
- * @param input the {@link InputStream} to read.
+ * @param input the {@link InputStream} to read.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
@@ -1291,18 +1417,16 @@ public static void copy(final InputStream input, final Writer writer) throws IOE
}
/**
- * Copies bytes from an {@link InputStream} to chars on a
- * {@link Writer} using the specified character encoding.
+ * Copies bytes from an {@link InputStream} to chars on a {@link Writer} using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* This method uses {@link InputStreamReader}.
*
*
- * @param input the {@link InputStream} to read.
- * @param writer the {@link Writer} to write to.
+ * @param input the {@link InputStream} to read.
+ * @param writer the {@link Writer} to write to.
* @param inputCharset the charset to use for the input stream, null means platform default.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
@@ -1313,22 +1437,19 @@ public static void copy(final InputStream input, final Writer writer, final Char
}
/**
- * Copies bytes from an {@link InputStream} to chars on a
- * {@link Writer} using the specified character encoding.
+ * Copies bytes from an {@link InputStream} to chars on a {@link Writer} using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link InputStreamReader}.
*
*
- * @param input the {@link InputStream} to read
- * @param writer the {@link Writer} to write to
+ * @param input the {@link InputStream} to read.
+ * @param writer the {@link Writer} to write to.
* @param inputCharsetName the name of the requested charset for the InputStream, null means platform default.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
@@ -1342,8 +1463,7 @@ public static void copy(final InputStream input, final Writer writer, final Stri
/**
* Copies bytes from a {@link ByteArrayOutputStream} to a {@link QueueInputStream}.
*
- * Unlike using JDK {@link PipedInputStream} and {@link PipedOutputStream} for this, this
- * solution works safely in a single thread environment.
+ * Unlike using JDK {@link PipedInputStream} and {@link PipedOutputStream} for this, this solution works safely in a single thread environment.
*
*
* Example usage:
@@ -1352,14 +1472,13 @@ public static void copy(final InputStream input, final Writer writer, final Stri
*
*
* @param outputStream the {@link ByteArrayOutputStream} to read.
* @return the {@link QueueInputStream} filled with the content of the outputStream.
* @throws NullPointerException if the {@link ByteArrayOutputStream} is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.12
*/
@SuppressWarnings("resource") // streams are closed by the caller.
@@ -1373,14 +1492,11 @@ public static QueueInputStream copy(final java.io.ByteArrayOutputStream outputSt
/**
* Copies chars from a {@link Reader} to a {@link Appendable}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * Large streams (over 2GB) will return a chars copied value of
- * {@code -1} after the copy has completed since the correct
- * number of chars cannot be returned as an int. For large streams
- * use the {@link #copyLarge(Reader, Writer)} method.
+ * Large streams (over 2GB) will return a chars copied value of {@code -1} after the copy has completed since the correct number of chars cannot be returned
+ * as an int. For large streams use the {@link #copyLarge(Reader, Writer)} method.
*
*
* @param reader the {@link Reader} to read.
@@ -1397,8 +1513,7 @@ public static long copy(final Reader reader, final Appendable output) throws IOE
/**
* Copies chars from a {@link Reader} to an {@link Appendable}.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedReader}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -1421,7 +1536,7 @@ public static long copy(final Reader reader, final Appendable output, final Char
}
/**
- * Copies chars from a {@link Reader} to bytes on an {@link OutputStream} using the the virtual machine's {@link Charset#defaultCharset() default charset},
+ * Copies chars from a {@link Reader} to bytes on an {@link OutputStream} using the virtual machine's {@linkplain Charset#defaultCharset() default charset},
* and calling flush.
*
* This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
@@ -1438,7 +1553,7 @@ public static long copy(final Reader reader, final Appendable output, final Char
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #copy(Reader, OutputStream, Charset)} instead
+ * @deprecated Use {@link #copy(Reader, OutputStream, Charset)} instead.
*/
@Deprecated
public static void copy(final Reader reader, final OutputStream output) throws IOException {
@@ -1478,7 +1593,7 @@ public static void copy(final Reader reader, final OutputStream output, final Ch
* This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* Due to the implementation of OutputStreamWriter, this method performs a flush.
@@ -1502,14 +1617,11 @@ public static void copy(final Reader reader, final OutputStream output, final St
/**
* Copies chars from a {@link Reader} to a {@link Writer}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * Large streams (over 2GB) will return a chars copied value of
- * {@code -1} after the copy has completed since the correct
- * number of chars cannot be returned as an int. For large streams
- * use the {@link #copyLarge(Reader, Writer)} method.
+ * Large streams (over 2GB) will return a chars copied value of {@code -1} after the copy has completed since the correct number of chars cannot be returned
+ * as an int. For large streams use the {@link #copyLarge(Reader, Writer)} method.
*
*
* @param reader the {@link Reader} to read.
@@ -1536,12 +1648,12 @@ public static int copy(final Reader reader, final Writer writer) throws IOExcept
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
*
- * @param url the {@link URL} to read.
+ * @param url the {@link URL} to read.
* @param file the {@link OutputStream} to write.
* @return the number of bytes copied.
* @throws NullPointerException if the URL is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.9.0
*/
public static long copy(final URL url, final File file) throws IOException {
@@ -1559,12 +1671,12 @@ public static long copy(final URL url, final File file) throws IOException {
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
*
- * @param url the {@link URL} to read.
+ * @param url the {@link URL} to read.
* @param outputStream the {@link OutputStream} to write.
* @return the number of bytes copied.
* @throws NullPointerException if the URL is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.9.0
*/
public static long copy(final URL url, final OutputStream outputStream) throws IOException {
@@ -1574,49 +1686,43 @@ public static long copy(final URL url, final OutputStream outputStream) throws I
}
/**
- * Copies bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}.
+ * Copies bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write.
* @return the number of bytes copied.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 1.3
*/
- public static long copyLarge(final InputStream inputStream, final OutputStream outputStream)
- throws IOException {
+ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream) throws IOException {
return copy(inputStream, outputStream, DEFAULT_BUFFER_SIZE);
}
/**
- * Copies bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}.
+ * Copies bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param inputStream the {@link InputStream} to read.
+ * @param inputStream the {@link InputStream} to read.
* @param outputStream the {@link OutputStream} to write.
- * @param buffer the buffer to use for the copy
+ * @param buffer the buffer to use for the copy.
* @return the number of bytes copied.
* @throws NullPointerException if the InputStream is {@code null}.
* @throws NullPointerException if the OutputStream is {@code null}.
- * @throws IOException if an I/O error occurs.
+ * @throws IOException if an I/O error occurs.
* @since 2.2
*/
@SuppressWarnings("resource") // streams are closed by the caller.
- public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer)
- throws IOException {
+ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer) throws IOException {
Objects.requireNonNull(inputStream, "inputStream");
Objects.requireNonNull(outputStream, "outputStream");
long count = 0;
@@ -1629,58 +1735,53 @@ public static long copyLarge(final InputStream inputStream, final OutputStream o
}
/**
- * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}, optionally skipping input bytes.
+ * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}, optionally skipping input bytes.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Note that the implementation uses {@link #skip(InputStream, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(InputStream, long)}. This means that the method may be considerably less efficient than using the actual
+ * skip implementation, this is done to guarantee that the correct number of characters are skipped.
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
*
- * @param input the {@link InputStream} to read.
- * @param output the {@link OutputStream} to write.
+ * @param input the {@link InputStream} to read.
+ * @param output the {@link OutputStream} to write.
* @param inputOffset number of bytes to skip from input before copying, these bytes are ignored.
- * @param length number of bytes to copy.
+ * @param length number of bytes to copy.
* @return the number of bytes copied.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
* @since 2.2
*/
- public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset,
- final long length) throws IOException {
- return copyLarge(input, output, inputOffset, length, getScratchByteArray());
+ public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset, final long length) throws IOException {
+ try (ScratchBytes scratch = ScratchBytes.get()) {
+ return copyLarge(input, output, inputOffset, length, scratch.array());
+ }
}
/**
- * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an
- * {@link OutputStream}, optionally skipping input bytes.
+ * Copies some or all bytes from a large (over 2GB) {@link InputStream} to an {@link OutputStream}, optionally skipping input bytes.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedInputStream}.
*
*
- * Note that the implementation uses {@link #skip(InputStream, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(InputStream, long)}. This means that the method may be considerably less efficient than using the actual
+ * skip implementation, this is done to guarantee that the correct number of characters are skipped.
*
*
- * @param input the {@link InputStream} to read.
- * @param output the {@link OutputStream} to write.
+ * @param input the {@link InputStream} to read.
+ * @param output the {@link OutputStream} to write.
* @param inputOffset number of bytes to skip from input before copying, these bytes are ignored.
- * @param length number of bytes to copy.
- * @param buffer the buffer to use for the copy.
+ * @param length number of bytes to copy.
+ * @param buffer the buffer to use for the copy.
* @return the number of bytes copied.
* @throws NullPointerException if the input or output is null.
* @throws IOException if an I/O error occurs.
* @since 2.2
*/
- public static long copyLarge(final InputStream input, final OutputStream output,
- final long inputOffset, final long length, final byte[] buffer) throws IOException {
+ public static long copyLarge(final InputStream input, final OutputStream output, final long inputOffset, final long length, final byte[] buffer)
+ throws IOException {
if (inputOffset > 0) {
skipFully(input, inputOffset);
}
@@ -1698,7 +1799,7 @@ public static long copyLarge(final InputStream input, final OutputStream output,
output.write(buffer, 0, read);
totalRead += read;
if (length > 0) { // only adjust length if not reading to the end
- // Note the cast must work because buffer.length is an integer
+ // Note the cast must work because bufferLength = buffer.length is an integer
bytesToRead = (int) Math.min(length - totalRead, bufferLength);
}
}
@@ -1708,8 +1809,7 @@ public static long copyLarge(final InputStream input, final OutputStream output,
/**
* Copies chars from a large (over 2GB) {@link Reader} to a {@link Writer}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* The buffer size is given by {@link #DEFAULT_BUFFER_SIZE}.
@@ -1723,22 +1823,23 @@ public static long copyLarge(final InputStream input, final OutputStream output,
* @since 1.3
*/
public static long copyLarge(final Reader reader, final Writer writer) throws IOException {
- return copyLarge(reader, writer, getScratchCharArray());
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ return copyLarge(reader, writer, scratch.array());
+ }
}
/**
* Copies chars from a large (over 2GB) {@link Reader} to a {@link Writer}.
*
- * This method uses the provided buffer, so there is no need to use a
- * {@link BufferedReader}.
+ * This method uses the provided buffer, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to source.
* @param writer the {@link Writer} to target.
- * @param buffer the buffer to be used for the copy
- * @return the number of characters copied
- * @throws NullPointerException if the input or output is null
- * @throws IOException if an I/O error occurs
+ * @param buffer the buffer to be used for the copy.
+ * @return the number of characters copied.
+ * @throws NullPointerException if the input or output is null.
+ * @throws IOException if an I/O error occurs.
* @since 2.2
*/
public static long copyLarge(final Reader reader, final Writer writer, final char[] buffer) throws IOException {
@@ -1770,7 +1871,9 @@ public static long copyLarge(final Reader reader, final Writer writer, final cha
* @since 2.2
*/
public static long copyLarge(final Reader reader, final Writer writer, final long inputOffset, final long length) throws IOException {
- return copyLarge(reader, writer, inputOffset, length, getScratchCharArray());
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ return copyLarge(reader, writer, inputOffset, length, scratch.array());
+ }
}
/**
@@ -1817,84 +1920,18 @@ public static long copyLarge(final Reader reader, final Writer writer, final lon
* Copies up to {@code size} bytes from the given {@link InputStream} into a new {@link UnsynchronizedByteArrayOutputStream}.
*
* @param input The {@link InputStream} to read; must not be {@code null}.
- * @param limit The maximum number of bytes to read; must be {@code >= 0}.
- * The actual bytes read are validated to equal {@code size}.
+ * @param limit The maximum number of bytes to read; must be {@code >= 0}. The actual bytes read are validated to equal {@code size}.
* @param bufferSize The buffer size of the output stream; must be {@code > 0}.
* @return a ByteArrayOutputStream containing the read bytes.
*/
- static UnsynchronizedByteArrayOutputStream copyToOutputStream(
- final InputStream input, final long limit, final int bufferSize) throws IOException {
- try (UnsynchronizedByteArrayOutputStream output = UnsynchronizedByteArrayOutputStream.builder()
- .setBufferSize(bufferSize)
- .get();
- InputStream boundedInput = BoundedInputStream.builder()
- .setMaxCount(limit)
- .setPropagateClose(false)
- .setInputStream(input)
- .get()) {
+ static UnsynchronizedByteArrayOutputStream copyToOutputStream(final InputStream input, final long limit, final int bufferSize) throws IOException {
+ try (UnsynchronizedByteArrayOutputStream output = UnsynchronizedByteArrayOutputStream.builder().setBufferSize(bufferSize).get();
+ InputStream boundedInput = BoundedInputStream.builder().setMaxCount(limit).setPropagateClose(false).setInputStream(input).get()) {
output.write(boundedInput);
return output;
}
}
- /**
- * Fills the given array with 0s.
- *
- * @param arr The non-null array to fill.
- * @return The given array.
- */
- private static byte[] fill0(final byte[] arr) {
- Arrays.fill(arr, (byte) 0);
- return arr;
- }
-
- /**
- * Fills the given array with 0s.
- *
- * @param arr The non-null array to fill.
- * @return The given array.
- */
- private static char[] fill0(final char[] arr) {
- Arrays.fill(arr, (char) 0);
- return arr;
- }
-
- /**
- * Gets the internal byte array buffer, intended for both reading and writing.
- *
- * @return the internal byte array buffer, intended for both reading and writing.
- */
- static byte[] getScratchByteArray() {
- return fill0(SCRATCH_BYTE_BUFFER_RW.get());
- }
-
- /**
- * Gets the internal byte array intended for write only operations.
- *
- * @return the internal byte array intended for write only operations.
- */
- static byte[] getScratchByteArrayWriteOnly() {
- return fill0(SCRATCH_BYTE_BUFFER_WO);
- }
-
- /**
- * Gets the char byte array buffer, intended for both reading and writing.
- *
- * @return the char byte array buffer, intended for both reading and writing.
- */
- static char[] getScratchCharArray() {
- return fill0(SCRATCH_CHAR_BUFFER_RW.get());
- }
-
- /**
- * Gets the internal char array intended for write only operations.
- *
- * @return the internal char array intended for write only operations.
- */
- static char[] getScratchCharArrayWriteOnly() {
- return fill0(SCRATCH_CHAR_BUFFER_WO);
- }
-
/**
* Returns the length of the given array in a null-safe manner.
*
@@ -1940,31 +1977,29 @@ public static int length(final Object[] array) {
}
/**
- * Returns an Iterator for the lines in an {@link InputStream}, using
- * the character encoding specified (or default encoding if null).
+ * Returns an Iterator for the lines in an {@link InputStream}, using the character encoding specified (or default encoding if null).
*
- * {@link LineIterator} holds a reference to the open
- * {@link InputStream} specified here. When you have finished with
- * the iterator you should close the stream to free internal resources.
- * This can be done by using a try-with-resources block, closing the stream directly, or by calling
+ * {@link LineIterator} holds a reference to the open {@link InputStream} specified here. When you have finished with the iterator you should close the
+ * stream to free internal resources. This can be done by using a try-with-resources block, closing the stream directly, or by calling
* {@link LineIterator#close()}.
*
*
* The recommended usage pattern is:
*
+ *
*
* try {
- * LineIterator it = IOUtils.lineIterator(stream, charset);
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
+ * LineIterator it = IOUtils.lineIterator(stream, charset);
+ * while (it.hasNext()) {
+ * String line = it.nextLine();
+ * /// do something with line
+ * }
* } finally {
- * IOUtils.closeQuietly(stream);
+ * IOUtils.closeQuietly(stream);
* }
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charset the charset to use, null means platform default.
* @return an Iterator of the lines in the reader, never null.
* @throws IllegalArgumentException if the input is null.
@@ -1975,31 +2010,29 @@ public static LineIterator lineIterator(final InputStream input, final Charset c
}
/**
- * Returns an Iterator for the lines in an {@link InputStream}, using
- * the character encoding specified (or default encoding if null).
+ * Returns an Iterator for the lines in an {@link InputStream}, using the character encoding specified (or default encoding if null).
*
- * {@link LineIterator} holds a reference to the open
- * {@link InputStream} specified here. When you have finished with
- * the iterator you should close the stream to free internal resources.
- * This can be done by using a try-with-resources block, closing the stream directly, or by calling
+ * {@link LineIterator} holds a reference to the open {@link InputStream} specified here. When you have finished with the iterator you should close the
+ * stream to free internal resources. This can be done by using a try-with-resources block, closing the stream directly, or by calling
* {@link LineIterator#close()}.
*
*
* The recommended usage pattern is:
*
+ *
*
* try {
- * LineIterator it = IOUtils.lineIterator(stream, StandardCharsets.UTF_8.name());
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
+ * LineIterator it = IOUtils.lineIterator(stream, StandardCharsets.UTF_8.name());
+ * while (it.hasNext()) {
+ * String line = it.nextLine();
+ * /// do something with line
+ * }
* } finally {
- * IOUtils.closeQuietly(stream);
+ * IOUtils.closeQuietly(stream);
* }
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charsetName the encoding to use, null means platform default.
* @return an Iterator of the lines in the reader, never null.
* @throws IllegalArgumentException if the input is null.
@@ -2013,24 +2046,22 @@ public static LineIterator lineIterator(final InputStream input, final String ch
/**
* Returns an Iterator for the lines in a {@link Reader}.
*
- * {@link LineIterator} holds a reference to the open
- * {@link Reader} specified here. When you have finished with the
- * iterator you should close the reader to free internal resources.
- * This can be done by using a try-with-resources block, closing the reader directly, or by calling
- * {@link LineIterator#close()}.
+ * {@link LineIterator} holds a reference to the open {@link Reader} specified here. When you have finished with the iterator you should close the reader to
+ * free internal resources. This can be done by using a try-with-resources block, closing the reader directly, or by calling {@link LineIterator#close()}.
*
*
* The recommended usage pattern is:
*
+ *
*
* try {
- * LineIterator it = IOUtils.lineIterator(reader);
- * while (it.hasNext()) {
- * String line = it.nextLine();
- * /// do something with line
- * }
+ * LineIterator it = IOUtils.lineIterator(reader);
+ * while (it.hasNext()) {
+ * String line = it.nextLine();
+ * /// do something with line
+ * }
* } finally {
- * IOUtils.closeQuietly(reader);
+ * IOUtils.closeQuietly(reader);
* }
*
*
@@ -2046,15 +2077,15 @@ public static LineIterator lineIterator(final Reader reader) {
/**
* Reads bytes from an input stream.
*
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link InputStream}.
+ * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for subclasses of
+ * {@link InputStream}.
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param buffer destination.
* @return actual length read; may be less than requested if EOF was reached.
- * @throws IOException if a read error occurs.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws IOException if a read error occurs.
* @since 2.2
*/
public static int read(final InputStream input, final byte[] buffer) throws IOException {
@@ -2064,50 +2095,26 @@ public static int read(final InputStream input, final byte[] buffer) throws IOEx
/**
* Reads bytes from an input stream.
*
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link InputStream}.
+ * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for subclasses of
+ * {@link InputStream}.
*
*
- * @param input where to read input.
+ * @param input where to read input.
* @param buffer destination.
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
* @return actual length read; may be less than requested if EOF was reached.
- * @throws IllegalArgumentException if length is negative.
- * @throws IOException if a read error occurs.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws IOException if a read error occurs.
* @since 2.2
*/
- public static int read(final InputStream input, final byte[] buffer, final int offset, final int length)
- throws IOException {
- if (length == 0) {
- return 0;
- }
- return read(input::read, buffer, offset, length);
- }
-
- /**
- * Reads bytes from an input. This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case
- * for subclasses of {@link InputStream}.
- *
- * @param input How to read input.
- * @param buffer destination.
- * @param offset initial offset into buffer.
- * @param length length to read, must be >= 0.
- * @return actual length read; may be less than requested if EOF was reached.
- * @throws IllegalArgumentException if length is negative.
- * @throws IOException if a read error occurs.
- * @since 2.2
- */
- static int read(final IOTriFunction input, final byte[] buffer, final int offset, final int length)
- throws IOException {
- if (length < 0) {
- throw new IllegalArgumentException("Length must not be negative: " + length);
- }
+ public static int read(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException {
+ checkFromIndexSize(buffer, offset, length);
int remaining = length;
while (remaining > 0) {
final int location = length - remaining;
- final int count = input.apply(buffer, offset + location, remaining);
+ final int count = input.read(buffer, offset + location, remaining);
if (EOF == count) {
break;
}
@@ -2119,12 +2126,11 @@ static int read(final IOTriFunction input, fi
/**
* Reads bytes from a ReadableByteChannel.
*
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link ReadableByteChannel}.
+ * This implementation guarantees that it will read as many bytes as possible before giving up; this may not always be the case for subclasses of
+ * {@link ReadableByteChannel}.
*
*
- * @param input the byte channel to read.
+ * @param input the byte channel to read.
* @param buffer byte buffer destination.
* @return the actual length read; may be less than requested if EOF was reached.
* @throws IOException if a read error occurs.
@@ -2144,9 +2150,8 @@ public static int read(final ReadableByteChannel input, final ByteBuffer buffer)
/**
* Reads characters from an input character stream.
*
- * This implementation guarantees that it will read as many characters
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link Reader}.
+ * This implementation guarantees that it will read as many characters as possible before giving up; this may not always be the case for subclasses of
+ * {@link Reader}.
*
*
* @param reader where to read input from.
@@ -2162,9 +2167,8 @@ public static int read(final Reader reader, final char[] buffer) throws IOExcept
/**
* Reads characters from an input character stream.
*
- * This implementation guarantees that it will read as many characters
- * as possible before giving up; this may not always be the case for
- * subclasses of {@link Reader}.
+ * This implementation guarantees that it will read as many characters as possible before giving up; this may not always be the case for subclasses of
+ * {@link Reader}.
*
*
* @param reader where to read input from.
@@ -2172,15 +2176,13 @@ public static int read(final Reader reader, final char[] buffer) throws IOExcept
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
* @return actual length read; may be less than requested if EOF was reached.
- * @throws IllegalArgumentException if length is negative.
- * @throws IOException if a read error occurs.
+ * @throws NullPointerException if {@code reader} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws IOException if a read error occurs.
* @since 2.2
*/
- public static int read(final Reader reader, final char[] buffer, final int offset, final int length)
- throws IOException {
- if (length < 0) {
- throw new IllegalArgumentException("Length must not be negative: " + length);
- }
+ public static int read(final Reader reader, final char[] buffer, final int offset, final int length) throws IOException {
+ checkFromIndexSize(buffer, offset, length);
int remaining = length;
while (remaining > 0) {
final int location = length - remaining;
@@ -2196,15 +2198,15 @@ public static int read(final Reader reader, final char[] buffer, final int offse
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may not read as many bytes as requested (most likely because of reaching
+ * EOF).
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param buffer destination.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of bytes read was incorrect.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws EOFException if the number of bytes read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
public static void readFully(final InputStream input, final byte[] buffer) throws IOException {
@@ -2214,21 +2216,21 @@ public static void readFully(final InputStream input, final byte[] buffer) throw
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may not read as many bytes as requested (most likely because of reaching
+ * EOF).
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param buffer destination.
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of bytes read was incorrect.
+ * @throws NullPointerException if {@code input} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws EOFException if the number of bytes read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
- public static void readFully(final InputStream input, final byte[] buffer, final int offset, final int length)
- throws IOException {
+ public static void readFully(final InputStream input, final byte[] buffer, final int offset, final int length) throws IOException {
final int actual = read(input, buffer, offset, length);
if (actual != length) {
throw new EOFException("Length to read: " + length + " actual: " + actual);
@@ -2238,11 +2240,11 @@ public static void readFully(final InputStream input, final byte[] buffer, final
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#read(byte[], int, int)} may not read as many bytes as requested (most likely because of reaching
+ * EOF).
*
*
- * @param input where to read input from.
+ * @param input where to read input from.
* @param length length to read, must be >= 0.
* @return the bytes read from input.
* @throws IOException if there is a problem reading the file.
@@ -2259,11 +2261,11 @@ public static byte[] readFully(final InputStream input, final int length) throws
/**
* Reads the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link ReadableByteChannel#read(ByteBuffer)} may
- * not read as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link ReadableByteChannel#read(ByteBuffer)} may not read as many bytes as requested (most likely because of
+ * reaching EOF).
*
*
- * @param input the byte channel to read.
+ * @param input the byte channel to read.
* @param buffer byte buffer destination.
* @throws IOException if there is a problem reading the file.
* @throws EOFException if the number of bytes read was incorrect.
@@ -2280,15 +2282,15 @@ public static void readFully(final ReadableByteChannel input, final ByteBuffer b
/**
* Reads the requested number of characters or fail if there are not enough left.
*
- * This allows for the possibility that {@link Reader#read(char[], int, int)} may
- * not read as many characters as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link Reader#read(char[], int, int)} may not read as many characters as requested (most likely because of reaching
+ * EOF).
*
*
* @param reader where to read input from.
* @param buffer destination.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of characters read was incorrect.
+ * @throws NullPointerException if {@code reader} or {@code buffer} is null.
+ * @throws EOFException if the number of characters read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
public static void readFully(final Reader reader, final char[] buffer) throws IOException {
@@ -2298,21 +2300,21 @@ public static void readFully(final Reader reader, final char[] buffer) throws IO
/**
* Reads the requested number of characters or fail if there are not enough left.
*
- * This allows for the possibility that {@link Reader#read(char[], int, int)} may
- * not read as many characters as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link Reader#read(char[], int, int)} may not read as many characters as requested (most likely because of reaching
+ * EOF).
*
*
* @param reader where to read input from.
* @param buffer destination.
* @param offset initial offset into buffer.
* @param length length to read, must be >= 0.
- * @throws IOException if there is a problem reading the file.
- * @throws IllegalArgumentException if length is negative.
- * @throws EOFException if the number of characters read was incorrect.
+ * @throws NullPointerException if {@code reader} or {@code buffer} is null.
+ * @throws IndexOutOfBoundsException if {@code offset} or {@code length} is negative, or if {@code offset + length} is greater than {@code buffer.length}.
+ * @throws EOFException if the number of characters read was incorrect.
+ * @throws IOException if there is a problem reading the file.
* @since 2.2
*/
- public static void readFully(final Reader reader, final char[] buffer, final int offset, final int length)
- throws IOException {
+ public static void readFully(final Reader reader, final char[] buffer, final int offset, final int length) throws IOException {
final int actual = read(reader, buffer, offset, length);
if (actual != length) {
throw new EOFException("Length to read: " + length + " actual: " + actual);
@@ -2334,11 +2336,10 @@ public static List readLines(final CharSequence csq) throws UncheckedIOE
}
/**
- * Gets the contents of an {@link InputStream} as a list of Strings,
- * one entry per line, using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of an {@link InputStream} as a list of Strings, one entry per line, using the virtual machine's {@linkplain Charset#defaultCharset()
+ * default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param input the {@link InputStream} to read, not null.
@@ -2346,7 +2347,7 @@ public static List readLines(final CharSequence csq) throws UncheckedIOE
* @throws NullPointerException if the input is null.
* @throws UncheckedIOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #readLines(InputStream, Charset)} instead
+ * @deprecated Use {@link #readLines(InputStream, Charset)} instead.
*/
@Deprecated
public static List readLines(final InputStream input) throws UncheckedIOException {
@@ -2354,14 +2355,12 @@ public static List readLines(final InputStream input) throws UncheckedIO
}
/**
- * Gets the contents of an {@link InputStream} as a list of Strings,
- * one entry per line, using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a list of Strings, one entry per line, using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charset the charset to use, null means platform default.
* @return the list of Strings, never null.
* @throws NullPointerException if the input is null.
@@ -2373,18 +2372,15 @@ public static List readLines(final InputStream input, final Charset char
}
/**
- * Gets the contents of an {@link InputStream} as a list of Strings,
- * one entry per line, using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a list of Strings, one entry per line, using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read, not null.
+ * @param input the {@link InputStream} to read, not null.
* @param charsetName the name of the requested charset, null means platform default.
* @return the list of Strings, never null.
* @throws NullPointerException if the input is null.
@@ -2397,11 +2393,9 @@ public static List readLines(final InputStream input, final String chars
}
/**
- * Gets the contents of a {@link Reader} as a list of Strings,
- * one entry per line.
+ * Gets the contents of a {@link Reader} as a list of Strings, one entry per line.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read, not null.
@@ -2437,7 +2431,7 @@ public static byte[] resourceToByteArray(final String name) throws IOException {
* Delegates to {@link #resourceToURL(String, ClassLoader)}.
*
*
- * @param name The resource name.
+ * @param name The resource name.
* @param classLoader the class loader that the resolution of the resource is delegated to.
* @return the requested byte array.
* @throws IOException if an I/O error occurs or the resource is not found.
@@ -2454,7 +2448,7 @@ public static byte[] resourceToByteArray(final String name, final ClassLoader cl
* Delegates to {@link #resourceToString(String, Charset, ClassLoader) resourceToString(String, Charset, null)}.
*
*
- * @param name The resource name.
+ * @param name The resource name.
* @param charset the charset to use, null means platform default.
* @return the requested String.
* @throws IOException if an I/O error occurs or the resource is not found.
@@ -2471,8 +2465,8 @@ public static String resourceToString(final String name, final Charset charset)
* Delegates to {@link #resourceToURL(String, ClassLoader)}.
*
*
- * @param name The resource name.
- * @param charset the Charset to use, null means platform default.
+ * @param name The resource name.
+ * @param charset the Charset to use, null means platform default.
* @param classLoader the class loader that the resolution of the resource is delegated to.
* @return the requested String.
* @throws IOException if an I/O error occurs.
@@ -2501,11 +2495,11 @@ public static URL resourceToURL(final String name) throws IOException {
/**
* Gets a URL pointing to the given resource.
*
- * If the {@code classLoader} is not null, call {@link ClassLoader#getResource(String)}, otherwise call
- * {@link Class#getResource(String) IOUtils.class.getResource(name)}.
+ * If the {@code classLoader} is not null, call {@link ClassLoader#getResource(String)}, otherwise call {@link Class#getResource(String)
+ * IOUtils.class.getResource(name)}.
*
*
- * @param name The resource name.
+ * @param name The resource name.
* @param classLoader Delegate to this class loader if not null.
* @return A URL object for reading the resource.
* @throws IOException if the resource is not found.
@@ -2543,7 +2537,9 @@ public static URL resourceToURL(final String name, final ClassLoader classLoader
* @since 2.0
*/
public static long skip(final InputStream input, final long skip) throws IOException {
- return skip(input, skip, IOUtils::getScratchByteArrayWriteOnly);
+ try (ScratchBytes scratch = ScratchBytes.get()) {
+ return skip(input, skip, scratch::array);
+ }
}
/**
@@ -2563,7 +2559,7 @@ public static long skip(final InputStream input, final long skip) throws IOExcep
*
*
* @param input byte stream to skip.
- * @param skip number of bytes to skip.
+ * @param skip number of bytes to skip.
* @param skipBufferSupplier Supplies the buffer to use for reading.
* @return number of bytes actually skipped.
* @throws IOException if there is a problem reading the file.
@@ -2595,11 +2591,9 @@ public static long skip(final InputStream input, final long skip, final Supplier
}
/**
- * Skips bytes from a ReadableByteChannel.
- * This implementation guarantees that it will read as many bytes
- * as possible before giving up.
+ * Skips bytes from a ReadableByteChannel. This implementation guarantees that it will read as many bytes as possible before giving up.
*
- * @param input ReadableByteChannel to skip.
+ * @param input ReadableByteChannel to skip.
* @param toSkip number of bytes to skip.
* @return number of bytes actually skipped.
* @throws IOException if there is a problem reading the ReadableByteChannel.
@@ -2625,15 +2619,12 @@ public static long skip(final ReadableByteChannel input, final long toSkip) thro
}
/**
- * Skips characters from an input character stream.
- * This implementation guarantees that it will read as many characters
- * as possible before giving up; this may not always be the case for
- * skip() implementations in subclasses of {@link Reader}.
+ * Skips characters from an input character stream. This implementation guarantees that it will read as many characters as possible before giving up; this
+ * may not always be the case for skip() implementations in subclasses of {@link Reader}.
*
- * Note that the implementation uses {@link Reader#read(char[], int, int)} rather
- * than delegating to {@link Reader#skip(long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link Reader#read(char[], int, int)} rather than delegating to {@link Reader#skip(long)}. This means that the method
+ * may be considerably less efficient than using the actual skip implementation, this is done to guarantee that the correct number of characters are
+ * skipped.
*
*
* @param reader character stream to skip.
@@ -2650,14 +2641,16 @@ public static long skip(final Reader reader, final long toSkip) throws IOExcepti
throw new IllegalArgumentException("Skip count must be non-negative, actual: " + toSkip);
}
long remain = toSkip;
- while (remain > 0) {
- // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip()
- final char[] charArray = getScratchCharArrayWriteOnly();
- final long n = reader.read(charArray, 0, (int) Math.min(remain, charArray.length));
- if (n < 0) { // EOF
- break;
+ try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
+ final char[] chars = scratch.array();
+ while (remain > 0) {
+ // See https://issues.apache.org/jira/browse/IO-203 for why we use read() rather than delegating to skip()
+ final long n = reader.read(chars, 0, (int) Math.min(remain, chars.length));
+ if (n < 0) { // EOF
+ break;
+ }
+ remain -= n;
}
- remain -= n;
}
return toSkip - remain;
}
@@ -2665,16 +2658,14 @@ public static long skip(final Reader reader, final long toSkip) throws IOExcepti
/**
* Skips the requested number of bytes or fail if there are not enough left.
*
- * This allows for the possibility that {@link InputStream#skip(long)} may
- * not skip as many bytes as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link InputStream#skip(long)} may not skip as many bytes as requested (most likely because of reaching EOF).
*
*
- * Note that the implementation uses {@link #skip(InputStream, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(InputStream, long)}. This means that the method may be considerably less efficient than using the actual
+ * skip implementation, this is done to guarantee that the correct number of characters are skipped.
*
*
- * @param input stream to skip.
+ * @param input stream to skip.
* @param toSkip the number of bytes to skip.
* @throws IOException if there is a problem reading the file.
* @throws IllegalArgumentException if toSkip is negative.
@@ -2683,7 +2674,7 @@ public static long skip(final Reader reader, final long toSkip) throws IOExcepti
* @since 2.0
*/
public static void skipFully(final InputStream input, final long toSkip) throws IOException {
- final long skipped = skip(input, toSkip, IOUtils::getScratchByteArrayWriteOnly);
+ final long skipped = skip(input, toSkip);
if (skipped != toSkip) {
throw new EOFException("Bytes to skip: " + toSkip + " actual: " + skipped);
}
@@ -2725,7 +2716,7 @@ public static void skipFully(final InputStream input, final long toSkip, final S
/**
* Skips the requested number of bytes or fail if there are not enough left.
*
- * @param input ReadableByteChannel to skip.
+ * @param input ReadableByteChannel to skip.
* @param toSkip the number of bytes to skip.
* @throws IOException if there is a problem reading the ReadableByteChannel.
* @throws IllegalArgumentException if toSkip is negative.
@@ -2745,13 +2736,11 @@ public static void skipFully(final ReadableByteChannel input, final long toSkip)
/**
* Skips the requested number of characters or fail if there are not enough left.
*
- * This allows for the possibility that {@link Reader#skip(long)} may
- * not skip as many characters as requested (most likely because of reaching EOF).
+ * This allows for the possibility that {@link Reader#skip(long)} may not skip as many characters as requested (most likely because of reaching EOF).
*
*
- * Note that the implementation uses {@link #skip(Reader, long)}.
- * This means that the method may be considerably less efficient than using the actual skip implementation,
- * this is done to guarantee that the correct number of characters are skipped.
+ * Note that the implementation uses {@link #skip(Reader, long)}. This means that the method may be considerably less efficient than using the actual skip
+ * implementation, this is done to guarantee that the correct number of characters are skipped.
*
*
* @param reader stream to skip.
@@ -2780,7 +2769,9 @@ public static void skipFully(final Reader reader, final long toSkip) throws IOEx
*
It has network timeout associated.
*
*
- * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
- * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray(InputStream)}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
@@ -2819,8 +2812,7 @@ public static InputStream toBufferedInputStream(final InputStream input, final i
}
/**
- * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
- * reader.
+ * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader.
*
* @param reader the reader to wrap or return (not null).
* @return the given reader or a new {@link BufferedReader} for the given reader.
@@ -2833,11 +2825,10 @@ public static BufferedReader toBufferedReader(final Reader reader) {
}
/**
- * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given
- * reader.
+ * Returns the given reader if it is a {@link BufferedReader}, otherwise creates a BufferedReader from the given reader.
*
* @param reader the reader to wrap or return (not null).
- * @param size the buffer size, if a new BufferedReader is created.
+ * @param size the buffer size, if a new BufferedReader is created.
* @return the given reader or a new {@link BufferedReader} for the given reader.
* @throws NullPointerException if the input parameter is null.
* @see #buffer(Reader)
@@ -2849,16 +2840,15 @@ public static BufferedReader toBufferedReader(final Reader reader, final int siz
/**
* Reads all the bytes from an input stream in a byte array.
- *
- *
The memory used by this method is proportional to the number
- * of bytes read, which is only limited by {@link Integer#MAX_VALUE}. Only streams
- * which fit into a single byte array with roughly 2 GiB limit can be processed
- * with this method.
+ *
+ * The memory used by this method is proportional to the number of bytes read, which is only limited by {@link Integer#MAX_VALUE}. Only
+ * streams which fit into a single byte array with roughly 2 GiB limit can be processed with this method.
+ *
*
* @param inputStream The {@link InputStream} to read; must not be {@code null}.
* @return A new byte array.
- * @throws IOException If an I/O error occurs while reading or if the maximum array size is exceeded.
- * @throws NullPointerException If {@code inputStream} is {@code null}.
+ * @throws IOException If an I/O error occurs while reading or if the maximum array size is exceeded.
+ * @throws NullPointerException If {@code inputStream} is {@code null}.
*/
public static byte[] toByteArray(final InputStream inputStream) throws IOException {
// Using SOFT_MAX_ARRAY_LENGTH guarantees that size() will not overflow
@@ -2871,10 +2861,10 @@ public static byte[] toByteArray(final InputStream inputStream) throws IOExcepti
/**
* Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
- *
- *
This variant always allocates the whole requested array size,
- * for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)},
- * which enforces stricter memory usage constraints.
+ *
+ * This variant always allocates the whole requested array size, for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)}, which
+ * enforces stricter memory usage constraints.
+ *
*
* @param input the {@link InputStream} to read; must not be {@code null}.
* @param size the exact number of bytes to read; must be {@code >= 0}.
@@ -2891,19 +2881,17 @@ public static byte[] toByteArray(final InputStream input, final int size) throws
/**
* Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
+ *
+ * The memory used by this method is proportional to the number of bytes read and limited by the specified {@code size}. This makes it
+ * suitable for processing large input streams, provided that sufficient heap space is available.
+ *
+ *
+ * This method processes the input stream in successive chunks of up to {@code chunkSize} bytes.
+ *
*
- *
The memory used by this method is proportional to the number
- * of bytes read and limited by the specified {@code size}. This makes it suitable for
- * processing large input streams, provided that sufficient heap space is
- * available.
- *
- *
This method processes the input stream in successive chunks of up to
- * {@code chunkSize} bytes.
- *
- * @param input the {@link InputStream} to read; must not be {@code null}.
- * @param size the exact number of bytes to read; must be {@code >= 0}.
- * The actual bytes read are validated to equal {@code size}.
- * @param chunkSize The chunk size for incremental reading; must be {@code > 0}.
+ * @param input the {@link InputStream} to read; must not be {@code null}.
+ * @param size the exact number of bytes to read; must be {@code >= 0}. The actual bytes read are validated to equal {@code size}.
+ * @param chunkSize The chunk size for incremental reading; must be {@code > 0}.
* @return a new byte array of length {@code size}.
* @throws IllegalArgumentException if {@code size} is negative or {@code chunkSize <= 0}.
* @throws EOFException if the stream ends before {@code size} bytes are read.
@@ -2914,25 +2902,26 @@ public static byte[] toByteArray(final InputStream input, final int size) throws
public static byte[] toByteArray(final InputStream input, final int size, final int chunkSize) throws IOException {
Objects.requireNonNull(input, "input");
if (chunkSize <= 0) {
- throw new IllegalArgumentException("Chunk size must be greater than zero: " + chunkSize);
+ throw new IllegalArgumentException(String.format("chunkSize <= 0, chunkSize = %,d", chunkSize));
}
if (size <= chunkSize) {
// throws if size < 0
return toByteArray(input::read, size);
}
final UnsynchronizedByteArrayOutputStream output = copyToOutputStream(input, size, chunkSize);
- if (output.size() != size) {
- throw new EOFException("Unexpected read size, current: " + output.size() + ", expected: " + size);
+ final int outSize = output.size();
+ if (outSize != size) {
+ throw new EOFException(String.format("Expected read size: %,d, actual: %,d", size, outSize));
}
return output.toByteArray();
}
/**
* Reads exactly {@code size} bytes from the given {@link InputStream} into a new {@code byte[]}.
- *
- *
This variant always allocates the whole requested array size,
- * for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)},
- * which enforces stricter memory usage constraints.
+ *
+ * This variant always allocates the whole requested array size, for a dynamic growing variant use {@link #toByteArray(InputStream, int, int)}, which
+ * enforces stricter memory usage constraints.
+ *
*
* @param input the {@link InputStream} to read; must not be {@code null}.
* @param size the exact number of bytes to read; must be {@code >= 0} and {@code <= Integer.MAX_VALUE}.
@@ -2946,7 +2935,7 @@ public static byte[] toByteArray(final InputStream input, final int size, final
*/
public static byte[] toByteArray(final InputStream input, final long size) throws IOException {
if (size > Integer.MAX_VALUE) {
- throw new IllegalArgumentException("Size cannot be greater than Integer max value: " + size);
+ throw new IllegalArgumentException(String.format("size > Integer.MAX_VALUE, size = %,d", size));
}
return toByteArray(input, (int) size);
}
@@ -2955,14 +2944,15 @@ public static byte[] toByteArray(final InputStream input, final long size) throw
* Gets the contents of an input as a {@code byte[]}.
*
* @param input the input to read, not null.
- * @param size the size of the input to read, where 0 < {@code size} <= length of input.
+ * @param size the size of the input to read, where 0 < {@code size} <= length of input.
* @return byte [] of length {@code size}.
- * @throws IOException if an I/O error occurs or input length is smaller than parameter {@code size}.
+ * @throws EOFException if the end of the input is reached before reading {@code size} bytes.
+ * @throws IOException if an I/O error occurs or input length is smaller than parameter {@code size}.
* @throws IllegalArgumentException if {@code size} is less than zero.
*/
static byte[] toByteArray(final IOTriFunction input, final int size) throws IOException {
if (size < 0) {
- throw new IllegalArgumentException("Size must be equal or greater than zero: " + size);
+ throw new IllegalArgumentException(String.format("size < 0, size = %,d", size));
}
if (size == 0) {
return EMPTY_BYTE_ARRAY;
@@ -2974,17 +2964,15 @@ static byte[] toByteArray(final IOTriFunction
offset += read;
}
if (offset != size) {
- throw new IOException("Unexpected read size, current: " + offset + ", expected: " + size);
+ throw new EOFException(String.format("Expected read size: %,d, actual: %,d", size, offset));
}
return data;
}
/**
- * Gets the contents of a {@link Reader} as a {@code byte[]}
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of a {@link Reader} as a {@code byte[]} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -2999,14 +2987,12 @@ public static byte[] toByteArray(final Reader reader) throws IOException {
}
/**
- * Gets the contents of a {@link Reader} as a {@code byte[]}
- * using the specified character encoding.
+ * Gets the contents of a {@link Reader} as a {@code byte[]} using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * @param reader the {@link Reader} to read.
+ * @param reader the {@link Reader} to read.
* @param charset the charset to use, null means platform default.
* @return the requested byte array.
* @throws NullPointerException if the input is null.
@@ -3021,18 +3007,15 @@ public static byte[] toByteArray(final Reader reader, final Charset charset) thr
}
/**
- * Gets the contents of a {@link Reader} as a {@code byte[]}
- * using the specified character encoding.
+ * Gets the contents of a {@link Reader} as a {@code byte[]} using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
- * @param reader the {@link Reader} to read.
+ * @param reader the {@link Reader} to read.
* @param charsetName the name of the requested charset, null means platform default.
* @return the requested byte array.
* @throws NullPointerException if the input is null.
@@ -3045,8 +3028,7 @@ public static byte[] toByteArray(final Reader reader, final String charsetName)
}
/**
- * Gets the contents of a {@link String} as a {@code byte[]}
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of a {@link String} as a {@code byte[]} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* This is the same as {@link String#getBytes()}.
*
@@ -3096,7 +3078,7 @@ public static byte[] toByteArray(final URL url) throws IOException {
* @param urlConnection the {@link URLConnection} to read.
* @return the requested byte array.
* @throws NullPointerException if the urlConn is null.
- * @throws IOException if an I/O exception occurs.
+ * @throws IOException if an I/O exception occurs.
* @since 2.4
*/
public static byte[] toByteArray(final URLConnection urlConnection) throws IOException {
@@ -3106,11 +3088,9 @@ public static byte[] toByteArray(final URLConnection urlConnection) throws IOExc
}
/**
- * Gets the contents of an {@link InputStream} as a character array
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of an {@link InputStream} as a character array using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param inputStream the {@link InputStream} to read.
@@ -3118,7 +3098,7 @@ public static byte[] toByteArray(final URLConnection urlConnection) throws IOExc
* @throws NullPointerException if the input is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #toCharArray(InputStream, Charset)} instead
+ * @deprecated Use {@link #toCharArray(InputStream, Charset)} instead.
*/
@Deprecated
public static char[] toCharArray(final InputStream inputStream) throws IOException {
@@ -3126,37 +3106,31 @@ public static char[] toCharArray(final InputStream inputStream) throws IOExcepti
}
/**
- * Gets the contents of an {@link InputStream} as a character array
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a character array using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param inputStream the {@link InputStream} to read.
- * @param charset the charset to use, null means platform default.
+ * @param charset the charset to use, null means platform default.
* @return the requested character array.
* @throws NullPointerException if the input is null.
* @throws IOException if an I/O error occurs.
* @since 2.3
*/
- public static char[] toCharArray(final InputStream inputStream, final Charset charset)
- throws IOException {
+ public static char[] toCharArray(final InputStream inputStream, final Charset charset) throws IOException {
final CharArrayWriter writer = new CharArrayWriter();
copy(inputStream, writer, charset);
return writer.toCharArray();
}
/**
- * Gets the contents of an {@link InputStream} as a character array
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a character array using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param inputStream the {@link InputStream} to read.
@@ -3174,8 +3148,7 @@ public static char[] toCharArray(final InputStream inputStream, final String cha
/**
* Gets the contents of a {@link Reader} as a character array.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -3191,8 +3164,8 @@ public static char[] toCharArray(final Reader reader) throws IOException {
}
/**
- * Converts the specified CharSequence to an input stream, encoded as bytes
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Converts the specified CharSequence to an input stream, encoded as bytes using the virtual machine's {@linkplain Charset#defaultCharset() default
+ * charset}.
*
* @param input the CharSequence to convert.
* @return an input stream.
@@ -3205,10 +3178,9 @@ public static InputStream toInputStream(final CharSequence input) {
}
/**
- * Converts the specified CharSequence to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified CharSequence to an input stream, encoded as bytes using the specified character encoding.
*
- * @param input the CharSequence to convert.
+ * @param input the CharSequence to convert.
* @param charset the charset to use, null means platform default.
* @return an input stream.
* @since 2.3
@@ -3218,14 +3190,12 @@ public static InputStream toInputStream(final CharSequence input, final Charset
}
/**
- * Converts the specified CharSequence to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified CharSequence to an input stream, encoded as bytes using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * @param input the CharSequence to convert.
+ * @param input the CharSequence to convert.
* @param charsetName the name of the requested charset, null means platform default.
* @return an input stream.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
@@ -3236,8 +3206,7 @@ public static InputStream toInputStream(final CharSequence input, final String c
}
/**
- * Converts the specified string to an input stream, encoded as bytes
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Converts the specified string to an input stream, encoded as bytes using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param input the string to convert.
* @return an input stream.
@@ -3250,10 +3219,9 @@ public static InputStream toInputStream(final String input) {
}
/**
- * Converts the specified string to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified string to an input stream, encoded as bytes using the specified character encoding.
*
- * @param input the string to convert.
+ * @param input the string to convert.
* @param charset the charset to use, null means platform default.
* @return an input stream.
* @since 2.3
@@ -3263,14 +3231,12 @@ public static InputStream toInputStream(final String input, final Charset charse
}
/**
- * Converts the specified string to an input stream, encoded as bytes
- * using the specified character encoding.
+ * Converts the specified string to an input stream, encoded as bytes using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * @param input the string to convert.
+ * @param input the string to convert.
* @param charsetName the name of the requested charset, null means platform default.
* @return an input stream.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
@@ -3281,8 +3247,7 @@ public static InputStream toInputStream(final String input, final String charset
}
/**
- * Gets the contents of a {@code byte[]} as a String
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of a {@code byte[]} as a String using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param input the byte array to read.
* @return the requested String.
@@ -3296,14 +3261,12 @@ public static String toString(final byte[] input) {
}
/**
- * Gets the contents of a {@code byte[]} as a String
- * using the specified character encoding.
+ * Gets the contents of a {@code byte[]} as a String using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * @param input the byte array to read.
+ * @param input the byte array to read.
* @param charsetName the name of the requested charset, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3313,11 +3276,9 @@ public static String toString(final byte[] input, final String charsetName) {
}
/**
- * Gets the contents of an {@link InputStream} as a String
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents of an {@link InputStream} as a String using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
* @param input the {@link InputStream} to read.
@@ -3332,14 +3293,12 @@ public static String toString(final InputStream input) throws IOException {
}
/**
- * Gets the contents of an {@link InputStream} as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a String using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read.
+ * @param input the {@link InputStream} to read.
* @param charset the charset to use, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3354,38 +3313,32 @@ public static String toString(final InputStream input, final Charset charset) th
}
/**
- * Gets the contents of an {@link InputStream} as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} as a String using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input the {@link InputStream} to read.
+ * @param input the {@link InputStream} to read.
* @param charsetName the name of the requested charset, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
* @throws IOException if an I/O error occurs.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
*/
- public static String toString(final InputStream input, final String charsetName)
- throws IOException {
+ public static String toString(final InputStream input, final String charsetName) throws IOException {
return toString(input, Charsets.toCharset(charsetName));
}
/**
- * Gets the contents of an {@link InputStream} from a supplier as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} from a supplier as a String using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input supplies the {@link InputStream} to read.
+ * @param input supplies the {@link InputStream} to read.
* @param charset the charset to use, null means platform default.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3399,15 +3352,13 @@ public static String toString(final IOSupplier input, final Charset
}
/**
- * Gets the contents of an {@link InputStream} from a supplier as a String
- * using the specified character encoding.
+ * Gets the contents of an {@link InputStream} from a supplier as a String using the specified character encoding.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedInputStream}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
- * @param input supplies the {@link InputStream} to read.
- * @param charset the charset to use, null means platform default.
+ * @param input supplies the {@link InputStream} to read.
+ * @param charset the charset to use, null means platform default.
* @param defaultString the default return value if the supplier or its value is null.
* @return the requested String.
* @throws NullPointerException if the input is null.
@@ -3426,8 +3377,7 @@ public static String toString(final IOSupplier input, final Charset
/**
* Gets the contents of a {@link Reader} as a String.
*
- * This method buffers the input internally, so there is no need to use a
- * {@link BufferedReader}.
+ * This method buffers the input internally, so there is no need to use a {@link BufferedReader}.
*
*
* @param reader the {@link Reader} to read.
@@ -3443,7 +3393,7 @@ public static String toString(final Reader reader) throws IOException {
}
/**
- * Gets the contents at the given URI using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents at the given URI using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param uri The URI source.
* @return The contents of the URL as a String.
@@ -3459,7 +3409,7 @@ public static String toString(final URI uri) throws IOException {
/**
* Gets the contents at the given URI.
*
- * @param uri The URI source.
+ * @param uri The URI source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3472,7 +3422,7 @@ public static String toString(final URI uri, final Charset encoding) throws IOEx
/**
* Gets the contents at the given URI.
*
- * @param uri The URI source.
+ * @param uri The URI source.
* @param charsetName The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3484,7 +3434,7 @@ public static String toString(final URI uri, final String charsetName) throws IO
}
/**
- * Gets the contents at the given URL using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the contents at the given URL using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @param url The URL source.
* @return The contents of the URL as a String.
@@ -3500,7 +3450,7 @@ public static String toString(final URL url) throws IOException {
/**
* Gets the contents at the given URL.
*
- * @param url The URL source.
+ * @param url The URL source.
* @param encoding The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3513,7 +3463,7 @@ public static String toString(final URL url, final Charset encoding) throws IOEx
/**
* Gets the contents at the given URL.
*
- * @param url The URL source.
+ * @param url The URL source.
* @param charsetName The encoding name for the URL contents.
* @return The contents of the URL as a String.
* @throws IOException if an I/O exception occurs.
@@ -3533,22 +3483,19 @@ public static String toString(final URL url, final String charsetName) throws IO
* @throws IOException if an I/O error occurs.
* @since 1.1
*/
- public static void write(final byte[] data, final OutputStream output)
- throws IOException {
+ public static void write(final byte[] data, final OutputStream output) throws IOException {
if (data != null) {
output.write(data);
}
}
/**
- * Writes bytes from a {@code byte[]} to chars on a {@link Writer}
- * using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes bytes from a {@code byte[]} to chars on a {@link Writer} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* This method uses {@link String#String(byte[])}.
*
*
- * @param data the byte array to write, do not modify during output,
- * null ignored
+ * @param data the byte array to write, do not modify during output, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3561,15 +3508,13 @@ public static void write(final byte[] data, final Writer writer) throws IOExcept
}
/**
- * Writes bytes from a {@code byte[]} to chars on a {@link Writer}
- * using the specified character encoding.
+ * Writes bytes from a {@code byte[]} to chars on a {@link Writer} using the specified character encoding.
*
* This method uses {@link String#String(byte[], String)}.
*
*
- * @param data the byte array to write, do not modify during output,
- * null ignored
- * @param writer the {@link Writer} to write to.
+ * @param data the byte array to write, do not modify during output, null ignored.
+ * @param writer the {@link Writer} to write to.
* @param charset the charset to use, null means platform default.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3584,7 +3529,7 @@ public static void write(final byte[] data, final Writer writer, final Charset c
/**
* Writes bytes from a {@code byte[]} to chars on a {@link Writer} using the specified character encoding.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#String(byte[], String)}.
@@ -3605,7 +3550,7 @@ public static void write(final byte[] data, final Writer writer, final String ch
/**
* Writes chars from a {@code char[]} to bytes on an {@link OutputStream}.
*
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
*
* @param data the char array to write, do not modify during output, null ignored.
@@ -3616,8 +3561,7 @@ public static void write(final byte[] data, final Writer writer, final String ch
* @deprecated Use {@link #write(char[], OutputStream, Charset)} instead.
*/
@Deprecated
- public static void write(final char[] data, final OutputStream output)
- throws IOException {
+ public static void write(final char[] data, final OutputStream output) throws IOException {
write(data, output, Charset.defaultCharset());
}
@@ -3643,7 +3587,7 @@ public static void write(final char[] data, final OutputStream output, final Cha
/**
* Writes chars from a {@code char[]} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#String(char[])} and {@link String#getBytes(String)}.
@@ -3657,8 +3601,7 @@ public static void write(final char[] data, final OutputStream output, final Cha
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 1.1
*/
- public static void write(final char[] data, final OutputStream output, final String charsetName)
- throws IOException {
+ public static void write(final char[] data, final OutputStream output, final String charsetName) throws IOException {
write(data, output, Charsets.toCharset(charsetName));
}
@@ -3692,8 +3635,7 @@ public static void write(final char[] data, final Writer writer) throws IOExcept
* @deprecated Use {@link #write(CharSequence, OutputStream, Charset)} instead.
*/
@Deprecated
- public static void write(final CharSequence data, final OutputStream output)
- throws IOException {
+ public static void write(final CharSequence data, final OutputStream output) throws IOException {
write(data, output, Charset.defaultCharset());
}
@@ -3710,8 +3652,7 @@ public static void write(final CharSequence data, final OutputStream output)
* @throws IOException if an I/O error occurs.
* @since 2.3
*/
- public static void write(final CharSequence data, final OutputStream output, final Charset charset)
- throws IOException {
+ public static void write(final CharSequence data, final OutputStream output, final Charset charset) throws IOException {
if (data != null) {
write(data.toString(), output, charset);
}
@@ -3720,7 +3661,7 @@ public static void write(final CharSequence data, final OutputStream output, fin
/**
* Writes chars from a {@link CharSequence} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#getBytes(String)}.
@@ -3734,15 +3675,14 @@ public static void write(final CharSequence data, final OutputStream output, fin
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 2.0
*/
- public static void write(final CharSequence data, final OutputStream output, final String charsetName)
- throws IOException {
+ public static void write(final CharSequence data, final OutputStream output, final String charsetName) throws IOException {
write(data, output, Charsets.toCharset(charsetName));
}
/**
* Writes chars from a {@link CharSequence} to a {@link Writer}.
*
- * @param data the {@link CharSequence} to write, null ignored.
+ * @param data the {@link CharSequence} to write, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3755,34 +3695,31 @@ public static void write(final CharSequence data, final Writer writer) throws IO
}
/**
- * Writes chars from a {@link String} to bytes on an
- * {@link OutputStream} using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Writes chars from a {@link String} to bytes on an {@link OutputStream} using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* This method uses {@link String#getBytes()}.
*
*
- * @param data the {@link String} to write, null ignored.
+ * @param data the {@link String} to write, null ignored.
* @param output the {@link OutputStream} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #write(String, OutputStream, Charset)} instead
+ * @deprecated Use {@link #write(String, OutputStream, Charset)} instead.
*/
@Deprecated
- public static void write(final String data, final OutputStream output)
- throws IOException {
+ public static void write(final String data, final OutputStream output) throws IOException {
write(data, output, Charset.defaultCharset());
}
/**
- * Writes chars from a {@link String} to bytes on an
- * {@link OutputStream} using the specified character encoding.
+ * Writes chars from a {@link String} to bytes on an {@link OutputStream} using the specified character encoding.
*
* This method uses {@link String#getBytes(String)}.
*
*
- * @param data the {@link String} to write, null ignored.
- * @param output the {@link OutputStream} to write to.
+ * @param data the {@link String} to write, null ignored.
+ * @param output the {@link OutputStream} to write to.
* @param charset the charset to use, null means platform default.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3799,33 +3736,30 @@ public static void write(final String data, final OutputStream output, final Cha
}
/**
- * Writes chars from a {@link String} to bytes on an
- * {@link OutputStream} using the specified character encoding.
+ * Writes chars from a {@link String} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#getBytes(String)}.
*
*
- * @param data the {@link String} to write, null ignored.
- * @param output the {@link OutputStream} to write to.
+ * @param data the {@link String} to write, null ignored.
+ * @param output the {@link OutputStream} to write to.
* @param charsetName the name of the requested charset, null means platform default.
- * @throws NullPointerException if output is null.
- * @throws IOException if an I/O error occurs.
+ * @throws NullPointerException if output is null.
+ * @throws IOException if an I/O error occurs.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 1.1
*/
- public static void write(final String data, final OutputStream output, final String charsetName)
- throws IOException {
+ public static void write(final String data, final OutputStream output, final String charsetName) throws IOException {
write(data, output, Charsets.toCharset(charsetName));
}
/**
* Writes chars from a {@link String} to a {@link Writer}.
*
- * @param data the {@link String} to write, null ignored.
+ * @param data the {@link String} to write, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3838,49 +3772,45 @@ public static void write(final String data, final Writer writer) throws IOExcept
}
/**
- * Writes chars from a {@link StringBuffer} to bytes on an
- * {@link OutputStream} using the default character encoding of the
- * platform.
+ * Writes chars from a {@link StringBuffer} to bytes on an {@link OutputStream} using the default character encoding of the platform.
*
* This method uses {@link String#getBytes()}.
*
*
- * @param data the {@link StringBuffer} to write, null ignored.
+ * @param data the {@link StringBuffer} to write, null ignored.
* @param output the {@link OutputStream} to write to.
* @throws NullPointerException if output is null.
- * @throws IOException if an I/O error occurs
+ * @throws IOException if an I/O error occurs.
* @since 1.1
* @deprecated Use {@link #write(CharSequence, OutputStream)}.
*/
@Deprecated
- public static void write(final StringBuffer data, final OutputStream output) //NOSONAR
+ public static void write(final StringBuffer data, final OutputStream output) // NOSONAR
throws IOException {
write(data, output, (String) null);
}
/**
- * Writes chars from a {@link StringBuffer} to bytes on an
- * {@link OutputStream} using the specified character encoding.
+ * Writes chars from a {@link StringBuffer} to bytes on an {@link OutputStream} using the specified character encoding.
*
- * Character encoding names can be found at
- * IANA.
+ * Character encoding names can be found at IANA.
*
*
* This method uses {@link String#getBytes(String)}.
*
*
- * @param data the {@link StringBuffer} to write, null ignored.
- * @param output the {@link OutputStream} to write to.
+ * @param data the {@link StringBuffer} to write, null ignored.
+ * @param output the {@link OutputStream} to write to.
* @param charsetName the name of the requested charset, null means platform default.
- * @throws NullPointerException if output is null.
- * @throws IOException if an I/O error occurs.
+ * @throws NullPointerException if output is null.
+ * @throws IOException if an I/O error occurs.
* @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 1.1
* @deprecated Use {@link #write(CharSequence, OutputStream, String)}.
*/
@Deprecated
- public static void write(final StringBuffer data, final OutputStream output, final String charsetName) //NOSONAR
- throws IOException {
+ public static void write(final StringBuffer data, final OutputStream output, final String charsetName) // NOSONAR
+ throws IOException {
if (data != null) {
write(data.toString(), output, Charsets.toCharset(charsetName));
}
@@ -3889,7 +3819,7 @@ public static void write(final StringBuffer data, final OutputStream output, fin
/**
* Writes chars from a {@link StringBuffer} to a {@link Writer}.
*
- * @param data the {@link StringBuffer} to write, null ignored.
+ * @param data the {@link StringBuffer} to write, null ignored.
* @param writer the {@link Writer} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
@@ -3897,7 +3827,7 @@ public static void write(final StringBuffer data, final OutputStream output, fin
* @deprecated Use {@link #write(CharSequence, Writer)}.
*/
@Deprecated
- public static void write(final StringBuffer data, final Writer writer) //NOSONAR
+ public static void write(final StringBuffer data, final Writer writer) // NOSONAR
throws IOException {
if (data != null) {
writer.write(data.toString());
@@ -3905,19 +3835,16 @@ public static void write(final StringBuffer data, final Writer writer) //NOSONAR
}
/**
- * Writes bytes from a {@code byte[]} to an {@link OutputStream} using chunked writes.
- * This is intended for writing very large byte arrays which might otherwise cause excessive
- * memory usage if the native code has to allocate a copy.
+ * Writes bytes from a {@code byte[]} to an {@link OutputStream} using chunked writes. This is intended for writing very large byte arrays which might
+ * otherwise cause excessive memory usage if the native code has to allocate a copy.
*
- * @param data the byte array to write, do not modify during output,
- * null ignored.
+ * @param data the byte array to write, do not modify during output, null ignored.
* @param output the {@link OutputStream} to write to.
* @throws NullPointerException if output is null.
* @throws IOException if an I/O error occurs.
* @since 2.5
*/
- public static void writeChunked(final byte[] data, final OutputStream output)
- throws IOException {
+ public static void writeChunked(final byte[] data, final OutputStream output) throws IOException {
if (data != null) {
int bytes = data.length;
int offset = 0;
@@ -3955,7 +3882,7 @@ public static void writeChunked(final char[] data, final Writer writer) throws I
/**
* Writes the {@link #toString()} value of each item in a collection to an {@link OutputStream} line by line, using the virtual machine's
- * {@link Charset#defaultCharset() default charset} and the specified line ending.
+ * {@linkplain Charset#defaultCharset() default charset} and the specified line ending.
*
* @param lines the lines to write, null entries produce blank lines.
* @param lineEnding the line separator to use, null is system default.
@@ -3963,7 +3890,7 @@ public static void writeChunked(final char[] data, final Writer writer) throws I
* @throws NullPointerException if the output is null.
* @throws IOException if an I/O error occurs.
* @since 1.1
- * @deprecated Use {@link #writeLines(Collection, String, OutputStream, Charset)} instead
+ * @deprecated Use {@link #writeLines(Collection, String, OutputStream, Charset)} instead.
*/
@Deprecated
public static void writeLines(final Collection> lines, final String lineEnding, final OutputStream output) throws IOException {
@@ -4009,7 +3936,7 @@ public static void writeLines(final Collection> lines, String lineEnding, fina
* Writes the {@link #toString()} value of each item in a collection to an {@link OutputStream} line by line, using the specified character encoding and the
* specified line ending.
*
- * Character encoding names can be found at IANA.
+ * Character encoding names can be found at IANA.
*
*
* @param lines the lines to write, null entries produce blank lines.
@@ -4051,11 +3978,10 @@ public static void writeLines(final Collection> lines, String lineEnding, fina
}
/**
- * Returns the given Appendable if it is already a {@link Writer}, otherwise creates a Writer wrapper around the
- * given Appendable.
+ * Returns the given Appendable if it is already a {@link Writer}, otherwise creates a Writer wrapper around the given Appendable.
*
* @param appendable the Appendable to wrap or return (not null).
- * @return the given Appendable or a Writer wrapper around the given Appendable.
+ * @return the given Appendable or a Writer wrapper around the given Appendable.
* @throws NullPointerException if the input parameter is null.
* @since 2.7
*/
@@ -4076,8 +4002,7 @@ public static Writer writer(final Appendable appendable) {
* @deprecated TODO Make private in 3.0.
*/
@Deprecated
- public IOUtils() { //NOSONAR
+ public IOUtils() { // NOSONAR
// empty
}
-
}
diff --git a/src/main/java/org/apache/commons/io/LineIterator.java b/src/main/java/org/apache/commons/io/LineIterator.java
index 293847e7a72..92a8bc7c035 100644
--- a/src/main/java/org/apache/commons/io/LineIterator.java
+++ b/src/main/java/org/apache/commons/io/LineIterator.java
@@ -56,9 +56,9 @@ public class LineIterator implements Iterator, Closeable {
* Closes a {@link LineIterator} quietly.
*
* @param iterator The iterator to close, or {@code null}.
+ * @see Throwable#addSuppressed(Throwable)
* @deprecated As of 2.6 deprecated without replacement. Please use the try-with-resources statement or handle
* suppressed exceptions manually.
- * @see Throwable#addSuppressed(Throwable)
*/
@Deprecated
public static void closeQuietly(final LineIterator iterator) {
@@ -77,17 +77,12 @@ public static void closeQuietly(final LineIterator iterator) {
/**
* Constructs an iterator of the lines for a {@link Reader}.
*
- * @param reader the {@link Reader} to read from, not null
- * @throws NullPointerException if the reader is null
+ * @param reader the {@link Reader} to read from, not null.
+ * @throws NullPointerException if the reader is null.
*/
@SuppressWarnings("resource") // Caller closes Reader
public LineIterator(final Reader reader) {
- Objects.requireNonNull(reader, "reader");
- if (reader instanceof BufferedReader) {
- bufferedReader = (BufferedReader) reader;
- } else {
- bufferedReader = new BufferedReader(reader);
- }
+ bufferedReader = IOUtils.buffer(Objects.requireNonNull(reader, "reader"));
}
/**
@@ -111,8 +106,8 @@ public void close() throws IOException {
* If there is an {@link IOException} then {@link #close()} will
* be called on this instance.
*
- * @return {@code true} if the Reader has more lines
- * @throws IllegalStateException if an IO exception occurs
+ * @return {@code true} if the Reader has more lines.
+ * @throws IllegalStateException if an IO exception occurs.
*/
@Override
public boolean hasNext() {
@@ -135,16 +130,16 @@ public boolean hasNext() {
}
}
} catch (final IOException ioe) {
- IOUtils.closeQuietly(this, ioe::addSuppressed);
- throw new IllegalStateException(ioe);
+ throw new IllegalStateException(IOUtils.closeQuietlySuppress(this, ioe));
}
}
/**
* Overridable method to validate each line that is returned.
* This implementation always returns true.
- * @param line the line that is to be validated
- * @return true if valid, false to remove from the iterator
+ *
+ * @param line the line that is to be validated.
+ * @return true if valid, false to remove from the iterator.
*/
protected boolean isValidLine(final String line) {
return true;
@@ -153,8 +148,8 @@ protected boolean isValidLine(final String line) {
/**
* Returns the next line in the wrapped {@link Reader}.
*
- * @return the next line from the input
- * @throws NoSuchElementException if there is no line to return
+ * @return the next line from the input.
+ * @throws NoSuchElementException if there is no line to return.
*/
@Override
public String next() {
@@ -164,8 +159,8 @@ public String next() {
/**
* Returns the next line in the wrapped {@link Reader}.
*
- * @return the next line from the input
- * @throws NoSuchElementException if there is no line to return
+ * @return the next line from the input.
+ * @throws NoSuchElementException if there is no line to return.
* @deprecated Use {@link #next()}.
*/
@Deprecated
@@ -181,7 +176,7 @@ public String nextLine() {
/**
* Unsupported.
*
- * @throws UnsupportedOperationException always
+ * @throws UnsupportedOperationException always.
*/
@Override
public void remove() {
diff --git a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
index 88f499d120b..3e8f5b0b609 100644
--- a/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
+++ b/src/main/java/org/apache/commons/io/RandomAccessFileMode.java
@@ -163,8 +163,8 @@ public static RandomAccessFileMode valueOfMode(final String mode) {
* @throws IOException Thrown by the given function.
* @since 2.18.0
*/
- public void accept(final Path file, final IOConsumer consumer) throws IOException {
- try (RandomAccessFile raf = create(file)) {
+ public void accept(final Path file, final IOConsumer consumer) throws IOException {
+ try (IORandomAccessFile raf = new IORandomAccessFile(file.toFile(), mode)) {
consumer.accept(raf);
}
}
@@ -195,8 +195,8 @@ public T apply(final Path file, final IOFunction functi
* Prefer {@link #create(Path)} over this.
*
*
- * @param file the file object
- * @return a random access file
+ * @param file the file object.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final File file) throws FileNotFoundException {
@@ -206,8 +206,8 @@ public RandomAccessFile create(final File file) throws FileNotFoundException {
/**
* Constructs a random access file to read from, and optionally to write to, the file specified by the {@link File} argument.
*
- * @param file the file object
- * @return a random access file
+ * @param file the file object.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final Path file) throws FileNotFoundException {
@@ -220,8 +220,8 @@ public RandomAccessFile create(final Path file) throws FileNotFoundException {
* Prefer {@link #create(Path)} over this.
*
*
- * @param name the file object
- * @return a random access file
+ * @param name the file object.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
*/
public RandomAccessFile create(final String name) throws FileNotFoundException {
@@ -282,8 +282,8 @@ public boolean implies(final RandomAccessFileMode other) {
/**
* Constructs a random access file to read from, and optionally to write to, the file specified by the {@link File} argument.
*
- * @param name the file object
- * @return a random access file
+ * @param name the system-dependent file name.
+ * @return a random access file.
* @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
* @since 2.18.0
*/
diff --git a/src/main/java/org/apache/commons/io/TaggedIOException.java b/src/main/java/org/apache/commons/io/TaggedIOException.java
index 5eb0b5df596..d997ecc0433 100644
--- a/src/main/java/org/apache/commons/io/TaggedIOException.java
+++ b/src/main/java/org/apache/commons/io/TaggedIOException.java
@@ -57,8 +57,8 @@ public class TaggedIOException extends IOExceptionWithCause {
* }
*
*
- * @param throwable The Throwable object to check
- * @param tag tag object
+ * @param throwable The Throwable object to check.
+ * @param tag tag object.
* @return {@code true} if the throwable has the specified tag,
* otherwise {@code false}
*/
@@ -86,9 +86,9 @@ public static boolean isTaggedWith(final Throwable throwable, final Object tag)
* }
*
*
- * @param throwable an exception
- * @param tag tag object
- * @throws IOException original exception from the tagged decorator, if any
+ * @param throwable an exception.
+ * @param tag tag object.
+ * @throws IOException original exception from the tagged decorator, if any.
*/
public static void throwCauseIfTaggedWith(final Throwable throwable, final Object tag)
throws IOException {
@@ -105,8 +105,8 @@ public static void throwCauseIfTaggedWith(final Throwable throwable, final Objec
/**
* Constructs a tagged wrapper for the given exception.
*
- * @param original the exception to be tagged
- * @param tag tag of this exception
+ * @param original the exception to be tagged.
+ * @param tag tag of this exception.
*/
public TaggedIOException(final IOException original, final Serializable tag) {
super(original.getMessage(), original);
@@ -117,7 +117,7 @@ public TaggedIOException(final IOException original, final Serializable tag) {
* Returns the wrapped exception. The only difference to the overridden
* {@link Throwable#getCause()} method is the narrower return type.
*
- * @return wrapped exception
+ * @return wrapped exception.
*/
@Override
public synchronized IOException getCause() {
@@ -127,7 +127,7 @@ public synchronized IOException getCause() {
/**
* Returns the serializable tag object.
*
- * @return tag object
+ * @return tag object.
*/
public Serializable getTag() {
return tag;
diff --git a/src/main/java/org/apache/commons/io/ThreadMonitor.java b/src/main/java/org/apache/commons/io/ThreadMonitor.java
index 4c2c37a2d3b..f9fe24957c5 100644
--- a/src/main/java/org/apache/commons/io/ThreadMonitor.java
+++ b/src/main/java/org/apache/commons/io/ThreadMonitor.java
@@ -52,7 +52,7 @@ static Thread start(final Duration timeout) {
/**
* Starts monitoring the specified thread.
*
- * @param thread The thread to monitor
+ * @param thread The thread to monitor.
* @param timeout The timeout amount. or no timeout if the value is zero or less.
* @return The monitor thread or {@code null} if the timeout amount is not greater than zero.
*/
@@ -60,7 +60,7 @@ static Thread start(final Thread thread, final Duration timeout) {
if (timeout.isZero() || timeout.isNegative()) {
return null;
}
- final Thread monitor = new Thread(new ThreadMonitor(thread, timeout), ThreadMonitor.class.getSimpleName());
+ final Thread monitor = new Thread(new ThreadMonitor(thread, timeout), "commons-io-ThreadMonitor");
monitor.setDaemon(true);
monitor.start();
return monitor;
@@ -104,6 +104,7 @@ public void run() {
thread.interrupt();
} catch (final InterruptedException ignored) {
// timeout not reached
+ Thread.currentThread().interrupt();
}
}
}
diff --git a/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java b/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java
index f31043769b7..6a5075c52ca 100644
--- a/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java
+++ b/src/main/java/org/apache/commons/io/UncheckedIOExceptions.java
@@ -47,6 +47,7 @@ public static UncheckedIOException create(final Object message) {
*
* This method exists because there is no String constructor in {@link UncheckedIOException}.
*
+ *
* @param e cause the {@link IOException}.
* @param message the detail message.
* @return a new {@link UncheckedIOException}.
diff --git a/src/main/java/org/apache/commons/io/build/AbstractOrigin.java b/src/main/java/org/apache/commons/io/build/AbstractOrigin.java
index d84aefdb79a..e64f4ae732d 100644
--- a/src/main/java/org/apache/commons/io/build/AbstractOrigin.java
+++ b/src/main/java/org/apache/commons/io/build/AbstractOrigin.java
@@ -31,6 +31,7 @@
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
+import java.net.URLConnection;
import java.nio.channels.Channel;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
@@ -43,8 +44,10 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
+import java.time.Duration;
import java.util.Arrays;
import java.util.Objects;
+import java.util.stream.Stream;
import org.apache.commons.io.Charsets;
import org.apache.commons.io.IORandomAccessFile;
@@ -366,6 +369,7 @@ public abstract static class AbstractRandomAccessFileOrigin
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public AbstractRandomAccessFileOrigin(final T origin) {
super(origin);
@@ -437,6 +441,7 @@ public static class ByteArrayOrigin extends AbstractOrigin
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public ChannelOrigin(final Channel origin) {
super(origin);
@@ -563,6 +569,7 @@ public static class CharSequenceOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public FileOrigin(final File origin) {
super(origin);
@@ -689,6 +697,7 @@ public static class InputStreamOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public PathOrigin(final Path origin) {
super(origin);
@@ -892,6 +903,7 @@ public static class ReaderOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public ReaderOrigin(final Reader origin) {
super(origin);
@@ -952,6 +964,80 @@ public Reader getReader(final Charset charset) throws IOException {
*/
public static class URIOrigin extends AbstractOrigin {
+ /**
+ * Options for connect and read from a URI.
+ *
+ * @since 2.22.0
+ */
+ public static final class URIOpenOption implements OpenOption {
+
+ /**
+ * Builds URIOpenOption.
+ */
+ public static class Builder extends AbstractSupplier {
+
+ private Duration connectTimeout;
+ private Duration readTimeout;
+
+ /**
+ * Constructs a new instance.
+ */
+ public Builder() {
+ // empty
+ }
+
+ @Override
+ public URIOpenOption get() {
+ return new URIOpenOption(this);
+ }
+
+ /**
+ * Sets the connect timeout duration.
+ *
+ * @param connectTimeout the connect timeout duration.
+ * @return {@code this instance}.
+ */
+ public Builder setConnectTimeout(final Duration connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ return asThis();
+ }
+
+ /**
+ * Sets the read timeout duration.
+ *
+ * @param readTimeout the read timeout duration.
+ * @return {@code this instance}.
+ */
+ public Builder setReadTimeout(final Duration readTimeout) {
+ this.readTimeout = readTimeout;
+ return asThis();
+ }
+ }
+
+ /**
+ * Creates a new builder.
+ *
+ * @return a new builder.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private final Duration connectTimeout;
+
+ private final Duration readTimeout;
+
+ private URIOpenOption(final Builder builder) {
+ connectTimeout = builder.connectTimeout;
+ readTimeout = builder.readTimeout;
+ }
+
+ @Override
+ public String toString() {
+ return "URIOpenOption [connectTimeout=" + connectTimeout + ", readTimeout=" + readTimeout + "]";
+ }
+ }
+
private static final String SCHEME_HTTPS = "https";
private static final String SCHEME_HTTP = "http";
@@ -959,17 +1045,23 @@ public static class URIOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public URIOrigin(final URI origin) {
super(origin);
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see URIOpenOption
+ */
@Override
protected Channel getChannel(final OpenOption... options) throws IOException {
final URI uri = get();
final String scheme = uri.getScheme();
if (SCHEME_HTTP.equalsIgnoreCase(scheme) || SCHEME_HTTPS.equalsIgnoreCase(scheme)) {
- return Channels.newChannel(uri.toURL().openStream());
+ return Channels.newChannel(getInputStream(uri, options));
}
return Files.newByteChannel(getPath(), options);
}
@@ -979,20 +1071,52 @@ public File getFile() {
return getPath().toFile();
}
+ /**
+ * {@inheritDoc}
+ *
+ * Set timeouts with a {@link URIOpenOption}.
+ *
+ *
+ * @see URIOpenOption
+ * @see URLConnection#setConnectTimeout(int)
+ * @see URLConnection#setReadTimeout(int)
+ */
@Override
public InputStream getInputStream(final OpenOption... options) throws IOException {
final URI uri = get();
final String scheme = uri.getScheme();
if (SCHEME_HTTP.equalsIgnoreCase(scheme) || SCHEME_HTTPS.equalsIgnoreCase(scheme)) {
- return uri.toURL().openStream();
+ return getInputStream(uri, options);
}
return Files.newInputStream(getPath(), options);
}
+ private InputStream getInputStream(final URI uri, final OpenOption... options) throws IOException {
+ final URLConnection connection = uri.toURL().openConnection();
+ if (options != null) {
+ Stream.of(options).forEach(option -> {
+ if (option instanceof URIOpenOption) {
+ final URIOpenOption connOption = (URIOpenOption) option;
+ if (connOption.connectTimeout != null) {
+ connection.setConnectTimeout(toMillis(connOption.connectTimeout));
+ }
+ if (connOption.readTimeout != null) {
+ connection.setReadTimeout(toMillis(connOption.readTimeout));
+ }
+ }
+ });
+ }
+ return connection.getInputStream();
+ }
+
@Override
public Path getPath() {
return Paths.get(get());
}
+
+ private int toMillis(final Duration duration) {
+ return Math.toIntExact(duration.toMillis());
+ }
}
/**
@@ -1007,6 +1131,7 @@ public static class WriterOrigin extends AbstractOrigin {
* Constructs a new instance for the given origin.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
public WriterOrigin(final Writer origin) {
super(origin);
@@ -1057,15 +1182,16 @@ public Writer getWriter(final Charset charset, final OpenOption... options) thro
* Constructs a new instance for subclasses.
*
* @param origin The origin, not null.
+ * @throws NullPointerException if {@code origin} is {@code null}.
*/
protected AbstractOrigin(final T origin) {
this.origin = Objects.requireNonNull(origin, "origin");
}
/**
- * Gets the origin.
+ * Gets the origin, never null.
*
- * @return the origin.
+ * @return the origin, never null.
*/
@Override
public T get() {
@@ -1090,7 +1216,7 @@ public byte[] getByteArray() throws IOException {
* @param length How many bytes to copy.
* @return this origin as a byte array, if possible.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
- * @throws ArithmeticException if the {@code position} overflows an int
+ * @throws ArithmeticException if the {@code position} overflows an int.
* @throws IOException if an I/O error occurs.
* @since 2.13.0
*/
@@ -1113,6 +1239,7 @@ public byte[] getByteArray(final long position, final int length) throws IOExcep
* @param The type of channel to return.
* @throws IOException If an I/O error occurs.
* @throws UnsupportedOperationException If this origin cannot be converted to a channel of the given type.
+ * @see #getChannel(OpenOption...)
* @since 2.21.0
*/
public final C getChannel(final Class channelType, final OpenOption... options) throws IOException {
@@ -1131,6 +1258,7 @@ public final C getChannel(final Class channelType, final
* @return A new Channel on the origin.
* @throws IOException If an I/O error occurs.
* @throws UnsupportedOperationException If this origin cannot be converted to a channel.
+ * @see #getChannel(Class, OpenOption...)
* @since 2.21.0
*/
protected Channel getChannel(final OpenOption... options) throws IOException {
@@ -1162,7 +1290,7 @@ public File getFile() {
/**
* Gets this origin as an InputStream, if possible.
*
- * @param options options specifying how the file is opened
+ * @param options options specifying how the file is opened.
* @return this origin as an InputStream, if possible.
* @throws IOException if an I/O error occurs.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
@@ -1174,7 +1302,7 @@ public InputStream getInputStream(final OpenOption... options) throws IOExceptio
/**
* Gets this origin as an OutputStream, if possible.
*
- * @param options options specifying how the file is opened
+ * @param options options specifying how the file is opened.
* @return this origin as an OutputStream, if possible.
* @throws IOException if an I/O error occurs.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
@@ -1217,6 +1345,11 @@ public Reader getReader(final Charset charset) throws IOException {
return Files.newBufferedReader(getPath(), Charsets.toCharset(charset));
}
+ /**
+ * Gets simple name of the underlying class.
+ *
+ * @return The simple name of the underlying class.
+ */
private String getSimpleClassName() {
return getClass().getSimpleName();
}
@@ -1224,8 +1357,8 @@ private String getSimpleClassName() {
/**
* Gets a new Writer on the origin, buffered by default.
*
- * @param charset the charset to use for encoding
- * @param options options specifying how the file is opened
+ * @param charset the charset to use for encoding.
+ * @param options options specifying how the file is opened.
* @return a new Writer on the origin.
* @throws IOException if an I/O error occurs opening or creating the file.
* @throws UnsupportedOperationException if the origin cannot be converted to a Path.
diff --git a/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java b/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
index 541548c7295..37986693b48 100644
--- a/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
+++ b/src/main/java/org/apache/commons/io/build/AbstractStreamBuilder.java
@@ -122,6 +122,20 @@ public int getBufferSizeDefault() {
return bufferSizeDefault;
}
+ /**
+ * Gets a byte array from the origin.
+ *
+ * @return A byte array.
+ * @throws IllegalStateException if the {@code origin} is {@code null}.
+ * @throws UnsupportedOperationException if the origin cannot be converted to a byte array.
+ * @throws IOException if an I/O error occurs.
+ * @see AbstractOrigin#getByteArray()
+ * @since 2.22.0
+ */
+ public byte[] getByteArray() throws IOException {
+ return checkOrigin().getByteArray();
+ }
+
/**
* Gets a Channel from the origin with OpenOption[].
*
@@ -142,7 +156,7 @@ public C getChannel(final Class channelType) throws IOExc
/**
* Gets a CharSequence from the origin with a Charset.
*
- * @return An input stream
+ * @return An input stream.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a CharSequence.
* @throws IOException if an I/O error occurs.
@@ -174,7 +188,7 @@ public Charset getCharsetDefault() {
/**
* Gets a File from the origin.
*
- * @return A File
+ * @return A File.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link File}.
* @see AbstractOrigin#getPath()
@@ -187,7 +201,7 @@ public File getFile() {
/**
* Gets an InputStream from the origin with OpenOption[].
*
- * @return An input stream
+ * @return An input stream.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to an {@link InputStream}.
* @throws IOException if an I/O error occurs.
@@ -202,7 +216,7 @@ public InputStream getInputStream() throws IOException {
/**
* Gets the OpenOption array.
*
- * @return the OpenOption array.
+ * @return the OpenOption array, this is not a defensive copy, modify at your own risk.
*/
public OpenOption[] getOpenOptions() {
return openOptions;
@@ -211,7 +225,7 @@ public OpenOption[] getOpenOptions() {
/**
* Gets an OutputStream from the origin with OpenOption[].
*
- * @return An OutputStream
+ * @return An OutputStream.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to an {@link OutputStream}.
* @throws IOException if an I/O error occurs.
@@ -226,7 +240,7 @@ public OutputStream getOutputStream() throws IOException {
/**
* Gets a Path from the origin.
*
- * @return A Path
+ * @return A Path.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link Path}.
* @see AbstractOrigin#getPath()
@@ -239,7 +253,7 @@ public Path getPath() {
/**
* Gets a RandomAccessFile from the origin.
*
- * @return A RandomAccessFile
+ * @return A RandomAccessFile.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link RandomAccessFile}.
* @throws IOException if an I/O error occurs.
@@ -252,7 +266,7 @@ public RandomAccessFile getRandomAccessFile() throws IOException {
/**
* Gets a Reader from the origin with a Charset.
*
- * @return A Reader
+ * @return A Reader.
* @throws IllegalStateException if the {@code origin} is {@code null}.
* @throws UnsupportedOperationException if the origin cannot be converted to a {@link Reader}.
* @throws IOException if an I/O error occurs.
@@ -285,7 +299,7 @@ public Writer getWriter() throws IOException {
* Subclasses may ignore this setting.
*
*
- * @param bufferSize the buffer size.
+ * @param bufferSize the buffer size, 0 resets to the default from {@link #getBufferSizeDefault()}.
* @return {@code this} instance.
*/
public B setBufferSize(final int bufferSize) {
@@ -299,7 +313,7 @@ public B setBufferSize(final int bufferSize) {
* Subclasses may ignore this setting.
*
*
- * @param bufferSize the buffer size, null resets to the default.
+ * @param bufferSize the buffer size, null resets to the default from {@link #getBufferSizeDefault()}.
* @return {@code this} instance.
*/
public B setBufferSize(final Integer bufferSize) {
@@ -325,11 +339,11 @@ public B setBufferSizeChecker(final IntUnaryOperator bufferSizeChecker) {
* Subclasses may ignore this setting.
*
*
- * @param bufferSizeDefault the buffer size, null resets to the default.
+ * @param bufferSizeDefault the buffer size, 0 resets to the default {@link IOUtils#DEFAULT_BUFFER_SIZE}.
* @return {@code this} instance.
*/
protected B setBufferSizeDefault(final int bufferSizeDefault) {
- this.bufferSizeDefault = bufferSizeDefault;
+ this.bufferSizeDefault = checkBufferSize(bufferSizeDefault > 0 ? bufferSizeDefault : IOUtils.DEFAULT_BUFFER_SIZE);
return asThis();
}
@@ -388,7 +402,7 @@ protected B setCharsetDefault(final Charset defaultCharset) {
}
/**
- * Sets the OpenOption[].
+ * Sets the OpenOption array.
*
* Normally used with InputStream, OutputStream, and Writer.
*
@@ -396,7 +410,7 @@ protected B setCharsetDefault(final Charset defaultCharset) {
* Subclasses may ignore this setting.
*
*
- * @param openOptions the OpenOption[] name, null resets to the default.
+ * @param openOptions the OpenOption[] name, null resets to the default, a defensive copy is made.
* @return {@code this} instance.
* @since 2.13.0
* @see #setInputStream(InputStream)
@@ -404,7 +418,7 @@ protected B setCharsetDefault(final Charset defaultCharset) {
* @see #setWriter(Writer)
*/
public B setOpenOptions(final OpenOption... openOptions) {
- this.openOptions = openOptions != null ? openOptions : DEFAULT_OPEN_OPTIONS;
+ this.openOptions = openOptions != null ? openOptions.clone() : DEFAULT_OPEN_OPTIONS;
return asThis();
}
diff --git a/src/main/java/org/apache/commons/io/build/package-info.java b/src/main/java/org/apache/commons/io/build/package-info.java
index bda177c354c..5eed609d544 100644
--- a/src/main/java/org/apache/commons/io/build/package-info.java
+++ b/src/main/java/org/apache/commons/io/build/package-info.java
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
/**
* Provides classes to implement the builder pattern for IO classes.
*
@@ -49,5 +50,4 @@
*
* @since 2.12.0
*/
-
package org.apache.commons.io.build;
diff --git a/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java b/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java
index 4135a815e83..57c38124875 100644
--- a/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java
+++ b/src/main/java/org/apache/commons/io/channels/ByteArraySeekableByteChannel.java
@@ -24,12 +24,16 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
+import java.nio.channels.NonWritableChannelException;
import java.nio.channels.SeekableByteChannel;
+import java.nio.file.OpenOption;
+import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.build.AbstractStreamBuilder;
/**
* A {@link SeekableByteChannel} implementation backed by a byte array.
@@ -38,25 +42,79 @@
* and it's not possible to {@link #position(long) set the position} or {@link #truncate(long) truncate} to a value bigger than that. The raw internal buffer is
* accessed via {@link ByteArraySeekableByteChannel#array()}.
*
+ *
+ * Building a read-only channel from an existing byte array is supported with:
+ *
+ *
+ * @since 2.22.0
+ */
+ public static class Builder extends AbstractStreamBuilder {
+
+ /**
+ * Constructs a new builder for {@link ByteArraySeekableByteChannel}.
+ */
+ public Builder() {
+ setByteArray(IOUtils.EMPTY_BYTE_ARRAY);
+ }
+
+ @Override
+ public ByteArraySeekableByteChannel get() throws IOException {
+ return new ByteArraySeekableByteChannel(this);
+ }
+ }
+
private static final int RESIZE_LIMIT = Integer.MAX_VALUE >> 1;
+ /**
+ * Constructs a new builder for {@link ByteArraySeekableByteChannel}.
+ *
+ * @return a new builder for {@link ByteArraySeekableByteChannel}.
+ * @since 2.22.0
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
/**
* Constructs a new channel backed directly by the given byte array.
*
- *
The channel initially contains the full contents of the array, with its
- * size set to {@code bytes.length} and its position set to {@code 0}.
+ *
+ * The channel initially contains the full contents of the array, with its size set to {@code bytes.length} and its position set to {@code 0}.
+ *
*
- *
Reads and writes operate on the shared array.
- * If a write operation extends beyond the current capacity, the channel will
- * automatically allocate a larger backing array and copy the existing contents.
+ *
+ * Reads and writes operate on the shared array. If a write operation extends beyond the current capacity, the channel will automatically allocate a larger
+ * backing array and copy the existing contents.
+ *
*
* @param bytes The byte array to wrap, must not be {@code null}
- * @return A new channel that uses the given array as its initial backing store
+ * @return A new channel that uses the given array as its initial backing store.
* @throws NullPointerException If {@code bytes} is {@code null}
* @see #array()
* @see ByteArrayInputStream#ByteArrayInputStream(byte[])
@@ -65,11 +123,11 @@ public static ByteArraySeekableByteChannel wrap(final byte[] bytes) {
Objects.requireNonNull(bytes, "bytes");
return new ByteArraySeekableByteChannel(bytes);
}
-
private byte[] data;
private volatile boolean closed;
- private int position;
+ private long position;
private int size;
+ private final boolean isWritable;
private final ReentrantLock lock = new ReentrantLock();
/**
@@ -84,10 +142,19 @@ public ByteArraySeekableByteChannel() {
this(IOUtils.DEFAULT_BUFFER_SIZE);
}
+ private ByteArraySeekableByteChannel(final Builder builder) throws IOException {
+ this.data = builder.getByteArray();
+ this.size = data.length;
+ final OpenOption[] openOptions = builder.getOpenOptions();
+ Arrays.sort(openOptions);
+ this.isWritable = openOptions.length == 0 || Arrays.binarySearch(openOptions, StandardOpenOption.WRITE) >= 0
+ || Arrays.binarySearch(openOptions, StandardOpenOption.APPEND) >= 0;
+ }
+
private ByteArraySeekableByteChannel(final byte[] data) {
this.data = data;
- this.position = 0;
this.size = data.length;
+ this.isWritable = true;
}
/**
@@ -104,8 +171,7 @@ public ByteArraySeekableByteChannel(final int size) {
throw new IllegalArgumentException("Size must be non-negative");
}
this.data = new byte[size];
- this.position = 0;
- this.size = 0;
+ this.isWritable = true;
}
/**
@@ -126,11 +192,16 @@ private void checkOpen() throws ClosedChannelException {
}
}
- private int checkRange(final long newSize, final String method) {
- if (newSize < 0L || newSize > IOUtils.SOFT_MAX_ARRAY_LENGTH) {
- throw new IllegalArgumentException(String.format("%s must be in range [0..%,d]: %,d", method, IOUtils.SOFT_MAX_ARRAY_LENGTH, newSize));
+ private void checkRange(final long newSize, final String method) {
+ if (newSize < 0L) {
+ throw new IllegalArgumentException(String.format("%s must be positive: %,d", method, newSize));
+ }
+ }
+
+ private void checkWritable() {
+ if (!isWritable) {
+ throw new NonWritableChannelException();
}
- return (int) newSize;
}
@Override
@@ -166,10 +237,10 @@ public long position() throws ClosedChannelException {
@Override
public SeekableByteChannel position(final long newPosition) throws IOException {
checkOpen();
- final int intPos = checkRange(newPosition, "position()");
+ checkRange(newPosition, "position()");
lock.lock();
try {
- position = intPos;
+ position = newPosition;
} finally {
lock.unlock();
}
@@ -181,15 +252,18 @@ public int read(final ByteBuffer buf) throws IOException {
checkOpen();
lock.lock();
try {
+ if (position > Integer.MAX_VALUE) {
+ return IOUtils.EOF;
+ }
int wanted = buf.remaining();
- final int possible = size - position;
+ final int possible = size - (int) position;
if (possible <= 0) {
return IOUtils.EOF;
}
if (wanted > possible) {
wanted = possible;
}
- buf.put(data, position, wanted);
+ buf.put(data, (int) position, wanted);
position += wanted;
return wanted;
} finally {
@@ -238,14 +312,15 @@ public byte[] toByteArray() {
@Override
public SeekableByteChannel truncate(final long newSize) throws ClosedChannelException {
checkOpen();
- final int intSize = checkRange(newSize, "truncate()");
+ checkWritable();
+ checkRange(newSize, "truncate()");
lock.lock();
try {
- if (size > intSize) {
- size = intSize;
+ if (size > newSize) {
+ size = (int) newSize;
}
- if (position > intSize) {
- position = intSize;
+ if (position > newSize) {
+ position = newSize;
}
} finally {
lock.unlock();
@@ -256,21 +331,30 @@ public SeekableByteChannel truncate(final long newSize) throws ClosedChannelExce
@Override
public int write(final ByteBuffer b) throws IOException {
checkOpen();
+ checkWritable();
+ //
+ if (position > Integer.MAX_VALUE) {
+ throw new IOException("position > Integer.MAX_VALUE");
+ }
lock.lock();
try {
final int wanted = b.remaining();
- final int possibleWithoutResize = Math.max(0, size - position);
- if (wanted > possibleWithoutResize) {
- final int newSize = position + wanted;
- if (newSize < 0 || newSize > IOUtils.SOFT_MAX_ARRAY_LENGTH) { // overflow
- throw new OutOfMemoryError("required array size " + Integer.toUnsignedString(newSize) + " too large");
- }
- resize(newSize);
+ // intPos <= Integer.MAX_VALUE
+ final int intPos = (int) position;
+ final long newPosition = position + wanted;
+ if (newPosition > IOUtils.SOFT_MAX_ARRAY_LENGTH) {
+ throw new IOException(String.format("Requested array size %,d is too large.", newPosition));
}
- b.get(data, position, wanted);
- position += wanted;
- if (size < position) {
- size = position;
+ if (newPosition > size) {
+ final int newPositionInt = (int) newPosition;
+ // Ensure that newPositionInt ≤ data.length
+ resize(newPositionInt);
+ size = newPositionInt;
+ }
+ b.get(data, intPos, wanted);
+ position = newPosition;
+ if (size < intPos) {
+ size = intPos;
}
return wanted;
} finally {
diff --git a/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java b/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java
index a9a462da73b..987e8427c7c 100644
--- a/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java
+++ b/src/main/java/org/apache/commons/io/channels/CloseShieldChannel.java
@@ -19,7 +19,16 @@
import java.io.Closeable;
import java.lang.reflect.Proxy;
+import java.nio.channels.AsynchronousChannel;
+import java.nio.channels.ByteChannel;
import java.nio.channels.Channel;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.InterruptibleChannel;
+import java.nio.channels.NetworkChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ScatteringByteChannel;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
@@ -28,8 +37,24 @@
* Creates a close-shielding proxy for a {@link Channel}.
*
*
- * The returned proxy will implement all {@link Channel} sub-interfaces that the delegate implements.
+ * The returned proxy implements all {@link Channel} sub-interfaces that are both supported by this implementation and actually implemented by the given
+ * delegate.
*
+ *
+ * The following interfaces are supported:
+ *
+ *
+ *
{@link AsynchronousChannel}
+ *
{@link ByteChannel}
+ *
{@link Channel}
+ *
{@link GatheringByteChannel}
+ *
{@link InterruptibleChannel}
+ *
{@link NetworkChannel}
+ *
{@link ReadableByteChannel}
+ *
{@link ScatteringByteChannel}
+ *
{@link SeekableByteChannel}
+ *
{@link WritableByteChannel}
+ *
*
* @see Channel
* @see Closeable
@@ -40,11 +65,15 @@ public final class CloseShieldChannel {
private static final Class>[] EMPTY = {};
private static Set> collectChannelInterfaces(final Class> type, final Set> out) {
+ Class> currentType = type;
// Visit interfaces
- for (final Class> iface : type.getInterfaces()) {
- if (Channel.class.isAssignableFrom(iface) && out.add(iface)) {
- collectChannelInterfaces(iface, out);
+ while (currentType != null) {
+ for (final Class> iface : currentType.getInterfaces()) {
+ if (CloseShieldChannelHandler.isSupported(iface) && out.add(iface)) {
+ collectChannelInterfaces(iface, out);
+ }
}
+ currentType = currentType.getSuperclass();
}
return out;
}
@@ -53,8 +82,10 @@ private static Set> collectChannelInterfaces(final Class> type, final
* Wraps a channel to shield it from being closed.
*
* @param channel The underlying channel to shield, not {@code null}.
- * @param Any Channel type (interface or class).
+ * @param A supported channel type.
* @return A proxy that shields {@code close()} and enforces closed semantics on other calls.
+ * @throws ClassCastException if {@code T} is not a supported channel type.
+ * @throws NullPointerException if {@code channel} is {@code null}.
*/
@SuppressWarnings({ "unchecked", "resource" }) // caller closes
public static T wrap(final T channel) {
diff --git a/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java b/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java
index f13b101c197..822c6b6186b 100644
--- a/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java
+++ b/src/main/java/org/apache/commons/io/channels/CloseShieldChannelHandler.java
@@ -21,14 +21,44 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import java.nio.channels.AsynchronousChannel;
+import java.nio.channels.ByteChannel;
import java.nio.channels.Channel;
import java.nio.channels.ClosedChannelException;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.InterruptibleChannel;
import java.nio.channels.NetworkChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.SeekableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.Set;
+/**
+ * An {@link InvocationHandler} supporting the implementation of {@link CloseShieldChannel}.
+ */
final class CloseShieldChannelHandler implements InvocationHandler {
+ private static final Set> SUPPORTED_INTERFACES;
+
+ static {
+ final Set> interfaces = new HashSet<>();
+ interfaces.add(AsynchronousChannel.class);
+ interfaces.add(ByteChannel.class);
+ interfaces.add(Channel.class);
+ interfaces.add(GatheringByteChannel.class);
+ interfaces.add(InterruptibleChannel.class);
+ interfaces.add(NetworkChannel.class);
+ interfaces.add(ReadableByteChannel.class);
+ interfaces.add(ScatteringByteChannel.class);
+ interfaces.add(SeekableByteChannel.class);
+ interfaces.add(WritableByteChannel.class);
+ SUPPORTED_INTERFACES = Collections.unmodifiableSet(interfaces);
+ }
+
/**
* Tests whether the given method is allowed to be called after the shield is closed.
*
@@ -42,6 +72,10 @@ private static boolean isAllowedAfterClose(final Class> declaringClass, final
return parameterCount == 0 && name.equals("supportedOptions") && NetworkChannel.class.equals(declaringClass);
}
+ static boolean isSupported(final Class> interfaceClass) {
+ return SUPPORTED_INTERFACES.contains(interfaceClass);
+ }
+
/**
* Tests whether the given method returns 'this' (the channel) as per JDK spec.
*
@@ -123,7 +157,7 @@ private Object invokeObjectMethod(final Object proxy, final Method method, final
return false;
}
default:
- // Not possible, all non-final Object methods are handled above
+ // Not possible, all non-final Object methods are handled above.
return null;
}
}
diff --git a/src/main/java/org/apache/commons/io/channels/FileChannels.java b/src/main/java/org/apache/commons/io/channels/FileChannels.java
index 30a80e8ab6b..7ef9e3f82c9 100644
--- a/src/main/java/org/apache/commons/io/channels/FileChannels.java
+++ b/src/main/java/org/apache/commons/io/channels/FileChannels.java
@@ -24,6 +24,7 @@
import java.nio.channels.SeekableByteChannel;
import java.util.Objects;
+import org.apache.commons.io.Buffers;
import org.apache.commons.io.IOUtils;
/**
@@ -67,36 +68,38 @@ public static boolean contentEquals(final ReadableByteChannel channel1, final Re
// Don't use ByteBuffer#compact() to avoid extra copying.
final ByteBuffer c1Buffer = ByteBuffer.allocateDirect(bufferCapacity);
final ByteBuffer c2Buffer = ByteBuffer.allocateDirect(bufferCapacity);
- int c1NumRead = 0;
- int c2NumRead = 0;
- boolean c1Read0 = false;
- boolean c2Read0 = false;
- // If a channel is a non-blocking channel, it may return 0 bytes read for any given call.
- while (true) {
- if (!c2Read0) {
- c1NumRead = readToLimit(channel1, c1Buffer);
- c1Buffer.clear();
- c1Read0 = c1NumRead == 0;
- }
- if (!c1Read0) {
- c2NumRead = readToLimit(channel2, c2Buffer);
- c2Buffer.clear();
- c2Read0 = c2NumRead == 0;
- }
- if (c1NumRead == IOUtils.EOF && c2NumRead == IOUtils.EOF) {
- return c1Buffer.equals(c2Buffer);
- }
- if (c1NumRead == 0 || c2NumRead == 0) {
- // 0 may be returned from a non-blocking channel.
- Thread.yield();
- continue;
- }
- if (c1NumRead != c2NumRead) {
- return false;
- }
- if (!c1Buffer.equals(c2Buffer)) {
- return false;
+ try {
+ int c1NumRead = 0;
+ int c2NumRead = 0;
+ boolean c1Read0 = false;
+ boolean c2Read0 = false;
+ // If a channel is a non-blocking channel, it may return 0 bytes read for any given call.
+ while (true) {
+ if (!c2Read0) {
+ c1NumRead = readToLimit(channel1, c1Buffer);
+ c1Buffer.clear();
+ c1Read0 = c1NumRead == 0;
+ }
+ if (!c1Read0) {
+ c2NumRead = readToLimit(channel2, c2Buffer);
+ c2Buffer.clear();
+ c2Read0 = c2NumRead == 0;
+ }
+ if (c1NumRead == IOUtils.EOF && c2NumRead == IOUtils.EOF) {
+ return c1Buffer.equals(c2Buffer);
+ }
+ if (c1NumRead == 0 || c2NumRead == 0) {
+ // 0 may be returned from a non-blocking channel.
+ Thread.yield();
+ continue;
+ }
+ if (c1NumRead != c2NumRead || !c1Buffer.equals(c2Buffer)) {
+ return false;
+ }
}
+ } finally {
+ Buffers.clear(c1Buffer);
+ Buffers.clear(c2Buffer);
}
}
@@ -135,7 +138,7 @@ public static boolean contentEquals(final SeekableByteChannel channel1, final Se
*
* @param channel The source channel.
* @param dst The buffer into which bytes are to be transferred.
- * @return The number of bytes read, never zero, or {@code -1} if the channel has reached end-of-stream
+ * @return The number of bytes read, never zero, or {@code -1} if the channel has reached end-of-stream.
* @throws IOException If some other I/O error occurs.
* @throws IllegalArgumentException If there is room in the given buffer.
*/
diff --git a/src/main/java/org/apache/commons/io/channels/FilterByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterByteChannel.java
new file mode 100644
index 00000000000..bcce45486b5
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterByteChannel.java
@@ -0,0 +1,125 @@
+/*
+ * 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.io.channels;
+
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link ByteChannel} filter which delegates to the wrapped {@link ByteChannel}.
+ *
+ * A {@code FilterByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or providing
+ * additional functionality. The class {@code FilterByteChannel} itself simply overrides methods of {@code ByteChannel} with versions that pass all requests to
+ * the wrapped channel. Subclasses of {@code FilterByteChannel} may of course override any methods declared or inherited by {@code FilterByteChannel}, and may
+ * also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterByteChannel#FilterByteChannel(ByteChannel) channel constructor} and more advanced instances through the
+ * {@link Builder}.
+ *
+ *
+ * @param the {@link ByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterByteChannel extends FilterChannel implements ByteChannel {
+
+ /**
+ * Builds instances of {@link FilterByteChannel} for subclasses.
+ *
+ * @param The {@link FilterByteChannel} type.
+ * @param The {@link ByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends ByteChannel, B extends AbstractBuilder>
+ extends FilterChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterByteChannel}.
+ */
+ protected AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, ByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterByteChannel get() throws IOException {
+ return new FilterByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forByteChannel() {
+ return new Builder();
+ }
+
+ FilterByteChannel(final AbstractBuilder, ?, ?> builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param byteChannel The channel to wrap.
+ */
+ public FilterByteChannel(final C byteChannel) {
+ super(byteChannel);
+ }
+
+ @Override
+ public int read(final ByteBuffer dst) throws IOException {
+ return channel.read(dst);
+ }
+
+ @Override
+ public int write(final ByteBuffer src) throws IOException {
+ return channel.write(src);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/FilterChannel.java b/src/main/java/org/apache/commons/io/channels/FilterChannel.java
new file mode 100644
index 00000000000..e76dd962082
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterChannel.java
@@ -0,0 +1,146 @@
+/*
+ * 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.io.channels;
+
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.channels.Channel;
+
+import org.apache.commons.io.build.AbstractStreamBuilder;
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link Channel} filter which delegates to the wrapped {@link Channel}.
+ *
+ * A {@code FilterChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or providing
+ * additional functionality. The class {@code FilterChannel} itself simply overrides methods of {@code Channel} with versions that pass all requests to the
+ * wrapped channel. Subclasses of {@code FilterChannel} may of course override any methods declared or inherited by {@code FilterChannel}, and may also provide
+ * additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterChannel#FilterChannel(Channel) channel constructor} and more advanced instances through the
+ * {@link Builder}.
+ *
+ *
+ * @param the {@link Channel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterChannel implements Channel {
+
+ /**
+ * Builds instances of {@link FilterChannel} for subclasses.
+ *
+ * @param The {@link FilterChannel} type.
+ * @param The {@link Channel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends Channel, B extends AbstractBuilder>
+ extends AbstractStreamBuilder> {
+
+ /**
+ * Constructs instance for subclasses.
+ */
+ protected AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterChannel}.
+ */
+ public static class Builder extends AbstractBuilder, Channel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterChannel get() throws IOException {
+ return new FilterChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forChannel() {
+ return new Builder();
+ }
+
+ final C channel;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param builder The source builder.
+ * @throws IOException if an I/O error occurs.
+ */
+ @SuppressWarnings("unchecked")
+ FilterChannel(final AbstractBuilder, ?, ?> builder) throws IOException {
+ channel = (C) builder.getChannel(Channel.class);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterChannel(final C channel) {
+ this.channel = channel;
+ }
+
+ @Override
+ public void close() throws IOException {
+ channel.close();
+ }
+
+ @Override
+ public boolean isOpen() {
+ return channel.isOpen();
+ }
+
+ /**
+ * Unwraps this instance by returning the underlying {@link Channel} of type {@code C}.
+ *
+ * Use with caution.
+ *
+ *
+ * @return the underlying channel of type {@code C}.
+ */
+ public C unwrap() {
+ return channel;
+ }
+}
diff --git a/src/test/java/org/apache/commons/io/channels/FileChannelProxy.java b/src/main/java/org/apache/commons/io/channels/FilterFileChannel.java
similarity index 57%
rename from src/test/java/org/apache/commons/io/channels/FileChannelProxy.java
rename to src/main/java/org/apache/commons/io/channels/FilterFileChannel.java
index ce7c0daddf7..c37d30dbf23 100644
--- a/src/test/java/org/apache/commons/io/channels/FileChannelProxy.java
+++ b/src/main/java/org/apache/commons/io/channels/FilterFileChannel.java
@@ -20,20 +20,90 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
+import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
+import java.util.Objects;
+
+import org.apache.commons.io.build.AbstractStreamBuilder;
/**
- * Proxies a FileChannel.
+ * Filters a {@link FileChannel}.
+ *
+ * A {@code FilterFileChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or providing
+ * additional functionality. The class {@code FilterFileChannel} itself simply overrides methods of {@code FileChannel} with versions that pass all requests to
+ * the wrapped channel. Subclasses of {@code FilterFileChannel} may of course override any methods declared or inherited by {@code FilterFileChannel}, and may
+ * also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterFileChannel#FilterFileChannel(FileChannel) channel constructor} and more advanced instances through the
+ * {@link Builder}.
+ *
+ *
+ * @since 2.22.0
*/
-class FileChannelProxy extends FileChannel {
+public class FilterFileChannel extends FileChannel {
+
+ /**
+ * Builds instances of {@link FilterFileChannel} for subclasses.
+ *
+ * @param The {@link FilterFileChannel} type.
+ * @param The {@link Channel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder>
+ extends AbstractStreamBuilder> {
+
+ /**
+ * Constructs instance for subclasses.
+ */
+ protected AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterFileChannel}.
+ */
+ public static class Builder extends AbstractBuilder {
- FileChannel fileChannel;
+ /**
+ * Builds instances of {@link FilterChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterFileChannel get() throws IOException {
+ return new FilterFileChannel(this);
+ }
+ }
- FileChannelProxy(final FileChannel fileChannel) {
- this.fileChannel = fileChannel;
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forFilterFileChannel() {
+ return new Builder();
+ }
+
+ final FileChannel fileChannel;
+
+ private FilterFileChannel(final Builder builder) throws IOException {
+ this.fileChannel = builder.getChannel(FileChannel.class);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param fileChannel the file channel to wrap.
+ */
+ public FilterFileChannel(final FileChannel fileChannel) {
+ this.fileChannel = Objects.requireNonNull(fileChannel, "fileChannel");
}
@Override
@@ -121,6 +191,18 @@ public FileLock tryLock(final long position, final long size, final boolean shar
return fileChannel.tryLock(position, size, shared);
}
+ /**
+ * Unwraps this instance by returning the underlying {@link FileChannel}.
+ *
+ * Use with caution.
+ *
+ *
+ * @return the underlying {@link FileChannel}.
+ */
+ public FileChannel unwrap() {
+ return fileChannel;
+ }
+
@Override
public int write(final ByteBuffer src) throws IOException {
return fileChannel.write(src);
diff --git a/src/main/java/org/apache/commons/io/channels/FilterReadableByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterReadableByteChannel.java
new file mode 100644
index 00000000000..377d3b1d043
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterReadableByteChannel.java
@@ -0,0 +1,120 @@
+/*
+ * 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.io.channels;
+
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ReadableByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link ReadableByteChannel} filter which delegates to the wrapped {@link ReadableByteChannel}.
+ *
+ * A {@code FilterReadableByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or
+ * providing additional functionality. The class {@code FilterReadableByteChannel} itself simply overrides methods of {@code ReadableByteChannel} with versions
+ * that pass all requests to the wrapped channel. Subclasses of {@code FilterReadableByteChannel} may of course override any methods declared or inherited by
+ * {@code FilterReadableByteChannel}, and may also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterReadableByteChannel#FilterReadableByteChannel(ReadableByteChannel) channel constructor} and more
+ * advanced instances through the {@link Builder}.
+ *
+ *
+ * @param the {@link ReadableByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterReadableByteChannel extends FilterChannel implements ReadableByteChannel {
+
+ /**
+ * Builds instances of {@link FilterReadableByteChannel} for subclasses.
+ *
+ * @param The {@link FilterReadableByteChannel} type.
+ * @param The {@link ReadableByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends ReadableByteChannel, B extends AbstractBuilder>
+ extends FilterChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterReadableByteChannel}.
+ */
+ public AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, ReadableByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterReadableByteChannel get() throws IOException {
+ return new FilterReadableByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forReadableByteChannel() {
+ return new Builder();
+ }
+
+ FilterReadableByteChannel(final Builder builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterReadableByteChannel(final C channel) {
+ super(channel);
+ }
+
+ @Override
+ public int read(final ByteBuffer dst) throws IOException {
+ return channel.read(dst);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/FilterSeekableByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterSeekableByteChannel.java
new file mode 100644
index 00000000000..11fbadc2c15
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterSeekableByteChannel.java
@@ -0,0 +1,134 @@
+/*
+ * 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.io.channels;
+
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.channels.SeekableByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link SeekableByteChannel} filter which delegates to the wrapped {@link SeekableByteChannel}.
+ *
+ * A {@code FilterSeekableByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or
+ * providing additional functionality. The class {@code FilterSeekableByteChannel} itself simply overrides methods of {@code SeekableByteChannel} with versions
+ * that pass all requests to the wrapped channel. Subclasses of {@code FilterSeekableByteChannel} may of course override any methods declared or inherited by
+ * {@code FilterSeekableByteChannel}, and may also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterSeekableByteChannel#FilterSeekableByteChannel(SeekableByteChannel) Channel constructor} and more
+ * advanced instances through the {@link Builder}.
+ *
+ *
+ * @param the {@link SeekableByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterSeekableByteChannel extends FilterByteChannel implements SeekableByteChannel {
+
+ /**
+ * Builds instances of {@link FilterSeekableByteChannel} for subclasses.
+ *
+ * @param The {@link FilterSeekableByteChannel} type.
+ * @param The {@link SeekableByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends SeekableByteChannel, B extends AbstractBuilder>
+ extends FilterByteChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterSeekableByteChannel}.
+ */
+ public AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterSeekableByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, SeekableByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterSeekableByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterSeekableByteChannel get() throws IOException {
+ return new FilterSeekableByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forSeekableByteChannel() {
+ return new Builder();
+ }
+
+ FilterSeekableByteChannel(final Builder builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterSeekableByteChannel(final C channel) {
+ super(channel);
+ }
+
+ @Override
+ public long position() throws IOException {
+ return channel.position();
+ }
+
+ @Override
+ public SeekableByteChannel position(final long newPosition) throws IOException {
+ return channel.position(newPosition);
+ }
+
+ @Override
+ public long size() throws IOException {
+ return channel.size();
+ }
+
+ @Override
+ public SeekableByteChannel truncate(final long size) throws IOException {
+ return channel.truncate(size);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/channels/FilterWritableByteChannel.java b/src/main/java/org/apache/commons/io/channels/FilterWritableByteChannel.java
new file mode 100644
index 00000000000..f07e8988c91
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/channels/FilterWritableByteChannel.java
@@ -0,0 +1,120 @@
+/*
+ * 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.io.channels;
+
+import java.io.FilterInputStream;
+import java.io.FilterOutputStream;
+import java.io.FilterReader;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+
+import org.apache.commons.io.input.ProxyInputStream;
+import org.apache.commons.io.input.ProxyReader;
+import org.apache.commons.io.output.ProxyOutputStream;
+import org.apache.commons.io.output.ProxyWriter;
+
+/**
+ * A {@link WritableByteChannel} filter which delegates to the wrapped {@link WritableByteChannel}.
+ *
+ * A {@code FilterWritableByteChannel} wraps some other channel, which it uses as its basic source of data, possibly transforming the data along the way or
+ * providing additional functionality. The class {@code FilterWritableByteChannel} itself simply overrides methods of {@code WritableByteChannel} with versions
+ * that pass all requests to the wrapped channel. Subclasses of {@code FilterWritableByteChannel} may of course override any methods declared or inherited by
+ * {@code WritableByteChannel}, and may also provide additional fields and methods.
+ *
+ *
+ * You construct s simple instance with the {@link FilterWritableByteChannel#FilterWritableByteChannel(WritableByteChannel) Channel constructor} and more
+ * advanced instances through the {@link Builder}.
+ *
+ *
+ * @param the {@link WritableByteChannel} type.
+ * @see FilterInputStream
+ * @see FilterOutputStream
+ * @see FilterReader
+ * @see FilterWritableByteChannel
+ * @see ProxyInputStream
+ * @see ProxyOutputStream
+ * @see ProxyReader
+ * @see ProxyWriter
+ * @since 2.22.0
+ */
+public class FilterWritableByteChannel extends FilterChannel implements WritableByteChannel {
+
+ /**
+ * Builds instances of {@link FilterWritableByteChannel} for subclasses.
+ *
+ * @param The {@link FilterWritableByteChannel} type.
+ * @param The {@link WritableByteChannel} type wrapped by the FilterChannel.
+ * @param The builder type.
+ */
+ public abstract static class AbstractBuilder, C extends WritableByteChannel, B extends AbstractBuilder>
+ extends FilterChannel.AbstractBuilder {
+
+ /**
+ * Constructs a new builder for {@link FilterWritableByteChannel}.
+ */
+ public AbstractBuilder() {
+ // empty
+ }
+ }
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ public static class Builder extends AbstractBuilder, WritableByteChannel, Builder> {
+
+ /**
+ * Builds instances of {@link FilterByteChannel}.
+ */
+ protected Builder() {
+ // empty
+ }
+
+ @Override
+ public FilterWritableByteChannel get() throws IOException {
+ return new FilterWritableByteChannel<>(this);
+ }
+ }
+
+ /**
+ * Creates a new {@link Builder}.
+ *
+ * @return a new {@link Builder}.
+ */
+ public static Builder forWritableByteChannel() {
+ return new Builder();
+ }
+
+ FilterWritableByteChannel(final Builder builder) throws IOException {
+ super(builder);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param channel The channel to wrap.
+ */
+ public FilterWritableByteChannel(final C channel) {
+ super(channel);
+ }
+
+ @Override
+ public int write(final ByteBuffer src) throws IOException {
+ return channel.write(src);
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java b/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java
index 8595be79e8a..a8aa9a3d50b 100644
--- a/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java
+++ b/src/main/java/org/apache/commons/io/charset/CharsetDecoders.java
@@ -30,7 +30,7 @@ public final class CharsetDecoders {
/**
* Returns the given non-null CharsetDecoder or a new default CharsetDecoder.
*
- * Null input maps to the virtual machine's {@link Charset#defaultCharset() default charset} decoder.
+ * Null input maps to the virtual machine's {@linkplain Charset#defaultCharset() default charset} decoder.
*
*
* @param charsetDecoder The CharsetDecoder to test.
diff --git a/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java b/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java
index d0f9cd04be1..a1fff5cf1f3 100644
--- a/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java
+++ b/src/main/java/org/apache/commons/io/charset/CharsetEncoders.java
@@ -31,7 +31,7 @@ public final class CharsetEncoders {
/**
* Returns the given non-null CharsetEncoder or a new default CharsetEncoder.
*
- * Null input maps to the virtual machine's {@link Charset#defaultCharset() default charset} decoder.
+ * Null input maps to the virtual machine's {@linkplain Charset#defaultCharset() default charset} decoder.
*
*
* @param charsetEncoder The CharsetEncoder to test.
diff --git a/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java b/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
index 0934f895f7a..dcc2d20428e 100644
--- a/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/CompositeFileComparator.java
@@ -58,7 +58,7 @@ public class CompositeFileComparator extends AbstractFileComparator implements S
/**
* Constructs a composite comparator for the set of delegate comparators.
*
- * @param delegates The delegate file comparators
+ * @param delegates The delegate file comparators.
*/
public CompositeFileComparator(@SuppressWarnings("unchecked") final Comparator... delegates) {
this.delegates = delegates == null ? emptyArray() : delegates.clone();
@@ -67,7 +67,7 @@ public CompositeFileComparator(@SuppressWarnings("unchecked") final Comparator> delegates) {
this.delegates = delegates == null ? emptyArray()
@@ -77,8 +77,8 @@ public CompositeFileComparator(final Iterable> delegates) {
/**
* Compares the two files using delegate comparators.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return the first non-zero result returned from the delegate comparators or zero.
*/
@Override
@@ -94,7 +94,7 @@ private Comparator[] emptyArray() {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java b/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java
index c447f085198..db580a1a2e1 100644
--- a/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/DefaultFileComparator.java
@@ -69,8 +69,8 @@ public DefaultFileComparator() {
/**
* Compares the two files using the {@link File#compareTo(File)} method.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return the result of calling file1's
* {@link File#compareTo(File)} with file2 as the parameter.
*/
diff --git a/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java b/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java
index 3b4e1e2e115..1d57ec8164f 100644
--- a/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/ExtensionFileComparator.java
@@ -93,7 +93,7 @@ public ExtensionFileComparator() {
/**
* Constructs a file extension comparator instance with the specified case-sensitivity.
*
- * @param ioCase how to handle case sensitivity, null means case-sensitive
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
*/
public ExtensionFileComparator(final IOCase ioCase) {
this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
@@ -102,8 +102,8 @@ public ExtensionFileComparator(final IOCase ioCase) {
/**
* Compares the extensions of two files the specified case sensitivity.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's extension
* is less than the second, zero if the extensions are the
* same and a positive value if the first files extension
@@ -119,7 +119,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java b/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java
index 41590fa6636..7e92a7fcb74 100644
--- a/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/NameFileComparator.java
@@ -89,7 +89,7 @@ public NameFileComparator() {
/**
* Constructs a file name comparator instance with the specified case-sensitivity.
*
- * @param ioCase how to handle case sensitivity, null means case-sensitive
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
*/
public NameFileComparator(final IOCase ioCase) {
this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
@@ -98,8 +98,8 @@ public NameFileComparator(final IOCase ioCase) {
/**
* Compares the names of two files with the specified case sensitivity.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's name
* is less than the second, zero if the names are the
* same and a positive value if the first files name
@@ -113,7 +113,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java b/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java
index 1f41eb74185..4ae379add58 100644
--- a/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/PathFileComparator.java
@@ -51,6 +51,7 @@
*
* Serialization is deprecated and will be removed in 3.0.
*
+ *
* @since 1.4
*/
public class PathFileComparator extends AbstractFileComparator implements Serializable {
@@ -88,7 +89,7 @@ public PathFileComparator() {
/**
* Constructs a file path comparator instance with the specified case-sensitivity.
*
- * @param ioCase how to handle case sensitivity, null means case-sensitive
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
*/
public PathFileComparator(final IOCase ioCase) {
this.ioCase = IOCase.value(ioCase, IOCase.SENSITIVE);
@@ -97,8 +98,8 @@ public PathFileComparator(final IOCase ioCase) {
/**
* Compares the paths of two files the specified case sensitivity.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's path
* is less than the second, zero if the paths are the
* same and a positive value if the first files path
@@ -112,7 +113,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java b/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java
index 5154d9b3256..a5ff78c0e59 100644
--- a/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java
+++ b/src/main/java/org/apache/commons/io/comparator/SizeFileComparator.java
@@ -107,8 +107,8 @@ public SizeFileComparator(final boolean sumDirectoryContents) {
/**
* Compares the length of two files.
*
- * @param file1 The first file to compare
- * @param file2 The second file to compare
+ * @param file1 The first file to compare.
+ * @param file2 The second file to compare.
* @return a negative value if the first file's length
* is less than the second, zero if the lengths are the
* same and a positive value if the first files length
@@ -141,7 +141,7 @@ public int compare(final File file1, final File file2) {
/**
* String representation of this file comparator.
*
- * @return String representation of this file comparator
+ * @return String representation of this file comparator.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/doc-files/leaf.svg b/src/main/java/org/apache/commons/io/doc-files/leaf.svg
new file mode 100644
index 00000000000..71de588c648
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/doc-files/leaf.svg
@@ -0,0 +1,45 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/apache/commons/io/doc-files/logo.png b/src/main/java/org/apache/commons/io/doc-files/logo.png
new file mode 100644
index 00000000000..02a758f0ed8
Binary files /dev/null and b/src/main/java/org/apache/commons/io/doc-files/logo.png differ
diff --git a/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java b/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java
index 1551231cfaf..3be7a325315 100644
--- a/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java
+++ b/src/main/java/org/apache/commons/io/file/AccumulatorPathVisitor.java
@@ -195,7 +195,6 @@ public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter f
* @since 2.12.0
* @deprecated Use {@link #builder()}.
*/
- @SuppressWarnings("deprecation")
@Deprecated
public AccumulatorPathVisitor(final PathCounters pathCounter, final PathFilter fileFilter, final PathFilter dirFilter,
final IOBiFunction visitFileFailed) {
@@ -251,10 +250,10 @@ public int hashCode() {
* Relativizes each directory path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
* sorting the result.
*
- * @param parent A parent path
- * @param sort Whether to sort
+ * @param parent A parent path.
+ * @param sort Whether to sort.
* @param comparator How to sort, null uses default sorting.
- * @return A new list
+ * @return A new list.
*/
public List relativizeDirectories(final Path parent, final boolean sort,
final Comparator super Path> comparator) {
@@ -265,10 +264,10 @@ public List relativizeDirectories(final Path parent, final boolean sort,
* Relativizes each file path with {@link Path#relativize(Path)} against the given {@code parent}, optionally
* sorting the result.
*
- * @param parent A parent path
- * @param sort Whether to sort
+ * @param parent A parent path.
+ * @param sort Whether to sort.
* @param comparator How to sort, null uses default sorting.
- * @return A new list
+ * @return A new list.
*/
public List relativizeFiles(final Path parent, final boolean sort,
final Comparator super Path> comparator) {
diff --git a/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java b/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java
index 7172b2d0671..45b761c971c 100644
--- a/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java
+++ b/src/main/java/org/apache/commons/io/file/CopyDirectoryVisitor.java
@@ -48,8 +48,8 @@ private static CopyOption[] toCopyOption(final CopyOption... copyOptions) {
* Constructs an instance that copies all files.
*
* @param pathCounter How to count visits.
- * @param sourceDirectory The source directory
- * @param targetDirectory The target directory
+ * @param sourceDirectory The source directory.
+ * @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
*/
public CopyDirectoryVisitor(final PathCounters pathCounter, final Path sourceDirectory, final Path targetDirectory, final CopyOption... copyOptions) {
@@ -65,8 +65,8 @@ public CopyDirectoryVisitor(final PathCounters pathCounter, final Path sourceDir
* @param pathCounter How to count visits.
* @param fileFilter How to filter file paths.
* @param dirFilter How to filter directory paths.
- * @param sourceDirectory The source directory
- * @param targetDirectory The target directory
+ * @param sourceDirectory The source directory.
+ * @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
* @since 2.9.0
*/
diff --git a/src/main/java/org/apache/commons/io/file/Counters.java b/src/main/java/org/apache/commons/io/file/Counters.java
index b1abd721d9c..10e05dc48f7 100644
--- a/src/main/java/org/apache/commons/io/file/Counters.java
+++ b/src/main/java/org/apache/commons/io/file/Counters.java
@@ -455,7 +455,7 @@ public static PathCounters noopPathCounters() {
/**
* Construct a new instance.
*
- * @deprecated Will be private in 4.0
+ * @deprecated Will be private in 3.0.
*/
@Deprecated
public Counters() {
diff --git a/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java b/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java
index ab02ad073e2..3f445010e26 100644
--- a/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java
+++ b/src/main/java/org/apache/commons/io/file/CountingPathVisitor.java
@@ -28,7 +28,6 @@
import org.apache.commons.io.file.Counters.PathCounters;
import org.apache.commons.io.filefilter.IOFileFilter;
-import org.apache.commons.io.filefilter.SymbolicLinkFileFilter;
import org.apache.commons.io.filefilter.TrueFileFilter;
import org.apache.commons.io.function.IOBiFunction;
@@ -152,7 +151,7 @@ static UnaryOperator defaultDirectoryTransformer() {
}
static IOFileFilter defaultFileFilter() {
- return new SymbolicLinkFileFilter(FileVisitResult.TERMINATE, FileVisitResult.CONTINUE);
+ return TrueFileFilter.INSTANCE;
}
static PathCounters defaultPathCounters() {
diff --git a/src/main/java/org/apache/commons/io/file/PathFilter.java b/src/main/java/org/apache/commons/io/file/PathFilter.java
index dbeef906261..ee54de29deb 100644
--- a/src/main/java/org/apache/commons/io/file/PathFilter.java
+++ b/src/main/java/org/apache/commons/io/file/PathFilter.java
@@ -34,7 +34,7 @@ public interface PathFilter {
*
* @param path The Path to test.
* @param attributes the path's basic attributes (may be null).
- * @return a FileVisitResult
+ * @return a FileVisitResult.
*/
FileVisitResult accept(Path path, BasicFileAttributes attributes);
}
diff --git a/src/main/java/org/apache/commons/io/file/PathUtils.java b/src/main/java/org/apache/commons/io/file/PathUtils.java
index 055bbe06a0b..8de95aa2169 100644
--- a/src/main/java/org/apache/commons/io/file/PathUtils.java
+++ b/src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -18,6 +18,7 @@
package org.apache.commons.io.file;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -75,6 +76,7 @@
import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IORandomAccessFile;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.RandomAccessFileMode;
import org.apache.commons.io.RandomAccessFiles;
@@ -137,9 +139,15 @@ private static boolean equalsIgnoreFileSystem(final Path path1, final Path path2
return extractKey(separator1, string1).equals(extractKey(separator2, string2));
}
+ /**
+ * Replaces the file separator in a path string with a string that is not legal in a path on Windows, Linux, and macOS.
+ *
+ * @param separator the file separator.
+ * @param string a path.
+ * @return a key.
+ */
static String extractKey(final String separator, final String string) {
- // Replace the file separator in a path string with a string that is not legal in a path on Windows, Linux, and macOS.
- return string.replaceAll("\\" + separator, ">");
+ return string.replace(separator, ">");
}
final boolean equals;
@@ -200,32 +208,38 @@ private RelativeSortedPaths(final Path dir1, final Path dir2, final int maxDepth
private static final OpenOption[] OPEN_OPTIONS_TRUNCATE = { StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING };
private static final OpenOption[] OPEN_OPTIONS_APPEND = { StandardOpenOption.CREATE, StandardOpenOption.APPEND };
+
/**
* Empty {@link CopyOption} array.
*
* @since 2.8.0
*/
public static final CopyOption[] EMPTY_COPY_OPTIONS = {};
+
/**
* Empty {@link DeleteOption} array.
*
* @since 2.8.0
*/
public static final DeleteOption[] EMPTY_DELETE_OPTION_ARRAY = {};
+
/**
* Empty {@link FileAttribute} array.
*
* @since 2.13.0
*/
public static final FileAttribute>[] EMPTY_FILE_ATTRIBUTE_ARRAY = {};
+
/**
* Empty {@link FileVisitOption} array.
*/
public static final FileVisitOption[] EMPTY_FILE_VISIT_OPTION_ARRAY = {};
+
/**
* Empty {@link LinkOption} array.
*/
public static final LinkOption[] EMPTY_LINK_OPTION_ARRAY = {};
+
/**
* {@link LinkOption} array for {@link LinkOption#NOFOLLOW_LINKS}.
*
@@ -234,16 +248,19 @@ private RelativeSortedPaths(final Path dir1, final Path dir2, final int maxDepth
*/
@Deprecated
public static final LinkOption[] NOFOLLOW_LINK_OPTION_ARRAY = { LinkOption.NOFOLLOW_LINKS };
+
/**
* A LinkOption used to follow link in this class, the inverse of {@link LinkOption#NOFOLLOW_LINKS}.
*
* @since 2.12.0
*/
static final LinkOption NULL_LINK_OPTION = null;
+
/**
* Empty {@link OpenOption} array.
*/
public static final OpenOption[] EMPTY_OPEN_OPTION_ARRAY = {};
+
/**
* Empty {@link Path} array.
*
@@ -266,7 +283,10 @@ private static AccumulatorPathVisitor accumulate(final Path directory, final int
}
/**
- * Cleans a directory by only deleting files, including in subdirectories, but without deleting the directories.
+ * Cleans a directory by only deleting files, including in subdirectories, without deleting directories.
+ *
+ * This leaves a directory empty of files but the directory and any subdirectories remain.
+ *
*
* @param directory directory to clean.
* @return The visitation path counters.
@@ -277,7 +297,10 @@ public static PathCounters cleanDirectory(final Path directory) throws IOExcepti
}
/**
- * Cleans a directory by only deleting files, including in subdirectories, but without deleting the directories.
+ * Cleans a directory by only deleting files, including in subdirectories, without deleting directories.
+ *
+ * This leaves a directory empty of files but the directory and any subdirectories remain.
+ *
*
* @param directory directory to clean.
* @param deleteOptions How to handle deletion.
@@ -289,6 +312,33 @@ public static PathCounters cleanDirectory(final Path directory, final DeleteOpti
return visitFileTree(new CleaningPathVisitor(Counters.longPathCounters(), deleteOptions), directory).getPathCounters();
}
+ /**
+ * Clears the contents at an existing Path by filling it with NUL ({@code 0)} bytes.
+ *
+ * @param path The target path to an existing file.
+ * @return The given path.
+ * @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
+ * @throws IOException Thrown writing to the Path.
+ * @since 2.23.0
+ */
+ public static Path clear(final Path path) throws IOException {
+ RandomAccessFileMode.READ_WRITE.accept(path, IORandomAccessFile::clear);
+ return path;
+ }
+
+ /**
+ * Clears the contents at a Path by filling it with NUL ({@code 0)} bytes.
+ *
+ * @param path The target path, may not exist, may be null.
+ * @return The given path.
+ * @throws FileNotFoundException See {@link IORandomAccessFile#IORandomAccessFile(File, String)}.
+ * @throws IOException Thrown writing to the Path.
+ * @since 2.23.0
+ */
+ public static Path clearIfExists(final Path path) throws IOException {
+ return exists(path) ? clear(path) : path;
+ }
+
/**
* Compares the given {@link Path}'s last modified time to the given file time.
*
@@ -378,7 +428,7 @@ public static PathCounters copyDirectory(final Path sourceDirectory, final Path
* @param sourceFile The source URL.
* @param targetFile The target file.
* @param copyOptions Specifies how the copying should be done.
- * @return The target file
+ * @return The target file.
* @throws IOException if an I/O error occurs.
* @see Files#copy(InputStream, Path, CopyOption...)
*/
@@ -393,7 +443,7 @@ public static Path copyFile(final URL sourceFile, final Path targetFile, final C
* @param sourceFile The source file.
* @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
- * @return The target file
+ * @return The target file.
* @throws IOException if an I/O error occurs.
* @see Files#copy(Path, Path, CopyOption...)
*/
@@ -410,7 +460,7 @@ public static Path copyFileToDirectory(final Path sourceFile, final Path targetD
* @param sourceFile The source URL.
* @param targetDirectory The target directory.
* @param copyOptions Specifies how the copying should be done.
- * @return The target file
+ * @return The target file.
* @throws IOException if an I/O error occurs.
* @see Files#copy(InputStream, Path, CopyOption...)
*/
@@ -499,7 +549,7 @@ public static Path current() {
*
*
*
A directory to delete does not have to be empty.
- *
You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
+ *
You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
*
*
* @param path file or directory to delete, must not be {@code null}
@@ -518,7 +568,7 @@ public static PathCounters delete(final Path path) throws IOException {
*
*
*
A directory to delete does not have to be empty.
- *
You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
+ *
You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
*
*
* @param path file or directory to delete, must not be {@code null}
@@ -540,7 +590,7 @@ public static PathCounters delete(final Path path, final DeleteOption... deleteO
*
*
*
A directory to delete does not have to be empty.
- *
You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
+ *
You get exceptions when a file or directory cannot be deleted; {@link File#delete()} returns a boolean.
+ *
* @param filter the filter to apply to the set of files.
* @param files the array of files to apply the filter to.
* @return a subset of {@code files} that is accepted by the
* file filter.
* @throws NullPointerException if the filter is {@code null}
* or {@code files} contains a {@code null} value.
- *
* @since 2.0
*/
public static File[] filter(final IOFileFilter filter, final File... files) {
@@ -259,13 +259,13 @@ public static File[] filter(final IOFileFilter filter, final File... files) {
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
*
+ *
* @param filter the filter to apply to each files in the list.
* @param files the collection of files to apply the filter to.
* @return a subset of {@code files} that is accepted by the
@@ -369,6 +371,7 @@ public static List filterList(final IOFileFilter filter, final Iterable
+ *
* @param filter the filter to apply to the set of files.
* @param files the collection of files to apply the filter to.
* @return a subset of {@code files} that is accepted by the
@@ -398,6 +401,7 @@ public static Set filterSet(final IOFileFilter filter, final File... files
* Set<File> javaFiles = FileFilterUtils.filterSet(allFiles,
* FileFilterUtils.suffixFileFilter(".java"));
*
+ *
* @param filter the filter to apply to the set of files.
* @param files the collection of files to apply the filter to.
* @return a subset of {@code files} that is accepted by the
@@ -495,8 +499,8 @@ public static IOFileFilter magicNumberFileFilter(final String magicNumber, final
* Passing in {@code null} will return a filter that accepts everything
* except CVS directories.
*
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
+ * @param filter the filter to decorate, null means an unrestricted filter.
+ * @return the decorated filter, never null.
* @since 1.1 (method existed but had a bug in 1.0)
*/
public static IOFileFilter makeCVSAware(final IOFileFilter filter) {
@@ -506,8 +510,8 @@ public static IOFileFilter makeCVSAware(final IOFileFilter filter) {
/**
* Decorates a filter so that it only applies to directories and not to files.
*
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
+ * @param filter the filter to decorate, null means an unrestricted filter.
+ * @return the decorated filter, never null.
* @see DirectoryFileFilter#DIRECTORY
* @since 1.3
*/
@@ -521,8 +525,8 @@ public static IOFileFilter makeDirectoryOnly(final IOFileFilter filter) {
/**
* Decorates a filter so that it only applies to files and not to directories.
*
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
+ * @param filter the filter to decorate, null means an unrestricted filter.
+ * @return the decorated filter, never null.
* @see FileFileFilter#INSTANCE
* @since 1.3
*/
@@ -538,8 +542,8 @@ public static IOFileFilter makeFileOnly(final IOFileFilter filter) {
* Passing in {@code null} will return a filter that accepts everything
* except SVN directories.
*
- * @param filter the filter to decorate, null means an unrestricted filter
- * @return the decorated filter, never null
+ * @param filter the filter to decorate, null means an unrestricted filter.
+ * @return the decorated filter, never null.
* @since 1.1
*/
public static IOFileFilter makeSVNAware(final IOFileFilter filter) {
@@ -549,8 +553,8 @@ public static IOFileFilter makeSVNAware(final IOFileFilter filter) {
/**
* Returns a filter that returns true if the file name matches the specified text.
*
- * @param name the file name
- * @return a name checking filter
+ * @param name the file name.
+ * @return a name checking filter.
* @see NameFileFilter
*/
public static IOFileFilter nameFileFilter(final String name) {
@@ -560,9 +564,9 @@ public static IOFileFilter nameFileFilter(final String name) {
/**
* Returns a filter that returns true if the file name matches the specified text.
*
- * @param name the file name
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @return a name checking filter
+ * @param name the file name.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @return a name checking filter.
* @see NameFileFilter
* @since 2.0
*/
@@ -573,8 +577,8 @@ public static IOFileFilter nameFileFilter(final String name, final IOCase ioCase
/**
* Returns a filter that NOTs the specified filter.
*
- * @param filter the filter to invert
- * @return a filter that NOTs the specified filter
+ * @param filter the filter to invert.
+ * @return a filter that NOTs the specified filter.
* @see NotFileFilter
*/
public static IOFileFilter notFileFilter(final IOFileFilter filter) {
@@ -585,7 +589,7 @@ public static IOFileFilter notFileFilter(final IOFileFilter filter) {
* Returns a filter that ORs the specified filters.
*
* @param filters the IOFileFilters that will be ORed together.
- * @return a filter that ORs the specified filters
+ * @return a filter that ORs the specified filters.
* @throws IllegalArgumentException if the filters are null or contain a
* null value.
* @see OrFileFilter
@@ -598,12 +602,12 @@ public static IOFileFilter or(final IOFileFilter... filters) {
/**
* Returns a filter that ORs the two specified filters.
*
- * @param filter1 the first filter
- * @param filter2 the second filter
- * @return a filter that ORs the two specified filters
+ * @param filter1 the first filter.
+ * @param filter2 the second filter.
+ * @return a filter that ORs the two specified filters.
* @see #or(IOFileFilter...)
* @see OrFileFilter
- * @deprecated use {@link #or(IOFileFilter...)}
+ * @deprecated Use {@link #or(IOFileFilter...)}
*/
@Deprecated
public static IOFileFilter orFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
@@ -613,8 +617,8 @@ public static IOFileFilter orFileFilter(final IOFileFilter filter1, final IOFile
/**
* Returns a filter that returns true if the file name starts with the specified text.
*
- * @param prefix the file name prefix
- * @return a prefix checking filter
+ * @param prefix the file name prefix.
+ * @return a prefix checking filter.
* @see PrefixFileFilter
*/
public static IOFileFilter prefixFileFilter(final String prefix) {
@@ -624,9 +628,9 @@ public static IOFileFilter prefixFileFilter(final String prefix) {
/**
* Returns a filter that returns true if the file name starts with the specified text.
*
- * @param prefix the file name prefix
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @return a prefix checking filter
+ * @param prefix the file name prefix.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @return a prefix checking filter.
* @see PrefixFileFilter
* @since 2.0
*/
@@ -637,8 +641,8 @@ public static IOFileFilter prefixFileFilter(final String prefix, final IOCase io
/**
* Returns a filter that returns true if the file is bigger than a certain size.
*
- * @param threshold the file size threshold
- * @return an appropriately configured SizeFileFilter
+ * @param threshold the file size threshold.
+ * @return an appropriately configured SizeFileFilter.
* @see SizeFileFilter
* @since 1.2
*/
@@ -649,9 +653,9 @@ public static IOFileFilter sizeFileFilter(final long threshold) {
/**
* Returns a filter that filters based on file size.
*
- * @param threshold the file size threshold
- * @param acceptLarger if true, larger files get accepted, if false, smaller
- * @return an appropriately configured SizeFileFilter
+ * @param threshold the file size threshold.
+ * @param acceptLarger if true, larger files get accepted, if false, smaller.
+ * @return an appropriately configured SizeFileFilter.
* @see SizeFileFilter
* @since 1.2
*/
@@ -663,9 +667,9 @@ public static IOFileFilter sizeFileFilter(final long threshold, final boolean ac
* Returns a filter that accepts files whose size is >= minimum size
* and <= maximum size.
*
- * @param minSizeInclusive the minimum file size (inclusive)
- * @param maxSizeInclusive the maximum file size (inclusive)
- * @return an appropriately configured IOFileFilter
+ * @param minSizeInclusive the minimum file size (inclusive).
+ * @param maxSizeInclusive the maximum file size (inclusive).
+ * @return an appropriately configured IOFileFilter.
* @see SizeFileFilter
* @since 1.3
*/
@@ -678,8 +682,8 @@ public static IOFileFilter sizeRangeFileFilter(final long minSizeInclusive, fina
/**
* Returns a filter that returns true if the file name ends with the specified text.
*
- * @param suffix the file name suffix
- * @return a suffix checking filter
+ * @param suffix the file name suffix.
+ * @return a suffix checking filter.
* @see SuffixFileFilter
*/
public static IOFileFilter suffixFileFilter(final String suffix) {
@@ -689,9 +693,9 @@ public static IOFileFilter suffixFileFilter(final String suffix) {
/**
* Returns a filter that returns true if the file name ends with the specified text.
*
- * @param suffix the file name suffix
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @return a suffix checking filter
+ * @param suffix the file name suffix.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @return a suffix checking filter.
* @see SuffixFileFilter
* @since 2.0
*/
@@ -702,8 +706,8 @@ public static IOFileFilter suffixFileFilter(final String suffix, final IOCase io
/**
* Create a List of file filters.
*
- * @param filters The file filters
- * @return The list of file filters
+ * @param filters The file filters.
+ * @return The list of file filters.
* @throws NullPointerException if the filters are null or contain a
* null value.
* @since 2.0
@@ -715,7 +719,7 @@ public static List toList(final IOFileFilter... filters) {
/**
* Returns a filter that always returns true.
*
- * @return a true filter
+ * @return a true filter.
* @see TrueFileFilter#TRUE
*/
public static IOFileFilter trueFileFilter() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/HiddenFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/HiddenFileFilter.java
index 6fff2241ab1..a8c49bbae8e 100644
--- a/src/main/java/org/apache/commons/io/filefilter/HiddenFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/HiddenFileFilter.java
@@ -95,7 +95,7 @@ protected HiddenFileFilter() {
/**
* Tests to see if the file is hidden.
*
- * @param file the File to check
+ * @param file the File to check.
* @return {@code true} if the file is
* hidden, otherwise {@code false}.
*/
@@ -107,7 +107,7 @@ public boolean accept(final File file) {
/**
* Tests to see if the file is hidden.
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
* @return {@code true} if the file is hidden, otherwise {@code false}.
* @since 2.9.0
diff --git a/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java
index 79aa55d68c1..3f28a7661cd 100644
--- a/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java
@@ -218,7 +218,7 @@ public MagicNumberFileFilter(final String magicNumber) {
* MagicNumberFileFilter tarFileFilter = MagicNumberFileFilter("ustar", 257);
*
*
- * This method uses the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
*
* @param magicNumber the magic number to look for in the file.
@@ -270,6 +270,7 @@ public boolean accept(final File file) {
* be rejected.
*
*
+ *
* @param file the file to accept or reject.
* @param attributes the path's basic attributes (may be null).
* @return {@code true} if the file contains the filter's magic number
diff --git a/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java
index 7eda934d906..5aa3c38a21b 100644
--- a/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/NameFileFilter.java
@@ -83,9 +83,9 @@ public class NameFileFilter extends AbstractFileFilter implements Serializable {
/**
* Constructs a new case-sensitive name file filter for a list of names.
*
- * @param names the names to allow, must not be null
- * @throws IllegalArgumentException if the name list is null
- * @throws ClassCastException if the list does not contain Strings
+ * @param names the names to allow, must not be null.
+ * @throws IllegalArgumentException if the name list is null.
+ * @throws ClassCastException if the list does not contain Strings.
*/
public NameFileFilter(final List names) {
this(names, null);
@@ -94,10 +94,10 @@ public NameFileFilter(final List names) {
/**
* Constructs a new name file filter for a list of names specifying case-sensitivity.
*
- * @param names the names to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the name list is null
- * @throws ClassCastException if the list does not contain Strings
+ * @param names the names to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the name list is null.
+ * @throws ClassCastException if the list does not contain Strings.
*/
public NameFileFilter(final List names, final IOCase ioCase) {
Objects.requireNonNull(names, "names");
@@ -108,8 +108,8 @@ public NameFileFilter(final List names, final IOCase ioCase) {
/**
* Constructs a new case-sensitive name file filter for a single name.
*
- * @param name the name to allow, must not be null
- * @throws IllegalArgumentException if the name is null
+ * @param name the name to allow, must not be null.
+ * @throws IllegalArgumentException if the name is null.
*/
public NameFileFilter(final String name) {
this(name, IOCase.SENSITIVE);
@@ -122,8 +122,8 @@ public NameFileFilter(final String name) {
* instance. This would be inadvisable however.
*
*
- * @param names the names to allow, must not be null
- * @throws IllegalArgumentException if the names array is null
+ * @param names the names to allow, must not be null.
+ * @throws IllegalArgumentException if the names array is null.
*/
public NameFileFilter(final String... names) {
this(names, IOCase.SENSITIVE);
@@ -132,9 +132,9 @@ public NameFileFilter(final String... names) {
/**
* Constructs a new name file filter specifying case-sensitivity.
*
- * @param name the name to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the name is null
+ * @param name the name to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the name is null.
*/
public NameFileFilter(final String name, final IOCase ioCase) {
Objects.requireNonNull(name, "name");
@@ -145,9 +145,9 @@ public NameFileFilter(final String name, final IOCase ioCase) {
/**
* Constructs a new name file filter for an array of names specifying case-sensitivity.
*
- * @param names the names to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the names array is null
+ * @param names the names to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the names array is null.
*/
public NameFileFilter(final String[] names, final IOCase ioCase) {
Objects.requireNonNull(names, "names");
@@ -158,8 +158,8 @@ public NameFileFilter(final String[] names, final IOCase ioCase) {
/**
* Tests to see if the file name matches.
*
- * @param file the File to check
- * @return true if the file name matches
+ * @param file the File to check.
+ * @return true if the file name matches.
*/
@Override
public boolean accept(final File file) {
@@ -169,9 +169,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the file name matches.
*
- * @param dir the File directory (ignored)
- * @param name the file name
- * @return true if the file name matches
+ * @param dir the File directory (ignored).
+ * @param name the file name.
+ * @return true if the file name matches.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -181,9 +181,9 @@ public boolean accept(final File dir, final String name) {
/**
* Checks to see if the file name matches.
*
- * @param path the File to check
+ * @param path the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file name matches
+ * @return true if the file name matches.
* @since 2.9.0
*/
@Override
@@ -202,7 +202,7 @@ private IOCase toIOCase(final IOCase ioCase) {
/**
* Provide a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/NotFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/NotFileFilter.java
index 8592e402129..4e92f9a47ac 100644
--- a/src/main/java/org/apache/commons/io/filefilter/NotFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/NotFileFilter.java
@@ -43,8 +43,8 @@ public class NotFileFilter extends AbstractFileFilter implements Serializable {
/**
* Constructs a new file filter that NOTs the result of another filter.
*
- * @param filter the filter, must not be null
- * @throws NullPointerException if the filter is null
+ * @param filter the filter, must not be null.
+ * @throws NullPointerException if the filter is null.
*/
public NotFileFilter(final IOFileFilter filter) {
Objects.requireNonNull(filter, "filter");
@@ -54,8 +54,8 @@ public NotFileFilter(final IOFileFilter filter) {
/**
* Returns the logical NOT of the underlying filter's return value for the same File.
*
- * @param file the File to check
- * @return true if the filter returns false
+ * @param file the File to check.
+ * @return true if the filter returns false.
*/
@Override
public boolean accept(final File file) {
@@ -65,9 +65,9 @@ public boolean accept(final File file) {
/**
* Returns the logical NOT of the underlying filter's return value for the same arguments.
*
- * @param file the File directory
- * @param name the file name
- * @return true if the filter returns false
+ * @param file the File directory.
+ * @param name the file name.
+ * @return true if the filter returns false.
*/
@Override
public boolean accept(final File file, final String name) {
@@ -77,9 +77,9 @@ public boolean accept(final File file, final String name) {
/**
* Returns the logical NOT of the underlying filter's return value for the same File.
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the filter returns false
+ * @return true if the filter returns false.
* @since 2.9.0
*/
@Override
@@ -94,7 +94,7 @@ private FileVisitResult not(final FileVisitResult accept) {
/**
* Provide a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/OrFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/OrFileFilter.java
index 57b8bcf0560..4017ce8f070 100644
--- a/src/main/java/org/apache/commons/io/filefilter/OrFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/OrFileFilter.java
@@ -76,6 +76,7 @@ private OrFileFilter(final int initialCapacity) {
/**
* Constructs a new instance for the give filters.
+ *
* @param fileFilters filters to OR.
* @since 2.9.0
*/
@@ -87,9 +88,9 @@ public OrFileFilter(final IOFileFilter... fileFilters) {
/**
* Constructs a new file filter that ORs the result of other filters.
*
- * @param filter1 the first filter, must not be null
- * @param filter2 the second filter, must not be null
- * @throws IllegalArgumentException if either filter is null
+ * @param filter1 the first filter, must not be null.
+ * @param filter2 the second filter, must not be null.
+ * @throws IllegalArgumentException if either filter is null.
*/
public OrFileFilter(final IOFileFilter filter1, final IOFileFilter filter2) {
this(2);
@@ -177,7 +178,7 @@ public void setFileFilters(final List fileFilters) {
/**
* Provide a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/PrefixFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/PrefixFileFilter.java
index 3a85c9e8e18..a1db0ae1203 100644
--- a/src/main/java/org/apache/commons/io/filefilter/PrefixFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/PrefixFileFilter.java
@@ -83,9 +83,9 @@ public class PrefixFileFilter extends AbstractFileFilter implements Serializable
/**
* Constructs a new Prefix file filter for a list of prefixes.
*
- * @param prefixes the prefixes to allow, must not be null
- * @throws NullPointerException if the prefix list is null
- * @throws ClassCastException if the list does not contain Strings
+ * @param prefixes the prefixes to allow, must not be null.
+ * @throws NullPointerException if the prefix list is null.
+ * @throws ClassCastException if the list does not contain Strings.
*/
public PrefixFileFilter(final List prefixes) {
this(prefixes, IOCase.SENSITIVE);
@@ -95,10 +95,10 @@ public PrefixFileFilter(final List prefixes) {
* Constructs a new Prefix file filter for a list of prefixes
* specifying case-sensitivity.
*
- * @param prefixes the prefixes to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the prefix list is null
- * @throws ClassCastException if the list does not contain Strings
+ * @param prefixes the prefixes to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the prefix list is null.
+ * @throws ClassCastException if the list does not contain Strings.
* @since 1.4
*/
public PrefixFileFilter(final List prefixes, final IOCase ioCase) {
@@ -110,8 +110,8 @@ public PrefixFileFilter(final List prefixes, final IOCase ioCase) {
/**
* Constructs a new Prefix file filter for a single prefix.
*
- * @param prefix the prefix to allow, must not be null
- * @throws IllegalArgumentException if the prefix is null
+ * @param prefix the prefix to allow, must not be null.
+ * @throws IllegalArgumentException if the prefix is null.
*/
public PrefixFileFilter(final String prefix) {
this(prefix, IOCase.SENSITIVE);
@@ -124,8 +124,8 @@ public PrefixFileFilter(final String prefix) {
* instance. This would be inadvisable however.
*
*
- * @param prefixes the prefixes to allow, must not be null
- * @throws IllegalArgumentException if the prefix array is null
+ * @param prefixes the prefixes to allow, must not be null.
+ * @throws IllegalArgumentException if the prefix array is null.
*/
public PrefixFileFilter(final String... prefixes) {
this(prefixes, IOCase.SENSITIVE);
@@ -135,9 +135,9 @@ public PrefixFileFilter(final String... prefixes) {
* Constructs a new Prefix file filter for a single prefix
* specifying case-sensitivity.
*
- * @param prefix the prefix to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the prefix is null
+ * @param prefix the prefix to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws IllegalArgumentException if the prefix is null.
* @since 1.4
*/
public PrefixFileFilter(final String prefix, final IOCase ioCase) {
@@ -150,9 +150,9 @@ public PrefixFileFilter(final String prefix, final IOCase ioCase) {
* Constructs a new Prefix file filter for any of an array of prefixes
* specifying case-sensitivity.
*
- * @param prefixes the prefixes to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the prefix is null
+ * @param prefixes the prefixes to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws IllegalArgumentException if the prefix is null.
* @since 1.4
*/
public PrefixFileFilter(final String[] prefixes, final IOCase ioCase) {
@@ -164,8 +164,8 @@ public PrefixFileFilter(final String[] prefixes, final IOCase ioCase) {
/**
* Tests to see if the file name starts with the prefix.
*
- * @param file the File to check
- * @return true if the file name starts with one of our prefixes
+ * @param file the File to check.
+ * @return true if the file name starts with one of our prefixes.
*/
@Override
public boolean accept(final File file) {
@@ -175,9 +175,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the file name starts with the prefix.
*
- * @param file the File directory
- * @param name the file name
- * @return true if the file name starts with one of our prefixes
+ * @param file the File directory.
+ * @param name the file name.
+ * @return true if the file name starts with one of our prefixes.
*/
@Override
public boolean accept(final File file, final String name) {
@@ -187,9 +187,9 @@ public boolean accept(final File file, final String name) {
/**
* Tests to see if the file name starts with the prefix.
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file name starts with one of our prefixes
+ * @return true if the file name starts with one of our prefixes.
* @since 2.9.0
*/
@Override
@@ -204,7 +204,7 @@ private boolean accept(final String name) {
/**
* Provides a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/RegexFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/RegexFileFilter.java
index f044800692c..db699d9b912 100644
--- a/src/main/java/org/apache/commons/io/filefilter/RegexFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/RegexFileFilter.java
@@ -132,8 +132,8 @@ public RegexFileFilter(final Pattern pattern, final Function pathT
/**
* Constructs a new regular expression filter.
*
- * @param pattern regular string expression to match
- * @throws NullPointerException if the pattern is null
+ * @param pattern regular string expression to match.
+ * @throws NullPointerException if the pattern is null.
*/
public RegexFileFilter(final String pattern) {
this(pattern, 0);
@@ -142,9 +142,9 @@ public RegexFileFilter(final String pattern) {
/**
* Constructs a new regular expression filter with the specified flags.
*
- * @param pattern regular string expression to match
+ * @param pattern regular string expression to match.
* @param flags pattern flags - e.g. {@link Pattern#CASE_INSENSITIVE}
- * @throws IllegalArgumentException if the pattern is null
+ * @throws IllegalArgumentException if the pattern is null.
*/
public RegexFileFilter(final String pattern, final int flags) {
this(compile(pattern, flags));
@@ -153,9 +153,9 @@ public RegexFileFilter(final String pattern, final int flags) {
/**
* Constructs a new regular expression filter with the specified flags case sensitivity.
*
- * @param pattern regular string expression to match
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the pattern is null
+ * @param pattern regular string expression to match.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws IllegalArgumentException if the pattern is null.
*/
public RegexFileFilter(final String pattern, final IOCase ioCase) {
this(compile(pattern, toFlags(ioCase)));
@@ -164,9 +164,9 @@ public RegexFileFilter(final String pattern, final IOCase ioCase) {
/**
* Tests to see if the file name matches one of the regular expressions.
*
- * @param dir the file directory (ignored)
- * @param name the file name
- * @return true if the file name matches one of the regular expressions
+ * @param dir the file directory (ignored).
+ * @param name the file name.
+ * @return true if the file name matches one of the regular expressions.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -176,9 +176,9 @@ public boolean accept(final File dir, final String name) {
/**
* Tests to see if the file name matches one of the regular expressions.
*
- * @param path the path
+ * @param path the path.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file name matches one of the regular expressions
+ * @return true if the file name matches one of the regular expressions.
*/
@Override
public FileVisitResult accept(final Path path, final BasicFileAttributes attributes) {
diff --git a/src/main/java/org/apache/commons/io/filefilter/SizeFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/SizeFileFilter.java
index 24b0b57f939..185f47bf2ef 100644
--- a/src/main/java/org/apache/commons/io/filefilter/SizeFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/SizeFileFilter.java
@@ -82,8 +82,8 @@ public class SizeFileFilter extends AbstractFileFilter implements Serializable {
* Constructs a new size file filter for files equal to or
* larger than a certain size.
*
- * @param size the threshold size of the files
- * @throws IllegalArgumentException if the size is negative
+ * @param size the threshold size of the files.
+ * @throws IllegalArgumentException if the size is negative.
*/
public SizeFileFilter(final long size) {
this(size, true);
@@ -93,10 +93,10 @@ public SizeFileFilter(final long size) {
* Constructs a new size file filter for files based on a certain size
* threshold.
*
- * @param size the threshold size of the files
+ * @param size the threshold size of the files.
* @param acceptLarger if true, files equal to or larger are accepted,
- * otherwise smaller ones (but not equal to)
- * @throws IllegalArgumentException if the size is negative
+ * otherwise smaller ones (but not equal to).
+ * @throws IllegalArgumentException if the size is negative.
*/
public SizeFileFilter(final long size, final boolean acceptLarger) {
if (size < 0) {
@@ -115,8 +115,8 @@ public SizeFileFilter(final long size, final boolean acceptLarger) {
* file IS selected.
*
*
- * @param file the File to check
- * @return true if the file name matches
+ * @param file the File to check.
+ * @return true if the file name matches.
*/
@Override
public boolean accept(final File file) {
@@ -134,9 +134,9 @@ private boolean accept(final long length) {
* file IS selected.
*
*
- * @param file the File to check
+ * @param file the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file name matches
+ * @return true if the file name matches.
*/
@Override
public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) {
@@ -146,7 +146,7 @@ public FileVisitResult accept(final Path file, final BasicFileAttributes attribu
/**
* Provide a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/SuffixFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/SuffixFileFilter.java
index d375433495a..e4780baf704 100644
--- a/src/main/java/org/apache/commons/io/filefilter/SuffixFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/SuffixFileFilter.java
@@ -84,9 +84,9 @@ public class SuffixFileFilter extends AbstractFileFilter implements Serializable
/**
* Constructs a new Suffix file filter for a list of suffixes.
*
- * @param suffixes the suffixes to allow, must not be null
- * @throws IllegalArgumentException if the suffix list is null
- * @throws ClassCastException if the list does not contain Strings
+ * @param suffixes the suffixes to allow, must not be null.
+ * @throws IllegalArgumentException if the suffix list is null.
+ * @throws ClassCastException if the list does not contain Strings.
*/
public SuffixFileFilter(final List suffixes) {
this(suffixes, IOCase.SENSITIVE);
@@ -96,10 +96,10 @@ public SuffixFileFilter(final List suffixes) {
* Constructs a new Suffix file filter for a list of suffixes
* specifying case-sensitivity.
*
- * @param suffixes the suffixes to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the suffix list is null
- * @throws ClassCastException if the list does not contain Strings
+ * @param suffixes the suffixes to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws IllegalArgumentException if the suffix list is null.
+ * @throws ClassCastException if the list does not contain Strings.
* @since 1.4
*/
public SuffixFileFilter(final List suffixes, final IOCase ioCase) {
@@ -111,8 +111,8 @@ public SuffixFileFilter(final List suffixes, final IOCase ioCase) {
/**
* Constructs a new Suffix file filter for a single extension.
*
- * @param suffix the suffix to allow, must not be null
- * @throws IllegalArgumentException if the suffix is null
+ * @param suffix the suffix to allow, must not be null.
+ * @throws IllegalArgumentException if the suffix is null.
*/
public SuffixFileFilter(final String suffix) {
this(suffix, IOCase.SENSITIVE);
@@ -125,8 +125,8 @@ public SuffixFileFilter(final String suffix) {
* instance. This would be inadvisable however.
*
*
- * @param suffixes the suffixes to allow, must not be null
- * @throws NullPointerException if the suffix array is null
+ * @param suffixes the suffixes to allow, must not be null.
+ * @throws NullPointerException if the suffix array is null.
*/
public SuffixFileFilter(final String... suffixes) {
this(suffixes, IOCase.SENSITIVE);
@@ -136,9 +136,9 @@ public SuffixFileFilter(final String... suffixes) {
* Constructs a new Suffix file filter for a single extension
* specifying case-sensitivity.
*
- * @param suffix the suffix to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the suffix is null
+ * @param suffix the suffix to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the suffix is null.
* @since 1.4
*/
public SuffixFileFilter(final String suffix, final IOCase ioCase) {
@@ -151,9 +151,9 @@ public SuffixFileFilter(final String suffix, final IOCase ioCase) {
* Constructs a new Suffix file filter for an array of suffixes
* specifying case-sensitivity.
*
- * @param suffixes the suffixes to allow, must not be null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the suffix array is null
+ * @param suffixes the suffixes to allow, must not be null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the suffix array is null.
* @since 1.4
*/
public SuffixFileFilter(final String[] suffixes, final IOCase ioCase) {
@@ -165,8 +165,8 @@ public SuffixFileFilter(final String[] suffixes, final IOCase ioCase) {
/**
* Tests to see if the file name ends with the suffix.
*
- * @param file the File to check
- * @return true if the file name ends with one of our suffixes
+ * @param file the File to check.
+ * @return true if the file name ends with one of our suffixes.
*/
@Override
public boolean accept(final File file) {
@@ -176,9 +176,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the file name ends with the suffix.
*
- * @param file the File directory
- * @param name the file name
- * @return true if the file name ends with one of our suffixes
+ * @param file the File directory.
+ * @param name the file name.
+ * @return true if the file name ends with one of our suffixes.
*/
@Override
public boolean accept(final File file, final String name) {
@@ -188,9 +188,9 @@ public boolean accept(final File file, final String name) {
/**
* Tests to see if the file name ends with the suffix.
*
- * @param path the File to check
+ * @param path the File to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file name ends with one of our suffixes
+ * @return true if the file name ends with one of our suffixes.
* @since 2.9.0
*/
@Override
@@ -205,7 +205,7 @@ private boolean accept(final String name) {
/**
* Provides a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilter.java
index 5c0d85a79a7..3869b0bcda5 100644
--- a/src/main/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/SymbolicLinkFileFilter.java
@@ -107,7 +107,7 @@ public SymbolicLinkFileFilter(final FileVisitResult onAccept, final FileVisitRes
/**
* Tests to see if the file is a symbolic link.
*
- * @param file the File to check
+ * @param file the File to check.
* @return true if the file exists and is a symbolic link to either another file or a directory,
* false otherwise.
*/
@@ -119,7 +119,7 @@ public boolean accept(final File file) {
/**
* Tests to see if the file is a symbolic link.
*
- * @param path the File Path to check
+ * @param path the File Path to check.
* @param attributes the path's basic attributes (may be null).
* @return {@code onAccept} from {@link #SymbolicLinkFileFilter(FileVisitResult, FileVisitResult)} if the file exists and is a symbolic link to either
* another file or a directory; returns {@code onReject} otherwise.
@@ -136,7 +136,7 @@ public FileVisitResult accept(final Path path, final BasicFileAttributes attribu
* test for why.)
*
*
- * @param filePath The filePath to test
+ * @param filePath The filePath to test.
* @return true if the file exists and is a symbolic link to either a file or directory, false otherwise.
*/
boolean isSymbolicLink(final Path filePath) {
diff --git a/src/main/java/org/apache/commons/io/filefilter/TrueFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/TrueFileFilter.java
index 70e27da55dc..9552e27a545 100644
--- a/src/main/java/org/apache/commons/io/filefilter/TrueFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/TrueFileFilter.java
@@ -60,8 +60,8 @@ protected TrueFileFilter() {
/**
* Returns true.
*
- * @param file the file to check (ignored)
- * @return true
+ * @param file the file to check (ignored).
+ * @return true.
*/
@Override
public boolean accept(final File file) {
@@ -71,9 +71,9 @@ public boolean accept(final File file) {
/**
* Returns true.
*
- * @param dir the directory to check (ignored)
- * @param name the file name (ignored)
- * @return true
+ * @param dir the directory to check (ignored).
+ * @param name the file name (ignored).
+ * @return true.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -83,9 +83,9 @@ public boolean accept(final File dir, final String name) {
/**
* Returns true.
*
- * @param file the file to check (ignored)
+ * @param file the file to check (ignored).
* @param attributes the path's basic attributes (may be null).
- * @return true
+ * @return true.
* @since 2.9.0
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/filefilter/WildcardFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/WildcardFileFilter.java
index 72a01c3789e..7e895e254e1 100644
--- a/src/main/java/org/apache/commons/io/filefilter/WildcardFileFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/WildcardFileFilter.java
@@ -174,9 +174,9 @@ private WildcardFileFilter(final Builder builder) {
/**
* Constructs a new wildcard filter for an array of wildcards specifying case-sensitivity.
*
- * @param wildcards the array of wildcards to match, not null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the pattern array is null
+ * @param wildcards the array of wildcards to match, not null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the pattern array is null.
*/
private WildcardFileFilter(final IOCase ioCase, final String... wildcards) {
this.wildcards = requireWildcards(wildcards).clone();
@@ -186,10 +186,10 @@ private WildcardFileFilter(final IOCase ioCase, final String... wildcards) {
/**
* Constructs a new case-sensitive wildcard filter for a list of wildcards.
*
- * @param wildcards the list of wildcards to match, not null
- * @throws IllegalArgumentException if the pattern list is null
- * @throws ClassCastException if the list does not contain Strings
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param wildcards the list of wildcards to match, not null.
+ * @throws IllegalArgumentException if the pattern list is null.
+ * @throws ClassCastException if the list does not contain Strings.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
public WildcardFileFilter(final List wildcards) {
@@ -199,11 +199,11 @@ public WildcardFileFilter(final List wildcards) {
/**
* Constructs a new wildcard filter for a list of wildcards specifying case-sensitivity.
*
- * @param wildcards the list of wildcards to match, not null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws IllegalArgumentException if the pattern list is null
- * @throws ClassCastException if the list does not contain Strings
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param wildcards the list of wildcards to match, not null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws IllegalArgumentException if the pattern list is null.
+ * @throws ClassCastException if the list does not contain Strings.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
public WildcardFileFilter(final List wildcards, final IOCase ioCase) {
@@ -213,9 +213,9 @@ public WildcardFileFilter(final List wildcards, final IOCase ioCase) {
/**
* Constructs a new case-sensitive wildcard filter for a single wildcard.
*
- * @param wildcard the wildcard to match
- * @throws IllegalArgumentException if the pattern is null
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param wildcard the wildcard to match.
+ * @throws IllegalArgumentException if the pattern is null.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
public WildcardFileFilter(final String wildcard) {
@@ -225,9 +225,9 @@ public WildcardFileFilter(final String wildcard) {
/**
* Constructs a new case-sensitive wildcard filter for an array of wildcards.
*
- * @param wildcards the array of wildcards to match
- * @throws NullPointerException if the pattern array is null
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param wildcards the array of wildcards to match.
+ * @throws NullPointerException if the pattern array is null.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
public WildcardFileFilter(final String... wildcards) {
@@ -237,10 +237,10 @@ public WildcardFileFilter(final String... wildcards) {
/**
* Constructs a new wildcard filter for a single wildcard specifying case-sensitivity.
*
- * @param wildcard the wildcard to match, not null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the pattern is null
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param wildcard the wildcard to match, not null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the pattern is null.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
public WildcardFileFilter(final String wildcard, final IOCase ioCase) {
@@ -250,10 +250,10 @@ public WildcardFileFilter(final String wildcard, final IOCase ioCase) {
/**
* Constructs a new wildcard filter for an array of wildcards specifying case-sensitivity.
*
- * @param wildcards the array of wildcards to match, not null
- * @param ioCase how to handle case sensitivity, null means case-sensitive
- * @throws NullPointerException if the pattern array is null
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param wildcards the array of wildcards to match, not null.
+ * @param ioCase how to handle case sensitivity, null means case-sensitive.
+ * @throws NullPointerException if the pattern array is null.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
public WildcardFileFilter(final String[] wildcards, final IOCase ioCase) {
@@ -263,8 +263,8 @@ public WildcardFileFilter(final String[] wildcards, final IOCase ioCase) {
/**
* Tests to see if the file name matches one of the wildcards.
*
- * @param file the file to check
- * @return true if the file name matches one of the wildcards
+ * @param file the file to check.
+ * @return true if the file name matches one of the wildcards.
*/
@Override
public boolean accept(final File file) {
@@ -274,9 +274,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the file name matches one of the wildcards.
*
- * @param dir the file directory (ignored)
- * @param name the file name
- * @return true if the file name matches one of the wildcards
+ * @param dir the file directory (ignored).
+ * @param name the file name.
+ * @return true if the file name matches one of the wildcards.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -286,7 +286,7 @@ public boolean accept(final File dir, final String name) {
/**
* Tests to see if the file name matches one of the wildcards.
*
- * @param path the file to check
+ * @param path the file to check.
* @param attributes the path's basic attributes (may be null).
* @return true if the file name matches one of the wildcards.
* @since 2.9.0
@@ -303,7 +303,7 @@ private boolean accept(final String name) {
/**
* Provide a String representation of this file filter.
*
- * @return a String representation
+ * @return a String representation.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/filefilter/WildcardFilter.java b/src/main/java/org/apache/commons/io/filefilter/WildcardFilter.java
index e435101fbd4..a28cd56c634 100644
--- a/src/main/java/org/apache/commons/io/filefilter/WildcardFilter.java
+++ b/src/main/java/org/apache/commons/io/filefilter/WildcardFilter.java
@@ -93,9 +93,9 @@ public class WildcardFilter extends AbstractFileFilter implements Serializable {
/**
* Constructs a new case-sensitive wildcard filter for a list of wildcards.
*
- * @param wildcards the list of wildcards to match
- * @throws NullPointerException if the pattern list is null
- * @throws ClassCastException if the list does not contain Strings
+ * @param wildcards the list of wildcards to match.
+ * @throws NullPointerException if the pattern list is null.
+ * @throws ClassCastException if the list does not contain Strings.
*/
public WildcardFilter(final List wildcards) {
Objects.requireNonNull(wildcards, "wildcards");
@@ -105,8 +105,8 @@ public WildcardFilter(final List wildcards) {
/**
* Constructs a new case-sensitive wildcard filter for a single wildcard.
*
- * @param wildcard the wildcard to match
- * @throws NullPointerException if the pattern is null
+ * @param wildcard the wildcard to match.
+ * @throws NullPointerException if the pattern is null.
*/
public WildcardFilter(final String wildcard) {
Objects.requireNonNull(wildcard, "wildcard");
@@ -116,8 +116,8 @@ public WildcardFilter(final String wildcard) {
/**
* Constructs a new case-sensitive wildcard filter for an array of wildcards.
*
- * @param wildcards the array of wildcards to match
- * @throws NullPointerException if the pattern array is null
+ * @param wildcards the array of wildcards to match.
+ * @throws NullPointerException if the pattern array is null.
*/
public WildcardFilter(final String... wildcards) {
Objects.requireNonNull(wildcards, "wildcards");
@@ -127,8 +127,8 @@ public WildcardFilter(final String... wildcards) {
/**
* Tests to see if the file name matches one of the wildcards.
*
- * @param file the file to check
- * @return true if the file name matches one of the wildcards
+ * @param file the file to check.
+ * @return true if the file name matches one of the wildcards.
*/
@Override
public boolean accept(final File file) {
@@ -141,9 +141,9 @@ public boolean accept(final File file) {
/**
* Tests to see if the file name matches one of the wildcards.
*
- * @param dir the file directory
- * @param name the file name
- * @return true if the file name matches one of the wildcards
+ * @param dir the file directory.
+ * @param name the file name.
+ * @return true if the file name matches one of the wildcards.
*/
@Override
public boolean accept(final File dir, final String name) {
@@ -156,9 +156,9 @@ public boolean accept(final File dir, final String name) {
/**
* Tests to see if the file name matches one of the wildcards.
*
- * @param path the file to check
+ * @param path the file to check.
* @param attributes the path's basic attributes (may be null).
- * @return true if the file name matches one of the wildcards
+ * @return true if the file name matches one of the wildcards.
* @since 2.9.0
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/function/IOBiConsumer.java b/src/main/java/org/apache/commons/io/function/IOBiConsumer.java
index a8e1bdf397d..ec217eafa0a 100644
--- a/src/main/java/org/apache/commons/io/function/IOBiConsumer.java
+++ b/src/main/java/org/apache/commons/io/function/IOBiConsumer.java
@@ -25,8 +25,8 @@
/**
* Like {@link BiConsumer} but throws {@link IOException}.
*
- * @param the type of the first argument to the operation
- * @param the type of the second argument to the operation
+ * @param the type of the first argument to the operation.
+ * @param the type of the second argument to the operation.
* @see BiConsumer
* @since 2.12.0
*/
@@ -36,8 +36,8 @@ public interface IOBiConsumer {
/**
* Returns the no-op singleton.
*
- * @param the type of the first argument to the operation
- * @param the type of the second argument to the operation
+ * @param the type of the first argument to the operation.
+ * @param the type of the second argument to the operation.
* @return The no-op singleton.
*/
@SuppressWarnings("unchecked")
@@ -48,8 +48,8 @@ static IOBiConsumer noop() {
/**
* Performs this operation on the given arguments.
*
- * @param t the first input argument
- * @param u the second input argument
+ * @param t the first input argument.
+ * @param u the second input argument.
* @throws IOException if an I/O error occurs.
*/
void accept(T t, U u) throws IOException;
@@ -59,10 +59,10 @@ static IOBiConsumer noop() {
* operation. If performing either operation throws an exception, it is relayed to the caller of the composed operation.
* If performing this operation throws an exception, the {@code after} operation will not be performed.
*
- * @param after the operation to perform after this operation
+ * @param after the operation to perform after this operation.
* @return a composed {@link IOBiConsumer} that performs in sequence this operation followed by the {@code after}
- * operation
- * @throws NullPointerException if {@code after} is null
+ * operation.
+ * @throws NullPointerException if {@code after} is null.
*/
default IOBiConsumer andThen(final IOBiConsumer super T, ? super U> after) {
Objects.requireNonNull(after);
diff --git a/src/main/java/org/apache/commons/io/function/IOBiFunction.java b/src/main/java/org/apache/commons/io/function/IOBiFunction.java
index a72b73f3581..fa5bd4c5db1 100644
--- a/src/main/java/org/apache/commons/io/function/IOBiFunction.java
+++ b/src/main/java/org/apache/commons/io/function/IOBiFunction.java
@@ -30,9 +30,9 @@
* {@link #apply(Object, Object)}.
*
*
- * @param the type of the first argument to the function
- * @param the type of the second argument to the function
- * @param the type of the result of the function
+ * @param the type of the first argument to the function.
+ * @param the type of the second argument to the function.
+ * @param the type of the result of the function.
* @see BiFunction
* @since 2.12.0
*/
@@ -44,10 +44,10 @@ public interface IOBiFunction {
* function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
* composed function.
*
- * @param the type of output of the {@code after} function, and of the composed function
- * @param after the function to apply after this function is applied
- * @return a composed function that first applies this function and then applies the {@code after} function
- * @throws NullPointerException if after is null
+ * @param the type of output of the {@code after} function, and of the composed function.
+ * @param after the function to apply after this function is applied.
+ * @return a composed function that first applies this function and then applies the {@code after} function.
+ * @throws NullPointerException if after is null.
*/
default IOBiFunction andThen(final IOFunction super R, ? extends V> after) {
Objects.requireNonNull(after);
@@ -57,9 +57,9 @@ default IOBiFunction andThen(final IOFunction super R, ? extends
/**
* Applies this function to the given arguments.
*
- * @param t the first function argument
- * @param u the second function argument
- * @return the function result
+ * @param t the first function argument.
+ * @param u the second function argument.
+ * @return the function result.
* @throws IOException if an I/O error occurs.
*/
R apply(T t, U u) throws IOException;
diff --git a/src/main/java/org/apache/commons/io/function/IOBinaryOperator.java b/src/main/java/org/apache/commons/io/function/IOBinaryOperator.java
index d3be4218177..6d7c70efed2 100644
--- a/src/main/java/org/apache/commons/io/function/IOBinaryOperator.java
+++ b/src/main/java/org/apache/commons/io/function/IOBinaryOperator.java
@@ -37,11 +37,11 @@ public interface IOBinaryOperator extends IOBiFunction {
* Creates a {@link IOBinaryOperator} which returns the greater of two elements according to the specified
* {@code Comparator}.
*
- * @param the type of the input arguments of the comparator
- * @param comparator a {@code Comparator} for comparing the two values
+ * @param the type of the input arguments of the comparator.
+ * @param comparator a {@code Comparator} for comparing the two values.
* @return a {@code BinaryOperator} which returns the greater of its operands, according to the supplied
* {@code Comparator}
- * @throws NullPointerException if the argument is null
+ * @throws NullPointerException if the argument is null.
*/
static IOBinaryOperator maxBy(final IOComparator super T> comparator) {
Objects.requireNonNull(comparator);
@@ -52,11 +52,11 @@ static IOBinaryOperator maxBy(final IOComparator super T> comparator) {
* Creates a {@link IOBinaryOperator} which returns the lesser of two elements according to the specified
* {@code Comparator}.
*
- * @param the type of the input arguments of the comparator
- * @param comparator a {@code Comparator} for comparing the two values
+ * @param the type of the input arguments of the comparator.
+ * @param comparator a {@code Comparator} for comparing the two values.
* @return a {@code BinaryOperator} which returns the lesser of its operands, according to the supplied
* {@code Comparator}
- * @throws NullPointerException if the argument is null
+ * @throws NullPointerException if the argument is null.
*/
static IOBinaryOperator minBy(final IOComparator super T> comparator) {
Objects.requireNonNull(comparator);
diff --git a/src/main/java/org/apache/commons/io/function/IOBooleanSupplier.java b/src/main/java/org/apache/commons/io/function/IOBooleanSupplier.java
index 0b8b1dcfd8b..f82f40adb8e 100644
--- a/src/main/java/org/apache/commons/io/function/IOBooleanSupplier.java
+++ b/src/main/java/org/apache/commons/io/function/IOBooleanSupplier.java
@@ -42,7 +42,7 @@ default BooleanSupplier asBooleanSupplier() {
/**
* Gets a result.
*
- * @return a result
+ * @return a result.
* @throws IOException if an I/O error occurs.
*/
boolean getAsBoolean() throws IOException;
diff --git a/src/main/java/org/apache/commons/io/function/IOComparator.java b/src/main/java/org/apache/commons/io/function/IOComparator.java
index eb31ef818ef..4d8e891eaa0 100644
--- a/src/main/java/org/apache/commons/io/function/IOComparator.java
+++ b/src/main/java/org/apache/commons/io/function/IOComparator.java
@@ -24,7 +24,7 @@
/**
* Like {@link Comparator} but throws {@link IOException}.
*
- * @param the type of objects that may be compared by this comparator
+ * @param the type of objects that may be compared by this comparator.
* @see Comparator
* @since 2.12.0
*/
@@ -48,7 +48,7 @@ default Comparator asComparator() {
* @param o2 the second object to be compared.
* @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than
* the second.
- * @throws NullPointerException if an argument is null and this comparator does not permit null arguments
+ * @throws NullPointerException if an argument is null and this comparator does not permit null arguments.
* @throws ClassCastException if the arguments' types prevent them from being compared by this comparator.
* @throws IOException if an I/O error occurs.
*/
diff --git a/src/main/java/org/apache/commons/io/function/IOConsumer.java b/src/main/java/org/apache/commons/io/function/IOConsumer.java
index 016b643f95f..ba85becc6f9 100644
--- a/src/main/java/org/apache/commons/io/function/IOConsumer.java
+++ b/src/main/java/org/apache/commons/io/function/IOConsumer.java
@@ -42,6 +42,21 @@ public interface IOConsumer {
// noop
};
+ /**
+ * Applies the given {@link IOConsumer} action to the object if the consumer is not {@code null}. Otherwise, does nothing.
+ *
+ * @param consumer the consumer to consume.
+ * @param object the object to be consumed.
+ * @param the type of the argument the consumer accepts.
+ * @throws IOException Thrown when the consumer fails.
+ * @since 2.23.0
+ */
+ static void accept(final IOConsumer consumer, final T object) throws IOException {
+ if (consumer != null) {
+ consumer.accept(object);
+ }
+ }
+
/**
* Performs an action for each element of the collection gathering any exceptions.
*
@@ -136,7 +151,7 @@ static IOConsumer noop() {
/**
* Performs this operation on the given argument.
*
- * @param t the input argument
+ * @param t the input argument.
* @throws IOException if an I/O error occurs.
*/
void accept(T t) throws IOException;
@@ -146,9 +161,9 @@ static IOConsumer noop() {
* operation. If performing either operation throws an exception, it is relayed to the caller of the composed operation.
* If performing this operation throws an exception, the {@code after} operation will not be performed.
*
- * @param after the operation to perform after this operation
- * @return a composed {@link Consumer} that performs in sequence this operation followed by the {@code after} operation
- * @throws NullPointerException if {@code after} is null
+ * @param after the operation to perform after this operation.
+ * @return a composed {@link Consumer} that performs in sequence this operation followed by the {@code after} operation.
+ * @throws NullPointerException if {@code after} is null.
*/
default IOConsumer andThen(final IOConsumer super T> after) {
Objects.requireNonNull(after, "after");
diff --git a/src/main/java/org/apache/commons/io/function/IOFunction.java b/src/main/java/org/apache/commons/io/function/IOFunction.java
index 07e9d539a99..92f1335fbb6 100644
--- a/src/main/java/org/apache/commons/io/function/IOFunction.java
+++ b/src/main/java/org/apache/commons/io/function/IOFunction.java
@@ -37,8 +37,8 @@ public interface IOFunction {
/**
* Returns a {@link IOFunction} that always returns its input argument.
*
- * @param the type of the input and output objects to the function
- * @return a function that always returns its input argument
+ * @param the type of the input and output objects to the function.
+ * @return a function that always returns its input argument.
*/
@SuppressWarnings("unchecked")
static IOFunction identity() {
@@ -50,9 +50,9 @@ static IOFunction identity() {
* {@code after} consumer to the result. If evaluation of either function throws an exception, it is relayed to the
* caller of the composed function.
*
- * @param after the consumer to apply after this function is applied
- * @return a composed function that first applies this function and then applies the {@code after} consumer
- * @throws NullPointerException if after is null
+ * @param after the consumer to apply after this function is applied.
+ * @return a composed function that first applies this function and then applies the {@code after} consumer.
+ * @throws NullPointerException if after is null.
* @see #compose(IOFunction)
*/
default IOConsumer andThen(final Consumer super R> after) {
@@ -65,10 +65,10 @@ default IOConsumer andThen(final Consumer super R> after) {
* {@code after} function to the result. If evaluation of either function throws an exception, it is relayed to the
* caller of the composed function.
*
- * @param the type of output of the {@code after} function, and of the composed function
- * @param after the function to apply after this function is applied
- * @return a composed function that first applies this function and then applies the {@code after} function
- * @throws NullPointerException if after is null
+ * @param the type of output of the {@code after} function, and of the composed function.
+ * @param after the function to apply after this function is applied.
+ * @return a composed function that first applies this function and then applies the {@code after} function.
+ * @throws NullPointerException if after is null.
* @see #compose(IOFunction)
*/
default IOFunction andThen(final Function super R, ? extends V> after) {
@@ -81,9 +81,9 @@ default IOFunction andThen(final Function super R, ? extends V> afte
* {@code after} consumer to the result. If evaluation of either function throws an exception, it is relayed to the
* caller of the composed function.
*
- * @param after the consumer to apply after this function is applied
- * @return a composed function that first applies this function and then applies the {@code after} consumer
- * @throws NullPointerException if after is null
+ * @param after the consumer to apply after this function is applied.
+ * @return a composed function that first applies this function and then applies the {@code after} consumer.
+ * @throws NullPointerException if after is null.
* @see #compose(IOFunction)
*/
default IOConsumer andThen(final IOConsumer super R> after) {
@@ -96,10 +96,10 @@ default IOConsumer andThen(final IOConsumer super R> after) {
* {@code after} function to the result. If evaluation of either function throws an exception, it is relayed to the
* caller of the composed function.
*
- * @param the type of output of the {@code after} function, and of the composed function
- * @param after the function to apply after this function is applied
- * @return a composed function that first applies this function and then applies the {@code after} function
- * @throws NullPointerException if after is null
+ * @param the type of output of the {@code after} function, and of the composed function.
+ * @param after the function to apply after this function is applied.
+ * @return a composed function that first applies this function and then applies the {@code after} function.
+ * @throws NullPointerException if after is null.
* @see #compose(IOFunction)
*/
default IOFunction andThen(final IOFunction super R, ? extends V> after) {
@@ -110,8 +110,8 @@ default IOFunction andThen(final IOFunction super R, ? extends V> af
/**
* Applies this function to the given argument.
*
- * @param t the function argument
- * @return the function result
+ * @param t the function argument.
+ * @return the function result.
* @throws IOException if an I/O error occurs.
*/
R apply(T t) throws IOException;
@@ -131,10 +131,10 @@ default Function asFunction() {
* this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
* composed function.
*
- * @param the type of input to the {@code before} function, and to the composed function
- * @param before the function to apply before this function is applied
- * @return a composed function that first applies the {@code before} function and then applies this function
- * @throws NullPointerException if before is null
+ * @param the type of input to the {@code before} function, and to the composed function.
+ * @param before the function to apply before this function is applied.
+ * @return a composed function that first applies the {@code before} function and then applies this function.
+ * @throws NullPointerException if before is null.
* @see #andThen(IOFunction)
*/
default IOFunction compose(final Function super V, ? extends T> before) {
@@ -147,10 +147,10 @@ default IOFunction compose(final Function super V, ? extends T> befo
* this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
* composed function.
*
- * @param the type of input to the {@code before} function, and to the composed function
- * @param before the function to apply before this function is applied
- * @return a composed function that first applies the {@code before} function and then applies this function
- * @throws NullPointerException if before is null
+ * @param the type of input to the {@code before} function, and to the composed function.
+ * @param before the function to apply before this function is applied.
+ * @return a composed function that first applies the {@code before} function and then applies this function.
+ * @throws NullPointerException if before is null.
* @see #andThen(IOFunction)
*/
default IOFunction compose(final IOFunction super V, ? extends T> before) {
@@ -163,9 +163,9 @@ default IOFunction compose(final IOFunction super V, ? extends T> be
* this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
* composed function.
*
- * @param before the supplier which feeds the application of this function
- * @return a composed function that first applies the {@code before} function and then applies this function
- * @throws NullPointerException if before is null
+ * @param before the supplier which feeds the application of this function.
+ * @return a composed function that first applies the {@code before} function and then applies this function.
+ * @throws NullPointerException if before is null.
* @see #andThen(IOFunction)
*/
default IOSupplier compose(final IOSupplier extends T> before) {
@@ -178,9 +178,9 @@ default IOSupplier compose(final IOSupplier extends T> before) {
* this function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
* composed function.
*
- * @param before the supplier which feeds the application of this function
- * @return a composed function that first applies the {@code before} function and then applies this function
- * @throws NullPointerException if before is null
+ * @param before the supplier which feeds the application of this function.
+ * @return a composed function that first applies the {@code before} function and then applies this function.
+ * @throws NullPointerException if before is null.
* @see #andThen(IOFunction)
*/
default IOSupplier compose(final Supplier extends T> before) {
diff --git a/src/main/java/org/apache/commons/io/function/IOIntConsumer.java b/src/main/java/org/apache/commons/io/function/IOIntConsumer.java
index 9c45b29a011..8f81eff6342 100644
--- a/src/main/java/org/apache/commons/io/function/IOIntConsumer.java
+++ b/src/main/java/org/apache/commons/io/function/IOIntConsumer.java
@@ -41,7 +41,7 @@ public interface IOIntConsumer {
/**
* Performs this operation on the given argument.
*
- * @param value the input argument
+ * @param value the input argument.
* @throws IOException if an I/O error occurs.
*/
void accept(int value) throws IOException;
@@ -51,9 +51,9 @@ public interface IOIntConsumer {
* operation throws an exception, it is relayed to the caller of the composed operation. If performing this operation throws an exception, the {@code after}
* operation will not be performed.
*
- * @param after the operation to perform after this operation
- * @return a composed {@code IOIntConsumer} that performs in sequence this operation followed by the {@code after} operation
- * @throws NullPointerException if {@code after} is null
+ * @param after the operation to perform after this operation.
+ * @return a composed {@code IOIntConsumer} that performs in sequence this operation followed by the {@code after} operation.
+ * @throws NullPointerException if {@code after} is null.
*/
default IOIntConsumer andThen(final IOIntConsumer after) {
Objects.requireNonNull(after);
diff --git a/src/main/java/org/apache/commons/io/function/IOIntSupplier.java b/src/main/java/org/apache/commons/io/function/IOIntSupplier.java
index 02e770cc3a3..058763d0a18 100644
--- a/src/main/java/org/apache/commons/io/function/IOIntSupplier.java
+++ b/src/main/java/org/apache/commons/io/function/IOIntSupplier.java
@@ -42,7 +42,7 @@ default IntSupplier asIntSupplier() {
/**
* Gets a result.
*
- * @return a result
+ * @return a result.
* @throws IOException if an I/O error occurs.
*/
int getAsInt() throws IOException;
diff --git a/src/main/java/org/apache/commons/io/function/IOIterable.java b/src/main/java/org/apache/commons/io/function/IOIterable.java
index 238040d1d65..dd656dff7dd 100644
--- a/src/main/java/org/apache/commons/io/function/IOIterable.java
+++ b/src/main/java/org/apache/commons/io/function/IOIterable.java
@@ -44,8 +44,8 @@ default Iterable asIterable() {
* Like {@link Iterable#iterator()}.
*
* @param action The action to be performed for each element.
- * @throws NullPointerException if the specified action is null.
- * @throws IOException thrown by the given action.
+ * @throws NullPointerException Thrown if the specified action is null.
+ * @throws IOException Thrown if an I/O error occurs for a remaining element, or the given action throws.
* @see Iterable#iterator()
*/
default void forEach(final IOConsumer super T> action) throws IOException {
@@ -75,6 +75,7 @@ default IOSpliterator spliterator() {
*
* Implementations may not have anything to unwrap and that behavior is undefined for now.
*
+ *
* @return the underlying Iterable.
*/
Iterable unwrap();
diff --git a/src/main/java/org/apache/commons/io/function/IOIterator.java b/src/main/java/org/apache/commons/io/function/IOIterator.java
index 42cc235fc39..85727a6e431 100644
--- a/src/main/java/org/apache/commons/io/function/IOIterator.java
+++ b/src/main/java/org/apache/commons/io/function/IOIterator.java
@@ -36,8 +36,8 @@ public interface IOIterator {
* Adapts the given Iterable as an IOIterator.
*
* @param the type of the stream elements.
- * @param iterable The iterable to adapt
- * @return A new IOIterator
+ * @param iterable The iterable to adapt.
+ * @return A new IOIterator.
* @since 2.17.0
*/
static IOIterator adapt(final Iterable iterable) {
@@ -48,8 +48,8 @@ static IOIterator adapt(final Iterable iterable) {
* Adapts the given Iterator as an IOIterator.
*
* @param the type of the stream elements.
- * @param iterator The iterator to adapt
- * @return A new IOIterator
+ * @param iterator The iterator to adapt.
+ * @return A new IOIterator.
*/
static IOIterator adapt(final Iterator iterator) {
return IOIteratorAdapter.adapt(iterator);
@@ -91,7 +91,7 @@ default void forEachRemaining(final IOConsumer super E> action) throws IOExcep
*
* @return See delegate.
* @throws IOException if an I/O error occurs.
- * @throws NoSuchElementException if the iteration has no more elements
+ * @throws NoSuchElementException if the iteration has no more elements.
*/
E next() throws IOException;
@@ -110,6 +110,7 @@ default void remove() throws IOException {
*
* Implementations may not have anything to unwrap and that behavior is undefined for now.
*
+ *
* @return the underlying Iterator.
*/
Iterator unwrap();
diff --git a/src/main/java/org/apache/commons/io/function/IOLongSupplier.java b/src/main/java/org/apache/commons/io/function/IOLongSupplier.java
index 8e90866273c..707d3b548a5 100644
--- a/src/main/java/org/apache/commons/io/function/IOLongSupplier.java
+++ b/src/main/java/org/apache/commons/io/function/IOLongSupplier.java
@@ -42,7 +42,7 @@ default LongSupplier asSupplier() {
/**
* Gets a result.
*
- * @return a result
+ * @return a result.
* @throws IOException if an I/O error occurs.
*/
long getAsLong() throws IOException;
diff --git a/src/main/java/org/apache/commons/io/function/IOPredicate.java b/src/main/java/org/apache/commons/io/function/IOPredicate.java
index fda3fddb6be..6186d85b4e5 100644
--- a/src/main/java/org/apache/commons/io/function/IOPredicate.java
+++ b/src/main/java/org/apache/commons/io/function/IOPredicate.java
@@ -25,7 +25,7 @@
/**
* Like {@link Predicate} but throws {@link IOException}.
*
- * @param the type of the input to the predicate
+ * @param the type of the input to the predicate.
* @since 2.12.0
*/
@FunctionalInterface
@@ -34,7 +34,7 @@ public interface IOPredicate {
/**
* Always false.
*
- * @param the type of the input to the predicate
+ * @param the type of the input to the predicate.
* @return a constant predicate that tests always false.
*/
@SuppressWarnings("unchecked")
@@ -45,7 +45,7 @@ static IOPredicate alwaysFalse() {
/**
* Always true.
*
- * @param the type of the input to the predicate
+ * @param the type of the input to the predicate.
* @return a constant predicate that tests always true.
*/
@SuppressWarnings("unchecked")
@@ -56,7 +56,7 @@ static IOPredicate alwaysTrue() {
/**
* Creates a predicate that tests if two arguments are equal using {@link Objects#equals(Object, Object)}.
*
- * @param the type of arguments to the predicate
+ * @param the type of arguments to the predicate.
* @param target the object to compare for equality, may be {@code null}
* @return a predicate that tests if two arguments are equal using {@link Objects#equals(Object, Object)}
*/
@@ -74,10 +74,10 @@ static IOPredicate isEqual(final Object target) {
* predicate throws an exception, the {@code other} predicate will not be evaluated.
*
*
- * @param other a predicate that will be logically-ANDed with this predicate
+ * @param other a predicate that will be logically-ANDed with this predicate.
* @return a composed predicate that represents the short-circuiting logical AND of this predicate and the {@code other}
- * predicate
- * @throws NullPointerException if other is null
+ * predicate.
+ * @throws NullPointerException if other is null.
*/
default IOPredicate and(final IOPredicate super T> other) {
Objects.requireNonNull(other);
@@ -97,7 +97,7 @@ default Predicate asPredicate() {
/**
* Creates a predicate that represents the logical negation of this predicate.
*
- * @return a predicate that represents the logical negation of this predicate
+ * @return a predicate that represents the logical negation of this predicate.
*/
default IOPredicate negate() {
return t -> !test(t);
@@ -113,10 +113,10 @@ default IOPredicate negate() {
* predicate throws an exception, the {@code other} predicate will not be evaluated.
*
*
- * @param other a predicate that will be logically-ORed with this predicate
+ * @param other a predicate that will be logically-ORed with this predicate.
* @return a composed predicate that represents the short-circuiting logical OR of this predicate and the {@code other}
- * predicate
- * @throws NullPointerException if other is null
+ * predicate.
+ * @throws NullPointerException if other is null.
*/
default IOPredicate or(final IOPredicate super T> other) {
Objects.requireNonNull(other);
@@ -126,7 +126,7 @@ default IOPredicate or(final IOPredicate super T> other) {
/**
* Evaluates this predicate on the given argument.
*
- * @param t the input argument
+ * @param t the input argument.
* @return {@code true} if the input argument matches the predicate, otherwise {@code false}
* @throws IOException if an I/O error occurs.
*/
diff --git a/src/main/java/org/apache/commons/io/function/IOQuadFunction.java b/src/main/java/org/apache/commons/io/function/IOQuadFunction.java
index 78db4284b67..f5852c09948 100644
--- a/src/main/java/org/apache/commons/io/function/IOQuadFunction.java
+++ b/src/main/java/org/apache/commons/io/function/IOQuadFunction.java
@@ -29,11 +29,11 @@
* {@link #apply(Object, Object, Object, Object)}.
*
*
- * @param the type of the first argument to the function
- * @param the type of the second argument to the function
- * @param the type of the third argument to the function
- * @param the type of the fourth argument to the function
- * @param the type of the result of the function
+ * @param the type of the first argument to the function.
+ * @param the type of the second argument to the function.
+ * @param the type of the third argument to the function.
+ * @param the type of the fourth argument to the function.
+ * @param the type of the result of the function.
* @see Function
* @since 2.12.0
*/
@@ -45,10 +45,10 @@ public interface IOQuadFunction {
* function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
* composed function.
*
- * @param the type of output of the {@code after} function, and of the composed function
- * @param after the function to apply after this function is applied
- * @return a composed function that first applies this function and then applies the {@code after} function
- * @throws NullPointerException if after is null
+ * @param the type of output of the {@code after} function, and of the composed function.
+ * @param after the function to apply after this function is applied.
+ * @return a composed function that first applies this function and then applies the {@code after} function.
+ * @throws NullPointerException if after is null.
*/
default IOQuadFunction andThen(final IOFunction super R, ? extends X> after) {
Objects.requireNonNull(after);
@@ -58,11 +58,11 @@ default IOQuadFunction andThen(final IOFunction super R, ?
/**
* Applies this function to the given arguments.
*
- * @param t the first function argument
- * @param u the second function argument
- * @param v the third function argument
- * @param w the fourth function argument
- * @return the function result
+ * @param t the first function argument.
+ * @param u the second function argument.
+ * @param v the third function argument.
+ * @param w the fourth function argument.
+ * @return the function result.
* @throws IOException if an I/O error occurs.
*/
R apply(T t, U u, V v, W w) throws IOException;
diff --git a/src/main/java/org/apache/commons/io/function/IOSpliterator.java b/src/main/java/org/apache/commons/io/function/IOSpliterator.java
index b266027e8f2..b8af9637303 100644
--- a/src/main/java/org/apache/commons/io/function/IOSpliterator.java
+++ b/src/main/java/org/apache/commons/io/function/IOSpliterator.java
@@ -35,8 +35,8 @@ public interface IOSpliterator {
* Adapts the given Spliterator as an IOSpliterator.
*
* @param the type of the stream elements.
- * @param iterator The iterator to adapt
- * @return A new IOSpliterator
+ * @param iterator The iterator to adapt.
+ * @return A new IOSpliterator.
*/
static IOSpliterator adapt(final Spliterator iterator) {
return IOSpliteratorAdapter.adapt(iterator);
@@ -55,7 +55,7 @@ default Spliterator asSpliterator() {
/**
* Like {@link Spliterator#characteristics()}.
*
- * @return a representation of characteristics
+ * @return a representation of characteristics.
*/
default int characteristics() {
return unwrap().characteristics();
@@ -74,8 +74,8 @@ default long estimateSize() {
/**
* Like {@link Spliterator#forEachRemaining(Consumer)}.
*
- * @param action The action
- * @throws NullPointerException if the specified action is null
+ * @param action The action.
+ * @throws NullPointerException if the specified action is null.
*/
default void forEachRemaining(final IOConsumer super T> action) {
while (tryAdvance(action)) { // NOPMD
@@ -105,7 +105,7 @@ default long getExactSizeIfKnown() {
/**
* Like {@link Spliterator#hasCharacteristics(int)}.
*
- * @param characteristics the characteristics to check for
+ * @param characteristics the characteristics to check for.
* @return {@code true} if all the specified characteristics are present, else {@code false}
*/
default boolean hasCharacteristics(final int characteristics) {
@@ -115,9 +115,9 @@ default boolean hasCharacteristics(final int characteristics) {
/**
* Like {@link Spliterator#tryAdvance(Consumer)}.
*
- * @param action The action
+ * @param action The action.
* @return {@code false} if no remaining elements existed upon entry to this method, else {@code true}.
- * @throws NullPointerException if the specified action is null
+ * @throws NullPointerException if the specified action is null.
*/
default boolean tryAdvance(final IOConsumer super T> action) {
return unwrap().tryAdvance(Objects.requireNonNull(action, "action").asConsumer());
@@ -127,7 +127,7 @@ default boolean tryAdvance(final IOConsumer super T> action) {
* Like {@link Spliterator#trySplit()}.
*
* @return a {@code Spliterator} covering some portion of the elements, or {@code null} if this spliterator cannot be
- * split
+ * split.
*/
default IOSpliterator trySplit() {
return adapt(unwrap().trySplit());
diff --git a/src/main/java/org/apache/commons/io/function/IOStream.java b/src/main/java/org/apache/commons/io/function/IOStream.java
index fb5ee13b58c..87c6c832baf 100644
--- a/src/main/java/org/apache/commons/io/function/IOStream.java
+++ b/src/main/java/org/apache/commons/io/function/IOStream.java
@@ -66,7 +66,7 @@ static IOStream adapt(final Stream stream) {
/**
* This class' version of {@link Stream#empty()}.
*
- * @param the type of the stream elements
+ * @param the type of the stream elements.
* @return an empty sequential {@code IOStreamImpl}.
* @see Stream#empty()
*/
@@ -135,9 +135,9 @@ static IOStream of(final T... values) {
/**
* Returns a sequential {@code IOStreamImpl} containing a single element.
*
- * @param t the single element
- * @param the type of stream elements
- * @return a singleton sequential stream
+ * @param t the single element.
+ * @param the type of stream elements.
+ * @return a singleton sequential stream.
*/
static IOStream of(final T t) {
return adapt(Stream.of(t));
diff --git a/src/main/java/org/apache/commons/io/function/IOTriConsumer.java b/src/main/java/org/apache/commons/io/function/IOTriConsumer.java
index f1e78d2de35..304e94440f4 100644
--- a/src/main/java/org/apache/commons/io/function/IOTriConsumer.java
+++ b/src/main/java/org/apache/commons/io/function/IOTriConsumer.java
@@ -24,9 +24,9 @@
/**
* Like {@link BiConsumer} but throws {@link IOException}.
*
- * @param the type of the first argument to the operation
- * @param the type of the second argument to the operation
- * @param the type of the third argument to the operation
+ * @param the type of the first argument to the operation.
+ * @param the type of the second argument to the operation.
+ * @param the type of the third argument to the operation.
* @see BiConsumer
* @since 2.12.0
*/
@@ -36,9 +36,9 @@ public interface IOTriConsumer {
/**
* Returns the no-op singleton.
*
- * @param the type of the first argument to the operation
- * @param the type of the second argument to the operation
- * @param the type of the third argument to the operation
+ * @param the type of the first argument to the operation.
+ * @param the type of the second argument to the operation.
+ * @param the type of the third argument to the operation.
* @return The no-op singleton.
*/
@SuppressWarnings("unchecked")
@@ -49,9 +49,9 @@ static IOTriConsumer noop() {
/**
* Performs this operation on the given arguments.
*
- * @param t the first input argument
- * @param u the second input argument
- * @param v the second third argument
+ * @param t the first input argument.
+ * @param u the second input argument.
+ * @param v the second third argument.
* @throws IOException if an I/O error occurs.
*/
void accept(T t, U u, V v) throws IOException;
@@ -61,10 +61,10 @@ static IOTriConsumer noop() {
* operation. If performing either operation throws an exception, it is relayed to the caller of the composed operation.
* If performing this operation throws an exception, the {@code after} operation will not be performed.
*
- * @param after the operation to perform after this operation
+ * @param after the operation to perform after this operation.
* @return a composed {@link IOTriConsumer} that performs in sequence this operation followed by the {@code after}
- * operation
- * @throws NullPointerException if {@code after} is null
+ * operation.
+ * @throws NullPointerException if {@code after} is null.
*/
default IOTriConsumer andThen(final IOTriConsumer super T, ? super U, ? super V> after) {
Objects.requireNonNull(after);
diff --git a/src/main/java/org/apache/commons/io/function/IOTriFunction.java b/src/main/java/org/apache/commons/io/function/IOTriFunction.java
index 1459c3962e8..d84069df1df 100644
--- a/src/main/java/org/apache/commons/io/function/IOTriFunction.java
+++ b/src/main/java/org/apache/commons/io/function/IOTriFunction.java
@@ -29,10 +29,10 @@
* {@link #apply(Object, Object, Object)}.
*
*
- * @param the type of the first argument to the function
- * @param the type of the second argument to the function
- * @param the type of the third argument to the function
- * @param the type of the result of the function
+ * @param the type of the first argument to the function.
+ * @param the type of the second argument to the function.
+ * @param the type of the third argument to the function.
+ * @param the type of the result of the function.
* @see Function
* @since 2.12.0
*/
@@ -44,10 +44,10 @@ public interface IOTriFunction {
* function to the result. If evaluation of either function throws an exception, it is relayed to the caller of the
* composed function.
*
- * @param the type of output of the {@code after} function, and of the composed function
- * @param after the function to apply after this function is applied
- * @return a composed function that first applies this function and then applies the {@code after} function
- * @throws NullPointerException if after is null
+ * @param the type of output of the {@code after} function, and of the composed function.
+ * @param after the function to apply after this function is applied.
+ * @return a composed function that first applies this function and then applies the {@code after} function.
+ * @throws NullPointerException if after is null.
*/
default IOTriFunction andThen(final IOFunction super R, ? extends W> after) {
Objects.requireNonNull(after);
@@ -57,10 +57,10 @@ default IOTriFunction andThen(final IOFunction super R, ? exte
/**
* Applies this function to the given arguments.
*
- * @param t the first function argument
- * @param u the second function argument
- * @param v the third function argument
- * @return the function result
+ * @param t the first function argument.
+ * @param u the second function argument.
+ * @param v the third function argument.
+ * @return the function result.
* @throws IOException if an I/O error occurs.
*/
R apply(T t, U u, V v) throws IOException;
diff --git a/src/main/java/org/apache/commons/io/function/UncheckedIOIterable.java b/src/main/java/org/apache/commons/io/function/UncheckedIOIterable.java
index 76ee5e05546..bfc479872d2 100644
--- a/src/main/java/org/apache/commons/io/function/UncheckedIOIterable.java
+++ b/src/main/java/org/apache/commons/io/function/UncheckedIOIterable.java
@@ -37,7 +37,7 @@ final class UncheckedIOIterable implements Iterable {
/**
* Constructs a new instance.
*
- * @param delegate The delegate
+ * @param delegate The delegate.
*/
UncheckedIOIterable(final IOIterable delegate) {
this.delegate = Objects.requireNonNull(delegate, "delegate");
diff --git a/src/main/java/org/apache/commons/io/function/UncheckedIOIterator.java b/src/main/java/org/apache/commons/io/function/UncheckedIOIterator.java
index ec0bfb9867e..0fbbafb31dc 100644
--- a/src/main/java/org/apache/commons/io/function/UncheckedIOIterator.java
+++ b/src/main/java/org/apache/commons/io/function/UncheckedIOIterator.java
@@ -37,7 +37,7 @@ final class UncheckedIOIterator implements Iterator {
/**
* Constructs a new instance.
*
- * @param delegate The delegate
+ * @param delegate The delegate.
*/
UncheckedIOIterator(final IOIterator delegate) {
this.delegate = Objects.requireNonNull(delegate, "delegate");
diff --git a/src/main/java/org/apache/commons/io/input/AbstractCharacterFilterReader.java b/src/main/java/org/apache/commons/io/input/AbstractCharacterFilterReader.java
index 53974b060e5..b9851d93b1d 100644
--- a/src/main/java/org/apache/commons/io/input/AbstractCharacterFilterReader.java
+++ b/src/main/java/org/apache/commons/io/input/AbstractCharacterFilterReader.java
@@ -40,7 +40,7 @@ public abstract class AbstractCharacterFilterReader extends FilterReader {
/**
* Constructs a new reader.
*
- * @param reader the reader to filter
+ * @param reader the reader to filter.
*/
protected AbstractCharacterFilterReader(final Reader reader) {
this(reader, SKIP_NONE);
diff --git a/src/main/java/org/apache/commons/io/input/AbstractLineEndingInputStream.java b/src/main/java/org/apache/commons/io/input/AbstractLineEndingInputStream.java
new file mode 100644
index 00000000000..e42462cf12a
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/input/AbstractLineEndingInputStream.java
@@ -0,0 +1,67 @@
+/*
+ * 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.io.input;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Abstracts {@link UnixLineEndingInputStream} and {@link WindowsLineEndingInputStream} to reduce duplication.
+ */
+abstract class AbstractLineEndingInputStream extends InputStream {
+
+ boolean atEos;
+
+ boolean atSlashCr;
+
+ boolean atSlashLf;
+
+ final InputStream in;
+
+ final boolean lineFeedAtEos;
+
+ /**
+ * Constructs an input stream that filters another stream
+ *
+ * @param inputStream The input stream to wrap.
+ * @param lineFeedAtEos true to ensure that the file ends with LF.
+ */
+ AbstractLineEndingInputStream(final InputStream inputStream, final boolean lineFeedAtEos) {
+ this.in = inputStream;
+ this.lineFeedAtEos = lineFeedAtEos;
+ }
+
+ /**
+ * Closes the stream. Also closes the underlying stream.
+ *
+ * @throws IOException If an I/O error occurs.
+ */
+ @Override
+ public void close() throws IOException {
+ super.close();
+ in.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void mark(final int readLimit) {
+ throw UnsupportedOperationExceptions.mark();
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/input/AutoCloseInputStream.java b/src/main/java/org/apache/commons/io/input/AutoCloseInputStream.java
index 81f6c6e771d..4659f3f7038 100644
--- a/src/main/java/org/apache/commons/io/input/AutoCloseInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/AutoCloseInputStream.java
@@ -112,7 +112,7 @@ private AutoCloseInputStream(final Builder builder) throws IOException {
/**
* Constructs an automatically closing proxy for the given input stream.
*
- * @param in underlying input stream
+ * @param in underlying input stream.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@SuppressWarnings("resource") // ClosedInputStream.nonNull() doesn't allocate
@@ -124,8 +124,8 @@ public AutoCloseInputStream(final InputStream in) {
/**
* Automatically closes the stream if the end of stream was reached.
*
- * @param n number of bytes read, or -1 if no more bytes are available
- * @throws IOException if the stream could not be closed
+ * @param n number of bytes read, or -1 if no more bytes are available.
+ * @throws IOException if the stream could not be closed.
* @since 2.0
*/
@Override
@@ -146,7 +146,7 @@ protected void afterRead(final int n) throws IOException {
* first called.
*
*
- * @throws IOException if the underlying input stream cannot be closed
+ * @throws IOException if the underlying input stream cannot be closed.
*/
@Override
public void close() throws IOException {
@@ -158,7 +158,7 @@ public void close() throws IOException {
* Ensures that the stream is closed before it gets garbage-collected. As mentioned in {@link #close()}, this is a no-op if the stream has already been
* closed.
*
- * @throws Throwable if an error occurs
+ * @throws Throwable if an error occurs.
*/
@Override
protected void finalize() throws Throwable {
diff --git a/src/main/java/org/apache/commons/io/input/BOMInputStream.java b/src/main/java/org/apache/commons/io/input/BOMInputStream.java
index acfe8d9ddbb..488860cc412 100644
--- a/src/main/java/org/apache/commons/io/input/BOMInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BOMInputStream.java
@@ -14,6 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.commons.io.input;
import static org.apache.commons.io.IOUtils.EOF;
@@ -31,8 +32,7 @@
/**
* This class is used to wrap a stream that includes an encoded {@link ByteOrderMark} as its first bytes.
*
- * This class detects these bytes and, if required, can automatically skip them and return the subsequent byte as the
- * first byte in the stream.
+ * This class detects these bytes and, if required, can automatically skip them and return the subsequent byte as the first byte in the stream.
*
*
* The {@link ByteOrderMark} implementation has the following predefined BOMs:
@@ -60,10 +60,7 @@
*
*
- * BOMInputStream bomIn = BOMInputStream.builder()
- * .setInputStream(in)
- * .setByteOrderMarks(ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE)
- * .get();
+ * BOMInputStream bomIn = BOMInputStream.builder().setInputStream(in)
+ * .setByteOrderMarks(ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE).get();
* if (bomIn.hasBOM() == false) {
* // No BOM found
* } else if (bomIn.hasBOM(ByteOrderMark.UTF_16LE)) {
@@ -134,14 +129,13 @@ public static class Builder extends AbstractBuilder {
/**
* For test access.
*
- * @return the default byte order mark
+ * @return the default byte order mark.
*/
static ByteOrderMark getDefaultByteOrderMark() {
return DEFAULT[0];
}
private ByteOrderMark[] byteOrderMarks = DEFAULT;
-
private boolean include;
/**
@@ -200,14 +194,13 @@ public Builder setByteOrderMarks(final ByteOrderMark... byteOrderMarks) {
* The default is false.
*
*
- * @param include true to include the UTF-8 BOM or false to exclude it. return this;
+ * @param include true to include the UTF-8 BOM or false to exclude it. return this;.
* @return {@code this} instance.
*/
public Builder setInclude(final boolean include) {
this.include = include;
return this;
}
-
}
/**
@@ -229,65 +222,68 @@ public static Builder builder() {
* BOMs are sorted from longest to shortest.
*/
private final List bomList;
-
- private ByteOrderMark byteOrderMark;
+ private final ByteOrderMark byteOrderMark;
private int fbIndex;
private int[] firstBytes;
private final boolean include;
private boolean markedAtStart;
private int markFbIndex;
+ /**
+ * Constructs a new instance.
+ *
+ * @param builder The builder.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ */
private BOMInputStream(final Builder builder) throws IOException {
super(builder);
if (IOUtils.length(builder.byteOrderMarks) == 0) {
throw new IllegalArgumentException("No ByteOrderMark specified.");
}
this.include = builder.include;
- final List list = Arrays.asList(builder.byteOrderMarks);
+ final List bomList = Arrays.asList(builder.byteOrderMarks);
// Sort the BOMs to match the longest BOM first because some BOMs have the same starting two bytes.
- list.sort(ByteOrderMarkLengthComparator);
- this.bomList = list;
+ bomList.sort(ByteOrderMarkLengthComparator);
+ this.bomList = bomList;
+ this.byteOrderMark = readBom();
}
/**
* Constructs a new BOM InputStream that excludes a {@link ByteOrderMark#UTF_8} BOM.
*
- * @param delegate
- * the InputStream to delegate to
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param delegate the InputStream to delegate to.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
- public BOMInputStream(final InputStream delegate) {
+ public BOMInputStream(final InputStream delegate) throws IOException {
this(delegate, false, Builder.DEFAULT);
}
/**
* Constructs a new BOM InputStream that detects a {@link ByteOrderMark#UTF_8} and optionally includes it.
*
- * @param delegate
- * the InputStream to delegate to
- * @param include
- * true to include the UTF-8 BOM or false to exclude it
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param delegate the InputStream to delegate to.
+ * @param include true to include the UTF-8 BOM or false to exclude it.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
- public BOMInputStream(final InputStream delegate, final boolean include) {
+ public BOMInputStream(final InputStream delegate, final boolean include) throws IOException {
this(delegate, include, Builder.DEFAULT);
}
/**
* Constructs a new BOM InputStream that detects the specified BOMs and optionally includes them.
*
- * @param delegate
- * the InputStream to delegate to
- * @param include
- * true to include the specified BOMs or false to exclude them
- * @param boms
- * The BOMs to detect and optionally exclude
- * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
+ * @param delegate the InputStream to delegate to.
+ * @param include true to include the specified BOMs or false to exclude them.
+ * @param boms The BOMs to detect and optionally exclude.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
- public BOMInputStream(final InputStream delegate, final boolean include, final ByteOrderMark... boms) {
+ public BOMInputStream(final InputStream delegate, final boolean include, final ByteOrderMark... boms) throws IOException {
super(delegate);
if (IOUtils.length(boms) == 0) {
throw new IllegalArgumentException("No BOMs specified");
@@ -297,19 +293,19 @@ public BOMInputStream(final InputStream delegate, final boolean include, final B
// Sort the BOMs to match the longest BOM first because some BOMs have the same starting two bytes.
list.sort(ByteOrderMarkLengthComparator);
this.bomList = list;
+ this.byteOrderMark = readBom();
}
/**
* Constructs a new BOM InputStream that excludes the specified BOMs.
*
- * @param delegate
- * the InputStream to delegate to
- * @param boms
- * The BOMs to detect and exclude
+ * @param delegate the InputStream to delegate to.
+ * @param boms The BOMs to detect and exclude.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
- public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) {
+ public BOMInputStream(final InputStream delegate, final ByteOrderMark... boms) throws IOException {
this(delegate, false, boms);
}
@@ -326,34 +322,26 @@ private ByteOrderMark find() {
* Gets the ByteOrderMark (Byte Order Mark).
*
* @return The BOM or null if none matched.
- * @throws IOException
- * if an error reading the first bytes of the stream occurs.
*/
- public ByteOrderMark getBOM() throws IOException {
- if (firstBytes == null) {
- byteOrderMark = readBom();
- }
+ public ByteOrderMark getBOM() {
return byteOrderMark;
}
/**
* Gets the BOM charset Name - {@link ByteOrderMark#getCharsetName()}.
*
- * @return The BOM charset Name or null if no BOM found
- * @throws IOException
- * if an error reading the first bytes of the stream occurs
+ * @return The BOM charset Name or null if no BOM found.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
*/
public String getBOMCharsetName() throws IOException {
- getBOM();
return byteOrderMark == null ? null : byteOrderMark.getCharsetName();
}
/**
* Tests whether the stream contains one of the specified BOMs.
*
- * @return true if the stream has one of the specified BOMs, otherwise false if it does not
- * @throws IOException
- * if an error reading the first bytes of the stream occurs
+ * @return true if the stream has one of the specified BOMs, otherwise false if it does not.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
*/
public boolean hasBOM() throws IOException {
return getBOM() != null;
@@ -362,13 +350,10 @@ public boolean hasBOM() throws IOException {
/**
* Tests whether the stream contains the specified BOM.
*
- * @param bom
- * The BOM to check for
- * @return true if the stream has the specified BOM, otherwise false if it does not
- * @throws IllegalArgumentException
- * if the BOM is not one the stream is configured to detect
- * @throws IOException
- * if an error reading the first bytes of the stream occurs
+ * @param bom The BOM to check for.
+ * @return true if the stream has the specified BOM, otherwise false if it does not.
+ * @throws IllegalArgumentException if the BOM is not one the stream is configured to detect.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
*/
public boolean hasBOM(final ByteOrderMark bom) throws IOException {
if (!bomList.contains(bom)) {
@@ -378,10 +363,9 @@ public boolean hasBOM(final ByteOrderMark bom) throws IOException {
}
/**
- * Invokes the delegate's {@code mark(int)} method.
+ * Invokes the delegate's {@link InputStream#mark(int)} method.
*
- * @param readLimit
- * read ahead limit
+ * @param readLimit read ahead limit.
*/
@Override
public synchronized void mark(final int readLimit) {
@@ -393,9 +377,8 @@ public synchronized void mark(final int readLimit) {
/**
* Checks if the bytes match a BOM.
*
- * @param bom
- * The BOM
- * @return true if the bytes match the bom, otherwise false
+ * @param bom The BOM.
+ * @return true if the bytes match the BOM, otherwise false.
*/
private boolean matches(final ByteOrderMark bom) {
return bom.matches(firstBytes);
@@ -404,9 +387,8 @@ private boolean matches(final ByteOrderMark bom) {
/**
* Invokes the delegate's {@code read()} method, detecting and optionally skipping BOM.
*
- * @return the byte read (excluding BOM) or -1 if the end of stream
- * @throws IOException
- * if an I/O error occurs
+ * @return the byte read (excluding BOM) or -1 if the end of stream.
+ * @throws IOException if an I/O error occurs.
*/
@Override
public int read() throws IOException {
@@ -416,15 +398,12 @@ public int read() throws IOException {
}
/**
- * Invokes the delegate's {@code read(byte[])} method, detecting and optionally skipping BOM.
+ * Invokes the delegate's {@link InputStream#read(byte[])} method, detecting and optionally skipping BOM.
*
- * @param buf
- * the buffer to read the bytes into, never {@code null}
- * @return the number of bytes read (excluding BOM) or -1 if the end of stream
- * @throws NullPointerException
- * if the buffer is {@code null}
- * @throws IOException
- * if an I/O error occurs
+ * @param buf the buffer to read the bytes into, never {@code null}
+ * @return the number of bytes read (excluding BOM) or -1 if the end of stream.
+ * @throws NullPointerException if the buffer is {@code null}
+ * @throws IOException if an I/O error occurs.
*/
@Override
public int read(final byte[] buf) throws IOException {
@@ -432,21 +411,15 @@ public int read(final byte[] buf) throws IOException {
}
/**
- * Invokes the delegate's {@code read(byte[], int, int)} method, detecting and optionally skipping BOM.
+ * Invokes the delegate's {@link InputStream#read(byte[], int, int)} method, detecting and optionally skipping BOM.
*
- * @param buf
- * the buffer to read the bytes into
- * @param off
- * The start offset
- * @param len
- * The number of bytes to read (excluding BOM)
- * @return the number of bytes read or -1 if the end of stream
- * @throws NullPointerException
- * if the buffer is {@code null}
- * @throws IndexOutOfBoundsException
- * if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code buf.length}
- * @throws IOException
- * if an I/O error occurs
+ * @param buf the buffer to read the bytes into.
+ * @param off The start offset.
+ * @param len The number of bytes to read (excluding BOM).
+ * @return the number of bytes read or -1 if the end of stream.
+ * @throws NullPointerException if the buffer is {@code null}.
+ * @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code buf.length}.
+ * @throws IOException if an I/O error occurs.
*/
@Override
public int read(final byte[] buf, int off, int len) throws IOException {
@@ -469,6 +442,12 @@ public int read(final byte[] buf, int off, int len) throws IOException {
return secondCount < 0 ? firstCount > 0 ? firstCount : EOF : firstCount + secondCount;
}
+ /**
+ * Reads the byte order mark.
+ *
+ * @return the byte order mark.
+ * @throws IOException if an error reading the first bytes of the stream occurs.
+ */
private ByteOrderMark readBom() throws IOException {
int fbLength = 0;
// BOMs are sorted from longest to shortest
@@ -501,18 +480,16 @@ private ByteOrderMark readBom() throws IOException {
* valid byte or -1 to indicate that the initial bytes have been processed already.
*
* @return the byte read (excluding BOM) or -1 if at the end of first bytes.
- * @throws IOException if an I/O error occurs
+ * @throws IOException if an I/O error occurs.
*/
private int readFirstBytes() throws IOException {
- getBOM();
return fbIndex < firstBytes.length ? firstBytes[fbIndex++] : EOF;
}
/**
- * Invokes the delegate's {@code reset()} method.
+ * Invokes the delegate's {@link InputStream#reset()} method.
*
- * @throws IOException
- * if an I/O error occurs
+ * @throws IOException if an I/O error occurs.
*/
@Override
public synchronized void reset() throws IOException {
@@ -524,13 +501,11 @@ public synchronized void reset() throws IOException {
}
/**
- * Invokes the delegate's {@code skip(long)} method, detecting and optionally skipping BOM.
+ * Invokes the delegate's {@link InputStream#skip(long)} method, detecting and optionally skipping BOM.
*
- * @param n
- * the number of bytes to skip
- * @return the number of bytes to skipped or -1 if the end of stream
- * @throws IOException
- * if an I/O error occurs
+ * @param n the number of bytes to skip.
+ * @return the number of bytes to skipped or -1 if the end of stream.
+ * @throws IOException if an I/O error occurs.
*/
@Override
public long skip(final long n) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/BoundedInputStream.java b/src/main/java/org/apache/commons/io/input/BoundedInputStream.java
index e3e2d86bf0f..d9fbac8b104 100644
--- a/src/main/java/org/apache/commons/io/input/BoundedInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BoundedInputStream.java
@@ -82,6 +82,7 @@
* .get();
* }
*
+ *
* @see Builder
* @since 2.0
*/
diff --git a/src/main/java/org/apache/commons/io/input/BoundedReader.java b/src/main/java/org/apache/commons/io/input/BoundedReader.java
index 5c1c255c0fe..a7d4513a1fb 100644
--- a/src/main/java/org/apache/commons/io/input/BoundedReader.java
+++ b/src/main/java/org/apache/commons/io/input/BoundedReader.java
@@ -36,12 +36,10 @@
*
* @since 2.5
*/
-public class BoundedReader extends Reader {
+public class BoundedReader extends ProxyReader {
private static final int INVALID = -1;
- private final Reader target;
-
private int charsRead;
private int markedAt = INVALID;
@@ -51,76 +49,59 @@ public class BoundedReader extends Reader {
private final int maxCharsFromTargetReader;
/**
- * Constructs a bounded reader
+ * Constructs a bounded reader.
*
- * @param target The target stream that will be used
- * @param maxCharsFromTargetReader The maximum number of characters that can be read from target
+ * @param target The target stream that will be used.
+ * @param maxCharsFromTargetReader The maximum number of characters that can be read from target.
*/
public BoundedReader(final Reader target, final int maxCharsFromTargetReader) {
- this.target = target;
+ super(target);
this.maxCharsFromTargetReader = maxCharsFromTargetReader;
}
/**
- * Closes the target
- *
- * @throws IOException If an I/O error occurs while calling the underlying reader's close method
- */
- @Override
- public void close() throws IOException {
- target.close();
- }
-
- /**
- * marks the target stream
+ * marks the target stream.
*
* @param readAheadLimit The number of characters that can be read while still retaining the ability to do #reset().
* Note that this parameter is not validated with respect to maxCharsFromTargetReader. There
* is no way to pass past maxCharsFromTargetReader, even if this value is greater.
*
- * @throws IOException If an I/O error occurs while calling the underlying reader's mark method
+ * @throws IOException If an I/O error occurs while calling the underlying reader's mark method.
* @see Reader#mark(int)
*/
@Override
public void mark(final int readAheadLimit) throws IOException {
this.readAheadLimit = readAheadLimit - charsRead;
-
markedAt = charsRead;
-
- target.mark(readAheadLimit);
+ super.mark(readAheadLimit);
}
/**
- * Reads a single character
+ * Reads a single character.
*
- * @return -1 on EOF or the character read
- * @throws IOException If an I/O error occurs while calling the underlying reader's read method
+ * @return -1 on EOF or the character read.
+ * @throws IOException If an I/O error occurs while calling the underlying reader's read method.
* @see Reader#read()
*/
@Override
public int read() throws IOException {
-
- if (charsRead >= maxCharsFromTargetReader) {
- return EOF;
- }
-
- if (markedAt >= 0 && charsRead - markedAt >= readAheadLimit) {
+ if (charsRead >= maxCharsFromTargetReader || markedAt >= 0 && charsRead - markedAt >= readAheadLimit) {
return EOF;
}
charsRead++;
- return target.read();
+ return super.read();
}
/**
- * Reads into an array
+ * Reads into an array.
*
- * @param cbuf The buffer to fill
- * @param off The offset
- * @param len The number of chars to read
- * @return the number of chars read
+ * @param cbuf The buffer to fill.
+ * @param off The offset.
+ * @param len The number of chars to read.
+ * @return the number of chars read.
* @throws NullPointerException if the buffer is {@code null}.
* @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code cbuf.length}.
- * @throws IOException If an I/O error occurs while calling the underlying reader's read method
+ * @throws IOException If an I/O error occurs while calling the underlying reader's read method.
* @see Reader#read(char[], int, int)
*/
@Override
@@ -138,14 +119,28 @@ public int read(final char[] cbuf, final int off, final int len) throws IOExcept
}
/**
- * Resets the target to the latest mark,
+ * Resets the target to the latest mark.
*
- * @throws IOException If an I/O error occurs while calling the underlying reader's reset method
+ * @throws IOException If an I/O error occurs while calling the underlying reader's reset method.
* @see Reader#reset()
*/
@Override
public void reset() throws IOException {
charsRead = markedAt;
- target.reset();
+ super.reset();
+ }
+
+ @Override
+ public long skip(final long n) throws IOException {
+ if (n <= 0) {
+ return super.skip(n);
+ }
+ final int remaining = maxCharsFromTargetReader - charsRead;
+ if (remaining <= 0) {
+ return 0;
+ }
+ final long skipped = super.skip(Math.min(n, remaining));
+ charsRead += (int) skipped;
+ return skipped;
}
}
diff --git a/src/main/java/org/apache/commons/io/input/BrokenInputStream.java b/src/main/java/org/apache/commons/io/input/BrokenInputStream.java
index bc491637dee..cd2e2fce9c3 100644
--- a/src/main/java/org/apache/commons/io/input/BrokenInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BrokenInputStream.java
@@ -106,7 +106,7 @@ public void close() throws IOException {
/**
* Gets the Throwable to throw. Package-private for testing.
*
- * @return the Throwable to throw.
+ * @return the Throwable to throw.
*/
Throwable getThrowable() {
return exceptionSupplier.get();
diff --git a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
index 8e81b34508a..4fab37a9838 100644
--- a/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/BufferedFileChannelInputStream.java
@@ -137,6 +137,8 @@ public static Builder builder() {
private final ByteBuffer byteBuffer;
+ private boolean clean;
+
private final FileChannel fileChannel;
@SuppressWarnings("resource")
@@ -150,7 +152,7 @@ private BufferedFileChannelInputStream(final Builder builder) throws IOException
* Constructs a new instance for the given File.
*
* @param file The file to stream.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -163,7 +165,7 @@ public BufferedFileChannelInputStream(final File file) throws IOException {
*
* @param file The file to stream.
* @param bufferSize buffer size.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -175,7 +177,7 @@ public BufferedFileChannelInputStream(final File file, final int bufferSize) thr
* Constructs a new instance for the given Path.
*
* @param path The path to stream.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -188,7 +190,7 @@ public BufferedFileChannelInputStream(final Path path) throws IOException {
*
* @param path The path to stream.
* @param bufferSize buffer size.
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -198,10 +200,7 @@ public BufferedFileChannelInputStream(final Path path, final int bufferSize) thr
@Override
public synchronized int available() throws IOException {
- if (!fileChannel.isOpen()) {
- return 0;
- }
- if (!refill()) {
+ if (!fileChannel.isOpen() || !refill()) {
return 0;
}
return byteBuffer.remaining();
@@ -212,26 +211,18 @@ public synchronized int available() throws IOException {
* disposed buffer. However, neither the bytes allocated to direct buffers nor file descriptors opened for memory-mapped buffers put pressure on the garbage
* collector. Waiting for garbage collection may lead to the depletion of off-heap memory or huge numbers of open files. There's unfortunately no standard
* API to manually dispose of these kinds of buffers.
- *
- * @param buffer the buffer to clean.
- */
- private void clean(final ByteBuffer buffer) {
- if (buffer.isDirect()) {
- cleanDirectBuffer(buffer);
- }
- }
-
- /**
+ *
* In Java 8, the type of {@code sun.nio.ch.DirectBuffer.cleaner()} was {@code sun.misc.Cleaner}, and it was possible to access the method
* {@code sun.misc.Cleaner.clean()} to invoke it. The type changed to {@code jdk.internal.ref.Cleaner} in later JDKs, and the {@code clean()} method is not
* accessible even with reflection. However {@code sun.misc.Unsafe} added an {@code invokeCleaner()} method in JDK 9+ and this is still accessible with
* reflection.
- *
- * @param buffer the buffer to clean. must be a DirectBuffer.
+ *
+ * @param buffer the buffer to clean.
*/
- private void cleanDirectBuffer(final ByteBuffer buffer) {
- if (ByteBufferCleaner.isSupported()) {
+ private void clean(final ByteBuffer buffer) {
+ if (!clean && ByteBufferCleaner.isSupported()) {
ByteBufferCleaner.clean(buffer);
+ clean = true;
}
}
@@ -244,6 +235,10 @@ public synchronized void close() throws IOException {
}
}
+ boolean isClean() {
+ return clean;
+ }
+
@Override
public synchronized int read() throws IOException {
if (!refill()) {
@@ -269,7 +264,7 @@ public synchronized int read(final byte[] b, final int offset, int len) throws I
/**
* Checks whether data is left to be read from the input stream.
*
- * @return true if data is left, false otherwise
+ * @return true if data is left, false otherwise.
* @throws IOException if an I/O error occurs.
*/
private boolean refill() throws IOException {
@@ -304,6 +299,7 @@ public synchronized long skip(final long n) throws IOException {
return skippedFromBuffer + skipFromFileChannel(toSkipFromFileChannel);
}
+
private long skipFromFileChannel(final long n) throws IOException {
final long currentFilePosition = fileChannel.position();
final long size = fileChannel.size();
diff --git a/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java b/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
index 743ea44253c..6debbfb8449 100644
--- a/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
+++ b/src/main/java/org/apache/commons/io/input/ByteBufferCleaner.java
@@ -14,19 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.apache.commons.io.input;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
+import org.apache.commons.io.Buffers;
+
/**
- * Cleans a direct {@link ByteBuffer}. Without manual intervention, direct ByteBuffers will be cleaned eventually upon
- * garbage collection. However, this should not be relied upon since it may not occur in a timely fashion -
- * especially since off heap ByeBuffers don't put pressure on the garbage collector.
+ * Cleans a direct {@link ByteBuffer}. Without manual intervention, direct ByteBuffers will be cleaned eventually upon garbage collection. However, this should
+ * not be relied upon since it may not occur in a timely fashion - especially since off heap ByeBuffers don't put pressure on the garbage collector.
*
- * Warning: Do not attempt to use a direct {@link ByteBuffer} that has been cleaned or bad things will happen.
- * Don't use this class unless you can ensure that the cleaned buffer will not be accessed anymore.
+ * Warning: Do not attempt to use a direct {@link ByteBuffer} that has been cleaned or bad things will happen. Don't use this class unless you
+ * can ensure that the cleaned buffer will not be accessed anymore.
*
*
* See JDK-4724038
@@ -35,6 +37,7 @@
final class ByteBufferCleaner {
private interface Cleaner {
+
void clean(ByteBuffer buffer) throws ReflectiveOperationException;
}
@@ -86,7 +89,10 @@ public void clean(final ByteBuffer buffer) throws ReflectiveOperationException {
*/
static void clean(final ByteBuffer buffer) {
try {
- INSTANCE.clean(buffer);
+ if (buffer.isDirect()) {
+ Buffers.clearWritable(buffer);
+ INSTANCE.clean(buffer);
+ }
} catch (final Exception e) {
throw new IllegalStateException("Failed to clean direct buffer.", e);
}
@@ -105,8 +111,8 @@ private static Cleaner getCleaner() {
}
/**
- * Tests if were able to load a suitable cleaner for the current JVM. Attempting to call
- * {@code ByteBufferCleaner#clean(ByteBuffer)} when this method returns false will result in an exception.
+ * Tests if were able to load a suitable cleaner for the current JVM. Attempting to call {@code ByteBufferCleaner#clean(ByteBuffer)} when this method
+ * returns false will result in an exception.
*
* @return {@code true} if cleaning is supported, {@code false} otherwise.
*/
diff --git a/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java b/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java
index 874dcf1cb39..689424c062f 100644
--- a/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/CharSequenceInputStream.java
@@ -281,6 +281,7 @@ CharsetEncoder getCharsetEncoder() {
/**
* {@inheritDoc}
+ *
* @param readLimit max read limit (ignored).
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/input/CharSequenceReader.java b/src/main/java/org/apache/commons/io/input/CharSequenceReader.java
index bb2be3692c9..60026b84429 100644
--- a/src/main/java/org/apache/commons/io/input/CharSequenceReader.java
+++ b/src/main/java/org/apache/commons/io/input/CharSequenceReader.java
@@ -99,8 +99,8 @@ public CharSequenceReader(final CharSequence charSequence) {
*
*
* @param charSequence The character sequence, may be {@code null}
- * @param start The start index in the character sequence, inclusive
- * @throws IllegalArgumentException if the start index is negative
+ * @param start The start index in the character sequence, inclusive.
+ * @throws IllegalArgumentException if the start index is negative.
* @since 2.7
*/
public CharSequenceReader(final CharSequence charSequence, final int start) {
@@ -120,9 +120,9 @@ public CharSequenceReader(final CharSequence charSequence, final int start) {
*
*
* @param charSequence The character sequence, may be {@code null}
- * @param start The start index in the character sequence, inclusive
- * @param end The end index in the character sequence, exclusive
- * @throws IllegalArgumentException if the start index is negative, or if the end index is smaller than the start index
+ * @param start The start index in the character sequence, inclusive.
+ * @param end The end index in the character sequence, exclusive.
+ * @throws IllegalArgumentException if the start index is negative, or if the end index is smaller than the start index.
* @since 2.7
*/
public CharSequenceReader(final CharSequence charSequence, final int start, final int end) {
@@ -168,7 +168,7 @@ private int end() {
/**
* Mark the current position.
*
- * @param readAheadLimit ignored
+ * @param readAheadLimit ignored.
*/
@Override
public void mark(final int readAheadLimit) {
@@ -202,10 +202,10 @@ public int read() {
/**
* Reads the specified number of characters into the array.
*
- * @param array The array to store the characters in
- * @param offset The starting position in the array to store
- * @param length The maximum number of characters to read
- * @return The number of characters read or -1 if there are no more
+ * @param array The array to store the characters in.
+ * @param offset The starting position in the array to store.
+ * @param length The maximum number of characters to read.
+ * @return The number of characters read or -1 if there are no more.
* @throws NullPointerException if the array is {@code null}.
* @throws IndexOutOfBoundsException if {@code offset} or {@code length} are negative, or if {@code offset + length} is greater than {@code array.length}.
*/
@@ -272,8 +272,8 @@ public void reset() {
/**
* Skip the specified number of characters.
*
- * @param n The number of characters to skip
- * @return The actual number of characters skipped
+ * @param n The number of characters to skip.
+ * @return The actual number of characters skipped.
*/
@Override
public long skip(final long n) {
@@ -302,7 +302,7 @@ private int start() {
* Gets a String representation of the underlying
* character sequence.
*
- * @return The contents of the character sequence
+ * @return The contents of the character sequence.
*/
@Override
public String toString() {
diff --git a/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java b/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
index fef0d6cf17b..4b2828390e8 100644
--- a/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ClassLoaderObjectInputStream.java
@@ -40,10 +40,10 @@ public class ClassLoaderObjectInputStream extends ObjectInputStream {
/**
* Constructs a new ClassLoaderObjectInputStream.
*
- * @param classLoader the ClassLoader from which classes should be loaded
- * @param inputStream the InputStream to work on
- * @throws IOException in case of an I/O error
- * @throws StreamCorruptedException if the stream is corrupted
+ * @param classLoader the ClassLoader from which classes should be loaded.
+ * @param inputStream the InputStream to work on.
+ * @throws IOException in case of an I/O error.
+ * @throws StreamCorruptedException if the stream is corrupted.
*/
public ClassLoaderObjectInputStream(
final ClassLoader classLoader, final InputStream inputStream)
@@ -56,10 +56,10 @@ public ClassLoaderObjectInputStream(
* Resolve a class specified by the descriptor using the
* specified ClassLoader or the super ClassLoader.
*
- * @param objectStreamClass descriptor of the class
- * @return the Class object described by the ObjectStreamClass
- * @throws IOException in case of an I/O error
- * @throws ClassNotFoundException if the Class cannot be found
+ * @param objectStreamClass descriptor of the class.
+ * @return the Class object described by the ObjectStreamClass.
+ * @throws IOException in case of an I/O error.
+ * @throws ClassNotFoundException if the Class cannot be found.
*/
@Override
protected Class> resolveClass(final ObjectStreamClass objectStreamClass)
@@ -76,10 +76,10 @@ protected Class> resolveClass(final ObjectStreamClass objectStreamClass)
* Create a proxy class that implements the specified interfaces using
* the specified ClassLoader or the super ClassLoader.
*
- * @param interfaces the interfaces to implement
- * @return a proxy class implementing the interfaces
- * @throws IOException in case of an I/O error
- * @throws ClassNotFoundException if the Class cannot be found
+ * @param interfaces the interfaces to implement.
+ * @return a proxy class implementing the interfaces.
+ * @throws IOException in case of an I/O error.
+ * @throws ClassNotFoundException if the Class cannot be found.
* @see ObjectInputStream#resolveProxyClass(String[])
* @since 2.1
*/
diff --git a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java b/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java
index 001bfca6f55..b58c6a891ac 100644
--- a/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/CloseShieldInputStream.java
@@ -16,8 +16,11 @@
*/
package org.apache.commons.io.input;
+import java.io.IOException;
import java.io.InputStream;
+import org.apache.commons.io.function.IOUnaryOperator;
+
/**
* Proxy stream that prevents the underlying input stream from being closed.
*
@@ -30,6 +33,50 @@
*/
public class CloseShieldInputStream extends ProxyInputStream {
+ /**
+ * Constructs a new builder for {@link CloseShieldInputStream}.
+ *
+ * @since 2.22.0
+ */
+ public static class Builder extends AbstractBuilder {
+
+ private IOUnaryOperator onClose = is -> ClosedInputStream.INSTANCE;
+
+ /**
+ * Constructs a new instance.
+ */
+ public Builder() {
+ // empty
+ }
+
+ @Override
+ public CloseShieldInputStream get() throws IOException {
+ return new CloseShieldInputStream(this);
+ }
+
+ /**
+ * Sets the {@code onClose} function. By default, replaces the underlying input stream when {@link #close()} is called.
+ *
+ * @param onClose the onClose function.
+ * @return {@code this} instance.
+ */
+ public Builder setOnClose(final IOUnaryOperator onClose) {
+ this.onClose = onClose;
+ return asThis();
+ }
+
+ }
+
+ /**
+ * Constructs a new builder for {@link CloseShieldInputStream}.
+ *
+ * @return the new builder.
+ * @since 2.22.0
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
/**
* Constructs a proxy that only shields {@link System#in} from closing.
*
@@ -44,18 +91,25 @@ public static InputStream systemIn(final InputStream inputStream) {
/**
* Constructs a proxy that shields the given input stream from being closed.
*
- * @param inputStream the input stream to wrap
- * @return the created proxy
+ * @param inputStream the input stream to wrap.
+ * @return the created proxy.
* @since 2.9.0
*/
public static CloseShieldInputStream wrap(final InputStream inputStream) {
return new CloseShieldInputStream(inputStream);
}
+ private final IOUnaryOperator onClose;
+
+ private CloseShieldInputStream(final Builder builder) throws IOException {
+ super(builder.getInputStream());
+ this.onClose = builder.onClose;
+ }
+
/**
* Constructs a proxy that shields the given input stream from being closed.
*
- * @param inputStream underlying input stream
+ * @param inputStream underlying input stream.
* @deprecated Using this constructor prevents IDEs from warning if the
* underlying input stream is never closed. Use
* {@link #wrap(InputStream)} instead.
@@ -63,16 +117,21 @@ public static CloseShieldInputStream wrap(final InputStream inputStream) {
@Deprecated
public CloseShieldInputStream(final InputStream inputStream) {
super(inputStream);
+ this.onClose = builder().onClose;
}
/**
- * Replaces the underlying input stream with a {@link ClosedInputStream}
- * sentinel. The original input stream will remain open, but this proxy will
- * appear closed.
+ * Applies the {@code onClose} function to the underlying input stream, replacing it with the result.
+ *
+ * By default, replaces the underlying input stream with a {@link ClosedInputStream} sentinel. The original input stream will remain open, but this proxy
+ * will appear closed.
+ *
+ *
+ * @throws IOException Thrown by the {@code onClose} function.
*/
@Override
- public void close() {
- in = ClosedInputStream.INSTANCE;
+ public void close() throws IOException {
+ in = onClose.apply(in);
}
}
diff --git a/src/main/java/org/apache/commons/io/input/CloseShieldReader.java b/src/main/java/org/apache/commons/io/input/CloseShieldReader.java
index c6f116db765..e271627ceea 100644
--- a/src/main/java/org/apache/commons/io/input/CloseShieldReader.java
+++ b/src/main/java/org/apache/commons/io/input/CloseShieldReader.java
@@ -33,8 +33,8 @@ public class CloseShieldReader extends ProxyReader {
/**
* Constructs a proxy that shields the given reader from being closed.
*
- * @param reader the reader to wrap
- * @return the created proxy
+ * @param reader the reader to wrap.
+ * @return the created proxy.
* @since 2.9.0
*/
public static CloseShieldReader wrap(final Reader reader) {
@@ -44,7 +44,7 @@ public static CloseShieldReader wrap(final Reader reader) {
/**
* Constructs a proxy that shields the given reader from being closed.
*
- * @param reader underlying reader
+ * @param reader underlying reader.
* @deprecated Using this constructor prevents IDEs from warning if the
* underlying reader is never closed. Use {@link #wrap(Reader)}
* instead.
diff --git a/src/main/java/org/apache/commons/io/input/CountingInputStream.java b/src/main/java/org/apache/commons/io/input/CountingInputStream.java
index f14e7130507..1182309f07f 100644
--- a/src/main/java/org/apache/commons/io/input/CountingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/CountingInputStream.java
@@ -40,7 +40,7 @@ public class CountingInputStream extends ProxyInputStream {
/**
* Constructs a new CountingInputStream.
*
- * @param in the InputStream to delegate to
+ * @param in the InputStream to delegate to.
*/
public CountingInputStream(final InputStream in) {
super(in);
@@ -57,7 +57,7 @@ public CountingInputStream(final InputStream in) {
/**
* Adds the number of read bytes to the count.
*
- * @param n number of bytes read, or -1 if no more bytes are available
+ * @param n number of bytes read, or -1 if no more bytes are available.
* @throws IOException Not thrown here but subclasses may throw.
* @since 2.0
*/
@@ -77,7 +77,7 @@ protected synchronized void afterRead(final int n) throws IOException {
* result in incorrect count for files over 2GB.
*
*
- * @return the number of bytes accumulated
+ * @return the number of bytes accumulated.
* @since 1.3
*/
public synchronized long getByteCount() {
@@ -92,8 +92,8 @@ public synchronized long getByteCount() {
* See {@link #getByteCount()} for a method using a {@code long}.
*
*
- * @return the number of bytes accumulated
- * @throws ArithmeticException if the byte count is too large
+ * @return the number of bytes accumulated.
+ * @throws ArithmeticException if the byte count is too large.
* @deprecated Use {@link #getByteCount()}.
*/
@Deprecated
@@ -113,7 +113,7 @@ public int getCount() {
* result in incorrect count for files over 2GB.
*
*
- * @return the count previous to resetting
+ * @return the count previous to resetting.
* @since 1.3
*/
public synchronized long resetByteCount() {
@@ -130,8 +130,8 @@ public synchronized long resetByteCount() {
* See {@link #resetByteCount()} for a method using a {@code long}.
*
*
- * @return the count previous to resetting
- * @throws ArithmeticException if the byte count is too large
+ * @return the count previous to resetting.
+ * @throws ArithmeticException if the byte count is too large.
* @deprecated Use {@link #resetByteCount()}.
*/
@Deprecated
@@ -147,8 +147,8 @@ public int resetCount() {
* Skips the stream over the specified number of bytes, adding the skipped
* amount to the count.
*
- * @param length the number of bytes to skip
- * @return the actual number of bytes skipped
+ * @param length the number of bytes to skip.
+ * @return the actual number of bytes skipped.
* @throws IOException if an I/O error occurs.
* @see InputStream#skip(long)
*/
diff --git a/src/main/java/org/apache/commons/io/input/DemuxInputStream.java b/src/main/java/org/apache/commons/io/input/DemuxInputStream.java
index ad49dca2793..3a0132dc8e6 100644
--- a/src/main/java/org/apache/commons/io/input/DemuxInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/DemuxInputStream.java
@@ -40,8 +40,8 @@ public DemuxInputStream() {
/**
* Binds the specified stream to the current thread.
*
- * @param input the stream to bind
- * @return the InputStream that was previously active
+ * @param input the stream to bind.
+ * @return the InputStream that was previously active.
*/
public InputStream bindStream(final InputStream input) {
final InputStream oldValue = inputStreamLocal.get();
@@ -52,7 +52,7 @@ public InputStream bindStream(final InputStream input) {
/**
* Closes stream associated with current thread.
*
- * @throws IOException if an error occurs
+ * @throws IOException if an error occurs.
*/
@SuppressWarnings("resource") // we actually close the stream here
@Override
@@ -63,8 +63,8 @@ public void close() throws IOException {
/**
* Reads byte from stream associated with current thread.
*
- * @return the byte read from stream
- * @throws IOException if an error occurs
+ * @return the byte read from stream.
+ * @throws IOException if an error occurs.
*/
@Override
public int read() throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/Input.java b/src/main/java/org/apache/commons/io/input/Input.java
index 70147681178..b5b626a42c6 100644
--- a/src/main/java/org/apache/commons/io/input/Input.java
+++ b/src/main/java/org/apache/commons/io/input/Input.java
@@ -18,14 +18,15 @@
package org.apache.commons.io.input;
import java.io.IOException;
+import java.io.InterruptedIOException;
/**
* Package-wide internals for input.
*/
-class Input {
+final class Input {
/**
- * Throws an IOException on false input.
+ * Throws an {@link IOException} on false input.
*
* @param isOpen whether an input is open or not.
* @throws IOException if {@code isOpen} is false indicating an input is closed.
@@ -36,4 +37,21 @@ static void checkOpen(final boolean isOpen) throws IOException {
}
}
+ /**
+ * Converts an {@link InterruptedException} to an {@link InterruptedIOException}.
+ *
+ * The cause of the returned InterruptedIOException is set to the original.
+ *
+ *
+ * @param e The InterruptedException to convert.
+ * @return The converted InterruptedIOException.
+ * @see InterruptedIOException
+ * @see Throwable#initCause(Throwable)
+ * @see Throwable#getCause()
+ */
+ static InterruptedIOException toInterruptedIOException(final InterruptedException e) {
+ final InterruptedIOException iio = new InterruptedIOException(e.getMessage());
+ iio.initCause(e);
+ return iio;
+ }
}
diff --git a/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java b/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java
index 44fb12ff56e..0ed0b0bfda6 100644
--- a/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MarkShieldInputStream.java
@@ -40,7 +40,7 @@ public class MarkShieldInputStream extends ProxyInputStream {
* Constructs a proxy that shields the given input stream from being
* marked or rest.
*
- * @param in underlying input stream
+ * @param in underlying input stream.
*/
public MarkShieldInputStream(final InputStream in) {
super(in);
diff --git a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
index 22fae70ca75..b8ddda491ec 100644
--- a/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MemoryMappedFileInputStream.java
@@ -172,7 +172,7 @@ public int available() throws IOException {
}
private void cleanBuffer() {
- if (ByteBufferCleaner.isSupported() && buffer.isDirect()) {
+ if (ByteBufferCleaner.isSupported()) {
ByteBufferCleaner.clean(buffer);
}
}
diff --git a/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java b/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
index 5f2fb452ef0..7188c564502 100644
--- a/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestCalculatingInputStream.java
@@ -148,7 +148,7 @@ public static class MessageDigestMaintainingObserver extends Observer {
/**
* Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
*
- * @param messageDigest the message digest to use
+ * @param messageDigest the message digest to use.
* @throws NullPointerException if messageDigest is null.
*/
public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
@@ -211,7 +211,7 @@ private MessageDigestCalculatingInputStream(final Builder builder) throws IOExce
* The MD5 algorithm is weak and should not be used.
*
*
- * @param inputStream the stream to calculate the message digest for
+ * @param inputStream the stream to calculate the message digest for.
* @throws NoSuchAlgorithmException if no Provider supports a MessageDigestSpi implementation for the specified algorithm.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@@ -226,8 +226,8 @@ public MessageDigestCalculatingInputStream(final InputStream inputStream) throws
* The MD5 cryptographic algorithm is weak and should not be used.
*
*
- * @param inputStream the stream to calculate the message digest for
- * @param messageDigest the message digest to use
+ * @param inputStream the stream to calculate the message digest for.
+ * @param messageDigest the message digest to use.
* @throws NullPointerException if messageDigest is null.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@@ -243,7 +243,7 @@ public MessageDigestCalculatingInputStream(final InputStream inputStream, final
* The MD5 cryptographic algorithm is weak and should not be used.
*
*
- * @param inputStream the stream to calculate the message digest for
+ * @param inputStream the stream to calculate the message digest for.
* @param algorithm the name of the algorithm requested. See the MessageDigest section in the
* Java Cryptography
* Architecture Standard Algorithm Name Documentation for information about standard algorithm names.
@@ -262,7 +262,7 @@ public MessageDigestCalculatingInputStream(final InputStream inputStream, final
* data has been read, if that is what you want. The easiest way to do so is by invoking {@link #consume()}.
*
*
- * @return the message digest used
+ * @return the message digest used.
*/
public MessageDigest getMessageDigest() {
return messageDigest;
diff --git a/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
index dac3f2afb5e..c8c3af88347 100644
--- a/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/MessageDigestInputStream.java
@@ -152,7 +152,7 @@ public static class MessageDigestMaintainingObserver extends Observer {
/**
* Constructs an MessageDigestMaintainingObserver for the given MessageDigest.
*
- * @param messageDigest the message digest to use
+ * @param messageDigest the message digest to use.
* @throws NullPointerException if messageDigest is null.
*/
public MessageDigestMaintainingObserver(final MessageDigest messageDigest) {
@@ -190,7 +190,7 @@ public static Builder builder() {
* The MD5 cryptographic algorithm is weak and should not be used.
*
*
- * @param builder A builder use to get the stream to calculate the message digest and the message digest to use
+ * @param builder A builder use to get the stream to calculate the message digest and the message digest to use.
* @throws NullPointerException if messageDigest is null.
*/
private MessageDigestInputStream(final Builder builder) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/NullInputStream.java b/src/main/java/org/apache/commons/io/input/NullInputStream.java
index 5fa9b817b5c..1f05410f636 100644
--- a/src/main/java/org/apache/commons/io/input/NullInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/NullInputStream.java
@@ -272,7 +272,7 @@ public int read() throws IOException {
/**
* Reads some bytes into the specified array.
*
- * @param bytes The byte array to read into
+ * @param bytes The byte array to read into.
* @return The number of bytes read or {@code -1} if the end of file has been reached and {@code throwEofException} is set to {@code false}.
* @throws NullPointerException if the byte array is {@code null}.
* @throws EOFException if the end of file is reached and {@code throwEofException} is set to {@code true}.
diff --git a/src/main/java/org/apache/commons/io/input/NullReader.java b/src/main/java/org/apache/commons/io/input/NullReader.java
index 28f3d37eb21..0405f3943d0 100644
--- a/src/main/java/org/apache/commons/io/input/NullReader.java
+++ b/src/main/java/org/apache/commons/io/input/NullReader.java
@@ -217,7 +217,7 @@ protected int processChar() {
* This implementation leaves the character array unchanged.
*
*
- * @param chars The character array
+ * @param chars The character array.
* @param offset The offset to start at.
* @param length The number of characters.
*/
@@ -250,7 +250,7 @@ public int read() throws IOException {
/**
* Reads some characters into the specified array.
*
- * @param chars The character array to read into
+ * @param chars The character array to read into.
* @return The number of characters read or {@code -1}
* if the end of file has been reached and
* {@code throwEofException} is set to {@code false}.
diff --git a/src/main/java/org/apache/commons/io/input/ObservableInputStream.java b/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
index a1287b857f7..1909f859a65 100644
--- a/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ObservableInputStream.java
@@ -144,7 +144,7 @@ public void data(final int value) throws IOException {
/**
* Called to indicate that an error occurred on the underlying stream.
*
- * @param exception the exception to throw
+ * @param exception the exception to throw.
* @throws IOException if an I/O error occurs.
*/
public void error(final IOException exception) throws IOException {
@@ -361,7 +361,7 @@ public int read(final byte[] buffer, final int offset, final int length) throws
/**
* Removes an Observer.
*
- * @param observer the observer to remove
+ * @param observer the observer to remove.
*/
public void remove(final Observer observer) {
observers.remove(observer);
diff --git a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
index b2e04c334b5..fdff24eac0e 100644
--- a/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ProxyInputStream.java
@@ -27,7 +27,7 @@
import org.apache.commons.io.function.IOIntConsumer;
/**
- * A proxy stream which acts as a {@link FilterInputStream}, by passing all method calls on to the proxied stream, not changing which methods are called.
+ * An input stream proxy which delegates to the wrapped input stream.
*
* It is an alternative base class to {@link FilterInputStream} to increase reusability, because {@link FilterInputStream} changes the methods being called,
* such as read(byte[]) to read(byte[], int, int).
@@ -298,7 +298,7 @@ public int read() throws IOException {
* @return the number of bytes read or {@link IOUtils#EOF EOF} if we reached the end of stream.
* @throws IOException
*
- *
If the first byte cannot be read for any reason other than the end of the file,
+ *
If the first byte cannot be read for any reason other than the end of the file,
*
if the input stream has been closed, or
*
if some other I/O error occurs.
*
@@ -325,7 +325,7 @@ public int read(final byte[] b) throws IOException {
* @return the number of bytes read or {@link IOUtils#EOF EOF} if we reached the end of stream.
* @throws IOException
*
- *
If the first byte cannot be read for any reason other than the end of the file,
+ *
If the first byte cannot be read for any reason other than the end of the file,
*
if the input stream has been closed, or
*
if some other I/O error occurs.
*
@@ -359,6 +359,9 @@ public synchronized void reset() throws IOException {
/**
* Sets the underlying input stream.
+ *
+ * Use with caution.
+ *
*
* @param in The input stream to set in {@link java.io.FilterInputStream#in}.
* @return {@code this} instance.
@@ -389,7 +392,7 @@ public long skip(final long n) throws IOException {
/**
* Unwraps this instance by returning the underlying {@link InputStream}.
*
- * Use with caution; useful to query the underlying {@link InputStream}.
+ * Use with caution.
*
*
* @return the underlying {@link InputStream}.
diff --git a/src/main/java/org/apache/commons/io/input/ProxyReader.java b/src/main/java/org/apache/commons/io/input/ProxyReader.java
index 7bfed636497..7e0be84fcfe 100644
--- a/src/main/java/org/apache/commons/io/input/ProxyReader.java
+++ b/src/main/java/org/apache/commons/io/input/ProxyReader.java
@@ -26,9 +26,7 @@
import org.apache.commons.io.IOUtils;
/**
- * A Proxy stream which acts as expected, that is it passes the method
- * calls on to the proxied stream and doesn't change which methods are
- * being called.
+ * A reader proxy which delegates to the wrapped reader.
*
* It is an alternative base class to FilterReader
* to increase reusability, because FilterReader changes the
@@ -40,7 +38,7 @@ public abstract class ProxyReader extends FilterReader {
/**
* Constructs a new ProxyReader.
*
- * @param delegate the Reader to delegate to
+ * @param delegate the Reader to delegate to.
*/
public ProxyReader(final Reader delegate) {
// the delegate is stored in a protected superclass variable named 'in'
@@ -55,13 +53,15 @@ public ProxyReader(final Reader delegate) {
* Subclasses can override this method to add common post-processing
* functionality without having to override all the read methods.
* The default implementation does nothing.
+ *
*
* Note this method is not called from {@link #skip(long)} or
* {@link #reset()}. You need to explicitly override those methods if
* you want to add post-processing steps also to them.
+ *
*
- * @param n number of chars read, or -1 if the end of stream was reached
- * @throws IOException if the post-processing fails
+ * @param n number of chars read, or -1 if the end of stream was reached.
+ * @throws IOException if the post-processing fails.
* @since 2.0
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
@@ -78,13 +78,15 @@ protected void afterRead(final int n) throws IOException {
* Subclasses can override this method to add common pre-processing
* functionality without having to override all the read methods.
* The default implementation does nothing.
+ *
*
* Note this method is not called from {@link #skip(long)} or
* {@link #reset()}. You need to explicitly override those methods if
* you want to add pre-processing steps also to them.
+ *
*
- * @param n number of chars that the caller asked to be read
- * @throws IOException if the pre-processing fails
+ * @param n number of chars that the caller asked to be read.
+ * @throws IOException if the pre-processing fails.
* @since 2.0
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
@@ -93,7 +95,8 @@ protected void beforeRead(final int n) throws IOException {
}
/**
- * Invokes the delegate's {@code close()} method.
+ * Closes the stream and releases any system resources associated with it by invoking the delegate's {@link Reader#close()} method.
+ *
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -110,7 +113,9 @@ public void close() throws IOException {
*
* This method provides a point to implement custom exception
* handling. The default behavior is to re-throw the exception.
- * @param e The IOException thrown
+ *
+ *
+ * @param e The IOException thrown.
* @throws IOException if an I/O error occurs.
* @since 2.0
*/
@@ -119,8 +124,9 @@ protected void handleIOException(final IOException e) throws IOException {
}
/**
- * Invokes the delegate's {@code mark(int)} method.
- * @param readAheadLimit read ahead limit
+ * Marks the present position in the stream by invoking the delegate's {@link Reader#mark(int)} method.
+ *
+ * @param readAheadLimit read ahead limit.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -133,8 +139,9 @@ public synchronized void mark(final int readAheadLimit) throws IOException {
}
/**
- * Invokes the delegate's {@code markSupported()} method.
- * @return true if mark is supported, otherwise false
+ * Tests whether this stream supports the {@link Reader#mark(int)} operation by invoking the delegate's {@link Reader#markSupported()} method.
+ *
+ * @return true if mark is supported, otherwise false.
*/
@Override
public boolean markSupported() {
@@ -142,8 +149,9 @@ public boolean markSupported() {
}
/**
- * Invokes the delegate's {@code read()} method.
- * @return the character read or -1 if the end of stream
+ * Reads characters into an array by invoking the delegate's {@link Reader#read()} method.
+ *
+ * @return the character read or -1 if the end of stream.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -161,8 +169,9 @@ public int read() throws IOException {
/**
* Invokes the delegate's {@code read(char[])} method.
- * @param chr the buffer to read the characters into
- * @return the number of characters read or -1 if the end of stream
+ *
+ * @param chr the buffer to read the characters into.
+ * @return the number of characters read or -1 if the end of stream.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -179,11 +188,12 @@ public int read(final char[] chr) throws IOException {
}
/**
- * Invokes the delegate's {@code read(char[], int, int)} method.
- * @param chr the buffer to read the characters into
- * @param st The start offset
- * @param len The number of bytes to read
- * @return the number of characters read or -1 if the end of stream
+ * Reads characters into a portion of an array by invoking the delegate's {@link Reader#read(char[], int, int)} method.
+ *
+ * @param chr the buffer to read the characters into.
+ * @param st The start offset.
+ * @param len The number of bytes to read.
+ * @return the number of characters read or -1 if the end of stream.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -200,9 +210,10 @@ public int read(final char[] chr, final int st, final int len) throws IOExceptio
}
/**
- * Invokes the delegate's {@code read(CharBuffer)} method.
- * @param target the char buffer to read the characters into
- * @return the number of characters read or -1 if the end of stream
+ * Attempts to read characters into the specified character buffer by invoking the delegate's {@link Reader#read(CharBuffer)} method.
+ *
+ * @param target the char buffer to read the characters into.
+ * @return the number of characters read or -1 if the end of stream.
* @throws IOException if an I/O error occurs.
* @since 2.0
*/
@@ -220,8 +231,9 @@ public int read(final CharBuffer target) throws IOException {
}
/**
- * Invokes the delegate's {@code ready()} method.
- * @return true if the stream is ready to be read
+ * Tells whether this stream is ready to be read by invoking the delegate's {@link Reader#ready()} method.
+ *
+ * @return true if the stream is ready to be read.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -235,7 +247,8 @@ public boolean ready() throws IOException {
}
/**
- * Invokes the delegate's {@code reset()} method.
+ * Resets the stream by invoking the delegate's {@link Reader#reset()} method.
+ *
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -248,9 +261,26 @@ public synchronized void reset() throws IOException {
}
/**
- * Invokes the delegate's {@code skip(long)} method.
- * @param ln the number of bytes to skip
- * @return the number of bytes to skipped or EOF if the end of stream
+ * Sets the underlying reader.
+ *
+ * Use with caution.
+ *
+ *
+ * @param in The input stream to set in {@code java.io.Reader#in}.
+ * @return {@code this} instance.
+ * @since 2.22.0
+ */
+ public ProxyReader setReference(final Reader in) {
+ this.in = in;
+ return this;
+ }
+
+
+ /**
+ * Skips characters by invoking the delegate's {@link Reader#skip(long)} method.
+ *
+ * @param ln the number of bytes to skip.
+ * @return the number of bytes to skipped or EOF if the end of stream.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -263,4 +293,17 @@ public long skip(final long ln) throws IOException {
}
}
+ /**
+ * Unwraps this instance by returning the underlying {@link Reader}.
+ *
+ * Use with caution.
+ *
+ *
+ * @return the underlying {@link Reader}.
+ * @since 2.22.0
+ */
+ public Reader unwrap() {
+ return in;
+ }
+
}
diff --git a/src/main/java/org/apache/commons/io/input/QueueInputStream.java b/src/main/java/org/apache/commons/io/input/QueueInputStream.java
index 5f701945cb3..d672d23fa2b 100644
--- a/src/main/java/org/apache/commons/io/input/QueueInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/QueueInputStream.java
@@ -229,7 +229,7 @@ public int read() {
/**
* Reads up to {@code length} bytes of data from the input stream into
- * an array of bytes. The first byte is read while honoring the timeout; the rest are read while not honoring
+ * an array of bytes. The first byte is read while honoring the timeout; the rest are read while not honoring
* the timeout. The number of bytes actually read is returned as an integer.
*
* @param b the buffer into which the data is read.
diff --git a/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java b/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java
index bcee009a431..152cd42a586 100644
--- a/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ReadAheadInputStream.java
@@ -20,7 +20,6 @@
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.concurrent.ExecutorService;
@@ -63,6 +62,9 @@ public class ReadAheadInputStream extends FilterInputStream {
* .setExecutorService(Executors.newSingleThreadExecutor(ReadAheadInputStream::newThread))
* .get();}
*
+ *
+ * If an {@link ExecutorService} is not set, then a single-threaded daemon executor service is used.
+ *
{@link ExecutorService}, if not set, a single-threaded daemon executor service is used.
*
*
* @return a new instance.
@@ -108,8 +110,11 @@ public ReadAheadInputStream get() throws IOException {
/**
* Sets the executor service for the read-ahead thread.
+ *
+ * If not set, a single-threaded daemon executor service is used.
+ *
*
- * @param executorService the executor service for the read-ahead thread.
+ * @param executorService the executor service for the read-ahead thread, may be {@code null}.
* @return {@code this} instance.
*/
public Builder setExecutorService(final ExecutorService executorService) {
@@ -203,7 +208,7 @@ private ReadAheadInputStream(final Builder builder) throws IOException {
}
/**
- * Constructs an instance with the specified buffer size and read-ahead threshold
+ * Constructs an instance with the specified buffer size and read-ahead threshold.
*
* @param inputStream The underlying input stream.
* @param bufferSizeInBytes The buffer size.
@@ -215,7 +220,7 @@ public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeI
}
/**
- * Constructs an instance with the specified buffer size and read-ahead threshold
+ * Constructs an instance with the specified buffer size and read-ahead threshold.
*
* @param inputStream The underlying input stream.
* @param bufferSizeInBytes The buffer size.
@@ -228,7 +233,7 @@ public ReadAheadInputStream(final InputStream inputStream, final int bufferSizeI
}
/**
- * Constructs an instance with the specified buffer size and read-ahead threshold
+ * Constructs an instance with the specified buffer size and read-ahead threshold.
*
* @param inputStream The underlying input stream.
* @param bufferSizeInBytes The buffer size.
@@ -239,7 +244,7 @@ private ReadAheadInputStream(final InputStream inputStream, final int bufferSize
final boolean shutdownExecutorService) {
super(Objects.requireNonNull(inputStream, "inputStream"));
if (bufferSizeInBytes <= 0) {
- throw new IllegalArgumentException("bufferSizeInBytes should be greater than 0, but the value is " + bufferSizeInBytes);
+ throw new IllegalArgumentException(String.format("bufferSizeInBytes <= 0, bufferSizeInBytes = %,d", bufferSizeInBytes));
}
this.executorService = Objects.requireNonNull(executorService, "executorService");
this.shutdownExecutorService = shutdownExecutorService;
@@ -287,21 +292,21 @@ public void close() throws IOException {
} finally {
stateChangeLock.unlock();
}
-
if (shutdownExecutorService) {
try {
- executorService.shutdownNow();
- executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
+ shutdownAwait();
} catch (final InterruptedException e) {
- final InterruptedIOException iio = new InterruptedIOException(e.getMessage());
- iio.initCause(e);
- throw iio;
+ Thread.currentThread().interrupt();
+ throw Input.toInterruptedIOException(e);
} finally {
if (isSafeToCloseUnderlyingInputStream) {
super.close();
}
}
}
+ if (isSafeToCloseUnderlyingInputStream) {
+ super.close();
+ }
}
private void closeUnderlyingInputStreamIfNecessary() {
@@ -346,7 +351,6 @@ public int read(final byte[] b, final int offset, int len) throws IOException {
if (len == 0) {
return 0;
}
-
if (!activeBuffer.hasRemaining()) {
// No remaining in active buffer - lock and switch to write ahead buffer.
stateChangeLock.lock();
@@ -459,6 +463,11 @@ private void readAsync() throws IOException {
});
}
+ boolean shutdownAwait() throws InterruptedException {
+ executorService.shutdownNow();
+ return executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
+ }
+
private void signalAsyncReadComplete() {
stateChangeLock.lock();
try {
@@ -532,7 +541,7 @@ private long skipInternal(final long n) throws IOException {
}
/**
- * Flips the active and read ahead buffer
+ * Flips the active and read ahead buffers.
*/
private void swapBuffers() {
final ByteBuffer temp = activeBuffer;
@@ -550,9 +559,8 @@ private void waitForAsyncReadComplete() throws IOException {
asyncReadComplete.await();
}
} catch (final InterruptedException e) {
- final InterruptedIOException iio = new InterruptedIOException(e.getMessage());
- iio.initCause(e);
- throw iio;
+ Thread.currentThread().interrupt();
+ throw Input.toInterruptedIOException(e);
} finally {
try {
isWaiting.set(false);
diff --git a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java
index 4d22d28f891..7e7379e9216 100644
--- a/src/main/java/org/apache/commons/io/input/ReaderInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ReaderInputStream.java
@@ -209,6 +209,7 @@ private static CharsetEncoder newEncoder(final Charset charset) {
* CharBuffer used as input for the decoder. It should be reasonably large as we read data from the underlying Reader into this buffer.
*/
private final CharBuffer encoderIn;
+
/**
* ByteBuffer used as output for the decoder. This buffer can be small as it is only used to transfer data from the decoder to the buffer provided by the
* caller.
@@ -225,11 +226,11 @@ private ReaderInputStream(final Builder builder) throws IOException {
}
/**
- * Constructs a new {@link ReaderInputStream} that uses the virtual machine's {@link Charset#defaultCharset() default charset} with a default input buffer
- * size of {@value IOUtils#DEFAULT_BUFFER_SIZE} characters.
+ * Constructs a new {@link ReaderInputStream} that uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} with a default input
+ * buffer size of {@value IOUtils#DEFAULT_BUFFER_SIZE} characters.
*
* @param reader the target {@link Reader}
- * @deprecated Use {@link ReaderInputStream#builder()} instead
+ * @deprecated Use {@link ReaderInputStream#builder()} instead.
*/
@Deprecated
public ReaderInputStream(final Reader reader) {
@@ -244,7 +245,7 @@ public ReaderInputStream(final Reader reader) {
*
*
* @param reader the target {@link Reader}
- * @param charset the charset encoding
+ * @param charset the charset encoding.
* @deprecated Use {@link ReaderInputStream#builder()} instead, will be protected for subclasses.
*/
@Deprecated
@@ -262,17 +263,11 @@ public ReaderInputStream(final Reader reader, final Charset charset) {
* @param reader the target {@link Reader}.
* @param charset the charset encoding.
* @param bufferSize the size of the input buffer in number of characters.
- * @deprecated Use {@link ReaderInputStream#builder()} instead
+ * @deprecated Use {@link ReaderInputStream#builder()} instead.
*/
@Deprecated
public ReaderInputStream(final Reader reader, final Charset charset, final int bufferSize) {
- // @formatter:off
- this(reader,
- Charsets.toCharset(charset).newEncoder()
- .onMalformedInput(CodingErrorAction.REPLACE)
- .onUnmappableCharacter(CodingErrorAction.REPLACE),
- bufferSize);
- // @formatter:on
+ this(reader, newEncoder(charset), bufferSize);
}
/**
@@ -284,9 +279,9 @@ public ReaderInputStream(final Reader reader, final Charset charset, final int b
*
*
* @param reader the target {@link Reader}
- * @param charsetEncoder the charset encoder
+ * @param charsetEncoder the charset encoder.
* @since 2.1
- * @deprecated Use {@link ReaderInputStream#builder()} instead
+ * @deprecated Use {@link ReaderInputStream#builder()} instead.
*/
@Deprecated
public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncoder) {
@@ -303,9 +298,9 @@ public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncode
*
* @param reader the target {@link Reader}
* @param charsetEncoder the charset encoder, null defaults to the default Charset encoder.
- * @param bufferSize the size of the input buffer in number of characters
+ * @param bufferSize the size of the input buffer in number of characters.
* @since 2.1
- * @deprecated Use {@link ReaderInputStream#builder()} instead
+ * @deprecated Use {@link ReaderInputStream#builder()} instead.
*/
@Deprecated
public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncoder, final int bufferSize) {
@@ -325,8 +320,8 @@ public ReaderInputStream(final Reader reader, final CharsetEncoder charsetEncode
*
*
* @param reader the target {@link Reader}
- * @param charsetName the name of the charset encoding
- * @deprecated Use {@link ReaderInputStream#builder()} instead
+ * @param charsetName the name of the charset encoding.
+ * @deprecated Use {@link ReaderInputStream#builder()} instead.
*/
@Deprecated
public ReaderInputStream(final Reader reader, final String charsetName) {
@@ -342,8 +337,8 @@ public ReaderInputStream(final Reader reader, final String charsetName) {
*
* @param reader the target {@link Reader}
* @param charsetName the name of the charset encoding, null maps to the default Charset.
- * @param bufferSize the size of the input buffer in number of characters
- * @deprecated Use {@link ReaderInputStream#builder()} instead
+ * @param bufferSize the size of the input buffer in number of characters.
+ * @deprecated Use {@link ReaderInputStream#builder()} instead.
*/
@Deprecated
public ReaderInputStream(final Reader reader, final String charsetName, final int bufferSize) {
@@ -372,7 +367,7 @@ public void close() throws IOException {
/**
* Fills the internal char buffer from the reader.
*
- * @throws IOException If an I/O error occurs
+ * @throws IOException If an I/O error occurs.
*/
private void fillBuffer() throws IOException {
if (endOfInput) {
@@ -415,7 +410,7 @@ CharsetEncoder getCharsetEncoder() {
/**
* Reads a single byte.
*
- * @return either the byte read or {@code -1} if the end of the stream has been reached
+ * @return either the byte read or {@code -1} if the end of the stream has been reached.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -436,7 +431,7 @@ public int read() throws IOException {
* Reads the specified number of bytes into an array.
*
* @param b the byte array to read into, must not be {@code null}
- * @return the number of bytes read or {@code -1} if the end of the stream has been reached
+ * @return the number of bytes read or {@code -1} if the end of the stream has been reached.
* @throws NullPointerException if the byte array is {@code null}.
* @throws IOException if an I/O error occurs.
*/
@@ -448,10 +443,10 @@ public int read(final byte[] b) throws IOException {
/**
* Reads the specified number of bytes into an array.
*
- * @param array the byte array to read into
- * @param off the offset to start reading bytes into
- * @param len the number of bytes to read
- * @return the number of bytes read or {@code -1} if the end of the stream has been reached
+ * @param array the byte array to read into.
+ * @param off the offset to start reading bytes into.
+ * @param len the number of bytes to read.
+ * @return the number of bytes read or {@code -1} if the end of the stream has been reached.
* @throws NullPointerException if the byte array is {@code null}.
* @throws IndexOutOfBoundsException if {@code off} or {@code len} are negative, or if {@code off + len} is greater than {@code array.length}.
* @throws IOException if an I/O error occurs.
diff --git a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
index 949ff8cbd8e..43ad4da1040 100644
--- a/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
+++ b/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java
@@ -25,7 +25,6 @@
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
@@ -93,6 +92,7 @@ public static class Builder extends AbstractStreamBuilder -1) {
if (!isLastFilePart && i < avoidNewlineSplitBufferSize) {
@@ -234,6 +241,10 @@ private String readLine() { //NOPMD Bug in PMD
line = new String(lineData, charset);
currentLastBytePos = i - newLineMatchByteCount;
+
+ if (isLastFilePart && currentLastBytePos == -1 && i == 0) {
+ leftOver = new byte[0];
+ }
break; // found line
}
@@ -242,14 +253,22 @@ private String readLine() { //NOPMD Bug in PMD
// end of file part handling
if (i < 0) {
- createLeftOver();
+ if (isLastFilePart) {
+ final int lineLengthBytes = currentLastBytePos + 1;
+ if (lineLengthBytes > 0) {
+ final byte[] lineData = Arrays.copyOf(data, lineLengthBytes);
+ line = new String(lineData, charset);
+ }
+ currentLastBytePos = -1;
+ } else {
+ createLeftOver();
+ }
break; // end of file part
}
}
- // last file part handling
- if (isLastFilePart && leftOver != null) {
- // there will be partNumber line break anymore, this is the first line of the file
+ // there will be partNumber line break anymore, this is the first line of the file
+ if (line == null && isLastFilePart && leftOver != null) {
line = new String(leftOver, charset);
leftOver = null;
}
@@ -260,8 +279,8 @@ private String readLine() { //NOPMD Bug in PMD
/**
* Handles block rollover
*
- * @return the new FilePart or null
- * @throws IOException if there was a problem reading the file
+ * @return the new FilePart or null.
+ * @throws IOException if there was a problem reading the file.
*/
private FilePart rollOver() throws IOException {
@@ -311,42 +330,42 @@ private ReversedLinesFileReader(final Builder builder) throws IOException {
this.blockSize = builder.getBufferSize();
this.charset = Charsets.toCharset(builder.getCharset());
// check & prepare encoding
- final CharsetEncoder charsetEncoder = this.charset.newEncoder();
+ final CharsetEncoder charsetEncoder = charset.newEncoder();
final float maxBytesPerChar = charsetEncoder.maxBytesPerChar();
- if (maxBytesPerChar == 1f || this.charset == StandardCharsets.UTF_8) {
+ if (maxBytesPerChar == 1f || charset == StandardCharsets.UTF_8) {
// all one byte encodings are partNumber problem
byteDecrement = 1;
- } else if (this.charset == Charset.forName("Shift_JIS") || // Same as for UTF-8
+ } else if (charset == Charset.forName("Shift_JIS") || // Same as for UTF-8
// http://www.herongyang.com/Unicode/JIS-Shift-JIS-Encoding.html
- this.charset == Charset.forName("windows-31j") || // Windows code page 932 (Japanese)
- this.charset == Charset.forName("x-windows-949") || // Windows code page 949 (Korean)
- this.charset == Charset.forName("gbk") || // Windows code page 936 (Simplified Chinese)
- this.charset == Charset.forName("x-windows-950")) { // Windows code page 950 (Traditional Chinese)
+ charset == Charset.forName("windows-31j") || // Windows code page 932 (Japanese)
+ charset == Charset.forName("x-windows-949") || // Windows code page 949 (Korean)
+ charset == Charset.forName("gbk") || // Windows code page 936 (Simplified Chinese)
+ charset == Charset.forName("x-windows-950")) { // Windows code page 950 (Traditional Chinese)
byteDecrement = 1;
- } else if (this.charset == StandardCharsets.UTF_16BE || this.charset == StandardCharsets.UTF_16LE) {
+ } else if (charset == StandardCharsets.UTF_16BE || charset == StandardCharsets.UTF_16LE) {
// UTF-16 new line sequences are not allowed as second tuple of four byte
// sequences,
// however byte order has to be specified
byteDecrement = 2;
- } else if (this.charset == StandardCharsets.UTF_16) {
+ } else if (charset == StandardCharsets.UTF_16) {
throw new UnsupportedEncodingException("For UTF-16, you need to specify the byte order (use UTF-16BE or UTF-16LE)");
} else {
throw new UnsupportedEncodingException("Encoding " + charset + " is not supported yet (feel free to submit a patch)");
}
// NOTE: The new line sequences are matched in the order given, so it is
// important that \r\n is BEFORE \n
- this.newLineSequences = new byte[][] { StandardLineSeparator.CRLF.getBytes(this.charset), StandardLineSeparator.LF.getBytes(this.charset),
- StandardLineSeparator.CR.getBytes(this.charset) };
+ this.newLineSequences = new byte[][] { StandardLineSeparator.CRLF.getBytes(charset), StandardLineSeparator.LF.getBytes(charset),
+ StandardLineSeparator.CR.getBytes(charset) };
this.avoidNewlineSplitBufferSize = newLineSequences[0].length;
// Open file
- this.channel = Files.newByteChannel(builder.getPath(), StandardOpenOption.READ);
+ this.channel = builder.getChannel(SeekableByteChannel.class);
this.totalByteLength = channel.size();
- int lastBlockLength = (int) (this.totalByteLength % blockSize);
+ int lastBlockLength = (int) (totalByteLength % blockSize);
if (lastBlockLength > 0) {
- this.totalBlockCount = this.totalByteLength / blockSize + 1;
+ this.totalBlockCount = totalByteLength / blockSize + 1;
} else {
- this.totalBlockCount = this.totalByteLength / blockSize;
- if (this.totalByteLength > 0) {
+ this.totalBlockCount = totalByteLength / blockSize;
+ if (totalByteLength > 0) {
lastBlockLength = blockSize;
}
}
@@ -354,9 +373,9 @@ private ReversedLinesFileReader(final Builder builder) throws IOException {
}
/**
- * Constructs a ReversedLinesFileReader with default block size of 4KB and the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Constructs a ReversedLinesFileReader with default block size of 4KB and the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
- * @param file the file to be read
+ * @param file the file to be read.
* @throws IOException if an I/O error occurs.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@@ -369,7 +388,7 @@ public ReversedLinesFileReader(final File file) throws IOException {
* Constructs a ReversedLinesFileReader with default block size of 4KB and the
* specified encoding.
*
- * @param file the file to be read
+ * @param file the file to be read.
* @param charset the charset to use, null uses the default Charset.
* @throws IOException if an I/O error occurs.
* @since 2.5
@@ -383,7 +402,7 @@ public ReversedLinesFileReader(final File file, final Charset charset) throws IO
/**
* Constructs a ReversedLinesFileReader with the given block size and encoding.
*
- * @param file the file to be read
+ * @param file the file to be read.
* @param blockSize size of the internal buffer (for ideal performance this
* should match with the block size of the underlying file
* system).
@@ -400,13 +419,13 @@ public ReversedLinesFileReader(final File file, final int blockSize, final Chars
/**
* Constructs a ReversedLinesFileReader with the given block size and encoding.
*
- * @param file the file to be read
+ * @param file the file to be read.
* @param blockSize size of the internal buffer (for ideal performance this
* should match with the block size of the underlying file
* system).
* @param charsetName the encoding of the file, null uses the default Charset.
- * @throws IOException if an I/O error occurs
- * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported
+ * @throws IOException if an I/O error occurs.
+ * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@Deprecated
@@ -418,7 +437,7 @@ public ReversedLinesFileReader(final File file, final int blockSize, final Strin
* Constructs a ReversedLinesFileReader with default block size of 4KB and the
* specified encoding.
*
- * @param file the file to be read
+ * @param file the file to be read.
* @param charset the charset to use, null uses the default Charset.
* @throws IOException if an I/O error occurs.
* @since 2.7
@@ -432,7 +451,7 @@ public ReversedLinesFileReader(final Path file, final Charset charset) throws IO
/**
* Constructs a ReversedLinesFileReader with the given block size and encoding.
*
- * @param file the file to be read
+ * @param file the file to be read.
* @param blockSize size of the internal buffer (for ideal performance this
* should match with the block size of the underlying file
* system).
@@ -449,13 +468,13 @@ public ReversedLinesFileReader(final Path file, final int blockSize, final Chars
/**
* Constructs a ReversedLinesFileReader with the given block size and encoding.
*
- * @param file the file to be read
+ * @param file the file to be read.
* @param blockSize size of the internal buffer (for ideal performance this
* should match with the block size of the underlying file
* system).
* @param charsetName the encoding of the file, null uses the default Charset.
- * @throws IOException if an I/O error occurs
- * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported
+ * @throws IOException if an I/O error occurs.
+ * @throws java.nio.charset.UnsupportedCharsetException if the encoding is not supported.
* @since 2.7
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}
*/
@@ -509,7 +528,7 @@ public Iterator unwrap() {
/**
* Returns the lines of the file from bottom to top.
*
- * @return the next line or null if the start of the file is reached
+ * @return the next line or null if the start of the file is reached.
* @throws IOException if an I/O error occurs.
*/
public String readLine() throws IOException {
@@ -541,7 +560,7 @@ public String readLine() throws IOException {
*
*
* @param lineCount How many lines to read.
- * @return A new list
+ * @return A new list.
* @throws IOException if an I/O error occurs.
* @since 2.8.0
*/
diff --git a/src/main/java/org/apache/commons/io/input/SequenceReader.java b/src/main/java/org/apache/commons/io/input/SequenceReader.java
index daeb71faa92..269ce1cb8be 100644
--- a/src/main/java/org/apache/commons/io/input/SequenceReader.java
+++ b/src/main/java/org/apache/commons/io/input/SequenceReader.java
@@ -44,7 +44,7 @@ public class SequenceReader extends Reader {
/**
* Constructs a new instance with readers
*
- * @param readers the readers to read
+ * @param readers the readers to read.
*/
public SequenceReader(final Iterable extends Reader> readers) {
this.readers = Objects.requireNonNull(readers, "readers").iterator();
@@ -54,7 +54,7 @@ public SequenceReader(final Iterable extends Reader> readers) {
/**
* Constructs a new instance with readers
*
- * @param readers the readers to read
+ * @param readers the readers to read.
*/
public SequenceReader(final Reader... readers) {
this(Arrays.asList(readers));
diff --git a/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java b/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
index a901ec6bc74..72e46367490 100644
--- a/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/SwappedDataInputStream.java
@@ -37,7 +37,7 @@ public class SwappedDataInputStream extends ProxyInputStream implements DataInpu
/**
* Constructs a SwappedDataInputStream.
*
- * @param input InputStream to read from
+ * @param input InputStream to read from.
*/
public SwappedDataInputStream(final InputStream input) {
super(input);
@@ -46,9 +46,9 @@ public SwappedDataInputStream(final InputStream input) {
/**
* Return {@code {@link #readByte()} != 0}
*
- * @return false if the byte read is zero, otherwise true
+ * @return false if the byte read is zero, otherwise true.
* @throws IOException if an I/O error occurs.
- * @throws EOFException if an end of file is reached unexpectedly
+ * @throws EOFException if an end of file is reached unexpectedly.
*/
@Override
public boolean readBoolean() throws IOException, EOFException {
@@ -58,9 +58,9 @@ public boolean readBoolean() throws IOException, EOFException {
/**
* Invokes the delegate's {@code read()} method.
*
- * @return the byte read or -1 if the end of stream
+ * @return the byte read or -1 if the end of stream.
* @throws IOException if an I/O error occurs.
- * @throws EOFException if an end of file is reached unexpectedly
+ * @throws EOFException if an end of file is reached unexpectedly.
*/
@Override
public byte readByte() throws IOException, EOFException {
@@ -70,9 +70,9 @@ public byte readByte() throws IOException, EOFException {
/**
* Reads a 2 byte, unsigned, little-endian UTF-16 code point.
*
- * @return the UTF-16 code point read or -1 if the end of stream
+ * @return the UTF-16 code point read or -1 if the end of stream.
* @throws IOException if an I/O error occurs.
- * @throws EOFException if an end of file is reached unexpectedly
+ * @throws EOFException if an end of file is reached unexpectedly.
*/
@Override
public char readChar() throws IOException, EOFException {
@@ -82,9 +82,9 @@ public char readChar() throws IOException, EOFException {
/**
* Reads an 8 byte, two's complement, little-endian long.
*
- * @return the read long
+ * @return the read long.
* @throws IOException if an I/O error occurs.
- * @throws EOFException if an end of file is reached unexpectedly
+ * @throws EOFException if an end of file is reached unexpectedly.
*/
@Override
public double readDouble() throws IOException, EOFException {
@@ -94,9 +94,9 @@ public double readDouble() throws IOException, EOFException {
/**
* Reads a 4 byte, IEEE 754, little-endian float.
*
- * @return the read float
+ * @return the read float.
* @throws IOException if an I/O error occurs.
- * @throws EOFException if an end of file is reached unexpectedly
+ * @throws EOFException if an end of file is reached unexpectedly.
*/
@Override
public float readFloat() throws IOException, EOFException {
@@ -106,8 +106,8 @@ public float readFloat() throws IOException, EOFException {
/**
* Invokes the delegate's {@code read(byte[] data, int, int)} method.
*
- * @param data the buffer to read the bytes into
- * @throws EOFException if an end of file is reached unexpectedly
+ * @param data the buffer to read the bytes into.
+ * @throws EOFException if an end of file is reached unexpectedly.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -118,10 +118,10 @@ public void readFully(final byte[] data) throws IOException, EOFException {
/**
* Invokes the delegate's {@code read(byte[] data, int, int)} method.
*
- * @param data the buffer to read the bytes into
- * @param offset The start offset
- * @param length The number of bytes to read
- * @throws EOFException if an end of file is reached unexpectedly
+ * @param data the buffer to read the bytes into.
+ * @param offset The start offset.
+ * @param length The number of bytes to read.
+ * @throws EOFException if an end of file is reached unexpectedly.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -143,8 +143,8 @@ public void readFully(final byte[] data, final int offset, final int length) thr
/**
* Reads a 4 byte, two's complement little-endian integer.
*
- * @return the read int
- * @throws EOFException if an end of file is reached unexpectedly
+ * @return the read int.
+ * @throws EOFException if an end of file is reached unexpectedly.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -155,10 +155,10 @@ public int readInt() throws IOException, EOFException {
/**
* Not currently supported - throws {@link UnsupportedOperationException}.
*
- * @return the line read
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- * @throws UnsupportedOperationException always
+ * @return the line read.
+ * @throws EOFException if an end of file is reached unexpectedly.
+ * @throws IOException if an I/O error occurs.
+ * @throws UnsupportedOperationException always.
*/
@Override
public String readLine() throws IOException, EOFException {
@@ -168,8 +168,8 @@ public String readLine() throws IOException, EOFException {
/**
* Reads an 8 byte, two's complement little-endian integer.
*
- * @return the read long
- * @throws EOFException if an end of file is reached unexpectedly
+ * @return the read long.
+ * @throws EOFException if an end of file is reached unexpectedly.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -180,8 +180,8 @@ public long readLong() throws IOException, EOFException {
/**
* Reads a 2 byte, two's complement, little-endian integer.
*
- * @return the read short
- * @throws EOFException if an end of file is reached unexpectedly
+ * @return the read short.
+ * @throws EOFException if an end of file is reached unexpectedly.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -192,8 +192,8 @@ public short readShort() throws IOException, EOFException {
/**
* Invokes the delegate's {@code read()} method.
*
- * @return the byte read or -1 if the end of stream
- * @throws EOFException if an end of file is reached unexpectedly
+ * @return the byte read or -1 if the end of stream.
+ * @throws EOFException if an end of file is reached unexpectedly.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -204,8 +204,8 @@ public int readUnsignedByte() throws IOException, EOFException {
/**
* Reads a 2 byte, unsigned, little-endian integer.
*
- * @return the read short
- * @throws EOFException if an end of file is reached unexpectedly
+ * @return the read short.
+ * @throws EOFException if an end of file is reached unexpectedly.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -216,10 +216,10 @@ public int readUnsignedShort() throws IOException, EOFException {
/**
* Not currently supported - throws {@link UnsupportedOperationException}.
*
- * @return never
- * @throws EOFException if an end of file is reached unexpectedly
- * @throws IOException if an I/O error occurs
- * @throws UnsupportedOperationException always
+ * @return never.
+ * @throws EOFException if an end of file is reached unexpectedly.
+ * @throws IOException if an I/O error occurs.
+ * @throws UnsupportedOperationException always.
*/
@Override
public String readUTF() throws IOException, EOFException {
@@ -229,9 +229,9 @@ public String readUTF() throws IOException, EOFException {
/**
* Invokes the delegate's {@code skip(int)} method.
*
- * @param count the number of bytes to skip
- * @return the number of bytes skipped or -1 if the end of stream
- * @throws IOException if an I/O error occurs
+ * @param count the number of bytes to skip.
+ * @return the number of bytes skipped or -1 if the end of stream.
+ * @throws IOException if an I/O error occurs.
*/
@Override
public int skipBytes(final int count) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/TaggedInputStream.java b/src/main/java/org/apache/commons/io/input/TaggedInputStream.java
index 141f9c54602..88ad492246d 100644
--- a/src/main/java/org/apache/commons/io/input/TaggedInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/TaggedInputStream.java
@@ -76,7 +76,7 @@ public class TaggedInputStream extends ProxyInputStream {
/**
* Constructs a tagging decorator for the given input stream.
*
- * @param proxy input stream to be decorated
+ * @param proxy input stream to be decorated.
*/
public TaggedInputStream(final InputStream proxy) {
super(proxy);
@@ -85,7 +85,7 @@ public TaggedInputStream(final InputStream proxy) {
/**
* Tags any IOExceptions thrown, wrapping and re-throwing.
*
- * @param e The IOException thrown
+ * @param e The IOException thrown.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -96,9 +96,9 @@ protected void handleIOException(final IOException e) throws IOException {
/**
* Tests if the given exception was caused by this stream.
*
- * @param exception an exception
+ * @param exception an exception.
* @return {@code true} if the exception was thrown by this stream,
- * {@code false} otherwise
+ * {@code false} otherwise.
*/
public boolean isCauseOf(final Throwable exception) {
return TaggedIOException.isTaggedWith(exception, tag);
@@ -111,8 +111,8 @@ public boolean isCauseOf(final Throwable exception) {
* original wrapped exception. Returns normally if the exception was
* not thrown by this stream.
*
- * @param throwable an exception
- * @throws IOException original exception, if any, thrown by this stream
+ * @param throwable an exception.
+ * @throws IOException original exception, if any, thrown by this stream.
*/
public void throwIfCauseOf(final Throwable throwable) throws IOException {
TaggedIOException.throwCauseIfTaggedWith(throwable, tag);
diff --git a/src/main/java/org/apache/commons/io/input/TaggedReader.java b/src/main/java/org/apache/commons/io/input/TaggedReader.java
index 97297a9fd28..2573873d271 100644
--- a/src/main/java/org/apache/commons/io/input/TaggedReader.java
+++ b/src/main/java/org/apache/commons/io/input/TaggedReader.java
@@ -75,7 +75,7 @@ public class TaggedReader extends ProxyReader {
/**
* Constructs a tagging decorator for the given reader.
*
- * @param proxy reader to be decorated
+ * @param proxy reader to be decorated.
*/
public TaggedReader(final Reader proxy) {
super(proxy);
@@ -84,7 +84,7 @@ public TaggedReader(final Reader proxy) {
/**
* Tags any IOExceptions thrown, wrapping and re-throwing.
*
- * @param e The IOException thrown
+ * @param e The IOException thrown.
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -95,8 +95,8 @@ protected void handleIOException(final IOException e) throws IOException {
/**
* Tests if the given exception was caused by this reader.
*
- * @param exception an exception
- * @return {@code true} if the exception was thrown by this reader, {@code false} otherwise
+ * @param exception an exception.
+ * @return {@code true} if the exception was thrown by this reader, {@code false} otherwise.
*/
public boolean isCauseOf(final Throwable exception) {
return TaggedIOException.isTaggedWith(exception, tag);
@@ -107,8 +107,8 @@ public boolean isCauseOf(final Throwable exception) {
* {@link TaggedIOException} wrapper created by this decorator, and then unwraps and throws the original wrapped
* exception. Returns normally if the exception was not thrown by this reader.
*
- * @param throwable an exception
- * @throws IOException original exception, if any, thrown by this reader
+ * @param throwable an exception.
+ * @throws IOException original exception, if any, thrown by this reader.
*/
public void throwIfCauseOf(final Throwable throwable) throws IOException {
TaggedIOException.throwCauseIfTaggedWith(throwable, tag);
diff --git a/src/main/java/org/apache/commons/io/input/Tailer.java b/src/main/java/org/apache/commons/io/input/Tailer.java
index 4d9fe9c4751..d8ef0db0818 100644
--- a/src/main/java/org/apache/commons/io/input/Tailer.java
+++ b/src/main/java/org/apache/commons/io/input/Tailer.java
@@ -275,7 +275,7 @@ protected Builder setOrigin(final AbstractOrigin, ?> origin) {
/**
* Sets the re-open behavior.
*
- * @param reOpen whether to close/reopen the file between chunks
+ * @param reOpen whether to close/reopen the file between chunks.
* @return {@code this} instance.
*/
public Builder setReOpen(final boolean reOpen) {
@@ -495,7 +495,7 @@ public String toString() {
private static final String RAF_READ_ONLY_MODE = "r";
/**
- * The the virtual machine's {@link Charset#defaultCharset() default charset} used for reading files.
+ * The the virtual machine's {@linkplain Charset#defaultCharset() default charset} used for reading files.
*/
private static final Charset DEFAULT_CHARSET = Charset.defaultCharset();
@@ -740,12 +740,12 @@ private Tailer(final Builder builder) {
* Creates a Tailer for the given file, with a specified buffer size.
*
* @param file the file to follow.
- * @param charset the Charset to be used for reading the file
+ * @param charset the Charset to be used for reading the file.
* @param tailerListener the TailerListener to use.
* @param delayMillis the delay between checks of the file for new content in milliseconds.
* @param end Set to true to tail from the end of the file, false to tail from the beginning of the file.
- * @param reOpen if true, close and reopen the file between reading chunks
- * @param bufSize Buffer size
+ * @param reOpen if true, close and reopen the file between reading chunks.
+ * @param bufSize Buffer size.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -800,7 +800,7 @@ public Tailer(final File file, final TailerListener tailerListener, final long d
* @param tailerListener the TailerListener to use.
* @param delayMillis the delay between checks of the file for new content in milliseconds.
* @param end Set to true to tail from the end of the file, false to tail from the beginning of the file.
- * @param reOpen if true, close and reopen the file between reading chunks
+ * @param reOpen if true, close and reopen the file between reading chunks.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -815,8 +815,8 @@ public Tailer(final File file, final TailerListener tailerListener, final long d
* @param tailerListener the TailerListener to use.
* @param delayMillis the delay between checks of the file for new content in milliseconds.
* @param end Set to true to tail from the end of the file, false to tail from the beginning of the file.
- * @param reOpen if true, close and reopen the file between reading chunks
- * @param bufferSize Buffer size
+ * @param reOpen if true, close and reopen the file between reading chunks.
+ * @param bufferSize Buffer size.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -831,7 +831,7 @@ public Tailer(final File file, final TailerListener tailerListener, final long d
* @param tailerListener the TailerListener to use.
* @param delayMillis the delay between checks of the file for new content in milliseconds.
* @param end Set to true to tail from the end of the file, false to tail from the beginning of the file.
- * @param bufferSize Buffer size
+ * @param bufferSize Buffer size.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -843,13 +843,13 @@ public Tailer(final File file, final TailerListener tailerListener, final long d
* Creates a Tailer for the given file, with a specified buffer size.
*
* @param tailable the file to follow.
- * @param charset the Charset to be used for reading the file
+ * @param charset the Charset to be used for reading the file.
* @param tailerListener the TailerListener to use.
* @param delayDuration the delay between checks of the file for new content in milliseconds.
* @param tailAtEnd Set to true to tail from the end of the file, false to tail from the beginning of the file.
- * @param reOpen if true, close and reopen the file between reading chunks
- * @param ignoreTouch if true, file timestamp changes without content change get ignored
- * @param bufferSize Buffer size
+ * @param reOpen if true, close and reopen the file between reading chunks.
+ * @param ignoreTouch if true, file timestamp changes without content change get ignored.
+ * @param bufferSize Buffer size.
*/
private Tailer(final Tailable tailable, final Charset charset, final TailerListener tailerListener, final Duration delayDuration, final boolean tailAtEnd,
final boolean reOpen, final int bufferSize, final boolean ignoreTouch) {
@@ -897,8 +897,8 @@ public Duration getDelayDuration() {
/**
* Gets the file.
*
- * @return the file
- * @throws IllegalStateException if constructed using a user provided {@link Tailable} implementation
+ * @return the file.
+ * @throws IllegalStateException if constructed using a user provided {@link Tailable} implementation.
*/
public File getFile() {
if (tailable instanceof TailablePath) {
@@ -920,7 +920,7 @@ protected boolean getRun() {
/**
* Gets the Tailable.
*
- * @return the Tailable
+ * @return the Tailable.
* @since 2.12.0
*/
public Tailable getTailable() {
@@ -930,8 +930,8 @@ public Tailable getTailable() {
/**
* Reads new lines.
*
- * @param reader The file to read
- * @return The new position after the lines have been read
+ * @param reader The file to read.
+ * @return The new position after the lines have been read.
* @throws IOException if an I/O error occurs.
*/
private long readLines(final RandomAccessResourceBridge reader) throws IOException {
@@ -1043,7 +1043,7 @@ public void run() {
* - gets "touched"
* - Files.getLastModifiedTime returns a new timestamp but newer data is not yet there (
* was reported to happen on busy systems or samba network shares, see IO-279)
- * The default behaviour is to replay the whole file. If this is unsdesired in your usecase,
+ * The default behavior is to replay the whole file. If this is undesired in your usecase,
* use the ignoreTouch builder flag
*/
if (!ignoreTouch) {
diff --git a/src/main/java/org/apache/commons/io/input/TailerListenerAdapter.java b/src/main/java/org/apache/commons/io/input/TailerListenerAdapter.java
index ac9380f3e79..1a9dfd76c4a 100644
--- a/src/main/java/org/apache/commons/io/input/TailerListenerAdapter.java
+++ b/src/main/java/org/apache/commons/io/input/TailerListenerAdapter.java
@@ -35,7 +35,7 @@ public TailerListenerAdapter() {
*
* Note: this is called from the tailer thread.
*
- * Note: a future version of commons-io will pull this method up to the TailerListener interface,
+ * Note: a future version of Commons IO will pull this method up to the TailerListener interface,
* for now clients must subclass this class to use this feature.
*
* @since 2.5
diff --git a/src/main/java/org/apache/commons/io/input/TeeInputStream.java b/src/main/java/org/apache/commons/io/input/TeeInputStream.java
index 1949f977e09..0c852cd5f88 100644
--- a/src/main/java/org/apache/commons/io/input/TeeInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/TeeInputStream.java
@@ -55,8 +55,8 @@ public class TeeInputStream extends ProxyInputStream {
* and copies all read bytes to the given {@link OutputStream}. The given
* output stream will not be closed when this stream gets closed.
*
- * @param input input stream to be proxied
- * @param branch output stream that will receive a copy of all bytes read
+ * @param input input stream to be proxied.
+ * @param branch output stream that will receive a copy of all bytes read.
*/
public TeeInputStream(final InputStream input, final OutputStream branch) {
this(input, branch, false);
@@ -68,10 +68,10 @@ public TeeInputStream(final InputStream input, final OutputStream branch) {
* output stream will be closed when this stream gets closed if the
* closeBranch parameter is {@code true}.
*
- * @param input input stream to be proxied
- * @param branch output stream that will receive a copy of all bytes read
+ * @param input input stream to be proxied.
+ * @param branch output stream that will receive a copy of all bytes read.
* @param closeBranch flag for closing also the output stream when this
- * stream is closed
+ * stream is closed.
*/
public TeeInputStream(
final InputStream input, final OutputStream branch, final boolean closeBranch) {
@@ -85,7 +85,7 @@ public TeeInputStream(
* output stream. An exception thrown from one stream will not prevent
* closing of the other stream.
*
- * @throws IOException if either of the streams could not be closed
+ * @throws IOException if either of the streams could not be closed.
*/
@Override
public void close() throws IOException {
@@ -102,8 +102,8 @@ public void close() throws IOException {
* Reads a single byte from the proxied input stream and writes it to
* the associated output stream.
*
- * @return next byte from the stream, or -1 if the stream has ended
- * @throws IOException if the stream could not be read (or written)
+ * @return next byte from the stream, or -1 if the stream has ended.
+ * @throws IOException if the stream could not be read (or written).
*/
@Override
public int read() throws IOException {
@@ -118,9 +118,9 @@ public int read() throws IOException {
* Reads bytes from the proxied input stream and writes the read bytes
* to the associated output stream.
*
- * @param bts byte buffer
- * @return number of bytes read, or -1 if the stream has ended
- * @throws IOException if the stream could not be read (or written)
+ * @param bts byte buffer.
+ * @return number of bytes read, or -1 if the stream has ended.
+ * @throws IOException if the stream could not be read (or written).
*/
@Override
public int read(final byte[] bts) throws IOException {
@@ -135,11 +135,11 @@ public int read(final byte[] bts) throws IOException {
* Reads bytes from the proxied input stream and writes the read bytes
* to the associated output stream.
*
- * @param bts byte buffer
- * @param st start offset within the buffer
- * @param end maximum number of bytes to read
- * @return number of bytes read, or -1 if the stream has ended
- * @throws IOException if the stream could not be read (or written)
+ * @param bts byte buffer.
+ * @param st start offset within the buffer.
+ * @param end maximum number of bytes to read.
+ * @return number of bytes read, or -1 if the stream has ended.
+ * @throws IOException if the stream could not be read (or written).
*/
@Override
public int read(final byte[] bts, final int st, final int end) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/TeeReader.java b/src/main/java/org/apache/commons/io/input/TeeReader.java
index 72fa4ecb2f5..892f1d575bf 100644
--- a/src/main/java/org/apache/commons/io/input/TeeReader.java
+++ b/src/main/java/org/apache/commons/io/input/TeeReader.java
@@ -50,8 +50,8 @@ public class TeeReader extends ProxyReader {
* Constructs a TeeReader that proxies the given {@link Reader} and copies all read characters to the given
* {@link Writer}. The given writer will not be closed when this reader gets closed.
*
- * @param input reader to be proxied
- * @param branch writer that will receive a copy of all characters read
+ * @param input reader to be proxied.
+ * @param branch writer that will receive a copy of all characters read.
*/
public TeeReader(final Reader input, final Writer branch) {
this(input, branch, false);
@@ -62,9 +62,9 @@ public TeeReader(final Reader input, final Writer branch) {
* {@link Writer}. The given writer will be closed when this reader gets closed if the closeBranch parameter is
* {@code true}.
*
- * @param input reader to be proxied
- * @param branch writer that will receive a copy of all characters read
- * @param closeBranch flag for closing also the writer when this reader is closed
+ * @param input reader to be proxied.
+ * @param branch writer that will receive a copy of all characters read.
+ * @param closeBranch flag for closing also the writer when this reader is closed.
*/
public TeeReader(final Reader input, final Writer branch, final boolean closeBranch) {
super(input);
@@ -76,7 +76,7 @@ public TeeReader(final Reader input, final Writer branch, final boolean closeBra
* Closes the proxied reader and, if so configured, the associated writer. An exception thrown from the reader will
* not prevent closing of the writer.
*
- * @throws IOException if either the reader or writer could not be closed
+ * @throws IOException if either the reader or writer could not be closed.
*/
@Override
public void close() throws IOException {
@@ -92,8 +92,8 @@ public void close() throws IOException {
/**
* Reads a single character from the proxied reader and writes it to the associated writer.
*
- * @return next character from the reader, or -1 if the reader has ended
- * @throws IOException if the reader could not be read (or written)
+ * @return next character from the reader, or -1 if the reader has ended.
+ * @throws IOException if the reader could not be read (or written).
*/
@Override
public int read() throws IOException {
@@ -107,9 +107,9 @@ public int read() throws IOException {
/**
* Reads characters from the proxied reader and writes the read characters to the associated writer.
*
- * @param chr character buffer
- * @return number of characters read, or -1 if the reader has ended
- * @throws IOException if the reader could not be read (or written)
+ * @param chr character buffer.
+ * @return number of characters read, or -1 if the reader has ended.
+ * @throws IOException if the reader could not be read (or written).
*/
@Override
public int read(final char[] chr) throws IOException {
@@ -123,11 +123,11 @@ public int read(final char[] chr) throws IOException {
/**
* Reads characters from the proxied reader and writes the read characters to the associated writer.
*
- * @param chr character buffer
- * @param st start offset within the buffer
- * @param end maximum number of characters to read
- * @return number of characters read, or -1 if the reader has ended
- * @throws IOException if the reader could not be read (or written)
+ * @param chr character buffer.
+ * @param st start offset within the buffer.
+ * @param end maximum number of characters to read.
+ * @return number of characters read, or -1 if the reader has ended.
+ * @throws IOException if the reader could not be read (or written).
*/
@Override
public int read(final char[] chr, final int st, final int end) throws IOException {
@@ -141,9 +141,9 @@ public int read(final char[] chr, final int st, final int end) throws IOExceptio
/**
* Reads characters from the proxied reader and writes the read characters to the associated writer.
*
- * @param target character buffer
- * @return number of characters read, or -1 if the reader has ended
- * @throws IOException if the reader could not be read (or written)
+ * @param target character buffer.
+ * @return number of characters read, or -1 if the reader has ended.
+ * @throws IOException if the reader could not be read (or written).
*/
@Override
public int read(final CharBuffer target) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/ThrottledInputStream.java b/src/main/java/org/apache/commons/io/input/ThrottledInputStream.java
index b081db3c6e5..e07cdc3eadb 100644
--- a/src/main/java/org/apache/commons/io/input/ThrottledInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/ThrottledInputStream.java
@@ -128,7 +128,7 @@ public ThrottledInputStream get() throws IOException {
* To test idle timeouts for example, use 1 byte per minute, 1 byte per 30 seconds, and so on.
*
*
- * @param value the maximum bytes
+ * @param value the maximum bytes.
* @param chronoUnit a duration scale goal.
* @return {@code this} instance.
* @throws IllegalArgumentException Thrown if maxBytesPerSecond <= 0.
@@ -151,7 +151,7 @@ public Builder setMaxBytes(final long value, final ChronoUnit chronoUnit) {
* To test idle timeouts for example, use 1 byte per minute, 1 byte per 30 seconds, and so on.
*
*
- * @param value the maximum bytes
+ * @param value the maximum bytes.
* @param duration a duration goal.
* @return {@code this} instance.
* @throws IllegalArgumentException Thrown if maxBytesPerSecond <= 0.
@@ -245,21 +245,38 @@ private long getBytesPerSecond() {
return getByteCount() / elapsedSeconds;
}
- // package private for testing.
+ /**
+ * Gets the maximum bytes per second.
+ *
+ * Package private for testing.
+ *
+ *
+ * @return The maximum bytes per second.
+ */
double getMaxBytesPerSecond() {
return maxBytesPerSecond;
}
- private long getSleepMillis() {
+ /**
+ * Gets the number of milliseconds to sleep to match to the maximum bytes per second.
+ *
+ * Package private for testing.
+ *
+ *
+ * @return the number of milliseconds to sleep to match to the maximum bytes per second.
+ */
+ long getSleepMillis() {
return toSleepMillis(getByteCount(), System.currentTimeMillis() - startTime, maxBytesPerSecond);
}
/**
* Gets the total duration spent in sleep.
+ *
+ * Package private for testing
+ *
*
* @return Duration spent in sleep.
*/
- // package private for testing
Duration getTotalSleepDuration() {
return totalSleepDuration;
}
@@ -271,7 +288,8 @@ private void throttle() throws InterruptedIOException {
try {
TimeUnit.MILLISECONDS.sleep(sleepMillis);
} catch (final InterruptedException e) {
- throw new InterruptedIOException("Thread aborted");
+ Thread.currentThread().interrupt();
+ throw Input.toInterruptedIOException(e);
}
}
}
diff --git a/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java b/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java
index ac6e003ab1f..eb6cf216251 100644
--- a/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/UncheckedFilterInputStream.java
@@ -110,7 +110,7 @@ public static Builder builder() {
* Constructs a {@link UncheckedFilterInputStream}.
*
* @param builder A builder providing the underlying input stream.
- * @throws IOException
+ * @throws IOException if an I/O error occurs.
*/
@SuppressWarnings("resource") // caller closes
private UncheckedFilterInputStream(final Builder builder) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java b/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java
index 3d0400fca71..88f31b7854f 100644
--- a/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/UnixLineEndingInputStream.java
@@ -28,37 +28,16 @@
*
* @since 2.5
*/
-public class UnixLineEndingInputStream extends InputStream {
-
- private boolean atEos;
-
- private boolean atSlashCr;
-
- private boolean atSlashLf;
-
- private final InputStream in;
-
- private final boolean lineFeedAtEndOfFile;
+public class UnixLineEndingInputStream extends AbstractLineEndingInputStream {
/**
* Constructs an input stream that filters another stream
*
- * @param inputStream The input stream to wrap
- * @param ensureLineFeedAtEndOfFile true to ensure that the file ends with LF
- */
- public UnixLineEndingInputStream(final InputStream inputStream, final boolean ensureLineFeedAtEndOfFile) {
- this.in = inputStream;
- this.lineFeedAtEndOfFile = ensureLineFeedAtEndOfFile;
- }
-
- /**
- * Closes the stream. Also closes the underlying stream.
- * @throws IOException If an I/O error occurs.
+ * @param inputStream The input stream to wrap.
+ * @param lineFeedAtEos true to ensure that the file ends with LF.
*/
- @Override
- public void close() throws IOException {
- super.close();
- in.close();
+ public UnixLineEndingInputStream(final InputStream inputStream, final boolean lineFeedAtEos) {
+ super(inputStream, lineFeedAtEos);
}
/**
@@ -68,7 +47,7 @@ public void close() throws IOException {
* @return The next char to output to the stream.
*/
private int handleEos(final boolean previousWasSlashCr) {
- if (previousWasSlashCr || !lineFeedAtEndOfFile) {
+ if (previousWasSlashCr || !lineFeedAtEos) {
return EOF;
}
if (!atSlashLf) {
@@ -78,14 +57,6 @@ private int handleEos(final boolean previousWasSlashCr) {
return EOF;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public synchronized void mark(final int readLimit) {
- throw UnsupportedOperationExceptions.mark();
- }
-
/**
* {@inheritDoc}
*/
@@ -95,7 +66,7 @@ public synchronized int read() throws IOException {
if (atEos) {
return handleEos(previousWasSlashR);
}
- final int target = readWithUpdate();
+ final int target = readUpdate();
if (atEos) {
return handleEos(previousWasSlashR);
}
@@ -112,10 +83,11 @@ public synchronized int read() throws IOException {
/**
* Reads the next item from the target, updating internal flags in the process
- * @return the next int read from the target stream
+ *
+ * @return the next int read from the target stream.
* @throws IOException If an I/O error occurs.
*/
- private int readWithUpdate() throws IOException {
+ private int readUpdate() throws IOException {
final int target = this.in.read();
atEos = target == EOF;
if (atEos) {
diff --git a/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java b/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java
index 63874faabb7..fea13e7c4cc 100644
--- a/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java
+++ b/src/main/java/org/apache/commons/io/input/UnsupportedOperationExceptions.java
@@ -31,7 +31,7 @@ final class UnsupportedOperationExceptions {
/**
* Constructs a new instance of UnsupportedOperationException for a {@code mark} method.
*
- * @return a new instance of UnsupportedOperationException
+ * @return a new instance of UnsupportedOperationException.
*/
static UnsupportedOperationException mark() {
// Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1.
@@ -41,8 +41,8 @@ static UnsupportedOperationException mark() {
/**
* Constructs a new instance of UnsupportedOperationException for the given unsupported a {@code method} name.
*
- * @param method A method name
- * @return a new instance of UnsupportedOperationException
+ * @param method A method name.
+ * @return a new instance of UnsupportedOperationException.
*/
static UnsupportedOperationException method(final String method) {
return new UnsupportedOperationException(method + " not supported");
@@ -51,7 +51,7 @@ static UnsupportedOperationException method(final String method) {
/**
* Constructs a new instance of UnsupportedOperationException for a {@code reset} method.
*
- * @return a new instance of UnsupportedOperationException
+ * @return a new instance of UnsupportedOperationException.
*/
static UnsupportedOperationException reset() {
// Use the same message as in java.io.InputStream.reset() in OpenJDK 8.0.275-1.
diff --git a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java
index bde55873f24..b67d9f5254a 100644
--- a/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java
+++ b/src/main/java/org/apache/commons/io/input/UnsynchronizedBufferedReader.java
@@ -77,7 +77,7 @@ public class UnsynchronizedBufferedReader extends UnsynchronizedReader {
*/
private char[] buf;
- private int pos;
+ private int bufPos;
private int end;
@@ -85,6 +85,9 @@ public class UnsynchronizedBufferedReader extends UnsynchronizedReader {
private int markLimit = -1;
+ private long pos;
+ private long posMark;
+
/**
* Constructs a new BufferedReader on the Reader {@code in}. The buffer gets the default size (8 KB).
*
@@ -113,8 +116,8 @@ public UnsynchronizedBufferedReader(final Reader in, final int size) {
* Peeks at the next input character, refilling the buffer if necessary. If this character is a newline character ("\n"), it is discarded.
*/
final void chompNewline() throws IOException {
- if ((pos != end || fillBuf() != EOF) && buf[pos] == LF) {
- pos++;
+ if ((bufPos != end || fillBuf() != EOF) && buf[bufPos] == LF) {
+ bufPos++;
}
}
@@ -134,24 +137,22 @@ public void close() throws IOException {
}
/**
- * Populates the buffer with data. It is an error to call this method when the buffer still contains data; ie. if {@code pos < end}.
+ * Fills the buffer with characters. It is an error to call this method when the buffer still contains data, that is, if {@code pos < end}.
*
* @return the number of bytes read into the buffer, or -1 if the end of the source stream has been reached.
*/
private int fillBuf() throws IOException {
// assert(pos == end);
-
- if (mark == EOF || pos - mark >= markLimit) {
+ if (mark == EOF || bufPos - mark >= markLimit) {
/* mark isn't set or has exceeded its limit. use the whole buffer */
final int result = in.read(buf, 0, buf.length);
if (result > 0) {
mark = -1;
- pos = 0;
+ bufPos = 0;
end = result;
}
return result;
}
-
if (mark == 0 && markLimit > buf.length) {
/* the only way to make room when mark=0 is by growing the buffer */
int newLength = buf.length * 2;
@@ -164,19 +165,48 @@ private int fillBuf() throws IOException {
} else if (mark > 0) {
/* make room by shifting the buffered data to left mark positions */
System.arraycopy(buf, mark, buf, 0, buf.length - mark);
- pos -= mark;
+ bufPos -= mark;
end -= mark;
mark = 0;
}
-
/* Set the new position and mark position */
- final int count = in.read(buf, pos, buf.length - pos);
+ final int count = in.read(buf, bufPos, buf.length - bufPos);
if (count != EOF) {
end += count;
}
return count;
}
+ /**
+ * Gets the character position in the reader.
+ *
+ * Returns {@link Long#MAX_VALUE} instead of overflowing.
+ *
+ *
+ * Since this is a Reader, this is the character position, not the byte position (use an InputStream to count bytes).
+ *
+ *
+ * @return the character position in the reader.
+ * @since 2.23.0
+ */
+ public long getPosition() {
+ return pos;
+ }
+
+ /**
+ * Increments the position by a given value, overflow sets the value to {@link Long#MAX_VALUE};
+ *
+ * @param v a value.
+ * @return the new position.
+ * @since 2.23.0
+ */
+ protected long incPos(final long v) {
+ // Like Math.addExact(long, long) but clamp to Long.MAX_VALUE.
+ final long r = pos + v;
+ // Overflow iff both arguments have the opposite sign of the result.
+ return pos = ((pos ^ r) & (v ^ r)) < 0 ? Long.MAX_VALUE : r;
+ }
+
/**
* Sets a mark position in this reader. The parameter {@code markLimit} indicates how many characters can be read before the mark is invalidated. Calling
* {@link #reset()} will reposition the reader back to the marked position if {@code markLimit} has not been surpassed.
@@ -194,7 +224,8 @@ public void mark(final int markLimit) throws IOException {
}
checkOpen();
this.markLimit = markLimit;
- mark = pos;
+ mark = bufPos;
+ posMark = pos;
}
/**
@@ -212,8 +243,8 @@ public boolean markSupported() {
/**
* Returns the next character in the current reader without consuming it. So the next call to {@link #read()} will still return this value.
*
- * @return the next character
- * @throws IOException If an I/O error occurs
+ * @return the next character.
+ * @throws IOException If an I/O error occurs.
*/
public int peek() throws IOException {
mark(1);
@@ -227,8 +258,8 @@ public int peek() throws IOException {
* still return the next value.
*
* @param buf the buffer to fill for the look ahead.
- * @return the buffer itself
- * @throws IOException If an I/O error occurs
+ * @return the buffer itself.
+ * @throws IOException If an I/O error occurs.
*/
public int peek(final char[] buf) throws IOException {
final int n = buf.length;
@@ -250,8 +281,9 @@ public int peek(final char[] buf) throws IOException {
public int read() throws IOException {
checkOpen();
/* Are there buffered characters available? */
- if (pos < end || fillBuf() != EOF) {
- return buf[pos++];
+ if (bufPos < end || fillBuf() != EOF) {
+ incPos(1);
+ return buf[bufPos++];
}
return EOF;
}
@@ -281,22 +313,19 @@ public int read(final char[] buffer, int offset, final int length) throws IOExce
if (length == 0) {
return 0;
}
-
int outstanding = length;
while (outstanding > 0) {
-
/*
* If there are bytes in the buffer, grab those first.
*/
- final int available = end - pos;
+ final int available = end - bufPos;
if (available > 0) {
final int count = available >= outstanding ? outstanding : available;
- System.arraycopy(buf, pos, buffer, offset, count);
- pos += count;
+ System.arraycopy(buf, bufPos, buffer, offset, count);
+ bufPos += count;
offset += count;
outstanding -= count;
}
-
/*
* Before attempting to read from the underlying stream, make sure we really, really want to. We won't bother if we're done, or if we've already got
* some bytes and reading from the underlying stream would block.
@@ -304,35 +333,31 @@ public int read(final char[] buffer, int offset, final int length) throws IOExce
if (outstanding == 0 || outstanding < length && !in.ready()) {
break;
}
-
// assert(pos == end);
-
/*
* If we're unmarked and the requested size is greater than our buffer, read the bytes directly into the caller's buffer. We don't read into smaller
* buffers because that could result in a many reads.
*/
- if ((mark == -1 || pos - mark >= markLimit) && outstanding >= buf.length) {
+ if ((mark == -1 || bufPos - mark >= markLimit) && outstanding >= buf.length) {
final int count = in.read(buffer, offset, outstanding);
if (count > 0) {
outstanding -= count;
mark = -1;
}
-
break; // assume the source stream gave us all that it could
}
-
if (fillBuf() == EOF) {
break; // source is exhausted
}
}
-
final int count = length - outstanding;
+ incPos(count);
return count > 0 || count == length ? count : EOF;
}
/**
* Returns the next line of text available from this reader. A line is represented by zero or more characters followed by {@code LF}, {@code CR},
- * {@code "\r\n"} or the end of the reader. The string does not include the newline sequence.
+ * {@code "\r\n"}, or the end of the reader. The string does not include the newline sequence.
*
* @return the contents of the line or {@code null} if no characters were read before the end of the reader has been reached.
* @throws IOException if this reader is closed or some other I/O error occurs.
@@ -340,37 +365,37 @@ public int read(final char[] buffer, int offset, final int length) throws IOExce
public String readLine() throws IOException {
checkOpen();
/* has the underlying stream been exhausted? */
- if (pos == end && fillBuf() == EOF) {
+ if (bufPos == end && fillBuf() == EOF) {
return null;
}
- for (int charPos = pos; charPos < end; charPos++) {
+ final int startPos = bufPos;
+ for (int charPos = bufPos; charPos < end; charPos++) {
final char ch = buf[charPos];
if (ch > CR) {
continue;
}
if (ch == LF) {
- final String res = new String(buf, pos, charPos - pos);
- pos = charPos + 1;
+ final String res = new String(buf, bufPos, charPos - bufPos);
+ bufPos = charPos + 1;
+ incPos(bufPos - startPos);
return res;
}
if (ch == CR) {
- final String res = new String(buf, pos, charPos - pos);
- pos = charPos + 1;
- if ((pos < end || fillBuf() != EOF) && buf[pos] == LF) {
- pos++;
+ final String res = new String(buf, bufPos, charPos - bufPos);
+ bufPos = charPos + 1;
+ if ((bufPos < end || fillBuf() != EOF) && buf[bufPos] == LF) {
+ bufPos++;
}
+ incPos(bufPos - startPos);
return res;
}
}
-
char eol = NUL;
+ // Typical Line Length
final StringBuilder result = new StringBuilder(80);
- /* Typical Line Length */
-
- result.append(buf, pos, end - pos);
+ result.append(buf, bufPos, end - bufPos);
while (true) {
- pos = end;
-
+ bufPos = end;
/* Are there buffered characters available? */
if (eol == LF) {
return result.toString();
@@ -380,19 +405,19 @@ public String readLine() throws IOException {
// characters or null.
return result.length() > 0 || eol != NUL ? result.toString() : null;
}
- for (int charPos = pos; charPos < end; charPos++) {
+ for (int charPos = bufPos; charPos < end; charPos++) {
final char c = buf[charPos];
if (eol != NUL) {
if (eol == CR && c == LF) {
- if (charPos > pos) {
- result.append(buf, pos, charPos - pos - 1);
+ if (charPos > bufPos) {
+ result.append(buf, bufPos, charPos - bufPos - 1);
}
- pos = charPos + 1;
+ bufPos = charPos + 1;
} else {
- if (charPos > pos) {
- result.append(buf, pos, charPos - pos - 1);
+ if (charPos > bufPos) {
+ result.append(buf, bufPos, charPos - bufPos - 1);
}
- pos = charPos;
+ bufPos = charPos;
}
return result.toString();
}
@@ -401,9 +426,9 @@ public String readLine() throws IOException {
}
}
if (eol == NUL) {
- result.append(buf, pos, end - pos);
+ result.append(buf, bufPos, end - bufPos);
} else {
- result.append(buf, pos, end - pos - 1);
+ result.append(buf, bufPos, end - bufPos - 1);
}
}
}
@@ -420,7 +445,7 @@ public String readLine() throws IOException {
@Override
public boolean ready() throws IOException {
checkOpen();
- return end - pos > 0 || in.ready();
+ return end - bufPos > 0 || in.ready();
}
/**
@@ -436,7 +461,8 @@ public void reset() throws IOException {
if (mark == -1) {
throw new IOException("mark == -1");
}
- pos = mark;
+ bufPos = mark;
+ pos = posMark;
}
/**
@@ -460,26 +486,39 @@ public long skip(final long amount) throws IOException {
if (amount < 1) {
return 0;
}
- if (end - pos >= amount) {
- pos += Math.toIntExact(amount);
- return amount;
+ if (end - bufPos >= amount) {
+ bufPos += Math.toIntExact(amount);
+ return incPos(amount);
}
-
- long read = end - pos;
- pos = end;
+ long read = end - bufPos;
+ bufPos = end;
while (read < amount) {
if (fillBuf() == EOF) {
- return read;
+ return incPos(read);
}
- if (end - pos >= amount - read) {
- pos += Math.toIntExact(amount - read);
- return amount;
+ if (end - bufPos >= amount - read) {
+ bufPos += Math.toIntExact(amount - read);
+ return incPos(amount);
}
// Couldn't get all the characters, skip what we read
- read += end - pos;
- pos = end;
+ read += end - bufPos;
+ bufPos = end;
}
- return amount;
+ return incPos(amount);
+ }
+
+
+ /**
+ * Unwraps this instance by returning the underlying {@link Reader}.
+ *
@@ -207,13 +203,13 @@ private static int requireNonNegative(final int value, final String name) {
private int markedOffset;
private UnsynchronizedByteArrayInputStream(final Builder builder) throws IOException {
- this(builder.checkOriginByteArray(), builder.offset, builder.length);
+ this(builder.getByteArray(), builder.offset, builder.length);
}
/**
* Constructs a new byte array input stream.
*
- * @param data the buffer
+ * @param data the buffer.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -224,9 +220,9 @@ public UnsynchronizedByteArrayInputStream(final byte[] data) {
/**
* Constructs a new byte array input stream.
*
- * @param data the buffer
- * @param offset the offset into the buffer
- * @throws IllegalArgumentException if the offset is less than zero
+ * @param data the buffer.
+ * @param offset the offset into the buffer.
+ * @throws IllegalArgumentException if the offset is less than zero.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
@@ -237,10 +233,10 @@ public UnsynchronizedByteArrayInputStream(final byte[] data, final int offset) {
/**
* Constructs a new byte array input stream.
*
- * @param data the buffer
- * @param offset the offset into the buffer
- * @param length the length of the buffer
- * @throws IllegalArgumentException if the offset or length less than zero
+ * @param data the buffer.
+ * @param offset the offset into the buffer.
+ * @param length the length of the buffer.
+ * @throws IllegalArgumentException if the offset or length less than zero.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
diff --git a/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java b/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java
index b09deec0d3e..24285adb6d3 100644
--- a/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/WindowsLineEndingInputStream.java
@@ -28,20 +28,10 @@
*
* @since 2.5
*/
-public class WindowsLineEndingInputStream extends InputStream {
-
- private boolean atEos;
-
- private boolean atSlashCr;
-
- private boolean atSlashLf;
-
- private final InputStream in;
+public class WindowsLineEndingInputStream extends AbstractLineEndingInputStream {
private boolean injectSlashLf;
- private final boolean lineFeedAtEos;
-
/**
* Constructs an input stream that filters another stream.
*
@@ -49,19 +39,7 @@ public class WindowsLineEndingInputStream extends InputStream {
* @param lineFeedAtEos true to ensure that the stream ends with CRLF.
*/
public WindowsLineEndingInputStream(final InputStream in, final boolean lineFeedAtEos) {
- this.in = in;
- this.lineFeedAtEos = lineFeedAtEos;
- }
-
- /**
- * Closes the stream. Also closes the underlying stream.
- *
- * @throws IOException If an I/O error occurs.
- */
- @Override
- public void close() throws IOException {
- super.close();
- in.close();
+ super(in, lineFeedAtEos);
}
/**
@@ -85,14 +63,6 @@ private int handleEos() {
return EOF;
}
- /**
- * {@inheritDoc}
- */
- @Override
- public synchronized void mark(final int readLimit) {
- throw UnsupportedOperationExceptions.mark();
- }
-
/**
* {@inheritDoc}
*/
diff --git a/src/main/java/org/apache/commons/io/input/XmlStreamReader.java b/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
index 7f5102e8218..3b667ef1655 100644
--- a/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
+++ b/src/main/java/org/apache/commons/io/input/XmlStreamReader.java
@@ -42,7 +42,6 @@
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.build.AbstractStreamBuilder;
import org.apache.commons.io.function.IOConsumer;
-import org.apache.commons.io.output.XmlStreamWriter;
/**
* Character stream that handles all the necessary Voodoo to figure out the charset encoding of the XML document within the stream.
@@ -76,7 +75,7 @@ public class XmlStreamReader extends Reader {
// @formatter:off
/**
- * Builds a new {@link XmlStreamWriter}.
+ * Builds a new {@link XmlStreamReader}.
*
* Constructs a Reader using an InputStream and the associated content-type header. This constructor is lenient regarding the encoding detection.
*
@@ -131,7 +130,7 @@ public Builder() {
}
/**
- * Builds a new {@link XmlStreamWriter}.
+ * Builds a new {@link XmlStreamReader}.
*
* You must set an aspect that supports {@link #getInputStream()}, otherwise, this method throws an exception.
*
@@ -278,8 +277,8 @@ public static Builder builder() {
/**
* Gets the charset parameter value, {@code null} if not present, {@code null} if httpContentType is {@code null}.
*
- * @param httpContentType the HTTP content type
- * @return The content type encoding (upcased)
+ * @param httpContentType the HTTP content type.
+ * @return The content type encoding (upcased).
*/
static String getContentTypeEncoding(final String httpContentType) {
String encoding = null;
@@ -298,8 +297,8 @@ static String getContentTypeEncoding(final String httpContentType) {
/**
* Gets the MIME type or {@code null} if httpContentType is {@code null}.
*
- * @param httpContentType the HTTP content type
- * @return The mime content type
+ * @param httpContentType the HTTP content type.
+ * @return The mime content type.
*/
static String getContentTypeMime(final String httpContentType) {
String mime = null;
@@ -315,8 +314,8 @@ static String getContentTypeMime(final String httpContentType) {
* Gets the encoding declared in the , {@code null} if none.
*
* @param inputStream InputStream to create the reader from.
- * @param guessedEnc guessed encoding
- * @return the encoding declared in the
+ * @param guessedEnc guessed encoding.
+ * @return the encoding declared in the .
* @throws IOException thrown if there is a problem reading the stream.
*/
private static String getXmlProlog(final InputStream inputStream, final String guessedEnc) throws IOException {
@@ -361,8 +360,8 @@ private static String getXmlProlog(final InputStream inputStream, final String g
/**
* Tests if the MIME type belongs to the APPLICATION XML family.
*
- * @param mime The mime type
- * @return true if the mime type belongs to the APPLICATION XML family, otherwise false
+ * @param mime The mime type.
+ * @return true if the mime type belongs to the APPLICATION XML family, otherwise false.
*/
static boolean isAppXml(final String mime) {
return mime != null && (mime.equals("application/xml") || mime.equals("application/xml-dtd") || mime.equals("application/xml-external-parsed-entity")
@@ -372,8 +371,8 @@ static boolean isAppXml(final String mime) {
/**
* Tests if the MIME type belongs to the TEXT XML family.
*
- * @param mime The mime type
- * @return true if the mime type belongs to the TEXT XML family, otherwise false
+ * @param mime The mime type.
+ * @return true if the mime type belongs to the TEXT XML family, otherwise false.
*/
static boolean isTextXml(final String mime) {
return mime != null && (mime.equals("text/xml") || mime.equals("text/xml-external-parsed-entity") || mime.startsWith("text/") && mime.endsWith("+xml"));
@@ -485,7 +484,7 @@ public XmlStreamReader(final InputStream inputStream, final boolean lenient) thr
*
* @param inputStream InputStream to create a Reader from.
* @param lenient indicates if the charset encoding detection should be relaxed.
- * @param defaultEncoding The default encoding
+ * @param defaultEncoding The default encoding.
* @throws NullPointerException if the input stream is {@code null}.
* @throws IOException thrown if there is a problem reading the stream.
* @throws XmlStreamReaderException thrown if the charset encoding could not be determined according to the specification.
@@ -498,7 +497,7 @@ public XmlStreamReader(final InputStream inputStream, final boolean lenient, fin
final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(Objects.requireNonNull(inputStream, "inputStream"), IOUtils.DEFAULT_BUFFER_SIZE),
false, BOMS);
final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES);
- this.encoding = processHttpStream(bom, pis, lenient);
+ this.encoding = toEncoding(bom, pis, lenient);
this.reader = new InputStreamReader(pis, encoding);
}
@@ -589,7 +588,7 @@ public XmlStreamReader(final InputStream inputStream, final String httpContentTy
* @param inputStream InputStream to create the reader from.
* @param httpContentType content-type header to use for the resolution of the charset encoding.
* @param lenient indicates if the charset encoding detection should be relaxed.
- * @param defaultEncoding The default encoding
+ * @param defaultEncoding The default encoding.
* @throws NullPointerException if the input stream is {@code null}.
* @throws IOException thrown if there is a problem reading the file.
* @throws XmlStreamReaderException thrown if the charset encoding could not be determined according to the specification.
@@ -603,7 +602,7 @@ public XmlStreamReader(final InputStream inputStream, final String httpContentTy
final BOMInputStream bom = new BOMInputStream(new BufferedInputStream(Objects.requireNonNull(inputStream, "inputStream"), IOUtils.DEFAULT_BUFFER_SIZE),
false, BOMS);
final BOMInputStream pis = new BOMInputStream(bom, true, XML_GUESS_BYTES);
- this.encoding = processHttpStream(bom, pis, lenient, httpContentType);
+ this.encoding = toEncoding(bom, pis, lenient, httpContentType);
this.reader = new InputStreamReader(pis, encoding);
}
@@ -662,7 +661,7 @@ public XmlStreamReader(final URL url) throws IOException {
*
*
* @param urlConnection URLConnection to create a Reader from.
- * @param defaultEncoding The default encoding
+ * @param defaultEncoding The default encoding.
* @throws NullPointerException if the input is {@code null}.
* @throws IOException thrown if there is a problem reading the stream of the URLConnection.
*/
@@ -687,51 +686,168 @@ public XmlStreamReader(final URLConnection urlConnection, final String defaultEn
.get();
// @formatter:on
if (urlConnection instanceof HttpURLConnection || contentType != null) {
- this.encoding = processHttpStream(bomInput, piInput, lenient, contentType);
+ this.encoding = toEncoding(bomInput, piInput, lenient, contentType);
} else {
- this.encoding = processHttpStream(bomInput, piInput, lenient);
+ this.encoding = toEncoding(bomInput, piInput, lenient);
}
this.reader = new InputStreamReader(piInput, encoding);
}
/**
- * Calculates the HTTP encoding.
- * @param bomEnc BOM encoding
- * @param xmlGuessEnc XML Guess encoding
- * @param xmlEnc XML encoding
+ * Closes the XmlStreamReader stream.
+ *
+ * @throws IOException thrown if there was a problem closing the stream.
+ */
+ @Override
+ public void close() throws IOException {
+ reader.close();
+ }
+
+ /**
+ * Gets the default encoding to use if none is set in HTTP content-type, XML prolog and the rules based on content-type are not adequate.
+ *
+ * If it is {@code null} the content-type based rules are used.
+ *
+ *
+ * @return the default encoding to use.
+ */
+ public String getDefaultEncoding() {
+ return defaultEncoding;
+ }
+
+ /**
+ * Gets the charset encoding of the XmlStreamReader.
+ *
+ * @return charset encoding.
+ */
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Reads the underlying reader's {@code read(char[], int, int)} method.
+ *
+ * @param buf the buffer to read the characters into.
+ * @param offset The start offset.
+ * @param len The number of bytes to read.
+ * @return the number of characters read or -1 if the end of stream.
+ * @throws IOException if an I/O error occurs.
+ */
+ @Override
+ public int read(final char[] buf, final int offset, final int len) throws IOException {
+ return reader.read(buf, offset, len);
+ }
+
+ /**
+ * Process the raw stream.
+ *
+ * @param bomInput BOMInputStream to detect byte order marks.
+ * @param piInput BOMInputStream to guess XML encoding.
+ * @param lenient indicates if the charset encoding detection should be relaxed.
+ * @return the encoding to be used.
+ * @throws IOException thrown if there is a problem reading the stream.
+ */
+ private String toEncoding(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient) throws IOException {
+ final String bomEnc = bomInput.getBOMCharsetName();
+ final String xmlGuessEnc = piInput.getBOMCharsetName();
+ final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc);
+ try {
+ return toRawEncoding(bomEnc, xmlGuessEnc, xmlEnc);
+ } catch (final XmlStreamReaderException ex) {
+ if (lenient) {
+ return toEncodingLenient(null, ex);
+ }
+ throw ex;
+ }
+ }
+
+ /**
+ * Processes an HTTP stream.
+ *
+ * @param bomInput BOMInputStream to detect byte order marks.
+ * @param piInput BOMInputStream to guess XML encoding.
* @param lenient indicates if the charset encoding detection should be relaxed.
- * @param httpContentType The HTTP content type
- * @return the HTTP encoding
+ * @param httpContentType The HTTP content type.
+ * @return the encoding to be used.
* @throws IOException thrown if there is a problem reading the stream.
*/
- String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String httpContentType)
+ private String toEncoding(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient, final String httpContentType)
throws IOException {
+ final String bomEnc = bomInput.getBOMCharsetName();
+ final String xmlGuessEnc = piInput.getBOMCharsetName();
+ final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc);
+ try {
+ return toHttpEncoding(bomEnc, xmlGuessEnc, xmlEnc, lenient, httpContentType);
+ } catch (final XmlStreamReaderException ex) {
+ if (lenient) {
+ return toEncodingLenient(httpContentType, ex);
+ }
+ throw ex;
+ }
+ }
+ /**
+ * Detects the encoding in lenient mode.
+ *
+ * @param httpContentType content-type header to use for the resolution of the charset encoding.
+ * @param ex The thrown exception.
+ * @return the encoding.
+ * @throws IOException thrown if there is a problem reading the stream.
+ */
+ private String toEncodingLenient(String httpContentType, XmlStreamReaderException ex) throws IOException {
+ if (httpContentType != null && httpContentType.startsWith("text/html")) {
+ httpContentType = httpContentType.substring("text/html".length());
+ httpContentType = "text/xml" + httpContentType;
+ try {
+ return toHttpEncoding(ex.getBomEncoding(), ex.getXmlGuessEncoding(), ex.getXmlEncoding(), true, httpContentType);
+ } catch (final XmlStreamReaderException ex2) {
+ ex = ex2;
+ }
+ }
+ String encoding = ex.getXmlEncoding();
+ if (encoding == null) {
+ encoding = ex.getContentTypeEncoding();
+ }
+ if (encoding == null) {
+ encoding = defaultEncoding == null ? UTF_8 : defaultEncoding;
+ }
+ return encoding;
+ }
+
+ /**
+ * Calculates the HTTP encoding.
+ *
+ * @param bomEnc BOM encoding.
+ * @param xmlGuessEnc XML Guess encoding.
+ * @param xmlEnc XML encoding.
+ * @param lenient indicates if the charset encoding detection should be relaxed.
+ * @param httpContentType The HTTP content type.
+ * @return the HTTP encoding.
+ * @throws IOException thrown if there is a problem reading the stream.
+ */
+ String toHttpEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc, final boolean lenient, final String httpContentType)
+ throws IOException {
// Lenient and has XML encoding
if (lenient && xmlEnc != null) {
return xmlEnc;
}
-
// Determine mime/encoding content types from HTTP Content Type
final String cTMime = getContentTypeMime(httpContentType);
final String cTEnc = getContentTypeEncoding(httpContentType);
final boolean appXml = isAppXml(cTMime);
final boolean textXml = isTextXml(cTMime);
-
// Mime type NOT "application/xml" or "text/xml"
if (!appXml && !textXml) {
final String msg = MessageFormat.format(HTTP_EX_3, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc);
throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc);
}
-
// No content type encoding
if (cTEnc == null) {
if (appXml) {
- return calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc);
+ return toRawEncoding(bomEnc, xmlGuessEnc, xmlEnc);
}
return defaultEncoding == null ? US_ASCII : defaultEncoding;
}
-
// UTF-16BE or UTF-16LE content type encoding
if (cTEnc.equals(UTF_16BE) || cTEnc.equals(UTF_16LE)) {
if (bomEnc != null) {
@@ -740,7 +856,6 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina
}
return cTEnc;
}
-
// UTF-16 content type encoding
if (cTEnc.equals(UTF_16)) {
if (bomEnc != null && bomEnc.startsWith(UTF_16)) {
@@ -749,7 +864,6 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina
final String msg = MessageFormat.format(HTTP_EX_2, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc);
throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc);
}
-
// UTF-32BE or UTF-132E content type encoding
if (cTEnc.equals(UTF_32BE) || cTEnc.equals(UTF_32LE)) {
if (bomEnc != null) {
@@ -758,7 +872,6 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina
}
return cTEnc;
}
-
// UTF-32 content type encoding
if (cTEnc.equals(UTF_32)) {
if (bomEnc != null && bomEnc.startsWith(UTF_32)) {
@@ -767,20 +880,19 @@ String calculateHttpEncoding(final String bomEnc, final String xmlGuessEnc, fina
final String msg = MessageFormat.format(HTTP_EX_2, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc);
throw new XmlStreamReaderException(msg, cTMime, cTEnc, bomEnc, xmlGuessEnc, xmlEnc);
}
-
return cTEnc;
}
/**
* Calculate the raw encoding.
*
- * @param bomEnc BOM encoding
- * @param xmlGuessEnc XML Guess encoding
- * @param xmlEnc XML encoding
- * @return the raw encoding
+ * @param bomEnc BOM encoding.
+ * @param xmlGuessEnc XML Guess encoding.
+ * @param xmlEnc XML encoding.
+ * @return the raw encoding.
* @throws IOException thrown if there is a problem reading the stream.
*/
- String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc) throws IOException {
+ String toRawEncoding(final String bomEnc, final String xmlGuessEnc, final String xmlEnc) throws IOException {
// BOM is Null
if (bomEnc == null) {
@@ -795,11 +907,7 @@ String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final
// BOM is UTF-8
if (bomEnc.equals(UTF_8)) {
- if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8)) {
- final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc);
- throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc);
- }
- if (xmlEnc != null && !xmlEnc.equals(UTF_8)) {
+ if (xmlGuessEnc != null && !xmlGuessEnc.equals(UTF_8) || xmlEnc != null && !xmlEnc.equals(UTF_8)) {
final String msg = MessageFormat.format(RAW_EX_1, bomEnc, xmlGuessEnc, xmlEnc);
throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc);
}
@@ -837,125 +945,4 @@ String calculateRawEncoding(final String bomEnc, final String xmlGuessEnc, final
throw new XmlStreamReaderException(msg, bomEnc, xmlGuessEnc, xmlEnc);
}
- /**
- * Closes the XmlStreamReader stream.
- *
- * @throws IOException thrown if there was a problem closing the stream.
- */
- @Override
- public void close() throws IOException {
- reader.close();
- }
-
- /**
- * Does lenient detection.
- *
- * @param httpContentType content-type header to use for the resolution of the charset encoding.
- * @param ex The thrown exception
- * @return the encoding
- * @throws IOException thrown if there is a problem reading the stream.
- */
- private String doLenientDetection(String httpContentType, XmlStreamReaderException ex) throws IOException {
- if (httpContentType != null && httpContentType.startsWith("text/html")) {
- httpContentType = httpContentType.substring("text/html".length());
- httpContentType = "text/xml" + httpContentType;
- try {
- return calculateHttpEncoding(ex.getBomEncoding(), ex.getXmlGuessEncoding(), ex.getXmlEncoding(), true, httpContentType);
- } catch (final XmlStreamReaderException ex2) {
- ex = ex2;
- }
- }
- String encoding = ex.getXmlEncoding();
- if (encoding == null) {
- encoding = ex.getContentTypeEncoding();
- }
- if (encoding == null) {
- encoding = defaultEncoding == null ? UTF_8 : defaultEncoding;
- }
- return encoding;
- }
-
- /**
- * Gets the default encoding to use if none is set in HTTP content-type, XML prolog and the rules based on content-type are not adequate.
- *
- * If it is {@code null} the content-type based rules are used.
- *
- *
- * @return the default encoding to use.
- */
- public String getDefaultEncoding() {
- return defaultEncoding;
- }
-
- /**
- * Gets the charset encoding of the XmlStreamReader.
- *
- * @return charset encoding.
- */
- public String getEncoding() {
- return encoding;
- }
-
- /**
- * Process the raw stream.
- *
- * @param bomInput BOMInputStream to detect byte order marks
- * @param piInput BOMInputStream to guess XML encoding
- * @param lenient indicates if the charset encoding detection should be relaxed.
- * @return the encoding to be used
- * @throws IOException thrown if there is a problem reading the stream.
- */
- private String processHttpStream(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient) throws IOException {
- final String bomEnc = bomInput.getBOMCharsetName();
- final String xmlGuessEnc = piInput.getBOMCharsetName();
- final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc);
- try {
- return calculateRawEncoding(bomEnc, xmlGuessEnc, xmlEnc);
- } catch (final XmlStreamReaderException ex) {
- if (lenient) {
- return doLenientDetection(null, ex);
- }
- throw ex;
- }
- }
-
- /**
- * Processes an HTTP stream.
- *
- * @param bomInput BOMInputStream to detect byte order marks
- * @param piInput BOMInputStream to guess XML encoding
- * @param lenient indicates if the charset encoding detection should be relaxed.
- * @param httpContentType The HTTP content type
- * @return the encoding to be used
- * @throws IOException thrown if there is a problem reading the stream.
- */
- private String processHttpStream(final BOMInputStream bomInput, final BOMInputStream piInput, final boolean lenient, final String httpContentType)
- throws IOException {
- final String bomEnc = bomInput.getBOMCharsetName();
- final String xmlGuessEnc = piInput.getBOMCharsetName();
- final String xmlEnc = getXmlProlog(piInput, xmlGuessEnc);
- try {
- return calculateHttpEncoding(bomEnc, xmlGuessEnc, xmlEnc, lenient, httpContentType);
- } catch (final XmlStreamReaderException ex) {
- if (lenient) {
- return doLenientDetection(httpContentType, ex);
- }
- throw ex;
- }
- }
-
- /**
- * Reads the underlying reader's {@code read(char[], int, int)} method.
- *
- * @param buf the buffer to read the characters into
- * @param offset The start offset
- * @param len The number of bytes to read
- * @return the number of characters read or -1 if the end of stream
- * @throws IOException if an I/O error occurs.
- */
- @Override
- public int read(final char[] buf, final int offset, final int len) throws IOException {
- return reader.read(buf, offset, len);
- }
-
}
diff --git a/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java b/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java
index b92163478d0..cea865ae066 100644
--- a/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/buffer/CircularBufferInputStream.java
@@ -104,8 +104,8 @@ protected void fillBuffer() throws IOException {
/**
* Fills the buffer from the input stream until the given number of bytes have been added to the buffer.
*
- * @param count number of byte to fill into the buffer
- * @return true if the buffer has bytes
+ * @param count number of byte to fill into the buffer.
+ * @return true if the buffer has bytes.
* @throws IOException in case of an error while reading from the input stream.
*/
protected boolean haveBytes(final int count) throws IOException {
diff --git a/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java b/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java
index 43c8e71bd4a..64780b7c709 100644
--- a/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java
+++ b/src/main/java/org/apache/commons/io/input/buffer/CircularByteBuffer.java
@@ -46,7 +46,7 @@ public CircularByteBuffer() {
/**
* Constructs a new instance with the given buffer size.
*
- * @param size the size of buffer to create
+ * @param size the size of buffer to create.
*/
public CircularByteBuffer(final int size) {
buffer = IOUtils.byteArray(size);
@@ -79,9 +79,9 @@ public void add(final byte value) {
* for the bytes at offsets {@code offset+0}, {@code offset+1}, ...,
* {@code offset+length-1} of byte array {@code targetBuffer}.
*
- * @param targetBuffer the buffer to copy
- * @param offset start offset
- * @param length length to copy
+ * @param targetBuffer the buffer to copy.
+ * @param offset start offset.
+ * @param length length to copy.
* @throws IllegalStateException The buffer doesn't have sufficient space. Use
* {@link #getSpace()} to prevent this exception.
* @throws IllegalArgumentException Either of {@code offset}, or {@code length} is negative.
@@ -119,7 +119,7 @@ public void clear() {
/**
* Gets the number of bytes, that are currently present in the buffer.
*
- * @return the number of bytes
+ * @return the number of bytes.
*/
public int getCurrentNumberOfBytes() {
return currentNumberOfBytes;
@@ -128,7 +128,7 @@ public int getCurrentNumberOfBytes() {
/**
* Gets the number of bytes, that can currently be added to the buffer.
*
- * @return the number of bytes that can be added
+ * @return the number of bytes that can be added.
*/
public int getSpace() {
return buffer.length - currentNumberOfBytes;
@@ -158,7 +158,7 @@ public boolean hasSpace() {
/**
* Tests whether there is currently room for the given number of bytes in the buffer.
*
- * @param count the byte count
+ * @param count the byte count.
* @return true whether there is currently room for the given number of bytes in the buffer.
* @see #hasSpace()
* @see #getSpace()
@@ -173,9 +173,9 @@ public boolean hasSpace(final int count) {
* removed from the buffer. If the result is true, then the following invocations
* of {@link #read()} are guaranteed to return exactly those bytes.
*
- * @param sourceBuffer the buffer to compare against
- * @param offset start offset
- * @param length length to compare
+ * @param sourceBuffer the buffer to compare against.
+ * @param offset start offset.
+ * @param length length to compare.
* @return True, if the next invocations of {@link #read()} will return the
* bytes at offsets {@code sourceBuffer}+0, {@code offset}+1, ...,
* {@code offset}+{@code length}-1 of byte array {@code sourceBuffer}.
diff --git a/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java b/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java
index ec96054fc43..82e8a60e019 100644
--- a/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java
+++ b/src/main/java/org/apache/commons/io/input/buffer/PeekableInputStream.java
@@ -50,11 +50,13 @@ public PeekableInputStream(final InputStream inputStream, final int bufferSize)
}
/**
- * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}. This is equivalent to
- * {@link #peek(byte[], int, int)} with {@code offset} == 0, and {@code length} == {@code sourceBuffer.length}
+ * Returns whether the next bytes in the buffer exactly match {@code sourceBuffer}. This is equivalent to
+ * {@link #peek(byte[], int, int)} with {@code offset} == 0, and {@code length} == {@code sourceBuffer.length}.
+ * This method does not perform a prefix or starts-with check; for example, peeking {@code "Some"} against a stream
+ * containing {@code "Some text buffer"} returns {@code false}. This method does not consume bytes from the stream.
*
- * @param sourceBuffer the buffer to compare against
- * @return true if the next bytes are as given
+ * @param sourceBuffer the buffer to compare against.
+ * @return true if the next bytes exactly match {@code sourceBuffer}.
* @throws IOException Refilling the buffer failed.
*/
public boolean peek(final byte[] sourceBuffer) throws IOException {
@@ -63,14 +65,14 @@ public boolean peek(final byte[] sourceBuffer) throws IOException {
}
/**
- * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}, {code offset}, and
- * {@code length}.
+ * Returns whether the next bytes in the buffer exactly match {@code length} bytes from {@code sourceBuffer}, starting at
+ * {@code offset}. This method does not consume bytes from the stream.
*
- * @param sourceBuffer the buffer to compare against
- * @param offset the start offset
- * @param length the length to compare
- * @return true if the next bytes in the buffer are as given
- * @throws IOException if there is a problem calling fillBuffer()
+ * @param sourceBuffer the buffer to compare against.
+ * @param offset the start offset in {@code sourceBuffer}.
+ * @param length the length to compare.
+ * @return true if the next bytes exactly match the requested range from {@code sourceBuffer}.
+ * @throws IOException if there is a problem calling fillBuffer().
*/
public boolean peek(final byte[] sourceBuffer, final int offset, final int length) throws IOException {
Objects.requireNonNull(sourceBuffer, "sourceBuffer");
diff --git a/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java b/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java
index ce64c8d4ed4..b7bf2a0cdb4 100644
--- a/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java
+++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationListener.java
@@ -31,56 +31,56 @@ public interface FileAlterationListener {
/**
* Directory changed Event.
*
- * @param directory The directory changed
+ * @param directory The directory changed.
*/
void onDirectoryChange(File directory);
/**
* Directory created Event.
*
- * @param directory The directory created
+ * @param directory The directory created.
*/
void onDirectoryCreate(File directory);
/**
* Directory deleted Event.
*
- * @param directory The directory deleted
+ * @param directory The directory deleted.
*/
void onDirectoryDelete(File directory);
/**
* File changed Event.
*
- * @param file The file changed
+ * @param file The file changed.
*/
void onFileChange(File file);
/**
* File created Event.
*
- * @param file The file created
+ * @param file The file created.
*/
void onFileCreate(File file);
/**
* File deleted Event.
*
- * @param file The file deleted
+ * @param file The file deleted.
*/
void onFileDelete(File file);
/**
* File system observer started checking event.
*
- * @param observer The file system observer
+ * @param observer The file system observer.
*/
void onStart(FileAlterationObserver observer);
/**
* File system observer finished checking event.
*
- * @param observer The file system observer
+ * @param observer The file system observer.
*/
void onStop(FileAlterationObserver observer);
}
diff --git a/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java b/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java
index 0b54bbd6723..c676470fa31 100644
--- a/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java
+++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationListenerAdaptor.java
@@ -36,7 +36,7 @@ public FileAlterationListenerAdaptor() {
/**
* Directory changed Event.
*
- * @param directory The directory changed (ignored)
+ * @param directory The directory changed (ignored).
*/
@Override
public void onDirectoryChange(final File directory) {
@@ -46,7 +46,7 @@ public void onDirectoryChange(final File directory) {
/**
* Directory created Event.
*
- * @param directory The directory created (ignored)
+ * @param directory The directory created (ignored).
*/
@Override
public void onDirectoryCreate(final File directory) {
@@ -56,7 +56,7 @@ public void onDirectoryCreate(final File directory) {
/**
* Directory deleted Event.
*
- * @param directory The directory deleted (ignored)
+ * @param directory The directory deleted (ignored).
*/
@Override
public void onDirectoryDelete(final File directory) {
@@ -66,7 +66,7 @@ public void onDirectoryDelete(final File directory) {
/**
* File changed Event.
*
- * @param file The file changed (ignored)
+ * @param file The file changed (ignored).
*/
@Override
public void onFileChange(final File file) {
@@ -76,7 +76,7 @@ public void onFileChange(final File file) {
/**
* File created Event.
*
- * @param file The file created (ignored)
+ * @param file The file created (ignored).
*/
@Override
public void onFileCreate(final File file) {
@@ -86,7 +86,7 @@ public void onFileCreate(final File file) {
/**
* File deleted Event.
*
- * @param file The file deleted (ignored)
+ * @param file The file deleted (ignored).
*/
@Override
public void onFileDelete(final File file) {
@@ -96,7 +96,7 @@ public void onFileDelete(final File file) {
/**
* File system observer started checking event.
*
- * @param observer The file system observer (ignored)
+ * @param observer The file system observer (ignored).
*/
@Override
public void onStart(final FileAlterationObserver observer) {
@@ -106,7 +106,7 @@ public void onStart(final FileAlterationObserver observer) {
/**
* File system observer finished checking event.
*
- * @param observer The file system observer (ignored)
+ * @param observer The file system observer (ignored).
*/
@Override
public void onStop(final FileAlterationObserver observer) {
diff --git a/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java b/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java
index 394e7aca661..b2fcbd8bb33 100644
--- a/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java
+++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationMonitor.java
@@ -98,7 +98,7 @@ public FileAlterationMonitor(final long interval, final FileAlterationObserver..
/**
* Adds a file system observer to this monitor.
*
- * @param observer The file system observer to add
+ * @param observer The file system observer to add.
*/
public void addObserver(final FileAlterationObserver observer) {
if (observer != null) {
@@ -107,16 +107,16 @@ public void addObserver(final FileAlterationObserver observer) {
}
/**
- * Returns the interval.
+ * Gets the interval.
*
- * @return the interval
+ * @return the interval.
*/
public long getInterval() {
return intervalMillis;
}
/**
- * Returns the set of {@link FileAlterationObserver} registered with
+ * Gets the set of {@link FileAlterationObserver} registered with
* this monitor.
*
* @return The set of {@link FileAlterationObserver}
@@ -128,7 +128,7 @@ public Iterable getObservers() {
/**
* Removes a file system observer from this monitor.
*
- * @param observer The file system observer to remove
+ * @param observer The file system observer to remove.
*/
public void removeObserver(final FileAlterationObserver observer) {
if (observer != null) {
@@ -148,8 +148,8 @@ public void run() {
}
try {
ThreadUtils.sleep(Duration.ofMillis(intervalMillis));
- } catch (final InterruptedException ignored) {
- // ignore
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
}
}
}
@@ -157,7 +157,7 @@ public void run() {
/**
* Sets the thread factory.
*
- * @param threadFactory the thread factory
+ * @param threadFactory the thread factory.
*/
public synchronized void setThreadFactory(final ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
@@ -166,7 +166,7 @@ public synchronized void setThreadFactory(final ThreadFactory threadFactory) {
/**
* Starts monitoring.
*
- * @throws Exception if an error occurs initializing the observer
+ * @throws Exception if an error occurs initializing the observer.
*/
public synchronized void start() throws Exception {
if (running) {
@@ -179,7 +179,7 @@ public synchronized void start() throws Exception {
if (threadFactory != null) {
thread = threadFactory.newThread(this);
} else {
- thread = new Thread(this);
+ thread = new Thread(this, "commons-io-FileAlterationMonitor");
}
thread.start();
}
@@ -187,7 +187,7 @@ public synchronized void start() throws Exception {
/**
* Stops monitoring.
*
- * @throws Exception if an error occurs initializing the observer
+ * @throws Exception if an error occurs initializing the observer.
*/
public synchronized void stop() throws Exception {
stop(intervalMillis);
@@ -198,7 +198,7 @@ public synchronized void stop() throws Exception {
*
* @param stopInterval the amount of time in milliseconds to wait for the thread to finish.
* A value of zero will wait until the thread is finished (see {@link Thread#join(long)}).
- * @throws Exception if an error occurs initializing the observer
+ * @throws Exception if an error occurs initializing the observer.
* @since 2.1
*/
public synchronized void stop(final long stopInterval) throws Exception {
diff --git a/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java b/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
index 277d80cb71e..9b39c10e190 100644
--- a/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
+++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
@@ -36,17 +36,17 @@
import org.apache.commons.io.filefilter.TrueFileFilter;
/**
- * FileAlterationObserver represents the state of files below a root directory, checking the file system and notifying listeners of create, change or delete
+ * Represents the state of files below a root directory, checking the file system and notifying listeners of create, change or delete
* events.
*
* To use this implementation:
*
- *
+ *
*
Create {@link FileAlterationListener} implementation(s) that process the file/directory create, change and delete events
*
Register the listener(s) with a {@link FileAlterationObserver} for the appropriate directory.
*
Either register the observer(s) with a {@link FileAlterationMonitor} or run manually.
- *
- *
Basic Usage
Create a {@link FileAlterationObserver} for the directory and register the listeners:
+ *
+ *
Observing a Directory
Create a {@link FileAlterationObserver} for the directory and register the listeners:
*
*
* {@link FileEntry} represents the state of a file or directory, capturing {@link File} attributes at a point in time. Custom implementations of
* {@link FileEntry} can be used to capture additional properties that the basic implementation does not support. The {@link FileEntry#refresh(File)} method is
@@ -118,7 +118,7 @@
*
*
Deprecating Serialization
*
- * Serialization is deprecated and will be removed in 3.0.
+ * Serialization is deprecated and will be removed in 3.0. Consider using a serialization proxy.
*
*
* @see FileAlterationListener
@@ -135,7 +135,9 @@ public class FileAlterationObserver implements Serializable {
public static final class Builder extends AbstractOriginSupplier {
private FileEntry rootEntry;
+
private FileFilter fileFilter;
+
private IOCase ioCase;
private Builder() {
@@ -149,7 +151,7 @@ private File checkOriginFile() {
/**
* Gets a new {@link FileAlterationObserver} instance.
*
- * @throws IOException if an I/O error occurs converting to an {@link File} using {@link AbstractOrigin#getFile()}.
+ * @throws IOException if an I/O error occurs converting to an {@link File} using {@link AbstractOrigin#getFile()}.
* @see #getUnchecked()
*/
@Override
@@ -189,7 +191,6 @@ public Builder setRootEntry(final FileEntry rootEntry) {
this.rootEntry = rootEntry;
return asThis();
}
-
}
private static final long serialVersionUID = 1185122225658782848L;
@@ -480,7 +481,7 @@ Comparator getComparator() {
}
/**
- * Returns the directory being observed.
+ * Gets the directory being observed.
*
* @return the directory being observed.
*/
@@ -489,7 +490,7 @@ public File getDirectory() {
}
/**
- * Returns the fileFilter.
+ * Gets the fileFilter.
*
* @return the fileFilter.
* @since 2.1
@@ -499,9 +500,9 @@ public FileFilter getFileFilter() {
}
/**
- * Returns the set of registered file system listeners.
+ * Gets the set of registered file system listeners.
*
- * @return The file system listeners
+ * @return The file system listeners.
*/
public Iterable getListeners() {
return new ArrayList<>(listeners);
@@ -533,7 +534,7 @@ private FileEntry[] listFileEntries(final File file, final FileEntry entry) {
* Lists the contents of a directory.
*
* @param directory The directory to list.
- * @return the directory contents or a zero length array if the empty or the file is not a directory
+ * @return the directory contents or a zero length array if the empty or the file is not a directory.
*/
private File[] listFiles(final File directory) {
return directory.isDirectory() ? sort(directory.listFiles(fileFilter)) : FileUtils.EMPTY_FILE_ARRAY;
diff --git a/src/main/java/org/apache/commons/io/monitor/FileEntry.java b/src/main/java/org/apache/commons/io/monitor/FileEntry.java
index d1e07fb885c..fac3317958b 100644
--- a/src/main/java/org/apache/commons/io/monitor/FileEntry.java
+++ b/src/main/java/org/apache/commons/io/monitor/FileEntry.java
@@ -48,6 +48,7 @@
*
* Serialization is deprecated and will be removed in 3.0.
*
+ *
* @see FileAlterationObserver
* @since 2.0
*/
@@ -84,7 +85,7 @@ public class FileEntry implements Serializable {
/**
* Constructs a new monitor for a specified {@link File}.
*
- * @param file The file being monitored
+ * @param file The file being monitored.
*/
public FileEntry(final File file) {
this(null, file);
@@ -107,7 +108,7 @@ public FileEntry(final FileEntry parent, final File file) {
*
* @return This directory's files or an empty
* array if the file is not a directory or the
- * directory is empty
+ * directory is empty.
*/
public FileEntry[] getChildren() {
return children != null ? children : EMPTY_FILE_ENTRY_ARRAY;
@@ -116,7 +117,7 @@ public FileEntry[] getChildren() {
/**
* Gets the file being monitored.
*
- * @return the file being monitored
+ * @return the file being monitored.
*/
public File getFile() {
return file;
@@ -145,7 +146,7 @@ public FileTime getLastModifiedFileTime() {
/**
* Gets the length.
*
- * @return the length
+ * @return the length.
*/
public long getLength() {
return length;
@@ -154,7 +155,7 @@ public long getLength() {
/**
* Gets the level
*
- * @return the level
+ * @return the level.
*/
public int getLevel() {
return parent == null ? 0 : parent.getLevel() + 1;
@@ -163,7 +164,7 @@ public int getLevel() {
/**
* Gets the file name.
*
- * @return the file name
+ * @return the file name.
*/
public String getName() {
return name;
@@ -172,7 +173,7 @@ public String getName() {
/**
* Gets the parent entry.
*
- * @return the parent entry
+ * @return the parent entry.
*/
public FileEntry getParent() {
return parent;
@@ -181,7 +182,7 @@ public FileEntry getParent() {
/**
* Tests whether the file is a directory or not.
*
- * @return whether the file is a directory or not
+ * @return whether the file is a directory or not.
*/
public boolean isDirectory() {
return directory;
@@ -191,7 +192,7 @@ public boolean isDirectory() {
* Tests whether the file existed the last time it
* was checked.
*
- * @return whether the file existed
+ * @return whether the file existed.
*/
public boolean isExists() {
return exists;
@@ -204,8 +205,8 @@ public boolean isExists() {
* a new instance of the appropriate type.
*
*
- * @param file The child file
- * @return a new child instance
+ * @param file The child file.
+ * @return a new child instance.
*/
public FileEntry newChildInstance(final File file) {
return new FileEntry(this, file);
@@ -224,8 +225,8 @@ public FileEntry newChildInstance(final File file) {
* and {@code length} properties are compared for changes
*
*
- * @param file the file instance to compare to
- * @return {@code true} if the file has changed, otherwise {@code false}
+ * @param file the file instance to compare to.
+ * @return {@code true} if the file has changed, otherwise {@code false}.
*/
public boolean refresh(final File file) {
// cache original values
@@ -253,7 +254,7 @@ public boolean refresh(final File file) {
/**
* Sets the directory's files.
*
- * @param children This directory's files, may be null
+ * @param children This directory's files, may be null.
*/
public void setChildren(final FileEntry... children) {
this.children = children;
@@ -262,7 +263,7 @@ public void setChildren(final FileEntry... children) {
/**
* Sets whether the file is a directory or not.
*
- * @param directory whether the file is a directory or not
+ * @param directory whether the file is a directory or not.
*/
public void setDirectory(final boolean directory) {
this.directory = directory;
@@ -272,7 +273,7 @@ public void setDirectory(final boolean directory) {
* Sets whether the file existed the last time it
* was checked.
*
- * @param exists whether the file exists or not
+ * @param exists whether the file exists or not.
*/
public void setExists(final boolean exists) {
this.exists = exists;
@@ -305,7 +306,7 @@ void setLastModified(final SerializableFileTime lastModified) {
/**
* Sets the length.
*
- * @param length the length
+ * @param length the length.
*/
public void setLength(final long length) {
this.length = length;
@@ -314,7 +315,7 @@ public void setLength(final long length) {
/**
* Sets the file name.
*
- * @param name the file name
+ * @param name the file name.
*/
public void setName(final String name) {
this.name = name;
diff --git a/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java b/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java
index 6b095474fb2..90b65d28801 100644
--- a/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/AbstractByteArrayOutputStream.java
@@ -56,7 +56,7 @@
* ignored.
*
*
- * @param The AbstractByteArrayOutputStream subclass
+ * @param The AbstractByteArrayOutputStream subclass.
* @since 2.7
*/
public abstract class AbstractByteArrayOutputStream> extends OutputStream {
@@ -110,7 +110,7 @@ public AbstractByteArrayOutputStream() {
/**
* Returns this instance typed to {@code T}.
*
- * @return {@code this} instance
+ * @return {@code this} instance.
*/
@SuppressWarnings("unchecked")
protected T asThis() {
@@ -232,7 +232,7 @@ protected byte[] toByteArrayImpl() {
/**
* Gets the current contents of this byte stream as an Input Stream. The
* returned stream is backed by buffers of {@code this} stream,
- * avoiding memory allocation and copy, thus saving space and time.
+ * avoiding memory allocation and copy, thus saving space and time.
*
* @return the current contents of this output stream.
* @see java.io.ByteArrayOutputStream#toByteArray()
@@ -244,9 +244,9 @@ protected byte[] toByteArrayImpl() {
/**
* Gets the current contents of this byte stream as an Input Stream. The
* returned stream is backed by buffers of {@code this} stream,
- * avoiding memory allocation and copy, thus saving space and time.
+ * avoiding memory allocation and copy, thus saving space and time.
*
- * @param the type of the InputStream which makes up
+ * @param the type of the InputStream which makes up
* the {@link SequenceInputStream}.
* @param isConstructor A constructor for an InputStream which makes
* up the {@link SequenceInputStream}.
@@ -257,12 +257,12 @@ protected byte[] toByteArrayImpl() {
* @since 2.7
*/
@SuppressWarnings("resource") // The result InputStream MUST be managed by the call site.
- protected InputStream toInputStream(final InputStreamConstructor isConstructor) {
+ protected InputStream toInputStream(final InputStreamConstructor isConstructor) {
int remaining = count;
if (remaining == 0) {
return ClosedInputStream.INSTANCE;
}
- final List list = new ArrayList<>(buffers.size());
+ final List list = new ArrayList<>(buffers.size());
for (final byte[] buf : buffers) {
final int c = Math.min(buf.length, remaining);
list.add(isConstructor.construct(buf, 0, c));
@@ -276,7 +276,7 @@ protected InputStream toInputStream(final InputStreamCon
}
/**
- * Gets the current contents of this byte stream as a string using the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * Gets the current contents of this byte stream as a string using the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
* @return the contents of the byte array as a String.
* @see java.io.ByteArrayOutputStream#toString()
@@ -349,7 +349,7 @@ public T write(final CharSequence data, final Charset charset) {
* this stream.
*
* @param in the input stream to read from.
- * @return total number of bytes read from the input stream (and written to this stream)
+ * @return total number of bytes read from the input stream (and written to this stream).
* @throws IOException if an I/O error occurs while reading the input stream.
* @since 1.4
*/
diff --git a/src/main/java/org/apache/commons/io/output/AppendableOutputStream.java b/src/main/java/org/apache/commons/io/output/AppendableOutputStream.java
index e8320d99d64..ed7727969b9 100644
--- a/src/main/java/org/apache/commons/io/output/AppendableOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/AppendableOutputStream.java
@@ -39,7 +39,7 @@ public class AppendableOutputStream extends OutputStream
/**
* Constructs a new instance with the specified appendable.
*
- * @param appendable the appendable to write to
+ * @param appendable the appendable to write to.
*/
public AppendableOutputStream(final T appendable) {
this.appendable = appendable;
@@ -48,7 +48,7 @@ public AppendableOutputStream(final T appendable) {
/**
* Gets the target appendable.
*
- * @return the target appendable
+ * @return the target appendable.
*/
public T getAppendable() {
return appendable;
@@ -57,7 +57,7 @@ public T getAppendable() {
/**
* Writes a character to the underlying appendable.
*
- * @param b the character to write
+ * @param b the character to write.
* @throws IOException If an I/O error occurs.
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/output/AppendableWriter.java b/src/main/java/org/apache/commons/io/output/AppendableWriter.java
index b1ace0b908c..4ac262ccea0 100644
--- a/src/main/java/org/apache/commons/io/output/AppendableWriter.java
+++ b/src/main/java/org/apache/commons/io/output/AppendableWriter.java
@@ -75,10 +75,10 @@ public Writer append(final CharSequence csq) throws IOException {
/**
* Appends a subsequence of the specified character sequence to the underlying appendable.
*
- * @param csq the character sequence from which a subsequence will be appended
- * @param start the index of the first character in the subsequence
- * @param end the index of the character following the last character in the subsequence
- * @return this writer
+ * @param csq the character sequence from which a subsequence will be appended.
+ * @param start the index of the first character in the subsequence.
+ * @param end the index of the character following the last character in the subsequence.
+ * @return this writer.
* @throws IndexOutOfBoundsException If {@code start} or {@code end} are negative, {@code start} is greater than
* {@code end}, or {@code end} is greater than {@code csq.length()}.
* @throws IOException If an I/O error occurs.
diff --git a/src/main/java/org/apache/commons/io/output/ByteArrayOutputStream.java b/src/main/java/org/apache/commons/io/output/ByteArrayOutputStream.java
index 48fb793669b..dee60bd69b9 100644
--- a/src/main/java/org/apache/commons/io/output/ByteArrayOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ByteArrayOutputStream.java
@@ -40,7 +40,9 @@ public class ByteArrayOutputStream extends AbstractByteArrayOutputStreamIt has network timeout associated.
*
*
- * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
- * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
@@ -95,8 +99,8 @@ public ByteArrayOutputStream() {
* Constructs a new byte array output stream, with a buffer capacity of
* the specified size, in bytes.
*
- * @param size the initial size
- * @throws IllegalArgumentException if size is negative
+ * @param size the initial size.
+ * @throws IllegalArgumentException if size is negative.
*/
public ByteArrayOutputStream(final int size) {
if (size < 0) {
diff --git a/src/main/java/org/apache/commons/io/output/ChunkedOutputStream.java b/src/main/java/org/apache/commons/io/output/ChunkedOutputStream.java
index 2588264e172..b47bd3d880a 100644
--- a/src/main/java/org/apache/commons/io/output/ChunkedOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ChunkedOutputStream.java
@@ -37,7 +37,7 @@ public class ChunkedOutputStream extends FilterOutputStream {
// @formatter:off
/**
- * Builds a new {@link UnsynchronizedByteArrayOutputStream}.
+ * Builds a new {@link ChunkedOutputStream}.
*
*
* Using File IO:
@@ -143,7 +143,7 @@ public ChunkedOutputStream(final OutputStream stream) {
/**
* Constructs a new stream that uses the specified chunk size.
*
- * @param stream the stream to wrap
+ * @param stream the stream to wrap.
* @param chunkSize the chunk size to use; must be a positive number.
* @throws IllegalArgumentException if the chunk size is <= 0.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
diff --git a/src/main/java/org/apache/commons/io/output/CloseShieldOutputStream.java b/src/main/java/org/apache/commons/io/output/CloseShieldOutputStream.java
index cefa71ad41f..876f3e5b7dc 100644
--- a/src/main/java/org/apache/commons/io/output/CloseShieldOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/CloseShieldOutputStream.java
@@ -34,7 +34,7 @@ public class CloseShieldOutputStream extends ProxyOutputStream {
* Constructs a proxy that shields the given output stream from being closed.
*
* @param outputStream the output stream to wrap.
- * @return the created proxy
+ * @return the created proxy.
* @since 2.9.0
*/
public static CloseShieldOutputStream wrap(final OutputStream outputStream) {
diff --git a/src/main/java/org/apache/commons/io/output/ClosedOutputStream.java b/src/main/java/org/apache/commons/io/output/ClosedOutputStream.java
index c7216ce6f90..664df91028d 100644
--- a/src/main/java/org/apache/commons/io/output/ClosedOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ClosedOutputStream.java
@@ -58,7 +58,7 @@ public ClosedOutputStream() {
/**
* Throws an {@link IOException} to indicate that the stream is closed.
*
- * @throws IOException always thrown
+ * @throws IOException always thrown.
*/
@Override
public void flush() throws IOException {
diff --git a/src/main/java/org/apache/commons/io/output/ClosedWriter.java b/src/main/java/org/apache/commons/io/output/ClosedWriter.java
index c4e1d93b93c..446b31b7950 100644
--- a/src/main/java/org/apache/commons/io/output/ClosedWriter.java
+++ b/src/main/java/org/apache/commons/io/output/ClosedWriter.java
@@ -38,6 +38,7 @@ public class ClosedWriter extends Writer {
* @since 2.12.0
*/
public static final ClosedWriter INSTANCE = new ClosedWriter();
+
/**
* The singleton instance.
*
@@ -61,7 +62,7 @@ public void close() throws IOException {
/**
* Throws an {@link IOException} to indicate that the stream is closed.
*
- * @throws IOException always thrown
+ * @throws IOException always thrown.
*/
@Override
public void flush() throws IOException {
diff --git a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
index 5c8672d5bd6..18697a7623f 100644
--- a/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/DeferredFileOutputStream.java
@@ -30,13 +30,13 @@
/**
* An output stream which will retain data in memory until a specified threshold is reached, and only then commit it to disk. If the stream is closed before the
- * threshold is reached, the data will not be written to disk at all.
+ * threshold is reached, the data will not be written to disk.
*
- * To build an instance, use {@link Builder}.
+ * To build an instance, use the {@link Builder builder}.
*
*
- * The caller is responsible for deleting the output file ({@link #getFile()}, {@link #getPath()}) created by a DeferredFileOutputStream when the caller only
- * configured a prefix.
+ * A temporary file created only when a prefix is configured (via {@link Builder#setPrefix(String)}) and is deleted automatically when {@link #close()}
+ * is called.
*
*
* The caller is responsible for deleting the output file passed to a constructor or builder through {@link Builder#setOutputFile(File)} or
@@ -82,6 +82,7 @@ public static class Builder extends AbstractStreamBuilder
+ * This only applies when a temporary file is created internally via a prefix/suffix configuration (i.e.,
+ * {@link #setPrefix(String)} is used). It has no effect when an explicit output file is provided via
+ * {@link #setOutputFile(File)} or {@link #setOutputFile(Path)}.
+ *
+ *
+ * @param deleteTempFileOnClose {@code true} to delete the temporary file on close (default), {@code false} to
+ * keep it (the caller is then responsible for deleting it).
+ * @return {@code this} instance.
+ * @since 2.23.0
+ */
+ public Builder setDeleteTempFileOnClose(final boolean deleteTempFileOnClose) {
+ this.deleteTempFileOnClose = deleteTempFileOnClose;
+ return this;
+ }
+
/**
* Sets the temporary file directory.
*
@@ -254,10 +273,21 @@ private static Path toPath(final Path file, final Supplier defaultPathSupp
*/
private boolean closed;
+ /**
+ * True when the output file was created internally as a temporary file by {@link #thresholdReached()}.
+ * Such a file is deleted automatically when {@link #close()} is called (subject to {@link #deleteTempFileOnClose}).
+ */
+ private boolean tempFile;
+
+ /**
+ * Controls whether a temporary file created internally is deleted when {@link #close()} is called.
+ */
+ private final boolean deleteTempFileOnClose;
+
/**
* Constructs an instance of this class which will trigger an event at the specified threshold, and save data either to a file beyond that point.
*
- * @param builder The construction data source.
+ * @param builder The construction data source.
*/
private DeferredFileOutputStream(final Builder builder) {
super(builder.threshold);
@@ -265,6 +295,7 @@ private DeferredFileOutputStream(final Builder builder) {
this.prefix = builder.prefix;
this.suffix = builder.suffix;
this.directory = toPath(builder.directory, PathUtils::getTempDirectory);
+ this.deleteTempFileOnClose = builder.deleteTempFileOnClose;
this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(builder.getBufferSize()));
this.currentOutputStream = memoryOutputStream;
}
@@ -300,6 +331,7 @@ private DeferredFileOutputStream(final int threshold, final File outputFile, fin
this.prefix = prefix;
this.suffix = suffix;
this.directory = toPath(directory, PathUtils::getTempDirectory);
+ this.deleteTempFileOnClose = true;
this.memoryOutputStream = new ByteArrayOutputStream(checkBufferSize(initialBufferSize));
this.currentOutputStream = memoryOutputStream;
}
@@ -351,14 +383,22 @@ public DeferredFileOutputStream(final int threshold, final String prefix, final
}
/**
- * Closes underlying output stream, and mark this as closed
+ * Closes underlying output stream, and marks this as closed. If the output was directed to a temporary file created
+ * internally via a prefix/suffix configuration, and {@link Builder#setDeleteTempFileOnClose(boolean)} is
+ * {@code true} (the default), that file is deleted.
*
* @throws IOException if an error occurs.
*/
@Override
public void close() throws IOException {
- super.close();
- closed = true;
+ try {
+ super.close();
+ } finally {
+ closed = true;
+ if (tempFile && deleteTempFileOnClose && outputPath != null) {
+ PathUtils.deleteIfExists(PathUtils.clearIfExists(outputPath));
+ }
+ }
}
/**
@@ -436,23 +476,26 @@ public boolean isInMemory() {
protected void thresholdReached() throws IOException {
if (prefix != null) {
outputPath = Files.createTempFile(directory, prefix, suffix);
+ tempFile = true;
}
PathUtils.createParentDirectories(outputPath, null, PathUtils.EMPTY_FILE_ATTRIBUTE_ARRAY);
- final OutputStream fos = Files.newOutputStream(outputPath);
+ final OutputStream os = Files.newOutputStream(Objects.requireNonNull(outputPath, "Either output file or prefix must be specified."));
try {
- memoryOutputStream.writeTo(fos);
+ memoryOutputStream.writeTo(os);
} catch (final IOException e) {
- fos.close();
+ os.close();
throw e;
}
- currentOutputStream = fos;
+ currentOutputStream = os;
memoryOutputStream = null;
}
/**
* Converts the current contents of this byte stream to an {@link InputStream}. If the data for this output stream has been retained in memory, the returned
- * stream is backed by buffers of {@code this} stream, avoiding memory allocation and copy, thus saving space and time.
+ * stream is backed by buffers of {@code this} stream, avoiding memory allocation and copy, thus saving space and time.
+ *
* Otherwise, the returned stream will be one that is created from the data that has been committed to disk.
+ *
*
* @return the current contents of this output stream.
* @throws IOException if this stream is not yet closed or an error occurs.
diff --git a/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java b/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java
index 42d378cc0a5..4b6ebe1ba3e 100644
--- a/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java
+++ b/src/main/java/org/apache/commons/io/output/FileWriterWithEncoding.java
@@ -188,11 +188,7 @@ private static OutputStreamWriter initWriter(final File file, final Object encod
}
return new OutputStreamWriter(outputStream, (String) encoding);
} catch (final IOException | RuntimeException ex) {
- try {
- IOUtils.close(outputStream);
- } catch (final IOException e) {
- ex.addSuppressed(e);
- }
+ IOUtils.closeQuietlySuppress(outputStream, ex);
if (!fileExistedAlready) {
FileUtils.deleteQuietly(file);
}
diff --git a/src/main/java/org/apache/commons/io/output/FlushShieldOutputStream.java b/src/main/java/org/apache/commons/io/output/FlushShieldOutputStream.java
new file mode 100644
index 00000000000..772edf190bf
--- /dev/null
+++ b/src/main/java/org/apache/commons/io/output/FlushShieldOutputStream.java
@@ -0,0 +1,118 @@
+/*
+ * 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.io.output;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.io.build.AbstractStreamBuilder;
+
+/**
+ * Re-implements {@link FilterOutputStream#flush()} to do nothing.
+ *
+ * @since 2.22.0
+ */
+public final class FlushShieldOutputStream extends ProxyOutputStream {
+
+ // @formatter:off
+ /**
+ * Builds a new {@link FlushShieldOutputStream}.
+ *
+ *
+ *
+ * @see #get()
+ */
+ // @formatter:on
+ public static class Builder extends AbstractStreamBuilder {
+
+ /**
+ * Constructs a new builder of {@link FlushShieldOutputStream}.
+ */
+ public Builder() {
+ // empty
+ }
+
+ /**
+ * Builds a new {@link FlushShieldOutputStream}.
+ *
+ * @return a new instance.
+ * @throws IllegalStateException if the {@code origin} is {@code null}.
+ * @throws UnsupportedOperationException if the origin cannot be converted to an {@link OutputStream}.
+ * @throws IOException if an I/O error occurs converting to an {@link OutputStream} using {@link #getOutputStream()}.
+ * @see #getOutputStream()
+ * @see #getBufferSize()
+ * @see #getUnchecked()
+ */
+ @Override
+ public FlushShieldOutputStream get() throws IOException {
+ return new FlushShieldOutputStream(this);
+ }
+
+ }
+
+ /**
+ * Constructs a new builder of {@link FlushShieldOutputStream}.
+ *
+ * @return a new builder of {@link FlushShieldOutputStream}.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ @SuppressWarnings("resource") // caller closes.
+ private FlushShieldOutputStream(final Builder builder) throws IOException {
+ super(builder.getOutputStream());
+ }
+
+ /**
+ * Constructs a {@code FlushShieldOutputStream} filter for the specified underlying output stream.
+ *
+ * @param out the underlying output stream to be assigned to the field {@code this.out} for later use, or {@code null} if this instance is to be created
+ * without an underlying stream.
+ */
+ public FlushShieldOutputStream(final OutputStream out) {
+ super(out);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ // shield: do nothing.
+ }
+}
diff --git a/src/main/java/org/apache/commons/io/output/LockableFileWriter.java b/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
index f15048e5c0e..1ee9391af8f 100644
--- a/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
+++ b/src/main/java/org/apache/commons/io/output/LockableFileWriter.java
@@ -204,7 +204,7 @@ public LockableFileWriter(final File file, final boolean append) throws IOExcept
/**
* Constructs a LockableFileWriter.
*
- * The new instance uses the virtual machine's {@link Charset#defaultCharset() default charset}.
+ * The new instance uses the virtual machine's {@linkplain Charset#defaultCharset() default charset}.
*
*
* @param file the file to write to, not null.
diff --git a/src/main/java/org/apache/commons/io/output/NullWriter.java b/src/main/java/org/apache/commons/io/output/NullWriter.java
index 635ffb044a6..e43b6427c75 100644
--- a/src/main/java/org/apache/commons/io/output/NullWriter.java
+++ b/src/main/java/org/apache/commons/io/output/NullWriter.java
@@ -69,7 +69,7 @@ public Writer append(final char c) {
* Does nothing, like writing to {@code /dev/null}.
*
* @param csq The character sequence to write.
- * @return this writer
+ * @return this writer.
* @since 2.0
*/
@Override
diff --git a/src/main/java/org/apache/commons/io/output/ProxyOutputStream.java b/src/main/java/org/apache/commons/io/output/ProxyOutputStream.java
index 090f2d059a7..06f91a21ab5 100644
--- a/src/main/java/org/apache/commons/io/output/ProxyOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ProxyOutputStream.java
@@ -25,8 +25,7 @@
import org.apache.commons.io.build.AbstractStreamBuilder;
/**
- * A Proxy stream which acts as expected, that is it passes the method calls on to the proxied stream and doesn't change which methods are being called. It is
- * an alternative base class to FilterOutputStream to increase reusability.
+ * An output stream proxy which delegates to the wrapped output stream.
*
* See the protected methods for ways in which a subclass can easily decorate a stream with custom pre-, post- or error processing functionality.
*
*
* @param out the underlying output stream.
* @return {@code this} instance.
@@ -175,12 +177,13 @@ public ProxyOutputStream setReference(final OutputStream out) {
/**
* Unwraps this instance by returning the underlying {@link OutputStream}.
*
- * Use with caution; useful to query the underlying {@link OutputStream}.
+ * Use with caution.
*
*
* @return the underlying {@link OutputStream}.
+ * @since 2.22.0
*/
- OutputStream unwrap() {
+ public OutputStream unwrap() {
return out;
}
diff --git a/src/main/java/org/apache/commons/io/output/ProxyWriter.java b/src/main/java/org/apache/commons/io/output/ProxyWriter.java
index ac88f4c6943..1cc4b1cb104 100644
--- a/src/main/java/org/apache/commons/io/output/ProxyWriter.java
+++ b/src/main/java/org/apache/commons/io/output/ProxyWriter.java
@@ -23,10 +23,11 @@
import org.apache.commons.io.IOUtils;
/**
- * A Proxy stream which acts as expected, that is it passes the method calls on to the proxied stream and doesn't
- * change which methods are being called. It is an alternative base class to FilterWriter to increase reusability,
- * because FilterWriter changes the methods being called, such as {@code write(char[]) to write(char[], int, int)}
- * and {@code write(String) to write(String, int, int)}.
+ * A writer proxy which delegates to the wrapped writer.
+ *
+ * It is an alternative base class to FilterWriter to increase reusability, because FilterWriter changes the methods being called, such as
+ * {@code write(char[]) to write(char[], int, int)} and {@code write(String) to write(String, int, int)}.
+ *
*/
public class ProxyWriter extends FilterWriter {
@@ -51,8 +52,8 @@ public ProxyWriter(final Writer delegate) {
* The default implementation does nothing.
*
*
- * @param n number of chars written
- * @throws IOException if the post-processing fails
+ * @param n number of chars written.
+ * @throws IOException if the post-processing fails.
* @since 2.0
*/
@SuppressWarnings("unused") // Possibly thrown from subclasses.
@@ -144,6 +145,7 @@ protected void beforeWrite(final int n) throws IOException {
/**
* Invokes the delegate's {@code close()} method.
+ *
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -153,6 +155,7 @@ public void close() throws IOException {
/**
* Invokes the delegate's {@code flush()} method.
+ *
* @throws IOException if an I/O error occurs.
*/
@Override
@@ -179,6 +182,34 @@ protected void handleIOException(final IOException e) throws IOException {
throw e;
}
+ /**
+ * Sets the underlying writer.
+ *
+ * Use with caution.
+ *
+ *
+ * @param out the underlying output writer.
+ * @return {@code this} instance.
+ * @since 2.22.0
+ */
+ public ProxyWriter setReference(final Writer out) {
+ this.out = out;
+ return this;
+ }
+
+ /**
+ * Unwraps this instance by returning the underlying {@link Writer}.
+ *
+ * Use with caution.
+ *
+ *
+ * @return the underlying {@link Writer}.
+ * @since 2.22.0
+ */
+ public Writer unwrap() {
+ return out;
+ }
+
/**
* Invokes the delegate's {@code write(char[])} method.
*
diff --git a/src/main/java/org/apache/commons/io/output/TeeOutputStream.java b/src/main/java/org/apache/commons/io/output/TeeOutputStream.java
index 72a1eb9e4c6..59f70ffaafd 100644
--- a/src/main/java/org/apache/commons/io/output/TeeOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/TeeOutputStream.java
@@ -35,8 +35,8 @@ public class TeeOutputStream extends ProxyOutputStream {
/**
* Constructs a TeeOutputStream.
*
- * @param out the main OutputStream
- * @param branch the second OutputStream
+ * @param out the main OutputStream.
+ * @param branch the second OutputStream.
*/
public TeeOutputStream(final OutputStream out, final OutputStream branch) {
super(out);
diff --git a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
index 742572b2ebc..9adf6a1a1e4 100644
--- a/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/ThresholdingOutputStream.java
@@ -52,7 +52,7 @@ public class ThresholdingOutputStream extends OutputStream {
private static final IOFunction NOOP_OS_GETTER = os -> NullOutputStream.INSTANCE;
/**
- * The threshold at which the event will be triggered.
+ * The number of bytes at which to trigger an event, a negative threshold is mapped to zero
*/
private final int threshold;
@@ -79,24 +79,24 @@ public class ThresholdingOutputStream extends OutputStream {
/**
* Constructs an instance of this class which will trigger an event at the specified threshold.
*
- * @param threshold The number of bytes at which to trigger an event.
+ * @param threshold The number of bytes at which to trigger an event, a negative threshold is mapped to zero.
*/
public ThresholdingOutputStream(final int threshold) {
this(threshold, IOConsumer.noop(), NOOP_OS_GETTER);
}
/**
- * Constructs an instance of this class which will trigger an event at the specified threshold.
- * A negative threshold has no meaning and will be treated as 0
+ * Constructs an instance of this class which will trigger an event at the specified threshold. A negative threshold has no meaning and will be treated as
+ * 0.
*
- * @param threshold The number of bytes at which to trigger an event.
- * @param thresholdConsumer Accepts reaching the threshold.
+ * @param threshold The number of bytes at which to trigger an event, a negative threshold is mapped to zero.
+ * @param thresholdConsumer Accepts reaching the threshold.
* @param outputStreamGetter Gets the output stream.
* @since 2.9.0
*/
public ThresholdingOutputStream(final int threshold, final IOConsumer thresholdConsumer,
final IOFunction outputStreamGetter) {
- this.threshold = threshold < 0 ? 0 : threshold;
+ this.threshold = Math.max(0, threshold);
this.thresholdConsumer = thresholdConsumer == null ? IOConsumer.noop() : thresholdConsumer;
this.outputStreamGetter = outputStreamGetter == null ? NOOP_OS_GETTER : outputStreamGetter;
}
@@ -111,7 +111,12 @@ public ThresholdingOutputStream(final int threshold, final IOConsumer threshold) {
thresholdExceeded = true;
- thresholdReached();
+ try {
+ thresholdReached();
+ } catch (final IOException | RuntimeException e) {
+ thresholdExceeded = false;
+ throw e;
+ }
}
}
@@ -180,7 +185,7 @@ protected OutputStream getStream() throws IOException {
/**
* Gets the threshold, in bytes, at which an event will be triggered.
*
- * @return The threshold point, in bytes.
+ * @return The threshold point, in bytes, at which an event will be triggered, zero or greater.
*/
public int getThreshold() {
return threshold;
@@ -192,7 +197,7 @@ public int getThreshold() {
* @return {@code true} if the threshold has been reached; {@code false} otherwise.
*/
public boolean isThresholdExceeded() {
- return written > threshold;
+ return thresholdExceeded;
}
/**
diff --git a/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream.java b/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream.java
index a47a3b2aa2a..0e361b8420a 100644
--- a/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/UnsynchronizedByteArrayOutputStream.java
@@ -113,7 +113,9 @@ public static Builder builder() {
*
It has network timeout associated.
*
*
- * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
- * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].
+ *
+ *
* This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
*
*
@@ -157,6 +161,7 @@ public static InputStream toBufferedInputStream(final InputStream input, final i
* Constructs a new byte array output stream. The buffer capacity is initially.
*
* {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary.
+ *
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
*/
@Deprecated
diff --git a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
index d17318f79b6..5f3274790b8 100644
--- a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
@@ -143,14 +143,14 @@ public WriterOutputStream get() throws IOException {
@Override
public Builder setCharset(final Charset charset) {
super.setCharset(charset);
- this.charsetDecoder = getCharset().newDecoder();
+ this.charsetDecoder = newDecoder(getCharset());
return this;
}
@Override
public Builder setCharset(final String charset) {
super.setCharset(charset);
- this.charsetDecoder = getCharset().newDecoder();
+ this.charsetDecoder = newDecoder(getCharset());
return this;
}
@@ -198,18 +198,18 @@ public static Builder builder() {
/**
* Checks if the JDK in use properly supports the given charset.
*
- * @param charset the charset to check the support for
+ * @param charset the charset to check the support for.
*/
private static void checkIbmJdkWithBrokenUTF16(final Charset charset) {
if (!StandardCharsets.UTF_16.name().equals(charset.name())) {
return;
}
- final String TEST_STRING_2 = "v\u00e9s";
- final byte[] bytes = TEST_STRING_2.getBytes(charset);
+ final String testString = "v\u00e9s";
+ final byte[] bytes = testString.getBytes(charset);
final CharsetDecoder charsetDecoder2 = charset.newDecoder();
final ByteBuffer bb2 = ByteBuffer.allocate(16);
- final CharBuffer cb2 = CharBuffer.allocate(TEST_STRING_2.length());
+ final CharBuffer cb2 = CharBuffer.allocate(testString.length());
final int len = bytes.length;
for (int i = 0; i < len; i++) {
bb2.put(bytes[i]);
@@ -223,14 +223,24 @@ private static void checkIbmJdkWithBrokenUTF16(final Charset charset) {
bb2.compact();
}
cb2.rewind();
- if (!TEST_STRING_2.equals(cb2.toString())) {
+ if (!testString.equals(cb2.toString())) {
throw new UnsupportedOperationException("UTF-16 requested when running on an IBM JDK with broken UTF-16 support. "
+ "Please find a JDK that supports UTF-16 if you intend to use UF-16 with WriterOutputStream");
}
}
+ private static CharsetDecoder newDecoder(final Charset charset) {
+ // @formatter:off
+ return Charsets.toCharset(charset).newDecoder()
+ .onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .replaceWith("?");
+ // @formatter:on
+ }
+
private final Writer writer;
+
private final CharsetDecoder decoder;
private final boolean writeImmediately;
@@ -251,9 +261,9 @@ private WriterOutputStream(final Builder builder) throws IOException {
}
/**
- * Constructs a new {@link WriterOutputStream} that uses the virtual machine's {@link Charset#defaultCharset() default charset} and with a default output
- * buffer size of {@value #BUFFER_SIZE} characters. The output buffer will only be flushed when it overflows or when {@link #flush()} or {@link #close()} is
- * called.
+ * Constructs a new {@link WriterOutputStream} that uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} and with a default
+ * output buffer size of {@value #BUFFER_SIZE} characters. The output buffer will only be flushed when it overflows or when {@link #flush()} or
+ * {@link #close()} is called.
*
* @param writer the target {@link Writer}.
* @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
@@ -289,15 +299,7 @@ public WriterOutputStream(final Writer writer, final Charset charset) {
*/
@Deprecated
public WriterOutputStream(final Writer writer, final Charset charset, final int bufferSize, final boolean writeImmediately) {
- // @formatter:off
- this(writer,
- Charsets.toCharset(charset).newDecoder()
- .onMalformedInput(CodingErrorAction.REPLACE)
- .onUnmappableCharacter(CodingErrorAction.REPLACE)
- .replaceWith("?"),
- bufferSize,
- writeImmediately);
- // @formatter:on
+ this(writer, newDecoder(charset), bufferSize, writeImmediately);
}
/**
diff --git a/src/main/java/org/apache/commons/io/serialization/ClassNameMatcher.java b/src/main/java/org/apache/commons/io/serialization/ClassNameMatcher.java
index 47103a4293d..0682c66b802 100644
--- a/src/main/java/org/apache/commons/io/serialization/ClassNameMatcher.java
+++ b/src/main/java/org/apache/commons/io/serialization/ClassNameMatcher.java
@@ -27,8 +27,8 @@ public interface ClassNameMatcher {
/**
* Returns {@code true} if the supplied class name matches this object's condition.
*
- * @param className fully qualified class name
- * @return {@code true} if the class name matches this object's condition
+ * @param className fully qualified class name.
+ * @return {@code true} if the class name matches this object's condition.
*/
boolean matches(String className);
}
\ No newline at end of file
diff --git a/src/main/java/org/apache/commons/io/serialization/FullClassNameMatcher.java b/src/main/java/org/apache/commons/io/serialization/FullClassNameMatcher.java
index 14f725f5975..ae0268b4a98 100644
--- a/src/main/java/org/apache/commons/io/serialization/FullClassNameMatcher.java
+++ b/src/main/java/org/apache/commons/io/serialization/FullClassNameMatcher.java
@@ -19,7 +19,6 @@
package org.apache.commons.io.serialization;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -36,10 +35,10 @@ final class FullClassNameMatcher implements ClassNameMatcher {
/**
* Constructs an object based on the specified class names.
*
- * @param classes a list of class names
+ * @param classes a list of class names.
*/
FullClassNameMatcher(final String... classes) {
- classesSet = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(classes)));
+ classesSet = new HashSet<>(Arrays.asList(classes));
}
@Override
diff --git a/src/main/java/org/apache/commons/io/serialization/ObjectStreamClassPredicate.java b/src/main/java/org/apache/commons/io/serialization/ObjectStreamClassPredicate.java
index 5a3375cd72e..c032b7def55 100644
--- a/src/main/java/org/apache/commons/io/serialization/ObjectStreamClassPredicate.java
+++ b/src/main/java/org/apache/commons/io/serialization/ObjectStreamClassPredicate.java
@@ -36,10 +36,14 @@
*/
public class ObjectStreamClassPredicate implements Predicate {
- // This is not a Set for now to avoid ClassNameMatchers requiring proper implementations of hashCode() and equals().
+ /**
+ * This is not a Set for now to avoid ClassNameMatchers requiring proper implementations of hashCode() and equals().
+ */
private final List acceptMatchers = new ArrayList<>();
- // This is not a Set for now to avoid ClassNameMatchers requiring proper implementations of hashCode() and equals().
+ /**
+ * This is not a Set for now to avoid ClassNameMatchers requiring proper implementations of hashCode() and equals().
+ */
private final List rejectMatchers = new ArrayList<>();
/**
@@ -55,8 +59,8 @@ public ObjectStreamClassPredicate() {
* The reject list takes precedence over the accept list.
*
*
- * @param classes Classes to accept
- * @return this object
+ * @param classes Classes to accept.
+ * @return this object.
*/
public ObjectStreamClassPredicate accept(final Class>... classes) {
Stream.of(classes).map(c -> new FullClassNameMatcher(c.getName())).forEach(acceptMatchers::add);
@@ -112,7 +116,7 @@ public ObjectStreamClassPredicate accept(final String... patterns) {
* The reject list takes precedence over the accept list.
*
*
- * @param classes Classes to reject
+ * @param classes Classes to reject.
* @return {@code this} instance.
*/
public ObjectStreamClassPredicate reject(final Class>... classes) {
@@ -126,7 +130,7 @@ public ObjectStreamClassPredicate reject(final Class>... classes) {
* The reject list takes precedence over the accept list.
*
*
- * @param m the matcher to use
+ * @param m the matcher to use.
* @return {@code this} instance.
*/
public ObjectStreamClassPredicate reject(final ClassNameMatcher m) {
@@ -140,7 +144,7 @@ public ObjectStreamClassPredicate reject(final ClassNameMatcher m) {
* The reject list takes precedence over the accept list.
*
*
- * @param pattern standard Java regexp
+ * @param pattern standard Java regexp.
* @return {@code this} instance.
*/
public ObjectStreamClassPredicate reject(final Pattern pattern) {
@@ -188,17 +192,8 @@ public boolean test(final ObjectStreamClass objectStreamClass) {
*/
public boolean test(final String name) {
// The reject list takes precedence over the accept list.
- for (final ClassNameMatcher m : rejectMatchers) {
- if (m.matches(name)) {
- return false;
- }
- }
- for (final ClassNameMatcher m : acceptMatchers) {
- if (m.matches(name)) {
- return true;
- }
- }
- return false;
+ final Predicate p = m -> m.matches(name);
+ return rejectMatchers.stream().noneMatch(p) && acceptMatchers.stream().anyMatch(p);
}
}
\ No newline at end of file
diff --git a/src/main/java/org/apache/commons/io/serialization/RegexpClassNameMatcher.java b/src/main/java/org/apache/commons/io/serialization/RegexpClassNameMatcher.java
index 7d204dfa4f7..adb76fdc511 100644
--- a/src/main/java/org/apache/commons/io/serialization/RegexpClassNameMatcher.java
+++ b/src/main/java/org/apache/commons/io/serialization/RegexpClassNameMatcher.java
@@ -34,8 +34,8 @@ final class RegexpClassNameMatcher implements ClassNameMatcher {
/**
* Constructs an object based on the specified pattern.
*
- * @param pattern a pattern for evaluating acceptable class names
- * @throws NullPointerException if {@code pattern} is null
+ * @param pattern a pattern for evaluating acceptable class names.
+ * @throws NullPointerException if {@code pattern} is null.
*/
RegexpClassNameMatcher(final Pattern pattern) {
this.pattern = Objects.requireNonNull(pattern, "pattern");
@@ -44,7 +44,7 @@ final class RegexpClassNameMatcher implements ClassNameMatcher {
/**
* Constructs an object based on the specified regular expression.
*
- * @param regex a regular expression for evaluating acceptable class names
+ * @param regex a regular expression for evaluating acceptable class names.
*/
RegexpClassNameMatcher(final String regex) {
this(Pattern.compile(regex));
diff --git a/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java b/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
index 6141cc59b1c..495d02677b6 100644
--- a/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
+++ b/src/main/java/org/apache/commons/io/serialization/ValidatingObjectInputStream.java
@@ -26,6 +26,7 @@
import java.util.regex.Pattern;
import org.apache.commons.io.build.AbstractStreamBuilder;
+import org.apache.commons.io.input.BoundedInputStream;
/**
* An {@link ObjectInputStream} that's restricted to deserialize a limited set of classes.
@@ -33,7 +34,7 @@
*
* Various accept/reject methods allow for specifying which classes can be deserialized.
*
- *
Reading safely
+ *
Deserlizing safely
*
* Here is the only way to safely read a HashMap of String keys and Integer values:
*
+ * You can further guard your application againt untrusted input by limiting how much data to process using a {@link BoundedInputStream}.
+ * For example:
+ *
* @since 2.5
*/
public class ValidatingObjectInputStream extends ObjectInputStream {
@@ -119,8 +158,8 @@ public Builder() {
/**
* Accepts the specified classes for deserialization, unless they are otherwise rejected.
*
- * @param classes Classes to accept
- * @return this object
+ * @param classes Classes to accept.
+ * @return this object.
* @since 2.18.0
*/
public Builder accept(final Class>... classes) {
@@ -204,7 +243,7 @@ public ObjectStreamClassPredicate getPredicate() {
/**
* Rejects the specified classes for deserialization, even if they are otherwise accepted.
*
- * @param classes Classes to reject
+ * @param classes Classes to reject.
* @return {@code this} instance.
* @since 2.18.0
*/
@@ -216,7 +255,7 @@ public Builder reject(final Class>... classes) {
/**
* Rejects class names where the supplied ClassNameMatcher matches for deserialization, even if they are otherwise accepted.
*
- * @param matcher the matcher to use
+ * @param matcher the matcher to use.
* @return {@code this} instance.
* @since 2.18.0
*/
@@ -228,7 +267,7 @@ public Builder reject(final ClassNameMatcher matcher) {
/**
* Rejects class names that match the supplied pattern for deserialization, even if they are otherwise accepted.
*
- * @param pattern standard Java regexp
+ * @param pattern standard Java regexp.
* @return {@code this} instance.
* @since 2.18.0
*/
@@ -285,8 +324,8 @@ private ValidatingObjectInputStream(final Builder builder) throws IOException {
* Constructs an instance to deserialize the specified input stream. At least one accept method needs to be called to specify which classes can be
* deserialized, as by default no classes are accepted.
*
- * @param input an input stream
- * @throws IOException if an I/O error occurs while reading stream header
+ * @param input an input stream.
+ * @throws IOException if an I/O error occurs while reading stream header.
* @deprecated Use {@link #builder()}.
*/
@Deprecated
@@ -313,7 +352,7 @@ private ValidatingObjectInputStream(final InputStream input, final ObjectStreamC
* The reject list takes precedence over the accept list.
*
*
- * @param classes Classes to accept
+ * @param classes Classes to accept.
* @return {@code this} instance.
*/
public ValidatingObjectInputStream accept(final Class>... classes) {
diff --git a/src/main/java/org/apache/commons/io/serialization/package-info.java b/src/main/java/org/apache/commons/io/serialization/package-info.java
index 2e42a361fd2..b8a677a8a13 100644
--- a/src/main/java/org/apache/commons/io/serialization/package-info.java
+++ b/src/main/java/org/apache/commons/io/serialization/package-info.java
@@ -17,5 +17,7 @@
/**
* Provides a framework for controlling the deserialization of classes.
+ *
+ * You can deserlialize an object tree safely using a {@link org.apache.commons.io.serialization.ValidatingObjectInputStream}.
*/
package org.apache.commons.io.serialization;
diff --git a/src/main/javadoc/overview.html b/src/main/javadoc/overview.html
index 7fa4bd1f700..7de36f6ede9 100644
--- a/src/main/javadoc/overview.html
+++ b/src/main/javadoc/overview.html
@@ -17,16 +17,18 @@
-->
-
-These classes aim to add to the standard JDK IO classes.
-The utilities provide convenience wrappers around the JDK, simplifying
-various operations into pre-tested units of code.
-The filters and streams provide useful implementations that perhaps should
-be in the JDK itself.
-
diff --git a/src/site/xdoc/index.xml b/src/site/xdoc/index.xml
index 54022e401ae..403c225db03 100644
--- a/src/site/xdoc/index.xml
+++ b/src/site/xdoc/index.xml
@@ -28,7 +28,7 @@ limitations under the License.
Apache Commons IO is a library of utilities to assist with developing IO functionality.
- Main areas include:
+ The Commons IO packages include: