Java로 파일을 읽는 방법

1. 개요

이 튜토리얼에서는 File in Java에서 읽는 다양한 방법을 살펴 봅니다 .

먼저 표준 Java 클래스를 사용하여 클래스 경로, URL 또는 JAR 파일에서 파일을로드하는 방법을 살펴 보겠습니다.

둘째, BufferedReader , Scanner , StreamTokenizer , DataInputStream , SequenceInputStreamFileChannel을 사용 하여 콘텐츠를 읽는 방법을 알아 봅니다 . 또한 UTF-8 인코딩 파일을 읽는 방법에 대해서도 설명합니다.

마지막으로 Java 7 및 Java 8에서 파일을로드하고 읽는 새로운 기술을 살펴 보겠습니다.

이 기사는 Baeldung에 대한 "Java – Back to Basic"시리즈의 일부입니다.

2. 설정

2.1 입력 파일

이 기사의 대부분의 예제에서는 한 줄이 포함 된 fileTest.txt 파일 이름의 텍스트 파일을 읽습니다 .

Hello, world!

몇 가지 예에서는 다른 파일을 사용합니다. 이 경우 파일과 그 내용을 명시 적으로 언급합니다.

2.2 도우미 방법

핵심 Java 클래스 만 사용하는 테스트 예제 세트를 사용하고 테스트에서는 Hamcrest 매처를 사용하여 어설 션을 사용합니다.

테스트는 결과를보다 쉽게 ​​주장 할 수 있도록 InputStreamString으로 변환하는 일반적인 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; 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); }

Note that you can use the readAllBytes() method as well if you need binary data.

5.2. Reading a Large File

If we want to read a large file with Files class, we can use the BufferedReader:

The following code reads the file using the new Files class and 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. Reading a File Using Files.lines()

JDK8 offers the lines() method inside the Files class. It returns a Stream of String elements.

Let’s look at an example of how to read data into bytes and decode using UTF-8 charset.

The following code reads the file using the new Files.lines():

@Test public void givenFilePath_whenUsingFilesLines_thenFileData() { String expectedData = "Hello, world!"; Path path = Paths.get(getClass().getClassLoader() .getResource("fileTest.txt").toURI()); Stream lines = Files.lines(path); String data = lines.collect(Collectors.joining("\n")); lines.close(); Assert.assertEquals(expectedData, data.trim()); }

Using Stream with IO channels like file operations, we need to close the stream explicitly using the close() method.

As we can see, the Files API offers another easy way to read the file contents into a String.

In the next sections, let's have a look at other, less common methods of reading a file, that may be appropriate in some situations.

6. Reading with Scanner

Next, let's use a Scanner to read from the File. Here, we'll use whitespace as the delimiter:

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

Note that the default delimiter is the whitespace, but multiple delimiters can be used with a Scanner.

The Scanner class is useful when reading content from the console, or when the content contains primitive values, with a known delimiter (eg: a list of integers separated by space).

7. Reading with StreamTokenizer

Next, let's read a text file into tokens using a StreamTokenizer.

The way the tokenizer works is – first, we need to figure out what the next token is – String or number; we do that by looking at the tokenizer.ttype field.

Then, we'll read the actual token based on this type:

  • tokenizer.nval – if the type was a number
  • tokenizer.sval – if the type was a String

In this example we'll use a different input file which simply contains:

Hello 1

The following code reads from the file both the String and the number:

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

Note how the end of file token is used at the end.

This approach is useful for parsing an input stream into tokens.

8. Reading with DataInputStream

We can use DataInputStream to read binary or primitive data type from a file.

The following test reads the file using a DataInputStream:

@Test public void whenReadWithDataInputStream_thenCorrect() throws IOException { String expectedValue = "Hello, world!"; String file; 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. Reading with FileChannel

If we are reading a large file, FileChannel can be faster than standard IO.

The following code reads data bytes from the file using FileChannel and 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. Reading a UTF-8 Encoded File

Now, let's see how to read a UTF-8 encoded file using BufferedReader. In this example, we'll read a file that contains Chinese characters:

@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. Reading Content from URL

To read content from a URL, we will use “/” URL in our example as:

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

There are also alternative ways of connecting to a URL. Here we used the URL and URLConnection class available in the standard SDK.

12. Reading a File from a JAR

To read a file which is located inside a JAR file, we will need a JAR with a file inside it. For our example we will read “LICENSE.txt” from the “hamcrest-library-1.3.jar” file:

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

Here we want to load LICENSE.txt that resides in Hamcrest library, so we will use the Matcher's class that helps to get a resource. The same file can be loaded using the classloader too.

13. Conclusion

As you can see, there are many possibilities for loading a file and reading data from it using plain Java.

You can load a file from various locations like classpath, URL or jar files.

그런 다음 BufferedReader 를 사용 하여 한 줄씩 읽고 스캐너 를 사용하여 다른 구분 기호 를 읽고 StreamTokenizer 를 사용하여 파일을 토큰 으로 읽고 DataInputStream 을 사용하여 이진 데이터 및 기본 데이터 유형을 읽고 SequenceInput Stream 을 사용하여 여러 파일을 하나의 스트림으로 연결하고 FileChannel 을 사용하여 더 빠르게 읽을 수 있습니다. 대용량 파일 등에서

다음 GitHub 저장소에서 소스 코드를 찾을 수 있습니다.