파일 내용에서 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.iojava.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 , ByteSourceCharSource 클래스를 참조하십시오 .


이 코드는 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.