1. 개요
이 튜토리얼에서는 File in Java에서 읽는 다양한 방법을 살펴 봅니다 .
먼저 클래스 경로, URL 또는 표준 Java 클래스를 사용하여 JAR 파일에서 파일을로드하는 방법을 배웁니다.
둘째, BufferedReader , Scanner , StreamTokenizer , DataInputStream , SequenceInputStream 및 FileChannel을 사용 하여 콘텐츠를 읽는 방법을 살펴 보겠습니다 . 또한 UTF-8 인코딩 파일을 읽는 방법에 대해서도 설명합니다.
마지막으로 Java 7 및 Java 8에서 파일을로드하고 읽는 새로운 기술을 살펴 보겠습니다.
이 기사는 Baeldung 에 대한 "Java – Back to Basic"시리즈의 일부입니다.
2. 설정
2.1 입력 파일
이 기사의 대부분의 예제에서는 한 줄이 포함 된 fileTest.txt 파일 이름의 텍스트 파일을 읽습니다 .
Hello, world!
몇 가지 예를 들어 다른 파일을 사용합니다. 이 경우 파일과 그 내용을 명시 적으로 언급합니다.
2.2 도우미 방법
핵심 Java 클래스에만 테스트 예제 세트를 사용하고 테스트에서는 Hamcrest 매처 와 함께 어설 션을 사용 합니다.
테스트는 결과를보다 쉽게 주장 할 수 있도록 InputStream 을 String으로 변환하는 일반적인 readFromInputStream 메서드를 공유합니다 .
private String readFromInputStream(InputStream inputStream)
throws IOException {
StringBuilder resultStringBuilder = new StringBuilder();
try (BufferedReader br
= new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = br.readLine()) != null) {
resultStringBuilder.append(line).append("\n");
}
}
return resultStringBuilder.toString();
}
이와 동일한 결과를 얻는 다른 방법이 있습니다. 이 문서 에서 몇 가지 대안을 참조 할 수 있습니다 .
3. 클래스 경로에서 파일 읽기
3.1. 표준 자바 사용
이 섹션에서는 클래스 경로에서 사용 가능한 파일을 읽는 방법을 설명합니다. src / main / resources 아래에 있는 " fileTest.txt "를 읽을 것입니다 .
@Test
public void givenFileNameAsAbsolutePath_whenUsingClasspath_thenFileData() {
String expectedData = "Hello, world!";
Class clazz = FileOperationsTest.class;
InputStream inputStream = clazz.getResourceAsStream("/fileTest.txt");
String data = readFromInputStream(inputStream);
Assert.assertThat(data, containsString(expectedData));
}
위의 코드 스 니펫에서 현재 클래스를 사용하여 getResourceAsStream 메소드를 사용하여 파일을로드하고로드 할 파일 의 절대 경로를 전달했습니다.
ClassLoader 인스턴스에서도 동일한 메서드를 사용할 수 있습니다.
ClassLoader classLoader = getClass().getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("fileTest.txt");
String data = readFromInputStream(inputStream);
getClass (). getClassLoader ()를 사용하여 현재 클래스 의 classLoader 를 얻습니다 .
주요 차이점은 ClassLoader 인스턴스 에서 getResourceAsStream 을 사용할 때 경로가 클래스 경로의 루트에서 시작하는 절대 경로로 처리 된다는 것 입니다.
대해 사용될 때, 클래스 인스턴스 , 경로는 슬래시 의해 암시되는 패키지 또는 절대 경로에 상대적 일 수있다.
물론, 실제로 는 우리 예제 의 InputStream 과 같이 열린 스트림은 항상 닫혀 있어야합니다 .
InputStream inputStream = null;
try {
File file = new File(classLoader.getResource("fileTest.txt").getFile());
inputStream = new FileInputStream(file);
//...
}
finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.2. 은 Using 공유지를-IO 라이브러리
또 다른 일반적인 옵션은 commons-io 패키지 의 FileUtils 클래스를 사용하는 것입니다 .
@Test
public void givenFileName_whenUsingFileUtils_thenFileData() {
String expectedData = "Hello, world!";
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("fileTest.txt").getFile());
String data = FileUtils.readFileToString(file, "UTF-8");
assertEquals(expectedData, data.trim());
}
여기서는 File 객체를 FileUtils 클래스 의 readFileToString () 메소드에 전달합니다 . 이 유틸리티 클래스는 InputStream 인스턴스 를 생성하고 데이터를 읽기 위해 상용구 코드를 작성할 필요없이 콘텐츠를로드하도록 관리합니다 .
동일한 라이브러리는 IOUtils 클래스 도 제공합니다 .
@Test
public void givenFileName_whenUsingIOUtils_thenFileData() {
String expectedData = "Hello, world!";
FileInputStream fis = new FileInputStream("src/test/resources/fileTest.txt");
String data = IOUtils.toString(fis, "UTF-8");
assertEquals(expectedData, data.trim());
}
여기에서 FileInputStream 객체를 IOUtils 클래스 의 toString () 메서드에 전달합니다 . 이 유틸리티 클래스는 InputStream 인스턴스 를 생성하고 데이터를 읽기 위해 이전 클래스와 동일한 방식으로 작동 합니다.
4. BufferedReader로 읽기
이제 파일 내용을 구문 분석하는 다양한 방법에 초점을 맞 춥니 다.
BufferedReader를 사용하여 파일에서 읽는 간단한 방법으로 시작합니다 .
@Test
public void whenReadWithBufferedReader_thenCorrect()
throws IOException {
String expected_value = "Hello, world!";
String file ="src/test/resources/fileTest.txt";
BufferedReader reader = new BufferedReader(new FileReader(file));
String currentLine = reader.readLine();
reader.close();
assertEquals(expected_value, currentLine);
}
참고 내의 readLine ()가 반환 널 (null)를 파일의 끝에 도달했을 때.
5. Java NIO를 사용하여 파일에서 읽기
JDK7에서는 NIO 패키지가 크게 업데이트되었습니다.
Files 클래스와 readAllLines 메서드 를 사용하는 예제를 살펴 보겠습니다 . readAllLines의 방법은 받아 경로.
경로 클래스는 몇 가지 추가 작업 이있는 java.io.File 의 업그레이드로 간주 될 수 있습니다 .
5.1. 작은 파일 읽기
다음 코드는 새 Files 클래스를 사용하여 작은 파일을 읽는 방법을 보여줍니다 .
@Test
public void whenReadSmallFileJava7_thenCorrect()
throws IOException {
String expected_value = "Hello, world!";
Path path = Paths.get("src/test/resources/fileTest.txt");
String read = Files.readAllLines(path).get(0);
assertEquals(expected_value, read);
}
바이너리 데이터가 필요한 경우에도 readAllBytes () 메서드를 사용할 수 있습니다 .
5.2. 큰 파일 읽기
Files 클래스 로 큰 파일을 읽으려면 BufferedReader를 사용할 수 있습니다 .
다음 코드는 새 Files 클래스와 BufferedReader를 사용하여 파일을 읽습니다 .
@Test
public void whenReadLargeFileJava7_thenCorrect()
throws IOException {
String expected_value = "Hello, world!";
Path path = Paths.get("src/test/resources/fileTest.txt");
BufferedReader reader = Files.newBufferedReader(path);
String line = reader.readLine();
assertEquals(expected_value, line);
}
5.3. Files.lines ()를 사용하여 파일 읽기
JDK8은 Files 클래스 내부에 lines () 메서드를 제공합니다 . Stream of String 요소를 반환합니다 .
데이터를 바이트로 읽고 UTF-8 문자 세트를 사용하여 디코딩하는 방법의 예를 살펴 보겠습니다.
다음 코드는 new Files.lines ()를 사용하여 파일을 읽습니다 .
@Test
public void givenFilePath_whenUsingFilesLines_thenFileData() {
String expectedData = "Hello, world!";
Path path = Paths.get(getClass().getClassLoader()
.getResource("fileTest.txt").toURI());
Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();
Assert.assertEquals(expectedData, data.trim());
}
파일 작업과 같은 IO 채널과 함께 Stream을 사용하려면 close () 메서드를 사용하여 명시 적으로 스트림을 닫아야합니다 .
보시다시피 Files API는 파일 내용을 문자열 로 읽는 또 다른 쉬운 방법을 제공합니다 .
다음 섹션에서는 일부 상황에서 적절할 수있는 덜 일반적인 파일 읽기 방법을 살펴 보겠습니다.
6. 스캐너로 읽기
다음으로 스캐너 를 사용 하여 파일에서 읽어 보겠습니다 . 여기서는 구분자로 공백을 사용합니다.
@Test
public void whenReadWithScanner_thenCorrect()
throws IOException {
String file = "src/test/resources/fileTest.txt";
Scanner scanner = new Scanner(new File(file));
scanner.useDelimiter(" ");
assertTrue(scanner.hasNext());
assertEquals("Hello,", scanner.next());
assertEquals("world!", scanner.next());
scanner.close();
}
기본 구분 기호는 공백이지만 Scanner에서 여러 구분 기호를 사용할 수 있습니다 .
스캐너 콘솔에서 콘텐츠를 판독하거나, 콘텐츠 프리미티브 값을 포함하는 경우 클래스 때 유용하다 (: 정수의리스트가 공백으로 분리 등)를 공지 된 구분자를.
7. StreamTokenizer로 읽기
이제 StreamTokenizer를 사용하여 텍스트 파일을 토큰으로 읽어 보겠습니다 .
토크 나이 저는 먼저 다음 토큰이 문자열 또는 숫자인지 파악하여 작동합니다. tokenizer.ttype 필드 를 살펴보면됩니다 .
그런 다음이 유형을 기반으로 실제 토큰을 읽습니다.
- tokenizer.nval – 유형이 숫자 인 경우
- tokenizer.sval – 유형이 문자열 인 경우
이 예제에서는 단순히 다음을 포함하는 다른 입력 파일을 사용합니다.
Hello 1
다음 코드는 파일에서 문자열과 숫자를 읽습니다.
@Test
public void whenReadWithStreamTokenizer_thenCorrectTokens()
throws IOException {
String file = "src/test/resources/fileTestTokenizer.txt";
FileReader reader = new FileReader(file);
StreamTokenizer tokenizer = new StreamTokenizer(reader);
// token 1
tokenizer.nextToken();
assertEquals(StreamTokenizer.TT_WORD, tokenizer.ttype);
assertEquals("Hello", tokenizer.sval);
// token 2
tokenizer.nextToken();
assertEquals(StreamTokenizer.TT_NUMBER, tokenizer.ttype);
assertEquals(1, tokenizer.nval, 0.0000001);
// token 3
tokenizer.nextToken();
assertEquals(StreamTokenizer.TT_EOF, tokenizer.ttype);
reader.close();
}
마지막에 파일 토큰의 끝이 어떻게 사용되는지 확인하십시오.
이 접근 방식은 입력 스트림을 토큰으로 구문 분석하는 데 유용합니다.
8. DataInputStream으로 읽기
DataInputStream 을 사용 하여 파일에서 이진 또는 원시 데이터 유형을 읽을 수 있습니다 .
다음 테스트는 DataInputStream을 사용하여 파일을 읽습니다 .
@Test
public void whenReadWithDataInputStream_thenCorrect() throws IOException {
String expectedValue = "Hello, world!";
String file ="src/test/resources/fileTest.txt";
String result = null;
DataInputStream reader = new DataInputStream(new FileInputStream(file));
int nBytesToRead = reader.available();
if(nBytesToRead > 0) {
byte[] bytes = new byte[nBytesToRead];
reader.read(bytes);
result = new String(bytes);
}
assertEquals(expectedValue, result);
}
9. FileChannel로 읽기
대용량 파일을 읽는 경우 FileChannel 이 표준 IO보다 빠를 수 있습니다.
다음 코드는 FileChannel 및 RandomAccessFile을 사용하여 파일에서 데이터 바이트를 읽습니다 .
@Test
public void whenReadWithFileChannel_thenCorrect()
throws IOException {
String expected_value = "Hello, world!";
String file = "src/test/resources/fileTest.txt";
RandomAccessFile reader = new RandomAccessFile(file, "r");
FileChannel channel = reader.getChannel();
int bufferSize = 1024;
if (bufferSize > channel.size()) {
bufferSize = (int) channel.size();
}
ByteBuffer buff = ByteBuffer.allocate(bufferSize);
channel.read(buff);
buff.flip();
assertEquals(expected_value, new String(buff.array()));
channel.close();
reader.close();
}
10. UTF-8 인코딩 파일 읽기
이제 BufferedReader를 사용하여 UTF-8로 인코딩 된 파일을 읽는 방법을 살펴 보겠습니다 . 이 예에서는 중국어 문자가 포함 된 파일을 읽습니다.
@Test
public void whenReadUTFEncodedFile_thenCorrect()
throws IOException {
String expected_value = "青空";
String file = "src/test/resources/fileTestUtf8.txt";
BufferedReader reader = new BufferedReader
(new InputStreamReader(new FileInputStream(file), "UTF-8"));
String currentLine = reader.readLine();
reader.close();
assertEquals(expected_value, currentLine);
}
11. URL에서 콘텐츠 읽기
URL에서 콘텐츠를 읽으려면 다음 예에서 " / "URL을 사용합니다 .
@Test
public void givenURLName_whenUsingURL_thenFileData() {
String expectedData = "Baeldung";
URL urlObject = new URL("/");
URLConnection urlConnection = urlObject.openConnection();
InputStream inputStream = urlConnection.getInputStream();
String data = readFromInputStream(inputStream);
Assert.assertThat(data, containsString(expectedData));
}
URL에 연결하는 다른 방법도 있습니다. 여기서는 표준 SDK에서 사용할 수 있는 URL 및 URLConnection 클래스를 사용했습니다.
12. JAR에서 파일 읽기
JAR 파일 안에있는 파일을 읽으려면 그 안에 파일이있는 JAR이 필요합니다. 이 예 에서는“ hamcrest-library-1.3.jar ”파일 에서 “ LICENSE.txt ”를 읽습니다 .
@Test
public void givenFileName_whenUsingJarFile_thenFileData() {
String expectedData = "BSD License";
Class clazz = Matchers.class;
InputStream inputStream = clazz.getResourceAsStream("/LICENSE.txt");
String data = readFromInputStream(inputStream);
Assert.assertThat(data, containsString(expectedData));
}
여기 에서 Hamcrest 라이브러리에있는 LICENSE.txt 를로드하려고 하므로 리소스를 얻는 데 도움이 되는 Matcher의 클래스를 사용합니다 . 클래스 로더를 사용하여 동일한 파일을로드 할 수도 있습니다.
13. 결론
보시다시피 일반 Java를 사용하여 파일을로드하고 데이터를 읽을 수있는 많은 가능성이 있습니다.
클래스 경로, URL 또는 jar 파일과 같은 다양한 위치에서 파일을로드 할 수 있습니다.
그런 다음 BufferedReader 를 사용 하여 한 줄씩 읽고 스캐너 를 사용하여 다른 구분 기호 를 읽고 StreamTokenizer 를 사용하여 파일을 토큰 으로 읽고 DataInputStream 을 사용하여 이진 데이터 및 기본 데이터 유형을 읽고 SequenceInput Stream 을 사용하여 여러 파일을 하나의 스트림으로 연결하고 FileChannel 을 사용하여 더 빠르게 읽을 수 있습니다. 대용량 파일 등에서
다음 GitHub 저장소 에서이 기사의 소스 코드를 찾을 수 있습니다 .
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/reading-file-in-java
'Java' 카테고리의 다른 글
스프링 부트 액추에이터 (0) | 2021.03.12 |
---|---|
Java에서 문자열에 개행 문자(줄 바꿈) 추가 (0) | 2021.03.11 |
OkHttp 가이드 (0) | 2021.03.11 |
Keycloak과 함께 사용자 지정 사용자 공급자 사용 (0) | 2021.03.11 |
Spring에서 캐싱 사용방법 (0) | 2021.03.10 |