79

How can I load a Spring resource contents and use it to set a bean property or pass it as an argument constructor?

The resource contains free text.

Adrian Ber
  • 20,474
  • 12
  • 67
  • 117
  • Probably this is what you need http://stackoverflow.com/questions/10202494/method-in-spring-to-read-txt-file – Parvez Dec 24 '12 at 16:43
  • Yep, like that, but I didn't want to write my own code for this. – Adrian Ber Dec 25 '12 at 00:41
  • 2
    Depending on what you want to do once you read the file you can try org/springframework/util/FileCopyUtils.html#copyToByteArray(java.io.File) – Parvez Dec 25 '12 at 03:29
  • Good idea! I updated my answer to reflect this too. This way Commons IO is not required anymore. I think I overlooked `FileCopyUtils`. – Adrian Ber Dec 25 '12 at 07:41

7 Answers7

63

In one line try this to read test.xml:

String msg = StreamUtils.copyToString( new ClassPathResource("test.xml").getInputStream(), Charset.defaultCharset()  );
GhostCat
  • 137,827
  • 25
  • 176
  • 248
N Piper
  • 731
  • 5
  • 2
  • 4
    I like this because it's using Spring utils: `org.springframework.util.StreamUtils` – Josue Abarca Apr 11 '18 at 23:11
  • 9
    `FileCopyUtils.copyToString()` would be a better solution here, because that will close the InputStream after use. (The javadoc of both classes reference each other, with this as the notable difference.) – Eirik Lygre Aug 19 '18 at 20:02
  • Works like a charm! And I love the combination with the [How to get files from resources folder. Spring Framework](https://stackoverflow.com/a/39472514/4964553) answer. This way I use `@Value(value = "classpath:test.xml") private Resource testXml;` and then simply use `String msg = StreamUtils.copyToString(testXml.getInputStream(), Charset.defaultCharset() );` – jonashackt Jun 12 '19 at 11:07
34
<bean id="contents" class="org.apache.commons.io.IOUtils" factory-method="toString">
    <constructor-arg value="classpath:path/to/resource.txt" type="java.io.InputStream" />
</bean>

This solution requires Apache Commons IO.

Another solution, suggested by @Parvez, without Apache Commons IO dependency is

<bean id="contents" class="java.lang.String">
    <constructor-arg>
        <bean class="org.springframework.util.FileCopyUtils" factory-method="copyToByteArray">
            <constructor-arg value="classpath:path/to/resource.txt" type="java.io.InputStream" />
        </bean>     
    </constructor-arg>
</bean>
Adrian Ber
  • 20,474
  • 12
  • 67
  • 117
  • Another similar solution with annotations only: http://stackoverflow.com/a/14679461/363573 – Stephan May 24 '14 at 22:19
  • how wolud you add the Charset to that constructor? i tried adding: but got: cvc-complex-type.2.4.d: Invalid content was found starting with element 'bean'. No child element is expected at this point. – Alfredo M Apr 27 '17 at 18:18
  • You should enclose that bean into another `` element. – Adrian Ber Apr 28 '17 at 09:21
15

Just read it :

    try {
        Resource resource = new ClassPathResource(fileLocationInClasspath);
        BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()),1024);
        StringBuilder stringBuilder = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            stringBuilder.append(line).append('\n');
        }
        br.close();
        return stringBuilder.toString();
    } catch (Exception e) {
        LOGGER.error(e);
    }
daoway
  • 779
  • 7
  • 8
8

Update in 2021.

You can use Spring's Resource Interface to get the content of text file, and then use StreamUtils.copyToString(resource.getInputStream(), Charset.defaultCharset()); to get the text.

An example as follow:

    @Value("classpath:appVersionFilePath")
    private Resource resource;

    @GetMapping(value = "/hello")
    public HttpResult<String> hello() throws IOException {
        String appVersion = StreamUtils.copyToString(resource.getInputStream(), Charset.defaultCharset());
        // ...
    }
Qianyue
  • 1,767
  • 19
  • 24
4

This is one way of doing it without using any external library.. default provided by spring.. environment.properties file contains key value pairs...reference each value with ${key}

here in my example, I am keeping database props

<bean id="propertyConfigurer"
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list value-type="org.springframework.core.io.Resource">
            <value>classpath:environment.properties</value>

        </list>
    </property>
</bean>
<bean id="mySQLdataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${JDBC.driver}" />
    <property name="url" value="${JDBC.URL}" />
    <property name="username" value="${JDBC.username}" />
    <property name="password" value="${JDBC.password}" />
</bean>
Chetan
  • 1,507
  • 7
  • 30
  • 43
  • 1
    Yes, but that file should be a properties file. I just wanted to load a plain text file. So actually your solution doesn't solve the problem. – Adrian Ber Dec 24 '12 at 16:30
  • 1
    What could be the possible content of that text file? In general most of the bean property are most likly in key value pair. So it is hard give a solution to the problem without getting actual requirement. I would suggest edit the question so that others can answer better. – Chetan Dec 24 '12 at 16:40
  • 1
    The contents of the file could be anything: a template, an SQL statement, a longer description, an HTML fragment ... The idea is to read that content into a String and pass it to a bean, which let's say have a property like `setDescription(String)`. – Adrian Ber Dec 24 '12 at 18:51
1

daoway answer was very helpful, and following Adrian remark I am adding a configuration snippet similar to daoway's code

<bean id="contents" class="org.springframework.core.io.ClassPathResource">
    <constructor-arg value="path/to/resource.txt"/>
</bean>

From your component

    @Autowired
    private Resource contents;

    @PostConstruct
    public void load(){
        try {
            final InputStream inputStream = contents.getInputStream();
                //use the stream 
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream ,1024);
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                stringBuilder.append(line).append('\n');
            }
            br.close();
     }catch (IOException e) {
            LOGGER.error(message);
     }
  }
Community
  • 1
  • 1
Haim Raman
  • 11,508
  • 6
  • 44
  • 70
1

Spring

    private String readResource(String fileName){
    ResourceLoader resourceLoader = new DefaultResourceLoader();
    Resource resource = resourceLoader.getResource("resourceSubfolder/"+fileName)
    try{
         Reader reader = new InputStreamReader(resource.getInputStream());
         return FileCopyUtils.copyToString(reader);
    } catch (IOException e){
         e.printStackTrace();
    }
    return null;
    }
vitalinvent
  • 433
  • 1
  • 5
  • 11