Java

파일 출력

1space 2025. 7. 18. 15:48

자바에서 fos.write('A'); 한 줄의 흐름

우리가 단순히 fos.write('A')라고 작성하면, 내부적으로는 아래와 같은 복잡한 과정을 거쳐 디스크에 저장됩니다.

 

1단계: 문자 → 코드 변환 (Encoding)

fos.write('A');

여기서 'A'는 문자입니다.

  • 자바 내부에서는 이 문자를 UTF-8 / UTF-16 / UTF-32 등으로 인코딩합니다.
  • 'A'는 UTF-8에서 0x41, 즉 65번입니다.
  • 인코딩에 따라 바이트 수가 달라질 수 있습니다:
    • ASCII / UTF-8: 1바이트
    • UTF-16: 2바이트
    • UTF-32: 4바이트

2단계: BOM 및 Endian 결정

문자를 바이트로 변환할 때, 문자열의 바이트 순서를 정하는 문제가 있습니다.

  • BOM(Byte Order Mark): 인코딩 방식 표시
  • Endian:
    • Big-endian: 상위 바이트부터 저장
    • Little-endian: 하위 바이트부터 저장

일반 텍스트 파일에는 BOM이 없지만, 특정 포맷에서는 매우 중요합니다 (예: UTF-16 파일 저장 시).

3단계: 스트림과 버퍼 처리

자바에서 FileOutputStream을 사용할 때 내부적으로 버퍼(buffer)가 동작합니다.

  • 데이터를 바로 하드디스크에 쓰지 않고, 버퍼에 임시 저장합니다.
  • 일정 크기만큼 쌓이면 flush() 또는 close()를 통해 실제 디스크로 전송됩니다.

4단계: 객체 참조와 호출 구조

fos.write('A')에서 fos는 FileOutputStream 객체입니다.

  • 이 객체는 내부적으로 OS에 등록된 파일 디스크립터(file descriptor)를 가지고 있고,
  • .write() 메서드는 결국 OS의 시스템 호출(System Call)로 이어집니다.

 

Java Platform → OS → 장치 Driver 흐름

이제 자바 플랫폼은 내부적으로 OS에 write 요청을 전달합니다.

  1. Java Platform:
    • write() / flush() 호출
  2. OS API (Kernel 호출):
    • write(fd, ..) 형식의 시스템 호출
    • fflush(stdout) 등으로 출력 버퍼 비우기도 포함
  3. 장치 드라이버(Device Driver):
    • 실제 디스크에 데이터를 쓰는 저수준 동작 처리

 

하드디스크에 기록되는 실제 정보

디스크에 데이터를 쓸 때는 아래와 같은 세부 정보까지 고려됩니다:

- 어떤 플래터에?         → 01001010010010101
- 어떤 트랙에?           → 01001101010010010
- 어떤 섹션에?           → 11011000101001010
- 어떤 옵셋에?           → 11011010100010001

즉, 단순히 ‘A’ 하나를 쓰더라도, 디스크 입장에서는

  • 플래터(원판),
  • 트랙(원형 경로),
  • 섹터(트랙을 나눈 조각),
  • 옵셋(위치 세부 조정)까지 계산되어야 합니다.

 

요약: fos.write('A')는 다음과 같은 단계로 실행됩니다

  1. 'A'라는 문자가 UTF-8/16/32로 변환됨 (문자 인코딩)
  2. BOM 또는 Endian 방식 고려 (바이트 순서)
  3. 버퍼에 저장됨 (스트림 처리)
  4. write()로 OS 호출 (객체 → OS API)
  5. OS는 장치 드라이버 호출 (System Call)
  6. 하드디스크 위치 계산 후 기록 (물리적 저장)