Java – 파일에 쓰기

1. 개요

이 자습서에서는 Java를 사용하여 파일에 쓰는 다양한 방법을 살펴 봅니다. 우리는 사용 할 수 있습니다 BufferedWriter의 , 의 PrintWriter , FileOutputStream에 , DataOutputStream 정렬 , RandomAccessFile의 , 되는 FileChannel, 그리고 자바 7 파일 유틸리티 클래스를.

또한 파일을 쓰는 동안 파일을 잠그는 방법을 살펴보고 파일 쓰기에 대한 몇 가지 최종 사항에 대해 논의 할 것입니다.

이 튜토리얼은 Baeldung에 대한 Java "Back to Basics"시리즈의 일부입니다.

2. BufferedWriter로 쓰기

간단하게 시작 하고 BufferedWriter 를 사용 하여 새 파일에 문자열 을 작성해 보겠습니다 .

public void whenWriteStringUsingBufferedWritter_thenCorrect() throws IOException { String str = "Hello"; BufferedWriter writer = new BufferedWriter(new FileWriter(fileName)); writer.write(str); writer.close(); }

파일의 출력은 다음과 같습니다.

Hello

그런 다음 기존 파일에 문자열추가 할 수 있습니다 .

@Test public void whenAppendStringUsingBufferedWritter_thenOldContentShouldExistToo() throws IOException { String str = "World"; BufferedWriter writer = new BufferedWriter(new FileWriter(fileName, true)); writer.append(' '); writer.append(str); writer.close(); }

그러면 파일은 다음과 같습니다.

Hello World

3. PrintWriter로 쓰기

다음으로 PrintWriter사용 하여 형식화 된 텍스트를 파일에 쓰는 방법 살펴 보겠습니다 .

@Test public void givenWritingStringToFile_whenUsingPrintWriter_thenCorrect() throws IOException { FileWriter fileWriter = new FileWriter(fileName); PrintWriter printWriter = new PrintWriter(fileWriter); printWriter.print("Some String"); printWriter.printf("Product name is %s and its price is %d $", "iPhone", 1000); printWriter.close(); }

결과 파일에는 다음이 포함됩니다.

Some String Product name is iPhone and its price is 1000$

원시 문자열 을 파일에 기록 할 뿐만 아니라 printf 메서드를 사용하여 서식이 지정된 텍스트도 작성하는 방법에 유의하십시오 .

FileWriter , BufferedWriter 또는 System.out을 사용하여 작성기를 만들 수 있습니다 .

4. FileOutputStream으로 쓰기

이제 FileOutputStream 을 사용 하여 바이너리 데이터를 파일쓰는 방법을 살펴 보겠습니다 .

다음 코드는 String 을 바이트 로 변환하고 FileOutputStream을 사용하여 바이트를 파일에 씁니다 .

@Test public void givenWritingStringToFile_whenUsingFileOutputStream_thenCorrect() throws IOException { String str = "Hello"; FileOutputStream outputStream = new FileOutputStream(fileName); byte[] strToBytes = str.getBytes(); outputStream.write(strToBytes); outputStream.close(); }

물론 파일의 출력은 다음과 같습니다.

Hello

5. DataOutputStream으로 쓰기

다음으로 DataOutputStream 을 사용 하여 문자열 을 파일 에 쓰는 방법을 살펴 보겠습니다 .

@Test public void givenWritingToFile_whenUsingDataOutputStream_thenCorrect() throws IOException { String value = "Hello"; FileOutputStream fos = new FileOutputStream(fileName); DataOutputStream outStream = new DataOutputStream(new BufferedOutputStream(fos)); outStream.writeUTF(value); outStream.close(); // verify the results String result; FileInputStream fis = new FileInputStream(fileName); DataInputStream reader = new DataInputStream(fis); result = reader.readUTF(); reader.close(); assertEquals(value, result); }

6. RandomAccessFile로 쓰기

이제 완전히 새로운 파일에 쓰거나 기존 파일에 추가 하는 대신 기존 파일 내 에서 쓰고 편집 하는 방법을 설명하겠습니다 . 간단히 말해, 랜덤 액세스가 필요합니다.

RandomAccessFile을 사용하면 오프셋 (파일 시작부터)이 주어진 파일의 특정 위치에 바이트 단위로 쓸 수 있습니다.

이 코드는 파일의 시작 부분에서 주어진 오프셋으로 정수 값을 씁니다.

private void writeToPosition(String filename, int data, long position) throws IOException { RandomAccessFile writer = new RandomAccessFile(filename, "rw"); writer.seek(position); writer.writeInt(data); writer.close(); }

특정 위치에 저장된 int읽으 려면 다음 메서드를 사용할 수 있습니다.

private int readFromPosition(String filename, long position) throws IOException { int result = 0; RandomAccessFile reader = new RandomAccessFile(filename, "r"); reader.seek(position); result = reader.readInt(); reader.close(); return result; }

함수를 테스트하기 위해 정수를 작성하고 편집 한 다음 마지막으로 다시 읽어 보겠습니다.

@Test public void whenWritingToSpecificPositionInFile_thenCorrect() throws IOException { int data1 = 2014; int data2 = 1500; writeToPosition(fileName, data1, 4); assertEquals(data1, readFromPosition(fileName, 4)); writeToPosition(fileName2, data2, 4); assertEquals(data2, readFromPosition(fileName, 4)); }

7. FileChannel로 쓰기

대용량 파일을 처리하는 경우 FileChannel 이 표준 IO보다 빠를 수 있습니다. 다음 코드는 FileChannel을 사용하여 파일에 String 을 씁니다 .

@Test public void givenWritingToFile_whenUsingFileChannel_thenCorrect() throws IOException { RandomAccessFile stream = new RandomAccessFile(fileName, "rw"); FileChannel channel = stream.getChannel(); String value = "Hello"; byte[] strBytes = value.getBytes(); ByteBuffer buffer = ByteBuffer.allocate(strBytes.length); buffer.put(strBytes); buffer.flip(); channel.write(buffer); stream.close(); channel.close(); // verify RandomAccessFile reader = new RandomAccessFile(fileName, "r"); assertEquals(value, reader.readLine()); reader.close(); }

8. 파일 클래스로 쓰기

Java 7은 새로운 유틸리티 클래스 인 Files 와 함께 파일 시스템으로 작업하는 새로운 방법을 도입했습니다 .

Files 클래스를 사용하여 파일과 디렉토리를 생성, 이동, 복사 및 삭제할 수 있습니다. 파일을 읽고 쓰는데도 사용할 수 있습니다.

@Test public void givenUsingJava7_whenWritingToFile_thenCorrect() throws IOException { String str = "Hello"; Path path = Paths.get(fileName); byte[] strToBytes = str.getBytes(); Files.write(path, strToBytes); String read = Files.readAllLines(path).get(0); assertEquals(str, read); }

9. 임시 파일에 쓰기

이제 임시 파일에 쓰겠습니다. 다음 코드는 임시 파일을 만들고 여기에 문자열 을 씁니다 .

@Test public void whenWriteToTmpFile_thenCorrect() throws IOException { String toWrite = "Hello"; File tmpFile = File.createTempFile("test", ".tmp"); FileWriter writer = new FileWriter(tmpFile); writer.write(toWrite); writer.close(); BufferedReader reader = new BufferedReader(new FileReader(tmpFile)); assertEquals(toWrite, reader.readLine()); reader.close(); }

보시다시피 흥미롭고 다른 것은 임시 파일의 생성 일뿐입니다. 그 후 파일 쓰기는 동일합니다.

10. 쓰기 전에 파일 잠금

마지막으로 파일에 쓸 때 다른 사람이 동시에 해당 파일에 쓰지 않도록 추가로 확인해야하는 경우가 있습니다. 기본적으로 작성하는 동안 해당 파일을 잠글 수 있어야합니다.

Let's make use of FileChannel to try locking the file before writing to it:

@Test public void whenTryToLockFile_thenItShouldBeLocked() throws IOException { RandomAccessFile stream = new RandomAccessFile(fileName, "rw"); FileChannel channel = stream.getChannel(); FileLock lock = null; try { lock = channel.tryLock(); } catch (final OverlappingFileLockException e) { stream.close(); channel.close(); } stream.writeChars("test lock"); lock.release(); stream.close(); channel.close(); }

Note that if the file is already locked when we try to acquire the lock, an OverlappingFileLockException will be thrown.

11. Notes

After exploring so many methods of writing to a file, let's discuss some important notes:

  • If we try to read from a file that doesn't exist, a FileNotFoundException will be thrown.
  • If we try to write to a file that doesn't exist, the file will be created first and no exception will be thrown.
  • It is very important to close the stream after using it, as it is not closed implicitly, to release any resources associated with it.
  • In output stream, the close() method calls flush() before releasing the resources, which forces any buffered bytes to be written to the stream.

Looking at the common usage practices, we can see, for example, that PrintWriter is used to write formatted text, FileOutputStream to write binary data, DataOutputStream to write primitive data types, RandomAccessFile to write to a specific position, and FileChannel to write faster in larger files. Some of the APIs of these classes do allow more, but this is a good place to start.

12. Conclusion

This article illustrated the many options of writing data to a file using Java.

이 모든 예제 및 코드 조각의 구현은 GitHub에서 찾을 수 있습니다.