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 요청을 전달합니다.
- Java Platform:
- write() / flush() 호출
- OS API (Kernel 호출):
- write(fd, ..) 형식의 시스템 호출
- fflush(stdout) 등으로 출력 버퍼 비우기도 포함
- 장치 드라이버(Device Driver):
- 실제 디스크에 데이터를 쓰는 저수준 동작 처리
하드디스크에 기록되는 실제 정보
디스크에 데이터를 쓸 때는 아래와 같은 세부 정보까지 고려됩니다:
- 어떤 플래터에? → 01001010010010101
- 어떤 트랙에? → 01001101010010010
- 어떤 섹션에? → 11011000101001010
- 어떤 옵셋에? → 11011010100010001
즉, 단순히 ‘A’ 하나를 쓰더라도, 디스크 입장에서는
- 플래터(원판),
- 트랙(원형 경로),
- 섹터(트랙을 나눈 조각),
- 옵셋(위치 세부 조정)까지 계산되어야 합니다.
요약: fos.write('A')는 다음과 같은 단계로 실행됩니다
- 'A'라는 문자가 UTF-8/16/32로 변환됨 (문자 인코딩)
- BOM 또는 Endian 방식 고려 (바이트 순서)
- 버퍼에 저장됨 (스트림 처리)
- write()로 OS 호출 (객체 → OS API)
- OS는 장치 드라이버 호출 (System Call)
- 하드디스크 위치 계산 후 기록 (물리적 저장)