질문자 :OscarRyz
나는 지금 얼마 동안 아래의 관용구를 사용하고 있습니다. 그리고 그것은 적어도 내가 방문한 사이트에서 가장 널리 퍼진 것 같습니다.
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(); } }
파일에서 모든 텍스트 읽기
Java 11은 줄 종결자를 유지하면서 작은 파일을 String
으로 읽는 readString() 메서드를 추가했습니다.
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 Stream<String>
을 생성하기 위해 Files.lines()
메서드를 추가했습니다. 다시 말하지만, 이 방법은 줄 구분자가 제거되기 때문에 손실이 있습니다. 파일을 읽는 동안 IOException
Stream
이 확인된 예외를 throw하는 람다를 허용하지 않기 때문에 UncheckedIOException
try (Stream<String> lines = Files.lines(path, encoding)) { lines.forEach(System.out::println); }
이 Stream
close()
호출이 필요합니다. 이것은 API에 제대로 문서화되어 있지 않으며 많은 사람들이 Stream
close()
메서드가 있다는 사실조차 알지 못하는 것 같습니다. 그림과 같이 ARM 블록을 사용해야 합니다.
파일이 아닌 소스로 작업하는 경우 BufferedReader
lines()
메서드를 대신 사용할 수 있습니다.
메모리 활용
줄 바꿈을 유지하는 첫 번째 방법은 일시적으로 파일 크기의 몇 배에 해당하는 메모리가 필요할 수 있습니다. 파일의 8비트로) 한 번에 메모리에 상주합니다. 사용 가능한 메모리에 비해 작은 것으로 알고 있는 파일에 적용하는 것이 가장 안전합니다.
두 번째 방법인 라인 읽기는 디코딩을 위한 입력 바이트 버퍼가 전체 파일을 포함할 필요가 없기 때문에 일반적으로 메모리 효율성이 더 높습니다. 그러나 사용 가능한 메모리에 비해 매우 큰 파일에는 여전히 적합하지 않습니다.
큰 파일을 읽으려면 스트림에서 텍스트 덩어리를 읽고 처리한 다음 동일한 고정 크기 메모리 블록을 재사용하여 다음으로 이동하는 프로그램에 대한 다른 디자인이 필요합니다. 여기서 "대형"은 컴퓨터 사양에 따라 다릅니다. 오늘날 이 임계값은 수 기가바이트의 RAM일 수 있습니다. Stream<String>
사용하는 세 번째 방법은 입력 "레코드"가 개별 행인 경우 이를 수행하는 한 가지 방법입니다. ( BufferedReader
readLine()
메서드를 사용하는 것은 이 접근 방식과 절차적으로 동일합니다.)
문자 인코딩
원본 게시물의 샘플에서 누락된 한 가지는 문자 인코딩입니다. 플랫폼 기본값이 원하는 것이지만 드문 경우이고 선택을 정당화할 수 있어야 하는 몇 가지 특별한 경우가 있습니다.
StandardCharsets
클래스는 모든 Java 런타임에 필요한 인코딩에 대한 몇 가지 상수를 정의합니다.
String content = readFile("test.txt", StandardCharsets.UTF_8);
플랫폼 기본값은 Charset
클래스 자체에서 사용할 수 있습니다.
String content = readFile("test.txt", Charset.defaultCharset());
참고: 이 답변은 Java 6 버전을 대체합니다. Java 7의 유틸리티는 코드를 안전하게 단순화하고 매핑된 바이트 버퍼를 사용하는 이전 답변은 매핑된 버퍼가 가비지 수집될 때까지 읽은 파일이 삭제되는 것을 방지했습니다. 이 답변의 "편집된" 링크를 통해 이전 버전을 볼 수 있습니다.
erickson외부 라이브러리를 사용하려는 경우 Apache Commons IO (200KB JAR)를 확인하십시오. 여기에는 한 줄의 코드로 File
String
로 읽을 수 org.apache.commons.io.FileUtils.readFileToString()
메서드가 포함되어 있습니다.
예시:
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); }
DaWilliScanner
기반의 매우 린 솔루션:
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의 블로그
Pablo Grisafiimport 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);
자바 7부터 이런 식으로 할 수 있습니다.
Jobin타사 라이브러리(예: 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(); } }
Dónal구아바 에는 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의 편집
Files#toString
은 더 이상 사용되지 않으며 2019년 10월 제거 예정입니다. 대신 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 작성): 위의 내용은 최신 Guava 버전의 소스 코드와 일치하지 않습니다. 현재 소스는 com.google.common.io 패키지의 Files , CharStreams , ByteSource 및 CharSource 클래스를 참조하세요.
Community Wikiimport 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 ""; }
user590444문자열 처리(병렬 처리)가 필요한 경우 Java 8에는 훌륭한 Stream 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
에서 더 많은 예제를 사용할 수 있습니다.
또 다른 하나의 라이너 예
String out = String.join("\n", Files.readAllLines(Paths.get("file.txt")));
Andrei N그 코드는 줄 바꿈을 정규화할 것입니다. 이것은 당신이 정말로 하고 싶은 것일 수도 있고 아닐 수도 있습니다.
다음은 그렇게 하지 않고 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(); } }
Jon Skeet디스크 또는 네트워크에서 파일을 문자열로 읽을 수 있는 모든 방법을 모았습니다.
구아바: Resources
, Files
클래스를 사용하는 Google
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 클래스를 사용하는 COMMONS 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") );*/ }
스트림 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 ); }
InputStreamReader
사용하는 BufferedReader
.
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(); } }
@보다
Yash텍스트 파일인 경우 apache commons-io를 사용하지 않는 이유는 무엇입니까?
그것은 다음과 같은 방법이 있습니다
public static String readFileToString(File file) throws IOException
라인을 목록으로 사용하려면
public static List<String> readLines(File file) throws IOException
Home in TimeJDK 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
leventov파일을 바이너리로 읽고 마지막에 변환하려면
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(); } }
Peter LawreyJava 7에서는 UTF-8 파일을 읽을 때 선호하는 옵션입니다.
String content = new String(Files.readAllBytes(Paths.get(filename)), "UTF-8");
Java 7부터 JDK에는 java.nio.file
API가 있으므로 간단한 파일 작업에 타사 라이브러리가 항상 필요한 것은 아닙니다.
Moritz PetersenJava는 모든 면에서 매우 일반적이고 유연하게 시도합니다. 결과적으로 스크립팅 언어에서 비교적 간단한 것(귀하의 코드는 open(file).read()
"로 대체됨)은 훨씬 더 복잡합니다. 외부 라이브러리를 사용하는 것을 제외하고는 더 짧은 방법이 없는 것 같습니다( Willi aus Rohr가 언급한 것처럼). 귀하의 옵션:
- 외부 라이브러리를 사용합니다.
- 이 코드를 모든 프로젝트에 복사하십시오.
- 자주 사용하는 기능이 담긴 나만의 미니 라이브러리를 만드세요.
가장 좋은 방법은 종속성이 가장 적기 때문에 아마도 두 번째 것입니다.
ClaudiuJDK 8 이상 사용:
외부 라이브러리가 사용되지 않음
파일 내용에서 새 String 개체를 만들 수 있습니다( java.nio.file
패키지의 클래스 사용).
public String readStringFromFile(String filePath) throws IOException { String fileContent = new String(Files.readAllBytes(Paths.get(filePath))); return fileContent; }
Saikat동일한 테마에 while 루프 대신 for 루프를 사용하여 라인 변수의 범위를 제한하는 변형이 있습니다. 그것이 "더 나은"것인지 여부는 개인 취향의 문제입니다.
for(String line = reader.readLine(); line != null; line = reader.readLine()) { stringBuilder.append(line); stringBuilder.append(ls); }
Dan DyerFiles
클래스에 액세스할 수 없는 경우 기본 솔루션을 사용할 수 있습니다.
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); }
Ilya GazmanStringWriter 와 함께 Apache commons-io의 IOUtils 를 사용하는 유연한 솔루션:
Reader input = new FileReader(); StringWriter output = new StringWriter(); try { IOUtils.copy(input, output); } finally { input.close(); } String fileContents = output.toString();
예를 들어 URL에서 읽을 때와 같이 모든 리더 또는 입력 스트림(파일뿐 아니라)과 함께 작동합니다.
waufileInputStream.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과 같은 다중 바이트 문자 인코딩에 적합 하지 않다는 점을 고려해야 합니다.
HenryRandomAccessFile.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 } } }
barjak스캐너 및 파일 클래스, 몇 줄 솔루션을 사용해 볼 수 있습니다.
try { String content = new Scanner(new File("file.txt")).useDelimiter("\\Z").next(); System.out.println(content); } catch(FileNotFoundException e) { System.out.println("not found!"); }
jamesjara@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()])); }
Muskovets사용자 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); }
Nitinpublic 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(); }
Scott S. McCoy다른 항목에 대해서는 아직 댓글을 달 수 없으므로 여기에 남겨 둡니다.
여기 최고의 답변 중 하나( 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(); } }
Ajk스캐너 다음에 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 사용을 고려하십시오. 더 이상 모든 것을 어지럽히는 점 닫기 물건이 없습니다. 그러나 그것은 대부분 문체적인 선택이라고 생각합니다.
이 작업을 많이 수행해야 하는 경우 java.nio.file.Files 에 작업을 더 잘 수행해야 하는 항목이 있어야 하기 때문에 나는 주로 완료주의를 위해 이것을 게시하고 있습니다.
내 제안은 Files#readAllBytes(Path) 를 사용하여 모든 바이트를 잡고 new String(byte[] Charset)에 공급 하여 신뢰할 수 있는 문자열을 가져오는 것입니다. Charsets는 평생 동안 당신에게 의미가 없을 것이므로 지금 이것을 조심하십시오.
다른 사람들은 코드와 물건을 제공했고 나는 그들의 영광을 훔치고 싶지 않습니다. ;)
Haakon Løtveit이 라이브러리를 사용하면 한 줄입니다.
String data = IO.from(new File("data.txt")).toString();
satnam또한 파일이 jar 내부에 있는 경우 다음을 사용할 수도 있습니다.
public String fromFileInJar(String path) { try ( Scanner scanner = new Scanner(getClass().getResourceAsStream(path))) { return scanner.useDelimiter("\\A").next(); } }
경로는 예를 들어 jar 파일인 경우 /
로 시작해야 합니다.
my.jar/com/some/thing/a.txt
그런 다음 다음과 같이 호출하려고 합니다.
String myTxt = fromFileInJar("/com/com/thing/a.txt");
OscarRyzReader가 있다고 가정하면 한 줄(Java 8)에서 다음을 수행합니다.
String sMessage = String.join("\n", reader.lines().collect(Collectors.toList()));
Malcolm Boekhoff출처 : http:www.stackoverflow.com/questions/326390/how-do-i-create-a-java-string-from-the-contents-of-a-file