Kaynak klasöründen nasıl dosya yüklerim?


240

Projem aşağıdaki yapıya sahip:

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

İçinde bir dosya var /src/test/resources/test.csvve dosyayı bir birim testten yüklemek istiyorum/src/test/java/MyTest.java

Ben işe yaramadı bu kodu var. "Böyle bir dosya veya dizin yok" ifadesinden şikayet ediyor.

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

Bunu da denedim

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

Bu da işe yaramıyor. Geri döner null. Projemi oluşturmak için Maven kullanıyorum.


Nasıl çalışmıyor? Senin hatan nedir?
Daniel Kaplan

17
Bunu deneyinthis.getClass().getResource("/test.csv")
SRy


@SRy çalıştı (çünkü bu mutlak yol url verecektir) ancak jar dosyasını yaptığım an onun bir kavanoz içinde çalışmıyor ve mutlak yol geçersiz olur, göreceli yolun kendisi ile oynamak için bir yol var
ShankPossible

Yanıtlar:


240

Sonrakini deneyin:

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

Yukarıdakiler işe yaramazsa, aşağıdaki projeye çeşitli projeler eklenmiştir: 1 (kod burada ). 2ClassLoaderUtil

İşte bu sınıfın nasıl kullanıldığına dair bazı örnekler:

src \ ana \ java \ com \ şirket \ test \ YourCallingClass.java
src \ ana \ java \ com \ OpenSymphony \ xwork2 \ util \ ClassLoaderUtil.java
src \ ana \ kaynaklar \ 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
}

notlar

  1. Çalışırken görün yılında Wayback Machine .
  2. Ayrıca GitHub'da .

14
cevap için teşekkürler, lütfen neden bu çok özel yükleyiciyi kullanmamız gerektiğini açıklayabilir misiniz?
Hui Wang

1
harika, o kadar aptaldım ki Object.class.getClassLoader();, işe yaramayan statik bir bağlamda kullanıyordum - bu öneri işe yarıyor - neredeyse, %20bana 20FileNotFoundException
03'te ycomp

5
@ycomp getResource bir dosya değil bir URL döndürür. Java.net.URL ait getFile yöntemi değil bir dosyaya bir URL dönüştürmek; yalnızca URL'nin yol ve sorgu bölümlerini döndürür. Hatta bunu bir Dosyaya dönüştürmeye çalışmamalısınız; sadece openStream'i arayın ve bundan okuyun.
VGR

Bu projeyi kontrol edin, kaynaklar klasör taramasını çözer: github.com/fraballi/resources-folder-scanner
Felix Aballi

60

Deneyin:

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

IIRC getResourceAsStream()varsayılan olarak sınıfın paketine göredir.

@Terran belirtildiği gibi, eklemeyi unutmayın /dosya başlangıç at


3
Akıl sağlığı arayanlar için, bu gönderi kaynağı bir String stackoverflow.com/a/35446009/544045
Trevor

12
"/" Anahtardır.
Terran

33

İşte Guava kullanımı ile hızlı bir çözüm :

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);
}

Kullanımı:

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

28

Flowing kodlarını İlkbahar projesinde deneyin

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

Veya bahar olmayan projelerde

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

InputStream kapatılmamalı mı?
030

7

Bahar olmayan proje:

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

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

Bahar projeleri için, kaynaklar klasörü altındaki herhangi bir dosyayı almak için bir satır kodu da kullanabilirsiniz:

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

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

5

Şimdi maven oluşturulan kaynaklar dizininden bir yazı tipi okumak için kaynak kodunu gösteriyorum,

scr / ana / kaynaklar / calibril.ttf

resim açıklamasını buraya girin

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;
}

Benim için çalıştı ve tüm kaynak kodu da size yardımcı olacağını umuyoruz, tadını çıkarın!


5

1.7'den sonra java için

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

"/Test.csv" kullanmalıyım (eğik çizgiyi not edin).
Leon

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

Bir kaynak bulmak için bağlam ClassLoader'ı kullanırsanız, kesinlikle uygulama performansına mal olacaktır.


4
Programcılar her zaman performans konusunda endişeli olmalıdır. Erken optimizasyondan kesinlikle kaçınılması gerekirken, daha etkili bir yaklaşımın bilinmesi her zaman iyidir. LinkedList ve ArrayList arasındaki farkı ve ne zaman veya diğerini kullanacağını bilmek gibidir.
Marvo

6
@Marvo: Programcılar her zaman kalite, yetenekler ve bakım kolaylığı konusunda endişe duymalıdır, performans kuyruktadır.
Igor Rodriguez

2

Aşağıdakileri içe aktarın:

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

Aşağıdaki yöntem, Dizelerin ArrayList'indeki bir dosyayı döndürür:

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

Aynı sorunla karşılaştım .

Dosya bir sınıf yükleyici tarafından bulunamadı, yani artefakta (kavanoz) paketlenmedi. Projeyi inşa etmeniz gerekiyor . Örneğin, maven ile:

mvn clean install

Böylece, kaynaklar klasörüne eklediğiniz dosyalar maven derlemesine girecek ve uygulama için kullanılabilir hale gelecektir.

Cevabımı tutmak istiyorum: Bir dosya (diğer cevaplar açıklamak yapmak) okumayı açıklamıyor, bu cevaplar neden InputStream ya resourceidi boş . Benzer cevap burada .


1
Teşekkürler, beni aklımı kaybettiğimi düşünmekten kurtardı!
StuPointerException

1

getResource () src/main/resourcesyalnızca yerleştirilen kaynak dosyalarıyla iyi çalışıyordu . src/main/resourcesSöylemekten başka yoldaki bir dosyayı almak içinsrc/test/java açıkça oluşturmanız gerekir.

aşağıdaki örnek size yardımcı olabilir

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

Kod, Maven-build jar'ünü çalıştırmadığınızda, örneğin IDE'nizden çalıştırıldığında çalışıyor mu? Öyleyse, dosyanın gerçekten kavanoza dahil edildiğinden emin olun. Resources klasörü, içindeki pom dosyasına dahil edilmelidir <build><resources>.


Tutulma kullanırken ve IDE'nin kendisinden kod çalıştırırken. Java biriminde "/ src / test / resources" adresinde bulunan kaynakları, özellikle birim testlerinde nasıl yükleyebiliriz? Standart bir maven proje yapısını düşünün.
Bhavesh

0

Aşağıdaki sınıf yüklemek için kullanılabilir resourcedan classpathve ayrıca verilen bir sorun olması ihtimaline karşı bir uydurma hata iletisi 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

Bu sorunu /scr/main/resourcesklasörüme klasör ekleyerek çözdümJava Build Path

resim açıklamasını buraya girin


bunu deneyin ama bu çözüm değil
Jasonw

0

Hem çalışan kavanozda hem de IDE'de

 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);

Dosya yapınız nasıl görünüyor?
luckydonald


0

Dosyanın URL'sini okumak için com.google.common.io.Resources.getResource 'u kullanabilir ve ardından dosyanın içeriğini okumak için java.nio.file.Files dosyasını kullanarak dosya içeriğini alabilirsiniz.

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

-2

Ben "class" veya "ClassLoader" herhangi bir başvuru olmadan çalışmak olsun.

Diyelim ki 'example.file' dosyasının bulunduğu üç senaryo var ve çalışma dizininiz (uygulamanızın yürüttüğü yer) home / mydocuments / program / projects / myapp:

a) Çalışma dizinine ait bir alt klasör: myapp / res / files / example.file

b) Çalışma dizinine ait olmayan bir alt klasör: projeler / dosyalar / örnek.file

b2) Çalışma dizinine ait olmayan başka bir alt klasör: program / files / example.file

c) Bir kök klasör: home / mydocuments / files / example.file (Linux; Windows'da home yerine / C :)

1) Doğru yolu seçin: 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"

Temel olarak, eğer bir kök klasör ise, yol adını baş eğik çizgi ile başlatın. Bir alt klasörse, yol adından önce eğik çizgi olmamalıdır. Eğer alt klasör çalışma dizinine ait değilse "../" kullanarak cd'ye yazmalısınız. Bu, sisteme bir klasör yukarı gitmesini söyler.

2) Doğru yolu geçerek bir File nesnesi oluşturun:

File file = new File(path);

3) Artık gitmekte fayda var:

BufferedReader br = new BufferedReader(new FileReader(file));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.