Spring Boot讀取resources目錄下的文本文件

Java 8

Spring Boot 2.7.3

IntelliJ IDEA 2022.3.2 (Community Edition)

--

 

開門見山

使用  ClassLoader 的 getResourceAsStream 讀取。

注,還可以使用 其下的 靜態方法 getSystemResourceAsStream 讀取。

函數源碼:

ClassLoader部分源碼
 public abstract class ClassLoader {
    
    /**
     * Returns an input stream for reading the specified resource.
     *
     * <p> The search order is described in the documentation for {@link
     * #getResource(String)}.  </p>
     *
     * @param  name
     *         The resource name
     *
     * @return  An input stream for reading the resource, or <tt>null</tt>
     *          if the resource could not be found
     *
     * @since  1.1
     */
    public InputStream getResourceAsStream(String name) {
        URL url = getResource(name);
        try {
            return url != null ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }

    /**
     * Open for reading, a resource of the specified name from the search path
     * used to load classes.  This method locates the resource through the
     * system class loader (see {@link #getSystemClassLoader()}).
     *
     * @param  name
     *         The resource name
     *
     * @return  An input stream for reading the resource, or <tt>null</tt>
     *          if the resource could not be found
     *
     * @since  1.1
     */
    public static InputStream getSystemResourceAsStream(String name) {
        URL url = getSystemResource(name);
        try {
            return url != null ? url.openStream() : null;
        } catch (IOException e) {
            return null;
        }
    }

}

  ben發佈於博客園

測試項目

名稱:bootweb

測試文件 爲項目 src/main/resources/txtFiles 目錄中 的 txtFile001.txt。

內容:僅 5行。文本文件,UTF-8編碼

  ben發佈於博客園

測試代碼

package com.lib.bootweb.runner;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * 讀取文件測試
 */
@Component
@Slf4j
public class ReadFileTest implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 輸出項目的 classpath
        URL url1 = this.getClass().getClassLoader().getResource("");
        log.info("URL url1={}", url1);
        URL url2 = this.getClass().getClassLoader().getResource("/");
        log.info("URL url2={}", url2);

        this.readTxtFileInResources("txtfiles/txtFile001.txt");

        log.info("ReadFileTest END.");
    }

    /**
     * 讀取 src/main/resources 下的 文本文件
     * @param relPath 文本文件相對於 src/main/resources 的 相對路徑
     */
    private void readTxtFileInResources(String relPath) {
        StringBuffer sb = new StringBuffer();

        try (InputStream fileIs = this.getClass().getClassLoader().getResourceAsStream(relPath)) {
            final int maxSize = 1024;
            byte[] buff = new byte[maxSize];
            int read = 0;

            while ((read = fileIs.read(buff, 0, maxSize)) > 0) {
                sb.append(new String(buff, 0, read));
            }
        } catch (IOException e) {
            log.error("發生異常:e=", e);
            throw new RuntimeException(e);
        }

        log.info("StringBuffer sb=\r\n{}", sb);
    }
}

 

疑問,如果緩存的長度不是 1024字節,該怎麼處理?如果文件不是UTF-8編碼,該怎麼處理?TODO ben發佈於博客園

解釋(參考資料#4):

 

測試方式:

運行bootweb項目,檢查輸出日誌。

注意輸出的 url1、url2 的信息。 ben發佈於博客園

 

在IDEA中運行

運行結果:

URL url1=file:/D:/bootweb/target/classes/
URL url2=null
StringBuffer sb=
123456789
abcdefgHIJKLMN
   232   @#$$@_+=
第4行

ReadFileTest END.

成功輸出了文件內容。

 

運行時,文件是從 classes 中獲取的:

  ben發佈於博客園

使用java -jar命令運行

打包(忽略 test):

打包後生成:bootweb-0.0.1-SNAPSHOT.jar

  ben發佈於博客園

使用 IDEA的終端 運行:亂碼問題

進入IDEA的終端,執行:

java -jar .\target\bootweb-0.0.1-SNAPSHOT.jar

 運行結果:

URL url1=jar:file:/D:/bootweb/target/bootweb-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!
/
URL url2=jar:file:/D:/bootweb/target/bootweb-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!
/
StringBuffer sb=
123456789
abcdefgHIJKLMN
   232   @#$$@_+=
絎?4琛?

ReadFileTest END.

運行正常。

但是,存在亂碼——原因:終端的 字符集不是UTF-8。 ben發佈於博客園

 

使用 參考資料#3 方式修改終端的編碼,再 添加 -Dfile.encoding=UTF-8 執行,但是還是亂碼。

 

使用Windows 本身的終端運行:正常

打開終端,執行 chcp 65001;

再執行:java -jar -Dfile.encoding=UTF-8 target\bootweb-0.0.1-SNAPSHOT.jar

執行結果:無亂碼

 

--END--

 

本文鏈接:

 https://www.cnblogs.com/luo630/p/17073436.html

 

參考資料

1、Java file.encoding 

https://www.cnblogs.com/virgosnail/p/10868402.html

2、java 讀取classpath下的文件

https://blog.csdn.net/leveretz/article/details/127984226

3、修改win10終端控制檯默認編碼爲utf-8

https://blog.csdn.net/weixin_45265547/article/details/121931397

在窗口中輸入chcp 65001

4、IO流 FileInputStream與FileReader

https://blog.csdn.net/weixin_45073048/article/details/102574013

5、

 

 

 ben發佈於博客園

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章