[java] 파일 내용에서 Java 문자열을 작성하는 방법

나는 지금 얼마 동안 아래 관용구를 사용하고 있습니다. 그리고 그것은 내가 방문한 사이트에서 가장 널리 퍼진 것 같습니다.

Java에서 파일을 문자열로 읽는 더 좋고 다른 방법이 있습니까?

private String readFile(String file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader (file));
    String         line = null;
    StringBuilder  stringBuilder = new StringBuilder();
    String         ls = System.getProperty("line.separator");

    try {
        while((line = reader.readLine()) != null) {
            stringBuilder.append(line);
            stringBuilder.append(ls);
        }

        return stringBuilder.toString();
    } finally {
        reader.close();
    }
}



답변

파일에서 모든 텍스트를 읽습니다.

자바 11 추가 readString () 메서드를 작은 파일을으로 String유지하면서 줄 종결 자로 보존했습니다.

String content = Files.readString(path, StandardCharsets.US_ASCII);

Java 7과 11 사이의 버전을 위해 다음은 유틸리티 방법으로 싸인 작고 강력한 관용구입니다.

static String readFile(String path, Charset encoding)
  throws IOException
{
  byte[] encoded = Files.readAllBytes(Paths.get(path));
  return new String(encoded, encoding);
}

파일에서 텍스트 줄 읽기

Java 7 은 파일을 텍스트 줄로 읽는 편리한 방법을 추가했습니다 .List<String> . 이 방법은 줄 구분 기호가 각 줄의 끝에서 벗겨지기 때문에 “손실”됩니다.

List<String> lines = Files.readAllLines(Paths.get(path), encoding);

Java 8 Files.lines()Stream<String>. 다시 말하지만,이 방법은 라인 구분 기호가 제거되어 손실됩니다. 이 경우 IOException파일을 읽는 동안 발생, 그것은에 싸여 UncheckedIOException있기 때문에,Stream 체크 된 예외를 던질 람다을 허용하지 않습니다.

try (Stream<String> lines = Files.lines(path, encoding)) {
  lines.forEach(System.out::println);
}

이것은 Stream필요합니다close() 전화를; 이것은 API에 제대로 문서화되어 있지 않으며 많은 사람들이 메소드를 Stream가지고 있지 않다고 생각 close()합니다. 그림과 같이 ARM 블록을 사용해야합니다.

파일 이외의 소스로 작업하는 경우 lines()BufferedReader 대신 방법을 .

메모리 활용

줄 바꿈을 유지하는 첫 번째 방법은 짧은 시간 동안 원시 파일 내용 (바이트 배열)과 디코딩 된 문자 (각각 인코딩 된 경우에도 16 비트 임)로 인해 파일 크기의 몇 배인 메모리를 일시적으로 요구할 수 있습니다. 파일에서 8 비트)는 한 번에 메모리에 상주합니다. 사용 가능한 메모리에 비해 작은 것으로 알고있는 파일에 적용하는 것이 가장 안전합니다.

디코딩을위한 입력 바이트 버퍼가 전체 파일을 포함 할 필요가 없기 때문에 라인을 읽는 두 번째 방법은 일반적으로 메모리 효율성이 높습니다. 그러나 여전히 사용 가능한 메모리에 비해 크기가 큰 파일에는 적합하지 않습니다.

큰 파일을 읽으려면 스트림에서 텍스트 청크를 읽고 처리 한 다음 다음으로 이동하여 동일한 고정 크기의 메모리 블록을 재사용하는 다른 디자인의 프로그램이 필요합니다. 여기서 “큰”은 컴퓨터 사양에 따라 다릅니다. 오늘날이 임계 값은 수 기가 바이트의 RAM 일 수 있습니다. Stream<String>입력 “레코드”가 개별 라인 인 경우이를 사용하는 세 번째 방법 은이 방법 중 하나입니다. (의 readLine()방법을 사용하는 것은이 방법과 BufferedReader절차 상 동등합니다.)

문자 인코딩

원래 게시물의 샘플에서 누락 된 것은 문자 인코딩입니다. 플랫폼 기본값이 원하는 특수한 경우가 있지만 드물기 때문에 선택을 정당화 할 수 있어야합니다.

StandardCharsets클래스는 모든 Java 런타임에 필요한 인코딩에 대한 상수를 정의합니다.

String content = readFile("test.txt", StandardCharsets.UTF_8);

플랫폼의 기본에서 사용할 수 클래스 자체 :Charset

String content = readFile("test.txt", Charset.defaultCharset());

참고 :이 답변은 Java 6 버전을 대체합니다. Java 7의 유틸리티는 코드를 안전하게 단순화하고 매핑 된 바이트 버퍼를 사용한 이전 답변은 매핑 된 버퍼가 가비지 수집 될 때까지 읽은 파일이 삭제되는 것을 방지했습니다. 이 답변의 “편집 된”링크를 통해 이전 버전을 볼 수 있습니다.


답변

외부 라이브러리를 사용하려면 Apache Commons IO (200KB JAR)를 확인하십시오. 여기 org.apache.commons.io.FileUtils.readFileToString()에 전체를 읽을 수 있는 방법 이 포함되어 있습니다 File.String한 줄의 코드 .

예:

import java.io.*;
import java.nio.charset.*;
import org.apache.commons.io.*;

public String readFile() throws IOException {
    File file = new File("data.txt");
    return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}


답변

다음을 기반으로하는 매우 린 솔루션 Scanner:

Scanner scanner = new Scanner( new File("poem.txt") );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

또는 문자셋을 설정하려는 경우 :

Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" );
String text = scanner.useDelimiter("\\A").next();
scanner.close(); // Put this call in a finally block

또는 try-with-resources 블록을 사용하여 다음을 요청 scanner.close()합니다.

try (Scanner scanner = new Scanner( new File("poem.txt"), "UTF-8" )) {
    String text = scanner.useDelimiter("\\A").next();
}

기억 Scanner생성자가 던질 수 있습니다 IOException. 그리고 수입하는 것을 잊지 마세요 java.iojava.util .

출처 : Pat Niemeyer의 블로그


답변

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

String content = new String(Files.readAllBytes(Paths.get("readMe.txt")), StandardCharsets.UTF_8);

Java 7부터는 이렇게 할 수 있습니다.


답변

타사 라이브러리를 포함하지 않는 대안 (예 : Commons I / O )을 찾고 있다면 Scanner 클래스를 사용할 수 있습니다 .

private String readFile(String pathname) throws IOException {

    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int)file.length());

    try (Scanner scanner = new Scanner(file)) {
        while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + System.lineSeparator());
        }
        return fileContents.toString();
    }
}


답변

구아바 에는 Willi aus Rohr가 언급 한 Commons IOUtils와 유사한 방법이 있습니다.

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

// ...

String text = Files.toString(new File(path), Charsets.UTF_8);

PiggyPiglet의 EDIT
Files#toString 은 더 이상 사용되지 않으며 Octobor 2019가 제거 될 예정입니다. 대신 사용
Files.asCharSource(new File(path), StandardCharsets.UTF_8).read();

Oscar Reyes에 의해 편집

이것은 인용 라이브러리의 (간체 화 된) 기본 코드입니다.

InputStream in = new FileInputStream(file);
byte[] b  = new byte[file.length()];
int len = b.length;
int total = 0;

while (total < len) {
  int result = in.read(b, total, len - total);
  if (result == -1) {
    break;
  }
  total += result;
}

return new String( b , Charsets.UTF_8 );

편집 (Jonik 작성) : 위 내용이 최신 구아바 버전의 소스 코드와 일치하지 않습니다. 현재 소스 는 com.google.common.io 패키지의 Files , CharStreams , ByteSourceCharSource 클래스를 참조하십시오 .


답변

import java.nio.file.Files;

…….

 String readFile(String filename) {
            File f = new File(filename);
            try {
                byte[] bytes = Files.readAllBytes(f.toPath());
                return new String(bytes,"UTF-8");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "";
    }