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


1513

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

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

7
누구나 NIO와 관련하여 매우 간단한 방법으로 나를 설명 할 수 있습니까? 내가 한대로도 읽어마다 :( 채널의 n 번째 언급에서 분실
— OscarRyz

7
파일의 행 구분 기호가 시스템의 행 구분 기호와 동일하지 않아도된다는 보장은 없습니다.
— Henrik Paul

138
독자를 닫는 적절한 시도를 드디어 삽입 해 주시겠습니까? 실제로이 예제를 사용하여 코드에 버그를 도입 할 수 있습니다.
— Hans-Peter Störr

6
위의 코드에는 마지막 줄에 줄 바꿈 문자를 추가하는 버그가 있습니다. 다음과 같아야합니다. if (line = reader.readLine ())! = null) {stringBuilder.append (line); } while (line = reader.readLine ())! = null) {stringBuilder.append (ls); stringBuilder.append (라인); }
— Deep

27
Java 7 byte[] Files.readAllBytes(file);에 '한 줄짜리'스캐너 솔루션을 제안하는 사람들이 소개 합니다.이를 닫을 필요가 없습니까?
— Val

답변:


1533

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

자바 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의 유틸리티는 코드를 안전하게 단순화하고 매핑 된 바이트 버퍼를 사용한 이전 답변은 매핑 된 버퍼가 가비지 수집 될 때까지 읽은 파일이 삭제되는 것을 방지했습니다. 이 답변의 "편집 된"링크를 통해 이전 버전을 볼 수 있습니다.


3
기술적으로 말하면 시간과 공간에서 O (n)입니다. 질적으로, Strings의 불변성 요구 사항 때문에 메모리에서는 꽤 어렵습니다. 일시적으로 메모리에 char 데이터의 사본 두 개와 인코딩 된 바이트를위한 공간이 있습니다. 단일 바이트 인코딩을 가정하면 파일의 각 문자에 대해 (일시적으로) 5 바이트의 메모리가 필요합니다. 질문은 구체적으로 문자열을 요구하기 때문에 내가 보여주는 것입니다. 그러나 "decode"에 의해 리턴 된 CharBuffer로 작업 할 수 있다면 메모리 요구 사항은 훨씬 적습니다. 시간이 지나면 핵심 Java 라이브러리에서 더 빨리 찾을 수 있다고 생각하지 않습니다.
— erickson 2016 년

5
가능한 오타? NIO에는 java.nio.charset.Charset이라는 Charset (CharSet 아님) 클래스가 있습니다. 이것이 CharSet이었던 것입니까?
— Jonathan Wright

31
참고 : 해당 코드를 약간 연습 한 후에는이 방법으로 파일을 읽은 직후 파일을 안정적으로 삭제할 수 없다는 것을 알았습니다.이 경우에는 문제가되지 않지만 내 경우는 아닙니다. 이 문제와 관련이있을 수 있습니다. bugs.sun.com/bugdatabase/view_bug.do?bug_id=4715154 ? 나는 마침내이 버그로 고통받지 않는 Jon Skeet의 제안과 함께 갔다. 어쨌든, 나는 단지 만일을 위해 다른 사람들을 위해 정보를주고 싶었다.
— Sébastien Nussbaumer

5
@ 세바스찬 Nussbaumer : 나는 또한이 문제에 부딪쳤다. 버그가 "Will Not Fix"로 표시되어 있다는 사실에 놀랍습니다. 이것은 본질적으로 FileChannel#map일반적으로 사용할 수 없음을 의미합니다 .
— Joonas Pulakka

4
@ Sébastien Nussbaumer : 버그가 Oracle / Sun Bug Database에서 삭제되었습니다 : "이 버그는 사용할 수 없습니다." 구글은 사이트 캐시 webcache.googleusercontent.com/search?q=cache:bugs.sun.com/...
— bobndrew

350

외부 라이브러리를 사용하려면 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);
}

제공 한 URL에서 해당 방법을 찾을 수 없습니다.
— OscarRyz

2
그것은 org.apache.commons.io.FileUtils 클래스에 있습니다
— Cyrille Ka

2
FileUtils도 사용하고 있지만 FileUtils 또는 허용되는 nio 답변을 사용하는 것보다 더 나은 것이 무엇인지 궁금합니다.
— 기 illa

4
@Guillaume : 가장 큰 문제는 타사 라이브러리에 의존하는 것이 편한지 여부입니다. 프로젝트에 Commons IO 또는 Guava가 있는 경우 코드 단순성을 위해 사용하십시오. 그렇지 않으면 눈에 띄는 차이가 없을 것입니다.
— Jonik

183

다음을 기반으로하는 매우 린 솔루션 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.io및java.util .

출처 : Pat Niemeyer의 블로그


4
\\ A는 "파일의 다른 시작"이 없기 때문에 작동하므로 실제로 마지막 토큰을 읽습니다. 첫 번째 토큰이기도합니다. \\ Z로 시도하지 마십시오. 또한 파일, 입력 스트림, 채널과 같이 읽을 수있는 모든 것을 읽을 수 있습니다 ...이 파일을 읽고 있는지 확실하지 않을 때 때때로이 코드를 사용하여 이클립스의 표시 창에서 읽습니다. 예, classpath는 나를 혼란스럽게합니다.
— Pablo Grisafi

1
포스터로서, 파일이 제대로 닫히면 언제인지 알 수 없다고 말할 수 있습니다 ...이 코드는 프로덕션 코드로 작성하지 않으며 테스트 또는 디버그에만 사용합니다.
— Pablo Grisafi 2016 년

2
그것은 내가 생각하는 1024 자의 제한이 있습니다
— Whimusical

20
스캐너는 Closeable을 구현합니다 (소스에서 닫기를 호출 함). 우아하지만 실제로는 하나의 라이너가 아니어야합니다. 버퍼의 기본 크기는 1024이지만 스캐너는 필요에 따라 크기를 늘립니다 (Scanner # makeSpace () 참조)
— earcam

8
이 파일은 빈 파일에 대해 실패합니다 java.util.NoSuchElementException.
— SpaceTrucker

116
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부터는 이렇게 할 수 있습니다.


이것은 응답으로 받아 들여 져야합니다-한 줄에 외부 라이브러리가 없습니다.
— Cherry

파일에없는 경우에도 끝에 줄 바꿈 문자가 추가되었습니다
— Stefan Haberl

79

타사 라이브러리를 포함하지 않는 대안 (예 : 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();
    }
}

2
이것이 최선의 방법이라고 생각합니다. java.sun.com/docs/books/tutorial/essential/io/scanning.html을
— Tarski

3
문자열을 받아들이는 스캐너 생성자는 문자열을 읽을 파일 이름으로 취급하지 않고 스캔 할 텍스트로 취급합니다. 나는 항상 그 실수를한다. :-/
— Alan Moore

@ 앨런, 잘 잡아. 나는 Don 's answer을 약간 수정하여 그 문제를 해결했다.
— Jonik

3
fileContents.append (scanner.nextLine ()). append (lineSeparator);
— 금지 지오 엔지니어링

1
초기화 명령문을로 변경하십시오 Scanner scanner = new Scanner((Readable) new BufferedReader(new FileReader(file)));. 그렇지 않으면 파일의 일부만 캡처 할 수 있습니다.
— 웨이 양

71

구아바 에는 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 , ByteSource 및 CharSource 클래스를 참조하십시오 .


이 코드는 long에서 int로 캐스팅하여 큰 파일로 미친 행동을 일으킬 수 있습니다. 추가 공간이 있고 입력 스트림을 어디에서 닫습니까?
— Mohamed Taher Alrefaie

@MTA : 스트림이 되어 폐쇄는 사용주의 Closer에서 CharSource을 . 답변의 코드는 실제 구아바 소스가 아닙니다.
— Jonik

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

6
또는 훨씬 더 간단합니다 :new String(Files.readAllBytes(FileSystems.getDefault().getPath( filename)));

12
또는 new String(Files.readAllBytes(Paths.get(filename)));:-)
— assafmo

1
잘 플레이하고 다음 사람 인 Paths구글링 을 구하기 위해 분명히 1.7 이상 입니다 FileSystems. (Dang it!)
— ruffin

4
이 답변에는 더 많은 투표권이 없습니다. 텍스트 파일을 문자열로 가져 오는 가장 빠르고 간단한 방법을 찾고있었습니다. 이것이 바로 위아래로 스크롤하지 않으면 놓쳤을 것입니다. OP는이 답변을 수락하여 맨 위로 이동하는 것을 고려해야합니다.
— 가시

@Thorn이 답변에는 끔찍한 오류 처리 기능이 있습니다. 프로덕션 코드에서이 방법을 사용하지 마십시오.
— xehpuk

51

문자열 처리 (병렬 처리)가 필요한 경우 Java 8에는 훌륭한 스트림 API가 있습니다.

String result = Files.lines(Paths.get("file.txt"))
                    .parallel() // for parallel processing 
                    .map(String::trim) // to change line   
                    .filter(line -> line.length() > 2) // to filter some lines by a predicate                        
                    .collect(Collectors.joining()); // to join lines

Oracle Java SE 8 다운로드 페이지sample/lambda/BulkDataOperations 에서 다운로드 할 수있는 JDK 샘플에서 더 많은 예제를 사용할 수 있습니다 .

다른 라이너 예

String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));

.parallel ()은 행을 읽은 후에 또는 그 이전에 발생합니까?
— Istvan

터미널 작업 collect (...)가 호출 된 이후 실제 작업이 시작됩니다. 스트림이 한 줄씩 느리게 채워집니다. 처리하기 전에 메모리에서 전체 파일을 읽을 필요가 없습니다 (예 : 필터링 및 매핑).
— Andrei N

비어 있지 않은 줄을 선택하기 전에 다듬 으시겠습니까?
— Thorbjørn Ravn Andersen 님이

50

이 코드는 줄 바꿈을 정규화하여 실제로 원하는 것이거나 아닐 수도 있습니다.

다음은 그렇게하지 않는 대안이며 NIO 코드보다 이해하기 쉬운 (IMO) 것입니다 (여전히을 사용하지만 java.nio.charset.Charset).

public static String readFile(String file, String csName)
            throws IOException {
    Charset cs = Charset.forName(csName);
    return readFile(file, cs);
}

public static String readFile(String file, Charset cs)
            throws IOException {
    // No real need to close the BufferedReader/InputStreamReader
    // as they're only wrapping the stream
    FileInputStream stream = new FileInputStream(file);
    try {
        Reader reader = new BufferedReader(new InputStreamReader(stream, cs));
        StringBuilder builder = new StringBuilder();
        char[] buffer = new char[8192];
        int read;
        while ((read = reader.read(buffer, 0, buffer.length)) > 0) {
            builder.append(buffer, 0, read);
        }
        return builder.toString();
    } finally {
        // Potential issue here: if this throws an IOException,
        // it will mask any others. Normally I'd use a utility
        // method which would log exceptions and swallow them
        stream.close();
    }        
}

1
이 오래된 의견을 되살려 주셔서 용서하십시오. 그러나 "file"이라는 String 객체를 전달한다는 의미입니까, 아니면 File 객체 여야합니까?
— Bryan Larson 2016 년

28

디스크 또는 네트워크에서 파일을 문자열로 읽는 가능한 모든 방법을 모았습니다.

  • 구아바 : Google 클래스 사용 Resources,Files

    static Charset charset = com.google.common.base.Charsets.UTF_8;
    public static String guava_ServerFile( URL url ) throws IOException {
        return Resources.toString( url, charset );
    }
    public static String guava_DiskFile( File file ) throws IOException {
        return Files.toString( file, charset );
    }

  • APACHE-클래스 IOUtils, FileUtils를 사용하는 공통 IO

    static Charset encoding = org.apache.commons.io.Charsets.UTF_8;
    public static String commons_IOUtils( URL url ) throws IOException {
        java.io.InputStream in = url.openStream();
        try {
            return IOUtils.toString( in, encoding );
        } finally {
            IOUtils.closeQuietly(in);
        }
    }
    public static String commons_FileUtils( File file ) throws IOException {
        return FileUtils.readFileToString( file, encoding );
        /*List<String> lines = FileUtils.readLines( fileName, encoding );
        return lines.stream().collect( Collectors.joining("\n") );*/
    }

  • Stream API를 사용하는 Java 8 BufferReader

    public static String streamURL_Buffer( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        BufferedReader reader = new BufferedReader( new InputStreamReader( source ) );
        //List<String> lines = reader.lines().collect( Collectors.toList() );
        return reader.lines().collect( Collectors.joining( System.lineSeparator() ) );
    }
    public static String streamFile_Buffer( File file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader( file ) );
        return reader.lines().collect(Collectors.joining(System.lineSeparator()));
    }

  • 정규식 스캐너 클래스 \A. 입력의 시작과 일치합니다.

    static String charsetName = java.nio.charset.StandardCharsets.UTF_8.toString();
    public static String streamURL_Scanner( URL url ) throws IOException {
        java.io.InputStream source = url.openStream();
        Scanner scanner = new Scanner(source, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }
    public static String streamFile_Scanner( File file ) throws IOException {
        Scanner scanner = new Scanner(file, charsetName).useDelimiter("\\A");
        return scanner.hasNext() ? scanner.next() : "";
    }

  • 자바 7 ( java.nio.file.Files.readAllBytes)

    public static String getDiskFile_Java7( File file ) throws IOException {
        byte[] readAllBytes = java.nio.file.Files.readAllBytes(Paths.get( file.getAbsolutePath() ));
        return new String( readAllBytes );
    }

  • BufferedReader사용하여 InputStreamReader.

    public static String getDiskFile_Lines( File file ) throws IOException {
        StringBuffer text = new StringBuffer();
        FileInputStream fileStream = new FileInputStream( file );
        BufferedReader br = new BufferedReader( new InputStreamReader( fileStream ) );
        for ( String line; (line = br.readLine()) != null; )
            text.append( line + System.lineSeparator() );
        return text.toString();
    }

위의 방법에 액세스하는 주요 방법의 예입니다.

public static void main(String[] args) throws IOException {
    String fileName = "E:/parametarisation.csv";
    File file = new File( fileName );

    String fileStream = commons_FileUtils( file );
            // guava_DiskFile( file );
            // streamFile_Buffer( file );
            // getDiskFile_Java7( file );
            // getDiskFile_Lines( file );
    System.out.println( " File Over Disk : \n"+ fileStream );


    try {
        String src = "https://code.jquery.com/jquery-3.2.1.js";
        URL url = new URL( src );

        String urlStream = commons_IOUtils( url );
                // guava_ServerFile( url );
                // streamURL_Scanner( url );
                // streamURL_Buffer( url );
        System.out.println( " File Over Network : \n"+ urlStream );
    } catch (MalformedURLException e) {
        e.printStackTrace();
    }
}

@보다


26

텍스트 파일 인 경우 apache commons-io를 사용하지 않는 이유는 무엇입니까?

다음과 같은 방법이 있습니다

public static String readFileToString(File file) throws IOException

줄을 목록으로 사용하려면

public static List<String> readLines(File file) throws IOException

25

JDK 11부터 :

String file = ...
Path path = Paths.get(file);
String content = Files.readString(path);
// Or readString(path, someCharset), if you need a Charset different from UTF-8

2018 년 기본 캐릭터 셋에 의존하는 새로운 방법을 소개하는 이유는 무엇입니까?
— mryan

2
@mryan이 방법은 기본 시스템 문자셋에 의존하지 않습니다. 기본값은 UTF-8입니다.
— leventov

@leventov 당신이 맞아요! Files.readAllLines도 마찬가지입니다! 파일 API는 이전 메소드와 일관성이 없지만 더 좋습니다.)
— mryan

17

파일을 바이너리로 읽고 마지막에 변환하려면

public static String readFileAsString(String filePath) throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
    try {
        long len = new File(filePath).length();
        if (len > Integer.MAX_VALUE) throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
        byte[] bytes = new byte[(int) len];
        dis.readFully(bytes);
        return new String(bytes, "UTF-8");
    } finally {
        dis.close();
    }
}

16

Java 7에서는 UTF-8 파일을 읽는 데 선호되는 옵션입니다.

String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");

Java 7부터 JDK에는 java.nio.file많은 바로 가기를 제공 하는 새로운 API가 있으므로 간단한 파일 작업에 타사 라이브러리가 항상 필요한 것은 아닙니다.


15

Java는 모든 일에서 매우 일반적이고 유연 해 지려고합니다. 결과적으로, 스크립팅 언어에서 비교적 간단한 것 ( open(file).read()파이썬에서는 코드가 " " 로 대체 됨 )이 훨씬 더 복잡합니다. 외부 라이브러리를 사용하는 것을 제외하고는 더 짧은 방법은없는 것 같습니다 ( Willi aus Rohr 언급). 귀하의 옵션 :

  • 외부 라이브러리를 사용하십시오.
  • 이 코드를 모든 프로젝트에 복사하십시오.
  • 자주 사용하는 기능이 포함 된 자체 미니 라이브러리를 만듭니다.

가장 좋은 방법은 아마도 두 번째 것입니다.


4
응 "고급"언어는 다른 의미를 갖습니다. Java는 C에 비해 높은 수준이지만 Python 또는 Ruby에 비해 낮습니다.
— OscarRyz

3
Java는 고급 추상화에는 길지만 편의 방법에는 부족하다는 데 동의하십시오.
— Dónal

3
사실, Java에는 파일을 처리하는 데 많은 방법이 있으며 많은 것들이 복잡해 보입니다. 그러나 이것은 우리가 더 높은 수준의 언어로 가지고있는 것에 상당히 가깝습니다.byte[] bytes = Files.readAllBytes(someFile.toPath());
— Thorn

11

JDK 8 이상 사용 :

외부 라이브러리를 사용하지 않음

파일 내용에서 새 String 객체를 만들 수 있습니다 ( java.nio.file패키지의 클래스 사용 ).

public String readStringFromFile(String filePath) throws IOException {
    String fileContent = new String(Files.readAllBytes(Paths.get(filePath)));
    return fileContent;
}

모리츠 피터슨 (Moritz Petersen)의 대답은 다음과 같이 썼다.
— Jean-Christophe Blanchard

8

동일한 테마에 선 변수의 범위를 제한하기 위해 while 루프 대신 for 루프를 사용하는 변형이 있습니다. 그것이 더 나은지 여부는 개인적인 취향의 문제입니다.

for(String line = reader.readLine(); line != null; line = reader.readLine()) {
    stringBuilder.append(line);
    stringBuilder.append(ls);
}

3
이것은 개행을 기본 개행 선택으로 변경합니다. 이것은 바람직하거나 의도하지 않은 것일 수 있습니다.
— Peter Lawrey

line변수 의 범위를 좁히기 때문에이 답변에 대한 편집을 롤백했습니다 . 편집에서 컴파일이 두 번 선언되었습니다.
— Dan Dyer

7

Files클래스에 액세스 할 수없는 경우 기본 솔루션을 사용할 수 있습니다.

static String readFile(File file, String charset)
        throws IOException
{
    FileInputStream fileInputStream = new FileInputStream(file);
    byte[] buffer = new byte[fileInputStream.available()];
    int length = fileInputStream.read(buffer);
    fileInputStream.close();
    return new String(buffer, 0, length, charset);
}

예를 들어 문자 집합을 호출?
— Thufir

4

StringWriter 와 함께 Apache commons-io의 IOUtil 을 사용하는 유연한 솔루션 :

Reader input = new FileReader();
StringWriter output = new StringWriter();
try {
  IOUtils.copy(input, output);
} finally {
  input.close();
}
String fileContents = output.toString();

URL에서 읽을 때와 같이 모든 파일이 아닌 리더 또는 입력 스트림에서 작동합니다.


3

fileInputStream.available()반환 된 정수를 사용할 때 실제 파일 크기를 나타낼 필요는 없지만 시스템이 IO를 차단하지 않고 스트림에서 읽을 수있는 바이트 수를 추측해야합니다. 안전하고 간단한 방법은 다음과 같습니다

public String readStringFromInputStream(FileInputStream fileInputStream) {
    StringBuffer stringBuffer = new StringBuffer();
    try {
        byte[] buffer;
        while (fileInputStream.available() > 0) {
            buffer = new byte[fileInputStream.available()];
            fileInputStream.read(buffer);
            stringBuffer.append(new String(buffer, "ISO-8859-1"));
        }
    } catch (FileNotFoundException e) {
    } catch (IOException e) { }
    return stringBuffer.toString();
}

이 접근법은 UTF-8과 같은 멀티 바이트 문자 인코딩 에는 적합 하지 않다는 점을 고려해야합니다 .


1
이 코드는 예측할 수없는 결과를 제공 할 수 있습니다. 메소드 의 문서 에 따르면 available()메소드가 0을 리턴하는 경우 파일 끝에 도달한다는 보장이 없습니다.이 경우 불완전한 파일로 끝날 수 있습니다. 더 나쁜 것은 실제로 읽은 바이트 수는 available()에서 반환 한 값보다 작을 수 있으며이 경우 출력이 손상됩니다.
— wau

3

이것은이 방법을 사용하며 RandomAccessFile.readFully, JDK 1.0에서 사용 가능한 것 같습니다!

public static String readFileContent(String filename, Charset charset) throws IOException {
    RandomAccessFile raf = null;
    try {
        raf = new RandomAccessFile(filename, "r");
        byte[] buffer = new byte[(int)raf.length()];
        raf.readFully(buffer);
        return new String(buffer, charset);
    } finally {
        closeStream(raf);
    }
} 


private static void closeStream(Closeable c) {
    if (c != null) {
        try {
            c.close();
        } catch (IOException ex) {
            // do nothing
        }
    }
}

3

몇 줄의 솔루션 인 스캐너 및 파일 클래스를 사용해 볼 수 있습니다

 try
{
  String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next();
  System.out.println(content);
}
catch(FileNotFoundException e)
{
  System.out.println("not found!");
}

3

java.nio.Files파일의 모든 줄을 읽는 사용자

public String readFile() throws IOException {
        File fileToRead = new File("file path");
        List<String> fileLines = Files.readAllLines(fileToRead.toPath());
        return StringUtils.join(fileLines, StringUtils.EMPTY);
}

3
public static String slurp (final File file)
throws IOException {
    StringBuilder result = new StringBuilder();

    BufferedReader reader = new BufferedReader(new FileReader(file));

    try {
        char[] buf = new char[1024];

        int r = 0;

        while ((r = reader.read(buf)) != -1) {
            result.append(buf, 0, r);
        }
    }
    finally {
        reader.close();
    }

    return result.toString();
}

플랫폼 기본 인코딩을 사용하는 것이 불편하다고 생각합니다. +1 어쨌든 :)
— OscarRyz

7
finally 블록은 try 블록에 정의 된 변수를 알지 못하는 것 같습니다. javac 1.6.0_21에서 오류가 발생 cannot find symbol합니다.
— 16:25에

자신의 코드를 사용해 보셨습니까? try / catch 블록에서 리더를 정의 했으므로 finally 블록에서 액세스 할 수 없습니다.
— mauron85

2

다른 항목은 아직 언급 할 수 없으므로 여기에 그대로 두겠습니다.

여기에 가장 좋은 답변 중 하나 ( https://stackoverflow.com/a/326448/1521167 ) :

private String readFile(String pathname) throws IOException {

File file = new File(pathname);
StringBuilder fileContents = new StringBuilder((int)file.length());
Scanner scanner = new Scanner(file);
String lineSeparator = System.getProperty("line.separator");

try {
    while(scanner.hasNextLine()) {        
        fileContents.append(scanner.nextLine() + lineSeparator);
    }
    return fileContents.toString();
} finally {
    scanner.close();
}
}

여전히 하나의 결함이 있습니다. 문자열 끝에 줄 바꿈 문자를 항상 넣으면 이상한 버그가 발생할 수 있습니다. 내 제안은 다음과 같이 변경하는 것입니다.

    private String readFile(String pathname) throws IOException {
    File file = new File(pathname);
    StringBuilder fileContents = new StringBuilder((int) file.length());
    Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
    String lineSeparator = System.getProperty("line.separator");

    try {
        if (scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine());
        }
        while (scanner.hasNextLine()) {
            fileContents.append(lineSeparator + scanner.nextLine());
        }
        return fileContents.toString();
    } finally {
        scanner.close();
    }
}

첫 번째 경우 끝에 줄 바꿈을 추가 할 수 있습니다. 두 번째 경우에는 하나를 생략 할 수 있습니다. 따라서 둘 다 똑같이 잘못되었습니다. 참고 이 문서
— 패트릭 파커

2

스캐너 다음에 Ctrl + F를 누른 후 스캐너 솔루션도 나열되어야한다고 생각합니다. 가장 읽기 쉬운 방식으로 다음과 같이 진행됩니다.

public String fileToString(File file, Charset charset) {
  Scanner fileReader = new Scanner(file, charset);
  fileReader.useDelimiter("\\Z"); // \Z means EOF.
  String out = fileReader.next();
  fileReader.close();
  return out;
}

Java 7 이상을 사용하는 경우 코드를보다 쉽게 ​​읽을 수 있도록 try-with-resources를 사용하는 것이 좋습니다. 더 이상 모든 것을 흩 뜨리는 물건이 없습니다. 그러나 그것은 주로 문체 선택 방법입니다.

당신이 이것을 많이 할 필요가있는 경우에 일이 있어야하기 때문에 나는 주로 completionism이를 게시하도록하겠습니다 java.nio.file.Files 에 작업을 더 잘 수행 .

내 제안은 Files # readAllBytes (Path) 를 사용하여 모든 바이트를 가져 와서 새로운 String (byte [] Charset)에 공급하는 것입니다. 하여 신뢰할 수있는 String을 가져 오는 것입니다. 캐릭터 세트는 평생 동안 당신에게 의미가 있으므로 지금이 물건에주의하십시오.

다른 사람들은 코드와 물건을 주었고, 나는 그들의 영광을 훔치고 싶지 않습니다. ;)



2

또한 파일이 항아리 안에 있으면 다음을 사용할 수도 있습니다.

public String fromFileInJar(String path) {
    try ( Scanner scanner 
            = new Scanner(getClass().getResourceAsStream(path))) {
        return scanner.useDelimiter("\\A").next();
    }
}

경로는 시작해야합니다 / 귀하의 항아리 인 경우, 예를 들어

my.jar/com/some/thing/a.txt

그런 다음 다음과 같이 호출하십시오.

String myTxt = fromFileInJar("/com/com/thing/a.txt");

2

한 줄 (Java 8)에서 독자가 있다고 가정하면 :

String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));

2

@erickson의 답변에 따라 다음을 사용할 수 있습니다.

public String readAll(String fileName) throws IOException {
    List<String> lines = Files.readAllLines(new File(fileName).toPath());
    return String.join("\n", lines.toArray(new String[lines.size()]));
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.