Làm cách nào để tải tập tin từ thư mục tài nguyên?


240

Dự án của tôi có cấu trúc như sau:

/src/main/java/
/src/main/resources/
/src/test/java/
/src/test/resources/

Tôi có một tệp trong /src/test/resources/test.csvvà tôi muốn tải tệp từ một bài kiểm tra đơn vị trong/src/test/java/MyTest.java

Tôi có mã này không hoạt động. Nó phàn nàn "Không có tập tin hoặc thư mục như vậy".

BufferedReader br = new BufferedReader (new FileReader(test.csv))

Tôi cũng đã thử điều này

InputStream is = (InputStream) MyTest.class.getResourcesAsStream(test.csv))

Điều này cũng không hoạt động. Nó trở lại null. Tôi đang sử dụng Maven để xây dựng dự án của mình.


Không hoạt động thế nào? Lỗi của bạn là gì
Daniel Kaplan

16
hãy thử điều nàythis.getClass().getResource("/test.csv")
SRy


@SRy nó đã hoạt động (vì điều này sẽ trả lại url đường dẫn tuyệt đối) tuy nhiên thời điểm tôi tạo tệp jar không hoạt động vì bên trong tệp jar và đường dẫn tuyệt đối trở nên không hợp lệ, có cách nào để chơi với chính đường dẫn tương đối
ShankPossible

Câu trả lời:


240

Hãy thử tiếp theo:

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("test.csv");

Nếu cách trên không hoạt động, các dự án khác nhau đã được thêm vào lớp sau: 1 (mã ở đây ). 2ClassLoaderUtil

Dưới đây là một số ví dụ về cách sử dụng lớp đó:

src \ main \ java \ com \ company \ test \ YourCallingClass.java
src \ main \ java \ com \ opensymphony \ xwork2 \ produc \ ClassLoaderUtil.java
src \ main \ resource \ test.csv
// java.net.URL
URL url = ClassLoaderUtil.getResource("test.csv", YourCallingClass.class);
Path path = Paths.get(url.toURI());
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// java.io.InputStream
InputStream inputStream = ClassLoaderUtil.getResourceAsStream("test.csv", YourCallingClass.class);
InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(streamReader);
for (String line; (line = reader.readLine()) != null;) {
    // Process line
}

Ghi chú

  1. Xem nó trong The Wayback Machine .
  2. Cũng trong GitHub .

14
Thx cho câu trả lời, bạn có thể vui lòng giải thích lý do tại sao chúng ta nên sử dụng trình tải rất cụ thể này nhưng không phải là của lớp không?
Hui Wang

1
tuyệt vời, tôi rất ngu ngốc mà tôi đã sử dụng Object.class.getClassLoader();, từ một bối cảnh tĩnh mà không làm việc - đề nghị này không - cũng gần như, nó tiêm nhiễm %20cho không gian mà mang lại cho tôi mộtFileNotFoundException
ycomp

5
@ycomp Vì getResource trả về URL chứ không phải tệp. Phương thức getFile của java.net.URL không chuyển đổi URL thành tệp; nó chỉ trả về các phần đường dẫn và truy vấn của URL. Bạn thậm chí không nên cố gắng chuyển đổi nó thành một Tệp; chỉ cần gọi openStream và đọc từ đó.
VGR

Kiểm tra dự án này, giải quyết việc quét thư mục tài nguyên: github.com/fraballi/resource-folder-scanner
Felix Aballi

60

Thử:

InputStream is = MyTest.class.getResourceAsStream("/test.csv");

IIRC getResourceAsStream()theo mặc định là liên quan đến gói của lớp.

Như @Terran đã lưu ý, đừng quên thêm vào /lúc bắt đầu tên tệp


3
Đối với những người tìm kiếm sự tỉnh táo, bài đăng này mang đến cho bạn tất cả các cách để có được tài nguyên dưới dạng String stackoverflow.com/a/35446009/544045
Trevor

12
"/" Là chìa khóa.
Terran

33

Đây là một giải pháp nhanh chóng với việc sử dụng ổi :

import com.google.common.base.Charsets;
import com.google.common.io.Resources;

public String readResource(final String fileName, Charset charset) throws IOException {
        return Resources.toString(Resources.getResource(fileName), charset);
}

Sử dụng:

String fixture = this.readResource("filename.txt", Charsets.UTF_8)

28

Thử mã Flowing trên dự án Spring

ClassPathResource resource = new ClassPathResource("fileName");
InputStream inputStream = resource.getInputStream();

Hoặc trên dự án không mùa xuân

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);

Không nên đóng InputStream?
030

6

Dự án phi xuân:

String filePath = Objects.requireNonNull(MyClass.class.getClassLoader().getResource("any.json")).getPath();

Stream<String> lines = Files.lines(Paths.get(filePath));

Đối với các dự án mùa xuân, bạn cũng có thể sử dụng một mã dòng để nhận bất kỳ tệp nào trong thư mục tài nguyên:

File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "any.json");

String content = new String(Files.readAllBytes(file.toPath()));

5

Bây giờ tôi đang minh họa mã nguồn để đọc một phông chữ từ thư mục tài nguyên được tạo bởi maven,

Scr / chính / tài nguyên / calibril.ttf

nhập mô tả hình ảnh ở đây

Font getCalibriLightFont(int fontSize){
    Font font = null;
    try{
        URL fontURL = OneMethod.class.getResource("/calibril.ttf");
        InputStream fontStream = fontURL.openStream();
        font = new Font(Font.createFont(Font.TRUETYPE_FONT, fontStream).getFamily(), Font.PLAIN, fontSize);
        fontStream.close();
    }catch(IOException | FontFormatException ief){
        font = new Font("Arial", Font.PLAIN, fontSize);
        ief.printStackTrace();
    }   
    return font;
}

Nó làm việc cho tôi và hy vọng rằng toàn bộ mã nguồn cũng sẽ giúp bạn, Hãy tận hưởng!


5

Cho java sau 1.7

 List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));

Tôi phải sử dụng "/test.csv" (lưu ý dấu gạch chéo).
Leon

4
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

Nếu bạn sử dụng bối cảnh ClassLoader để tìm tài nguyên thì chắc chắn nó sẽ tốn hiệu năng ứng dụng.


4
Các lập trình viên nên luôn luôn quan tâm đến hiệu suất. Mặc dù tối ưu hóa sớm là chắc chắn nên tránh, biết cách tiếp cận hiệu quả hơn để luôn luôn tốt. Nó giống như biết sự khác biệt giữa LinkedList và ArrayList và khi nào nên sử dụng cái này hay cái khác.
Marvo

6
@Marvo: Các lập trình viên phải luôn quan tâm đến chất lượng, khả năng và dễ bảo trì, hiệu suất đang ở hàng đợi.
Igor Rodriguez

2

Nhập khẩu sau:

import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.ArrayList;

Phương thức sau đây trả về một tệp trong ArrayList of String:

public ArrayList<String> loadFile(String filename){

  ArrayList<String> lines = new ArrayList<String>();

  try{

    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    InputStream inputStream = classloader.getResourceAsStream(filename);
    InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    BufferedReader reader = new BufferedReader(streamReader);
    for (String line; (line = reader.readLine()) != null;) {
      lines.add(line);
    }

  }catch(FileNotFoundException fnfe){
    // process errors
  }catch(IOException ioe){
    // process errors
  }
  return lines;
}

2

Tôi phải đối mặt với cùng một vấn đề .

Tập tin không được tìm thấy bởi trình tải lớp, có nghĩa là nó không được đóng gói vào tạo phẩm (jar). Bạn cần xây dựng dự án . Ví dụ: với maven:

mvn clean install

Vì vậy, các tệp bạn đã thêm vào thư mục tài nguyên sẽ được đưa vào maven build và có sẵn cho ứng dụng.

Tôi muốn giữ câu trả lời của mình: nó không giải thích cách đọc một tệp (các câu trả lời khác giải thích điều đó), nó trả lời tại sao InputStream hoặc resourcenull . Câu trả lời tương tự là ở đây .


1
Cảm ơn, đã cứu tôi khỏi nghĩ rằng tôi đang mất trí!
StuPulumException

1

getResource () đã hoạt động tốt với các tệp tài nguyên được đặt trong src/main/resources. Để có được một tập tin ở đường dẫn khác hơn là src/main/resourcesnóisrc/test/java bạn cần để tạo ra nó exlicitly.

ví dụ sau đây có thể giúp bạn

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws URISyntaxException, IOException {
        URL location = Main.class.getProtectionDomain().getCodeSource().getLocation();
        BufferedReader br = new BufferedReader(new FileReader(location.getPath().toString().replace("/target/classes/", "/src/test/java/youfilename.txt")));
    }
}

0

Mã có hoạt động khi không chạy jar Maven-build không, ví dụ như khi chạy từ IDE của bạn? Nếu vậy, hãy chắc chắn rằng tập tin thực sự được bao gồm trong jar. Thư mục tài nguyên nên được bao gồm trong tệp pom, trong <build><resources>.


Khi sử dụng nhật thực và chạy mã từ chính IDE. Làm cách nào chúng ta có thể tải tài nguyên ở "/ src / test / resource" trong mã Java cụ thể trong các thử nghiệm đơn vị. Hãy xem xét một cấu trúc dự án maven tiêu chuẩn.
Bhavesh

0

Lớp sau có thể được sử dụng để tải a resourcetừ classpathvà cũng nhận được thông báo lỗi phù hợp trong trường hợp có vấn đề với cái đã cho filePath.

import java.io.InputStream;
import java.nio.file.NoSuchFileException;

public class ResourceLoader
{
    private String filePath;

    public ResourceLoader(String filePath)
    {
        this.filePath = filePath;

        if(filePath.startsWith("/"))
        {
            throw new IllegalArgumentException("Relative paths may not have a leading slash!");
        }
    }

    public InputStream getResource() throws NoSuchFileException
    {
        ClassLoader classLoader = this.getClass().getClassLoader();

        InputStream inputStream = classLoader.getResourceAsStream(filePath);

        if(inputStream == null)
        {
            throw new NoSuchFileException("Resource file not found. Note that the current directory is the source folder!");
        }

        return inputStream;
    }
}

0

Tôi đã giải quyết vấn đề này bằng cách thêm /scr/main/resourcesthư mục vàoJava Build Path

nhập mô tả hình ảnh ở đây


Hãy thử điều này nhưng đây không phải là giải pháp
Jasonw

0

Tôi đã làm cho nó hoạt động trên cả chạy jar và trong IDE bằng cách viết như

 InputStream schemaStream = ProductUtil.class.getClassLoader().getResourceAsStream(jsonSchemaPath);
            byte[] buffer = new byte[schemaStream.available()];
            schemaStream.read(buffer);

        File tempFile = File.createTempFile("com/package/schema/testSchema", "json");
        tempFile.deleteOnExit();
        FileOutputStream out = new FileOutputStream(tempFile);
        out.write(buffer);

Làm thế nào để cấu trúc tập tin của bạn trông như thế nào?
luckydonald


0

Bạn có thể sử dụng com.google.common.io.Resource.getResource để đọc url của tệp và sau đó lấy nội dung tệp bằng java.nio.file.Files để đọc nội dung của tệp.

URL urlPath = Resources.getResource("src/main/resource");
List<String> multilineContent= Files.readAllLines(Paths.get(urlPath.toURI()));

-2

Tôi làm cho nó hoạt động mà không có bất kỳ tham chiếu nào đến "class" hoặc "ClassLoader".

Giả sử chúng ta có ba kịch bản với vị trí của tệp 'example.file' và thư mục làm việc của bạn (nơi ứng dụng của bạn thực thi) là home / mydocument / chương trình / dự án / myapp:

a) Một thư mục con xuống thư mục làm việc: myapp / res / files / example.file

b) Một thư mục con không xuống thư mục làm việc: dự án / tập tin / example.file

b2) Một thư mục con khác không hạ xuống thư mục làm việc: chương trình / files / example.file

c) Một thư mục gốc: home / mydocument / files / example.file (Linux; trong Windows thay thế home / bằng C :)

1) Lấy đúng đường dẫn: a) String path = "res/files/example.file"; b) String path = "../projects/files/example.file" b2) String path = "../../program/files/example.file" c)String path = "/home/mydocuments/files/example.file"

Về cơ bản, nếu đó là một thư mục gốc, hãy bắt đầu tên đường dẫn bằng dấu gạch chéo hàng đầu. Nếu nó là một thư mục con, không được gạch chéo trước tên đường dẫn. Nếu thư mục con không xuống thư mục làm việc, bạn phải cd vào thư mục đó bằng cách sử dụng "../". Điều này báo cho hệ thống đi lên một thư mục.

2) Tạo một đối tượng Tệp bằng cách chuyển đúng đường dẫn:

File file = new File(path);

3) Bây giờ bạn tốt để đi:

BufferedReader br = new BufferedReader(new FileReader(file));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.