리소스 텍스트 파일을 문자열로 읽는 유틸리티 (Java) [닫기]


215

리소스의 텍스트 파일을 문자열로 읽는 데 도움이되는 유틸리티가 있습니까? 나는 이것이 대중적인 요구 사항이라고 생각하지만 인터넷 검색 후 유틸리티를 찾을 수 없습니다.


1
"리소스 텍스트 파일"과 "리소스의 텍스트 파일"의 의미를 명확히하십시오. 달성하려는 내용을 이해하기가 쉽지 않습니다.
Mat

"classpath * : mytext / text.txt"와 같은 classpath에있는 텍스트 파일입니다.
Loc Phan

답변:


301

예, 구아바Resources수업 시간에 이것을 제공합니다 . 예를 들면 다음과 같습니다.

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

21
@JonSkeet 이것은 훌륭하지만 웹 응용 프로그램의 경우 최상의 솔루션이 아닐 수 있습니다. 구현 getResource은 사용 Resource.class.getClassLoader중이지만 웹 응용 프로그램에서는 "귀하의"클래스 로더가 아닐 수 있으므로 사용하는 것이 좋습니다 (예 : [1]). Thread.currentThread().getContextClassLoader().getResourceAsStream대신 (참조 [1] : stackoverflow.com/questions/676250/… )
Eran Medan

2
@EranMedan : 예, 컨텍스트 클래스 로더를 원한다면 명시 적으로 사용하고 싶습니다.
Jon Skeet 2016 년

6
리소스가 클래스 옆에있는 특수한 경우 Resources.toString(MyClass.getResource("foo.txt"), Charsets.UTF_8)올바른 클래스 로더 사용을 보장 할 수 있습니다 .
Bogdan Calmac

2
com.google.common.io.ResourcesSonarQube
Ghilteras

1
guava구현이 변경되었습니다. 구아바 23의 구현은 다음과 같습니다. ClassLoader loader = MoreObjects.firstNonNull( Thread.currentThread().getContextClassLoader(), Resources.class.getClassLoader());
xxy

171

구아바와 같은 추가 종속성없이 이전 Stupid Scanner 트릭 oneliner를 사용할 수 있습니다 .

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

여러분, 정말로 필요하지 않은 한 타사 제품을 사용하지 마십시오. JDK에는 이미 많은 기능이 있습니다.


41
제 3자를 피하는 것이 합리적인 원칙입니다. 불행히도 핵심 라이브러리는 실제 사용 사례 모델링에 알레르기가있는 것으로 보입니다. Java 7의 파일을 살펴보고 클래스 경로 리소스에서 모든 것을 읽는 것이 거기에 포함되지 않은 이유를 알려주십시오. 또는 최소한 표준화 된 '파일 시스템'을 사용하십시오.
Dilum Ranatunga

3
스트림을 닫는 것도 필요합니까? 구아바는 내부적으로 시내를 닫습니다.
virgo47

나도 아름답게 일했다! 나는 또한 제 3 자에 대해서도 동의합니다 : 많은 답변에서 기본 응답은 항상 일부 타사 라이브러리를 사용하는 것 같습니다-Apache 또는 다른 사람의 라이브러리입니다.
Terje Dahl

1
srm / test / resources와 같은 현재 jar에 리소스를로드 CartApplication.class.getResourceAsStream하도록 변경CartApplication.class.getClassLoader().getResourceAsStream
Chris DaMour

5
나는 이것을 사용했지만 타사 패키지를 피하는 것에 완전히 동의하지 않습니다. Java에서 파일을 문자열로 쉽게 읽을 수있는 유일한 방법은 스캐너 트릭을 사용하는 것입니다. 타사 라이브러리를 사용하는 대신 모든 사람이 자신의 래퍼를 만들 수 있습니다. 이런 종류의 작업이 필요한 경우 IO 핸드 다운 용 Guava가 승리합니다. 내가 동의 할 곳은 코드에 원하는 위치가 하나만있는 경우 타사 패키지를 가져 오지 않아야한다는 것입니다. 그것은 과잉이 될 것입니다.
Kenny Cason

90

자바 7의 경우 :

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

3
이것이 왜 효과가 있고, 다른 대안보다 좋은 이유와 필요한 성능 / 인코딩 고려 사항을 설명하십시오.
nanofarad

5
Java 1.7에서 nio 2입니다. 자바의 기본 기능입니다. 사용하는 새로운 문자열을 인코딩 (바이트, StandardCharsets.UTF_8)
Kovalsky Dmitryi

5
내 경우에는 필요 getClass().getClassLoader()하지만 다른 방법으로는 훌륭한 솔루션이 필요했습니다 !
Emmanuel Touzery

3
앱이 항아리에 패키지되면 작동하지 않습니다.
Daniel Bo

65

순수하고 단순하며 항아리 친화적 인 Java 8+ 솔루션

아래의 간단한 방법은 Java 8 이상을 사용하는 경우 잘 작동합니다.

/**
 * 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()));
        }
    }
}

또한 jar 파일의 리소스와 함께 작동합니다 .

텍스트 인코딩 정보 : InputStreamReader지정하지 않은 경우 기본 시스템 문자 세트를 사용합니다. 다음과 같이 디코딩 문제를 피하기 위해 직접 지정할 수 있습니다.

new InputStreamReader(isr, StandardCharsets.UTF_8);

불필요한 의존성을 피하십시오

항상 크고 뚱뚱한 라이브러리에 의존하지 않는 것이 좋습니다. 다른 작업에 이미 Guava 또는 Apache Commons IO를 사용하지 않는 한 파일에서 읽을 수 있도록 해당 라이브러리를 프로젝트에 추가하는 것은 너무 많은 것 같습니다.

"간단한"방법? 농담 해

나는 순수한 Java가 이와 같은 간단한 작업을 수행 할 때 잘 작동하지 않는다는 것을 이해합니다. 예를 들어, Node.js의 파일에서 읽는 방법은 다음과 같습니다.

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

간단하고 읽기 쉽다 (사람들은 여전히 ​​대부분의 무지 때문에 많은 의존성에 의존하기를 좋아하지만). 또는 파이썬에서 :

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

슬프지만 Java 표준에서는 여전히 간단하며 위의 방법을 프로젝트에 복사하여 사용하기 만하면됩니다. 나는 거기에서 무슨 일이 일어나고 있는지 이해하지 않아도됩니다. 왜냐하면 그것은 누구에게나 중요하지 않기 때문입니다. 그냥 작동합니다. 기간 :-)


4
@zakmck 의견을 건설적으로 유지하십시오. 성숙한 개발자로 성장함에 따라 때때로 "바퀴를 재창조하고 싶다"는 것을 알게됩니다. 예를 들어 바이너리를 임계 값 이하로 유지해야 할 수도 있습니다. 라이브러리는 종종 응용 프로그램 크기를 몇 배나 증가시킵니다. "코드를 작성할 필요가 없습니다. 예, 매번 라이브러리를 가져 오십시오"라고 말한 것과 반대되는 주장을 할 수 있습니다. 3 줄의 코드를 저장하기 위해 라이브러리를 가져 오는 것을 정말로 원하십니까? 라이브러리를 추가하면 LOC가 그 이상으로 증가합니다. 열쇠는 균형입니다.
Lucio Paiva

3
모든 사람이 클라우드에서 무언가를 실행하고있는 것은 아닙니다. 예를 들어 Java를 실행하는 모든 곳에서 임베디드 시스템이 있습니다. 나는 당신이 당신의 코드에서 JDK를 직접 사용하라는 제안을 받아 들일 것이라고 스스로 말하면서, 완전히 유효한 접근법을 제공하는 답변을 비판하는 당신의 요점을 보지 못합니다. 어쨌든, 의견을 논의하지 말고 답변을 개선하는 데 도움이되도록 의견을 엄격히 지키도록합시다.
Lucio Paiva

1
좋은 JDK 전용 솔루션. InputStream변수 is가 아닌지 확인 만 추가 null합니다.
scrutari

2
좋은. 나는 이것을 사용했다. 스트림 / 리더 닫기도 고려할 수 있습니다.
dimplex

1
@RobertBain 문자셋 경고에 대한 정보를 추가하기 위해 답변을 편집했습니다. AWS의 클래스 로더에 어떤 문제가 있는지 알려 주면 답변에 추가 할 수 있습니다. 감사!
Lucio Paiva

57

구아바 에는 파일을 문자열로 읽는 "toString"메소드가 있습니다.

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

이 방법은 파일이 클래스 경로에 있어야 할 필요는 없습니다 ( Jon Skeet 이전 답변 에서와 같이 ).


2
또는 입력 스트림 인 경우 구아바도이를위한 좋은 방법입니다.String stringFromStream = CharStreams.toString(new InputStreamReader(resourceAsStream, "UTF-8"));
Eran Medan

1
이것은 구아바 24.1에서 더 이상 사용되지 않습니다
Andrey

47

yegor256Apache Commons IO를 사용하여 훌륭한 솔루션을 찾았습니다 .

import org.apache.commons.io.IOUtils;

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

이 기능을 사용할 수없는 경우 ""를 선호합니다.
user833970

11
컴팩트하지만 입력 스트림이 올바르게 닫힙니다 IOUtils.toString(this.getClass().getResource("foo.xml"), "UTF-8").
Bogdan Calmac

1
이 솔루션이 작동하지 않으면 getClassLoader()메소드 체인에 추가 하십시오. String text = IOUtils.toString( getClass().getClassLoader().getResourceAsStream("foo.xml"), StandardCharsets.UTF_8);
Abdull

39

apache-commons-io 의 유틸리티 이름은 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
인코딩을 지정 해야하는 이유는 무엇입니까? 파일을 읽으면 파일에 포함 된 내용 만 원하므로 편집자가 어떤 인코딩을 사용하는지 파악해야합니다. 메모장이나 ++에서 열면 사용할 인코딩을 알려주지 않습니다. 이 방법을 사용하고 나중에 writeStringToFile ...을 사용하고 있지만 내용이 다릅니다. 복제 된 파일에서 이상한 토큰을 얻습니다. 인코딩을 지정해야하는 이유를 알 수 없습니다.
mmm

11
@Hamidan, 올바른 인코딩을 선택하는 것은 매우 복잡한 알고리즘입니다. 종종 텍스트 편집기에서 구현되지만 때로는 올바른 인코딩을 감지하지 못합니다. 파일 읽기 API가 복잡한 알고리즘을 포함하여 내 파일을 읽을 것으로 기대하지 않습니다.
Vincent Robert

1
@SecretService 또한 이러한 알고리즘은 운영 체제의 언어, 로캘 및 기타 지역 설정과 같은 정보를 사용하므로 인코딩을 지정하지 않고 파일을 읽는 것은 설정에서 작동하지만 다른 사람에게는 작동하지 않을 수 있습니다.
Feuermurmel

아파치 FileUtils . readLines (파일) 및 copyURLToFile (URL, tempFile).
Yash

2
항아리 안에 리소스가있는 경우 이것이 효과가 있다고 생각하지 않습니다. 그런 다음 파일이 아닙니다.
Ville Oikarinen

16

나는 종종이 문제를 스스로했다. 작은 프로젝트에 대한 의존성을 피하기 위해 공통점이 필요하지 않을 때 종종 작은 유틸리티 함수를 작성합니다. 다음은 파일의 내용을 문자열 버퍼에로드하는 코드입니다.

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

이 경우 인코딩을 지정하는 것이 중요합니다. 파일을 UTF-8로 편집 한 후 jar 파일에 넣고 파일을 여는 컴퓨터에 CP-1251이 기본 파일 인코딩으로있을 수 있기 때문입니다. ; 따라서이 경우 대상 인코딩을 알 수 없으므로 명시 적 인코딩 정보가 중요합니다. 또한 char로 파일 char를 읽는 루프는 비효율적이지만 BufferedReader에서 사용되므로 실제로 매우 빠릅니다.


15

다음 코드 양식 Java를 사용할 수 있습니다

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

"파일"및 "경로"클래스를 가져 오기 위해 어떤 가져 오기 명령문이 필요합니까?
스티브 셰러

1
둘 다 JDK 7+에서 사용 가능한 java.nio.file 패키지의 일부입니다
Raghu K Nair

jar 파일에있을 때는 작동하지 않습니다.
Displee

4

프로젝트의 src / main / resources에있는 testcase / foo.json 파일과 같은 프로젝트 리소스에서 문자열을 가져 오려면 다음과 같이하십시오.

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

getClassLoader () 메소드는 다른 예제 중 일부에서 누락되었습니다.


2

Apache Commons의 FileUtils를 사용하십시오. readFileToString 메소드가 있습니다.


파일은 파일 인 클래스 경로 리소스에만 작동합니다. .jar 파일의 요소이거나 팻 jar의 일부인 경우 다른 클래스 로더 구현 중 하나가 아닙니다.
toolforger

2

다음에서 리소스 파일을 읽는 데 다음을 사용하고 있습니다 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() : "";
        }
    }
}

타사 종속성이 필요하지 않습니다.


1

정적 수입 세트를 통해 Guava 솔루션은 매우 컴팩트 한 단일 라이너가 될 수 있습니다.

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

다음과 같은 수입품이 필요합니다 :

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

적어도 Apache commons-io 2.5에서 IOUtils.toString () 메소드는 URI 인수를 지원하고 클래스 경로의 jar 내에있는 파일의 컨텐츠를 리턴합니다.

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

1

나는 Stupid Scanner Trick에 대한 akosicki의 대답을 좋아합니다. Java 8에서 작동하는 외부 종속성없이 실제로 볼 수있는 가장 간단합니다 (실제로 Java 5로 돌아갑니다). Java 9 이상을 사용할 수 있다면 더 간단한 대답 이 있습니다 ( InputStream.readAllBytes()Java 9에서 추가되었으므로).

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

0

구아바는 또한 라인 단위 Files.readLines()로 반환 값을 원한다면 List<String>:

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

텍스트 파일에서 얻는 3 가지 방법 ( 대 구아바 대 구아바 )을 비교 하려면 여기 를 참조하십시오 .BufferedReaderFilesResourcesString


Charsets 클래스 란 무엇입니까? 네이티브가 아닙니다
e-info128

@ e-info128 Charsets도 구아바에 있습니다. 다음을 참조하십시오 : google.github.io/guava/releases/23.0/api/docs
philipjkim

0

여기 내 접근 방식이 제대로 작동했습니다.

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는 어디에서 왔습니까? 출처는 명확하게 참조해야합니다.
ehecatl

0

한 번의 간단한 호출 로 readResource () 메소드를 작성 했습니다. 그것은 Guava 라이브러리에 달려 있지만 다른 답변에서 제안 된 JDK 전용 방법을 좋아하며 이러한 방식으로 변경할 것이라고 생각합니다.


0

구아바를 포함하면 다음을 사용할 수 있습니다.

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

(다른 솔루션은 Guava에 대한 다른 방법을 언급했지만 더 이상 사용되지 않습니다)


0

다음 코드는 나를 위해 작동합니다.

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을 사용하는 솔루션입니다 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

나는 다음과 같이 NO 의존성 정적 방법을 만들었습니다.

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 utils를 좋아하고 특히 /src/test/resources단위 / 통합 테스트의 일부로 JSON 파일을 읽을 때이 정확한 유스 케이스 (클래스 패스에서 파일 읽기)를 광범위하게 사용 합니다. 예 :

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

}

테스트 목적으로, 잡아서 IOException던지는 것이 좋을 수 있습니다 RuntimeException-테스트 클래스는 다음과 같습니다.

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

답변에 간단한 설명을 추가하십시오.
Nikolay Mihaylov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.