diff --git a/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java b/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java index 958b3babce7c..bc1b2e95186f 100644 --- a/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java @@ -25,7 +25,10 @@ import java.net.URLConnection; import java.nio.channels.FileChannel; import java.nio.channels.ReadableByteChannel; +import java.nio.charset.Charset; +import java.nio.file.Files; import java.nio.file.NoSuchFileException; +import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import org.springframework.util.ResourceUtils; @@ -298,6 +301,39 @@ protected void customizeConnection(HttpURLConnection con) throws IOException { con.setRequestMethod("HEAD"); } + /** + * This implementation returns the contents of a file as a string using the + * system default Charset. Provided the resource exists and the context has + * access to it, the contents will be returned as a single string with line + * feed characters retained. + * @return the contents of the requested file as a {@code String}. + * @throws FileNotFoundException in the event the file path is invalid. + * @throws IOException if the file can not be read or cannot be serialzied. + */ + @Override + public String getContentAsString() throws IOException { + + if( !exists() ) { + throw new FileNotFoundException(getDescription() + " cannot be found."); + } + if ( !isReadable() ) { + throw new IOException(getDescription() + " cannot be opened for reading."); + } + return new String(Files.readAllBytes(Paths.get(getFile().getAbsolutePath())), Charset.defaultCharset()); + } + + @Override + public String getContentAsString(Charset charset) throws IOException { + + if( !exists() ) { + throw new FileNotFoundException(getDescription() + " cannot be found."); + } + if ( !isReadable() ) { + throw new IOException(getDescription() + " cannot be opened for reading."); + } + return new String(Files.readAllBytes(Paths.get(getFile().getAbsolutePath())), charset); + + } /** * Inner delegate class, avoiding a hard JBoss VFS API dependency at runtime. diff --git a/spring-core/src/main/java/org/springframework/core/io/Resource.java b/spring-core/src/main/java/org/springframework/core/io/Resource.java index 1995ee783e6d..4945b9406ff3 100644 --- a/spring-core/src/main/java/org/springframework/core/io/Resource.java +++ b/spring-core/src/main/java/org/springframework/core/io/Resource.java @@ -17,12 +17,14 @@ package org.springframework.core.io; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; +import java.nio.charset.Charset; import org.springframework.lang.Nullable; @@ -175,4 +177,41 @@ default ReadableByteChannel readableChannel() throws IOException { */ String getDescription(); + /** + * Return a {@link ReadableByteChannel}. + *

It is expected that each call creates a fresh channel. + *

The default implementation returns {@link Channels#newChannel(InputStream)} + * with the result of {@link #getInputStream()}. + * @return the byte channel for the underlying resource (must not be {@code null}) + * @throws java.io.FileNotFoundException if the underlying resource doesn't exist + * @throws IOException if the content channel could not be opened + * @since 5.0 + * @see #getInputStream() + */ + + /** + * Returns the contents of a file as a string using the system default Charset. + *

The default implementation returns a {@link Object#toString()} representation of the resource. + * @return the contents of the requested file as a {@code String}. + * @throws FileNotFoundException in the event the file path is invalid. + * @throws IOException if the file can not be read or cannot be accessed. + * @since 5.2.5 + */ + default String getContentAsString() throws IOException{ + return toString(); + } + + /** + * Returns the contents of a file as a string using the specified Charset. + *

The default implementation returns a {@link Object#toString()} representation of the resource. + * @param charset the {@code Charset} to use to deserialize the content. Defaults to system default. + * @return the contents of the requested file as a {@code String}. + * @throws FileNotFoundException in the event the file path is invalid. + * @throws IOException if the file can not be read or cannot be accessed. + * @since 5.2.5 + */ + default String getContentAsString(Charset charset) throws IOException{ + return toString(); + } + } diff --git a/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java index 838656757593..6bb074937766 100644 --- a/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java +++ b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java @@ -337,4 +337,25 @@ void readableChannelNotFoundOnClassPathResource() throws IOException { new ClassPathResource("Resource.class", getClass()).createRelative("X").readableChannel()); } + @Test + void getContentAsString_givenValidFile_ShouldReturnFileContent() throws IOException { + String expectedString = "\n" + + "\n" + + "\n" + + "\tbar\n" + + ""; + + String fileDirString = + new ClassPathResource("org/springframework/core/io/example.xml").getContentAsString(); + assertThat(fileDirString).isNotBlank(); + assertThat(fileDirString).isEqualTo(expectedString); + } + + @Test + void getContentAsString_givenAnInvalidFile_ShouldThrowFileNotFoundException(){ + assertThatExceptionOfType(FileNotFoundException.class) + .isThrownBy(new ClassPathResource("nonExistantFile")::getContentAsString); + + } + } diff --git a/spring-core/src/test/resources/org/springframework/core/io/example.xml b/spring-core/src/test/resources/org/springframework/core/io/example.xml index 1d638537e108..b9d4450840e9 100644 --- a/spring-core/src/test/resources/org/springframework/core/io/example.xml +++ b/spring-core/src/test/resources/org/springframework/core/io/example.xml @@ -2,5 +2,4 @@ bar - - + \ No newline at end of file