Kaynak metin dosyasını Dize (Java) olarak okumak için araçlar [kapalı]


215

Kaynaktaki bir metin dosyasını bir String'e okumaya yardımcı olan herhangi bir yardımcı program var mı? Bunun popüler bir gereklilik olduğunu düşünüyorum, ancak Google'dan sonra herhangi bir yardımcı program bulamadım.


1
lütfen "kaynak metin dosyası" ve "kaynak metin dosyası" ile ne demek istediğinizi açıklığa kavuşturun - ne elde etmeye çalıştığınızı anlamak kolay değildir.
Mat

Bu sadece sınıf yolu altında "classpath *: mytext / text.txt" gibi bir metin dosyası
Loc Phan

Yanıtlar:


301

Evet, Guava bunu Resourcessınıfta sağlıyor. Örneğin:

URL url = Resources.getResource("foo.txt");
String text = Resources.toString(url, StandardCharsets.UTF_8);

21
@JonSkeet Bu harika, ancak web uygulamaları için en iyi çözüm olmayabilir, uygulanması getResourcekullanılıyor, Resource.class.getClassLoaderancak web uygulamalarında bu "sizin" sınıf yükleyiciniz olmayabilir, bu nedenle (örneğin [1] 'de) kullanılması önerilir. Thread.currentThread().getContextClassLoader().getResourceAsStreamyerine (referans [1]: stackoverflow.com/questions/676250/… )
Eran Medan

2
@EranMedan: Evet, bağlam sınıf yükleyicisini istiyorsanız bunu açıkça kullanmak istersiniz.
Jon Skeet

6
Kaynak sınıfınızın yanında olduğunda özel durumda Resources.toString(MyClass.getResource("foo.txt"), Charsets.UTF_8), doğru sınıf yükleyicinin kullanımını garanti eden işlemleri yapabilirsiniz .
Bogdan Calmac

2
com.google.common.io.ResourcesSonarQube
Ghilteras

1
guavauygulamayı değiştirdi. Guava 23 için uygulama aşağıdakileri sever. ClassLoader loader = MoreObjects.firstNonNull( Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());
xxy

171

Bunu yapmak için eski Stupid Scanner hile oneliner'ı guava gibi ek bir bağımlılık olmadan kullanabilirsiniz:

String text = new Scanner(AppropriateClass.class.getResourceAsStream("foo.txt"), "UTF-8").useDelimiter("\\A").next();

Çocuklar, gerçekten ihtiyacınız olmadığı sürece 3. parti eşyalarını kullanmayın. JDK'da zaten çok fazla işlevsellik var.


41
3. kişiden kaçınmak makul bir ilkedir. Maalesef çekirdek kütüphane gerçek hayattaki kullanım örneklerini modellemeye alerjik görünüyor. Java 7'nin Dosyalarına bakın ve neden bir sınıf yolu kaynağından her şeyi okumanın neden orada olmadığını söyleyin? Veya en azından standart bir 'dosya sistemi' kullanarak.
Dilum Ranatunga

3
Akışı da kapatmak gerekli mi, yoksa gerekli değil mi? Guava akışı dâhili kapatır.
virgo47

Benim için de güzel çalıştı! Üçüncü taraf hakkında da aynı fikirdeyim: Birçok yanıtta, varsayılan yanıt her zaman bazı üçüncü taraf kütüphanelerini kullanmak gibi görünüyor - Apache'den veya başka birinden olsun.
Terje Dahl

1
değiştirmek CartApplication.class.getResourceAsStreamiçin CartApplication.class.getClassLoader().getResourceAsStreamgeçerli jar..like srm / test / kaynaklardaki kaynaklarını yüklemek için
Chris Damour

5
Bunu kullanırken üçüncü taraf paketlerinden kaçınmaya tamamen katılmıyorum. Java'da, bir dosyayı dizeye kolayca okumanın tek yolunun tarayıcı hilesi olması oldukça üzücüdür. Üçüncü taraf bir lib kullanmanın alternatifi, herkesin sadece kendi paketleyicilerini oluşturacağıdır. Bu tür bir operasyon için çok fazla ihtiyacınız varsa, IO eller için Guava kazanır. Kabul edeceğim yer, kodunuzda bunu yapmak istediğinizde yalnızca bir yer varsa, 3. taraf paketini almamanızdır. Bu aşırı derecede imo olurdu.
Kenny Cason

90

Java 7 için:

new String(Files.readAllBytes(Paths.get(getClass().getResource("foo.txt").toURI())));

3
Lütfen bunun neden işe yaradığını, neden diğer alternatiflerden daha iyi olduğunu ve gereken performans / kodlama hususlarını açıklayın.
nanofarad

5
Java 1.7'de nio 2'dir. Java'nın doğal fetüsü. Kodlama için yeni Dize (bayt, StandardCharsets.UTF_8) kullanın
Kovalsky Dmitryi

5
benim durumumda getClass().getClassLoader()ama başka türlü harika bir çözüme ihtiyacım vardı !
Emmanuel Touzery

3
Uygulama bir kavanoza paketlendikten sonra bu işe yaramaz.
Daniel Bo

65

Saf ve basit, kavanoz dostu, Java 8+ çözümü

Java 8 veya üstünü kullanıyorsanız aşağıdaki basit yöntem işe yarayacaktır:

/**
 * Reads given resource file as a string.
 *
 * @param fileName path to the resource file
 * @return the file's contents
 * @throws IOException if read fails for any reason
 */
static String getResourceFileAsString(String fileName) throws IOException {
    ClassLoader classLoader = ClassLoader.getSystemClassLoader();
    try (InputStream is = classLoader.getResourceAsStream(fileName)) {
        if (is == null) return null;
        try (InputStreamReader isr = new InputStreamReader(is);
             BufferedReader reader = new BufferedReader(isr)) {
            return reader.lines().collect(Collectors.joining(System.lineSeparator()));
        }
    }
}

Ayrıca jar dosyalarındaki kaynaklarla da çalışır .

Metin kodlaması hakkında: InputStreamReaderbir tane belirtmemeniz durumunda varsayılan sistem karakter kümesini kullanır. Aşağıdaki gibi kod çözme sorunlarından kaçınmak için kendiniz belirtmek isteyebilirsiniz:

new InputStreamReader(isr, StandardCharsets.UTF_8);

Gereksiz bağımlılıklardan kaçının

Her zaman büyük, şişman kütüphanelere bağlı kalmamayı tercih edin. Zaten başka görevler için Guava veya Apache Commons IO kullanmıyorsanız, bu kütüphaneleri bir dosyadan okuyabilmek için projenize eklemek biraz fazla görünüyor.

"Basit" yöntem? Benimle dalga geçiyor olmalısın

Bu gibi basit görevler söz konusu olduğunda saf Java'nın iyi bir iş yapmadığını anlıyorum. Örneğin, Node.js'deki bir dosyadan şu şekilde okuyoruz:

const fs = require("fs");
const contents = fs.readFileSync("some-file.txt", "utf-8");

Basit ve okunması kolay (insanlar yine de çoğunlukla cehalet nedeniyle birçok bağımlılığa güvenmek ister). Veya Python'da:

with open('some-file.txt', 'r') as f:
    content = f.read()

Üzücü, ama Java'nın standartları için hala basit ve tek yapmanız gereken yukarıdaki yöntemi projenize kopyalayıp kullanmak. Orada neler olup bittiğini anlamanızı bile istemiyorum, çünkü bu gerçekten kimsenin önemi yok. Sadece çalışıyor, nokta :-)


4
@zakmck lütfen yorumlarınızı yapıcı tutmaya çalışın. Olgun bir geliştirici olarak büyüdükçe, bazen "tekerleği yeniden icat etmek" istediğinizi öğrenirsiniz. Örneğin, ikili dosyalarınızı eşik boyutunun altında tutmanız gerekebilir. Kütüphaneler genellikle uygulama boyutunuzu büyüklük derecelerine göre büyütür. Söylediklerinizin tam tersi olabilir: "Kod yazmaya gerek yok. Evet, her seferinde kütüphaneleri içe aktaralım". Size sadece 3 satır kod kaydetmek için bir kitaplığı içe aktarmayı gerçekten tercih eder misiniz? Bahse girerim, kütüphaneyi eklemeniz LOC'nizi bundan daha fazla artıracaktır. Anahtar denge.
Lucio Paiva

3
Peki, herkes bulut üzerinde bir şeyler çalıştırmıyor. Örneğin Java'nın çalıştığı her yerde gömülü sistemler var. JDK'yı doğrudan kendi kodunuzda kullanma önerisini kabul edeceğinizden bahsettiğinizden, tamamen geçerli yaklaşımlar sunan cevapları eleştirmede amacınızı görmüyorum. Her neyse, lütfen görüşlerinizi tartışmak yerine cevapları geliştirmeye yardımcı olmak için yorumları kesinlikle tutmaya çalışalım.
Lucio Paiva

1
Sadece JDK için iyi bir çözüm. Eğer sadece onay eklersiniz InputStreamdeğişken isolduğu nullya da değil.
scrutari

2
Güzel. Bunu kullandım. Akışları / okuyucuları da kapatmayı düşünebilirsiniz.
19'da dimplex

1
@RobertBain Karakter uyarısı hakkında bilgi eklemek için cevabı düzenledim. AWS'deki sınıf yükleyicide neyin yanlış gittiğini öğrenirseniz bana yanıtı da ekleyebilirim. Teşekkürler!
Lucio Paiva

57

Guava , bir dosyayı bir String'e okumak için "toString" yöntemine sahiptir:

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

String content = Files.toString(new File("/home/x1/text.log"), Charsets.UTF_8);

Bu yöntem, dosyanın sınıf yolunda olmasını gerektirmez ( önceki Jon Skeet yanıtında olduğu gibi).


2
Ya da bir girdi akışı ise, guava'nın da bunun için güzel bir yolu varString stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream, "UTF-8"));
Eran Medan

1
Bu Guava 24.1
Andrey

47

yegor256 , Apache Commons IO kullanarak güzel bir çözüm buldu :

import org.apache.commons.io.IOUtils;

String text = IOUtils.toString(this.getClass().getResourceAsStream("foo.xml"),
                               "UTF-8");

Bu durumda kullanılamaması durumunda "" tercih ediyorum
user833970

11
Sadece kompakt olarak değil, giriş akışının düzgün kapanış ile: IOUtils.toString(this.getClass().getResource("foo.xml"), "UTF-8").
Bogdan Calmac

1
Bu çözüm işe yaramazsa, getClassLoader()yöntem zincirine eklemeyi deneyin : String text = IOUtils.toString( getClass().getClassLoader().getResourceAsStream("foo.xml"), StandardCharsets.UTF_8);
Abdull

39

apache-commons-io bir yardımcı program adına sahiptir FileUtils:

URL url = Resources.getResource("myFile.txt");
File myFile = new File(url.toURI());

String content = FileUtils.readFileToString(myFile, "UTF-8");  // or any other encoding

1
Neden bir kodlama belirtmek zorunda, bunu anlamıyorum. Dosyayı okursam, sadece içinde ne olduğunu istiyorum, editörümün yaptığı gibi hangi kodlamayı anlaması gerekir. Notepad veya ++ ile açtığımda, hangi kodlamayı kullanması gerektiğini söylemiyorum. Bu yöntemi kullanıyorum ve daha sonra writeStringToFile ... ama içeriği farklı. Klonlanmış dosyada garip belirteçler alıyorum .. Neden bir kodlama belirtmek zorundayım anlamıyorum.
20mm

11
@Hamidan, doğru kodlamayı seçmek çok karmaşık bir algoritmadır. Genellikle metin düzenleyicide uygulanır, ancak bazen doğru kodlamayı algılayamazlar. Bir dosya okuma API dosyamı okumak için böyle karmaşık algoritma gömmek beklemem.
Vincent Robert

1
@SecretService Ayrıca, bu algoritmalar işletim sisteminin dili, yerel ayarları ve diğer bölgesel ayarlar gibi bilgileri kullanır; bu, bir kodlama belirtmeden bir dosyanın okunmasının kurulumunuzda çalışabileceğini, ancak başka birinin üzerinde çalışmayabileceği anlamına gelir.
Feuermurmel

Apache FileUtils . readLines (dosya) ve copyURLToFile (URL, tempFile).
Yash

2
Kaynak bir kavanozun içinde bulunursa bunun işe yarayacağını sanmıyorum. O zaman bir dosya olmayacak.
Ville Oikarinen

16

Sık sık bu problemi kendim yaşadım. Küçük projelere bağımlılıklardan kaçınmak için, ortak kullanıma veya başka bir şeye ihtiyacım olmadığında genellikle küçük bir yardımcı program işlevi yazarım. Dosyanın içeriğini bir dize arabelleğine yüklemek için kod:

StringBuffer sb = new StringBuffer();

BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("path/to/textfile.txt"), "UTF-8"));
for (int c = br.read(); c != -1; c = br.read()) sb.append((char)c);

System.out.println(sb.toString());   

Kodlamayı belirtilmesi olan UTF-8 dosyanızı düzenlenmiş ve daha sonra bir kavanoza koyun ve dosyayı açar bilgisayar CP-1251 onun doğal dosya kodlama olarak sahip olabilir olabilir, çünkü bu durumda önemli (örneğin) ; bu nedenle hedef kodlamayı asla bilemezsiniz, bu nedenle açık kodlama bilgileri çok önemlidir. Ayrıca char'ı char ile okumak için döngü verimsiz görünüyor, ancak bir BufferedReader'da kullanılıyor ve bu yüzden oldukça hızlı.


15

Aşağıdaki kod formunu Java kullanabilirsiniz

new String(Files.readAllBytes(Paths.get(getClass().getResource("example.txt").toURI())));

"Dosyalar" ve "Yollar" sınıflarında hangi içe aktarma ifadeleri gerekir?
Steve Scherer

1
her ikisi de JDK 7+
Raghu K Nair

Bir kavanoz dosyasında çalışmaz.
Displee

4

Dizenizi, projenizdeki src / main / resources içindeki testcase / foo.json gibi bir proje kaynağından almak istiyorsanız, şunu yapın:

String myString= 
 new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("testcase/foo.json").toURI())));

Bazı örneklerde getClassLoader () yönteminin eksik olduğunu unutmayın.


2

Apache ortaklarının FileUtils'ini kullanın. ReadFileToString yöntemine sahip


Dosya yalnızca dosyalar olan sınıf yolu kaynakları için çalışır. Bir .jar dosyasındaki öğeler veya bir yağ kavanozunun parçasıysa, diğer sınıf yükleyici uygulamalarından biri değilse.
toolforger

2

Kaynak dosyaları okumak için aşağıdakileri kullanıyorum classpath:

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.util.Scanner;

public class ResourceUtilities
{
    public static String resourceToString(String filePath) throws IOException, URISyntaxException
    {
        try (InputStream inputStream = ResourceUtilities.class.getClassLoader().getResourceAsStream(filePath))
        {
            return inputStreamToString(inputStream);
        }
    }

    private static String inputStreamToString(InputStream inputStream)
    {
        try (Scanner scanner = new Scanner(inputStream).useDelimiter("\\A"))
        {
            return scanner.hasNext() ? scanner.next() : "";
        }
    }
}

Üçüncü taraf bağımlılığı gerekmez.


1

Statik ithalat seti ile Guava çözümü çok kompakt bir astar olabilir:

toString(getResource("foo.txt"), UTF_8);

Aşağıdaki ithalatlar gereklidir:

import static com.google.common.io.Resources.getResource
import static com.google.common.io.Resources.toString
import static java.nio.charset.StandardCharsets.UTF_8

1
package test;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        try {
            String fileContent = getFileFromResources("resourcesFile.txt");
            System.out.println(fileContent);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //USE THIS FUNCTION TO READ CONTENT OF A FILE, IT MUST EXIST IN "RESOURCES" FOLDER
    public static String getFileFromResources(String fileName) throws Exception {
        ClassLoader classLoader = Main.class.getClassLoader();
        InputStream stream = classLoader.getResourceAsStream(fileName);
        String text = null;
        try (Scanner scanner = new Scanner(stream, StandardCharsets.UTF_8.name())) {
            text = scanner.useDelimiter("\\A").next();
        }
        return text;
    }
}

1

En azından Apache commons-io 2.5'den itibaren, IOUtils.toString () yöntemi bir URI bağımsız değişkenini destekler ve sınıfyolundaki kavanozların içinde bulunan dosyaların içeriğini döndürür:

IOUtils.toString(SomeClass.class.getResource(...).toURI(), ...)

1

Akosicki'nin Stupid Scanner Trick ile cevabını seviyorum. Java 8'de çalışan dış bağımlılıklar olmadan gördüğüm en basit şey (ve aslında Java 5'e kadar). Java 9 veya üstünü kullanabiliyorsanız (Java 9'daInputStream.readAllBytes() eklendiğinden beri) daha da basit bir cevap :

String text = new String(AppropriateClass.class.getResourceAsStream("foo.txt").readAllBytes());

0

Guava ayrıca satır satır satır Files.readLines()olarak bir dönüş değeri istiyorsanız List<String>:

List<String> lines = Files.readLines(new File("/file/path/input.txt"), Charsets.UTF_8);

Bir metin dosyasından ulaşmak için 3 yolu ( Guava'ya karşı Guava'ya karşı ) karşılaştırmak için lütfen buraya bakın .BufferedReaderFilesResourcesString


Charsets sınıfı nedir? yerli değil
E-info128

@ e-info128 Charsetsde Guava'dadır . Şuna
philipjkim

0

İşte yaklaşımım iyi çalıştı

public String getFileContent(String fileName) {
    String filePath = "myFolder/" + fileName+ ".json";
    try(InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(filePath)) {
        return IOUtils.toString(stream, "UTF-8");
    } catch (IOException e) {
        // Please print your Exception
    }
}

2
IOUtils nereden geliyor? Kaynak açıkça belirtilmelidir.
ehecatl

0

Ben basit bir çağrıda yapabilmek için, burada readResource () yöntemleri yazdım . Bu Guava kütüphanesine bağlıdır, ancak diğer cevaplarda önerilen yalnızca JDK yöntemlerini seviyorum ve bunları bu şekilde değiştireceğim.


0

Guava'yı eklerseniz şunları kullanabilirsiniz:

String fileContent = Files.asCharSource(new File(filename), Charset.forName("UTF-8")).read();

(Diğer çözümler Guava için başka bir yöntemden bahsetmiştir ancak kullanımdan kaldırılmıştır)


0

Aşağıdaki kodlar benim için çalışıyor:

compile group: 'commons-io', name: 'commons-io', version: '2.6'

@Value("classpath:mockResponse.json")
private Resource mockResponse;

String mockContent = FileUtils.readFileToString(mockResponse.getFile(), "UTF-8");

0

Java 11'leri kullanan bir çözüm Files.readString:

public class Utils {
    public static String readResource(String name) throws URISyntaxException, IOException {
        var uri = Utils.class.getResource("/" + name).toURI();
        var path = Paths.get(uri);
        return Files.readString(path);
    }
}

0

Böyle NO bağımlılık statik yöntem yaptı:

import java.nio.file.Files;
import java.nio.file.Paths;

public class ResourceReader {
    public  static String asString(String resourceFIleName) {
        try  {
            return new String(Files.readAllBytes(Paths.get(new CheatClassLoaderDummyClass().getClass().getClassLoader().getResource(resourceFIleName).toURI())));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
class CheatClassLoaderDummyClass{//cheat class loader - for sql file loading
}

0

Apache commons bu tür şeyler için araçlar gibi ve test ederken, özellikle /src/test/resourcesbirim / entegrasyon testinin bir parçası olarak JSON dosyalarını okumak için bu sınıf tam olarak kullanmak (sınıf yolundan dosyaları okuma) yaygın kullanın . Örneğin

public class FileUtils {

    public static String getResource(String classpathLocation) {
        try {
            String message = IOUtils.toString(FileUtils.class.getResourceAsStream(classpathLocation),
                    Charset.defaultCharset());
            return message;
        }
        catch (IOException e) {
            throw new RuntimeException("Could not read file [ " + classpathLocation + " ] from classpath", e);
        }
    }

}

Test amacıyla, yakalamak IOExceptionve atmak güzel olabilir RuntimeException- test sınıfınız örn.

    @Test
    public void shouldDoSomething () {
        String json = FileUtils.getResource("/json/input.json");

        // Use json as part of test ...
    }

-2
public static byte[] readResoureStream(String resourcePath) throws IOException {
    ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
    InputStream in = CreateBffFile.class.getResourceAsStream(resourcePath);

    //Create buffer
    byte[] buffer = new byte[4096];
    for (;;) {
        int nread = in.read(buffer);
        if (nread <= 0) {
            break;
        }
        byteArray.write(buffer, 0, nread);
    }
    return byteArray.toByteArray();
}

Charset charset = StandardCharsets.UTF_8;
String content = new   String(FileReader.readResoureStream("/resource/...*.txt"), charset);
String lines[] = content.split("\\n");

Lütfen cevabınıza kısa bir açıklama ekleyin.
Nikolay Mihaylov
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.