HOWTO · C++
C++에서 파일에 쓰는 방법
이 기사에서는 C++로 파일에 쓰는 방법을 보여줍니다. 파일 스트림과 다양한 파일 모드를 알아보고, C++ 프로그램에서 파일 작업을 효과적으로 관리하기 위한 명확한 예제를 확인하세요. 데이터를 추가해야 하든 기존 내용을 덮어써야 하든, 이 가이드가 도움이 될 것입니다.
이 페이지의 내용
일반 텍스트를 파일에 쓰려면 std::ofstream과 삽입 연산자(<<)를 사용합니다. 파일 끝에 데이터를 추가하려면 std::ios::app으로 열고, 기존 내용을 바꾸려면 std::ios::trunc을 사용합니다. 쓸 문자나 바이트 수가 정해져 있다면 스트림의 write 멤버 함수를 사용할 수 있으며, C 스타일의 대안은 fwrite입니다.
C++의 파일 스트림 이해하기
파일 스트림은 C++ 프로그램과 이름이 지정된 파일을 연결합니다. <fstream>을 포함하고 출력에는 std::ofstream을 만드세요. 같은 스트림에서 입력과 출력을 모두 해야 한다면 std::fstream을 사용합니다. 삽입 연산자는 서식이 있는 텍스트를 쓰기에 편리하며, 문자열에 줄바꿈 문자를 넣으면 파일에서 다음 줄이 시작됩니다. 경로가 올바르게 보여도 파일에 접근할 수 없거나 저장 공간을 사용할 수 없을 수 있으므로 파일을 연 뒤와 쓴 뒤에 스트림 상태를 확인하세요.
다음 예제를 실행해 보세요.
#include <fstream>
#include <iostream>
int main() {
std::ofstream file("example.txt");
if (!file) {
std::cerr << "Could not open example.txt\n";
return 1;
}
file << "Hello, C++!\n";
file << "File output is ready.\n";
file.close();
if (!file) {
std::cerr << "Could not finish writing example.txt\n";
return 1;
}
std::cout << "Wrote example.txt\n";
return 0;
}
Wrote example.txt
메시지는 콘솔에 출력되고, file을 통해 쓴 두 줄은 example.txt에 저장됩니다. 텍스트 편집기로 파일을 열어 내용을 확인하세요. 기본 출력 전용 std::ofstream은 상위 디렉터리가 존재하면 파일을 만들며, 파일을 열 때 기존 내용은 일반적으로 지웁니다.
파일을 여러 모드로 쓰기
열기 모드는 기존 데이터가 어떻게 처리되는지를 결정합니다. std::ios::app은 쓸 때마다 파일 끝에 위치시키므로 로그나 계속 누적해야 하는 기록에 유용합니다. 파일이 없더라도 경로와 권한이 허용하면 출력을 위해 열 때 새 파일을 만들 수 있습니다. 다음 독립 예제는 추가 모드로 한 줄을 씁니다. 기존 example.txt가 없어도 됩니다.
#include <fstream>
#include <iostream>
int main() {
std::ofstream file("example.txt", std::ios::app);
if (!file) {
std::cerr << "Could not open example.txt\n";
return 1;
}
file << "A new log entry\n";
file.close();
if (!file) {
std::cerr << "Could not finish writing example.txt\n";
return 1;
}
return 0;
}
제공된 런타임 사례는 성공적으로 완료되었으며 콘솔 출력은 없었습니다. 코드는 A new log entry 뒤에 줄바꿈 문자를 씁니다. 파일에 기존 데이터가 있으면 새 줄은 그 뒤에 추가됩니다.
ios::trunc으로 파일 쓰기 및 덮어쓰기
std::ios::trunc은 파일을 열 때 기존 내용을 버립니다. std::ios::app 없이 출력을 위해 std::ofstream을 열어도 일반적으로 같은 방식으로 기존 내용이 잘립니다. 이 동작을 명시하려면 std::ios::trunc을 지정하세요. 이전 데이터를 유지해야 한다면 두 방식 모두 사용하지 마세요.
#include <fstream>
#include <iostream>
int main() {
std::ofstream file("example.txt", std::ios::trunc);
if (!file) {
std::cerr << "Could not open example.txt\n";
return 1;
}
file << "Current report\n";
file.close();
if (!file) {
std::cerr << "Could not finish writing example.txt\n";
return 1;
}
return 0;
}
제공된 런타임 사례는 성공적으로 완료되었으며 콘솔 출력은 없었습니다. 코드는 example.txt에 Current report와 줄바꿈 문자만 씁니다. 따라서 기존 내용은 모두 대체됩니다.
fstream::write로 파일에 쓰기
데이터가 문자 버퍼에 있고 그 길이를 알고 있다면 스트림 멤버 함수 write를 사용하세요. 이 함수에는 문자 포인터와 쓸 문자 수를 전달합니다. 함수가 문자열 끝 표시 문자나 줄바꿈을 자동으로 추가하지는 않습니다. 전달하는 값은 스트림 크기이므로 data.size()를 넘기면 끝의 널 문자는 포함하지 않고 문자열에 저장된 문자만 씁니다. 쓰기에 실패했는지 확인하려면 호출 후 스트림 상태를 점검하세요. 인터페이스는 cppreference의 basic_ostream::write 문서를 참고하세요.
#include <fstream>
#include <iostream>
#include <string>
int main() {
const std::string data = "C++ buffer data\n";
std::fstream file("buffer.txt", std::ios::out | std::ios::trunc);
if (!file) {
std::cerr << "Could not open buffer.txt\n";
return 1;
}
file.write(data.data(), static_cast<std::streamsize>(data.size()));
if (!file) {
std::cerr << "Could not write buffer.txt\n";
return 1;
}
file.close();
if (!file) {
std::cerr << "Could not finish writing buffer.txt\n";
return 1;
}
return 0;
}
제공된 런타임 사례는 성공적으로 완료되었으며 콘솔 출력은 없었습니다. 코드는 data의 문자를 buffer.txt에 씁니다. 줄바꿈은 문자열에 포함되어 있지만 끝의 널 문자는 쓰이지 않습니다.
문자 쓰기와 바이트 쓰기는 데이터가 서식화되는지 여부에서 다릅니다. 삽입 연산자는 값을 텍스트로 변환하지만, write와 fwrite는 버퍼의 바이트를 서식화하지 않고 그대로 복사합니다. 다만 바이트를 복사하는 것만으로는 파일에 변경 없이 도달한다는 보장이 되지 않습니다. 텍스트 모드로 연 스트림은 줄 끝 표기가 다른 플랫폼에서 개행 문자를 변환할 수 있습니다. 예를 들어 Windows는 출력 시 \n을 \r\n으로 변환합니다. 정확한 바이트가 중요하다면 std::ios::out | std::ios::binary | std::ios::trunc와 같이 스트림을 바이너리 모드로 열거나, fopen에 "w" 대신 "wb"를 전달하여 변환이 일어나지 않게 하세요.
C의 fwrite 함수로 파일에 쓰기
C 스타일 파일 입출력에서 fwrite에는 포인터, 요소 크기, 요소 개수, FILE*을 전달합니다. 반환값은 쓴 바이트 수가 아니라 쓴 요소 수입니다. 요소 크기가 1인 경우에만 두 값이 같습니다. 반환된 개수를 확인한 다음 파일을 닫고 fclose의 반환값도 확인하세요. 버퍼에 남아 있던 쓰기 오류가 닫는 과정에서 드러날 수 있습니다.
#include <cstdio>
#include <cstring>
#include <iostream>
int main() {
const char data[] = "C file output\n";
const std::size_t size = std::strlen(data);
std::FILE* file = std::fopen("c-output.txt", "w");
if (file == nullptr) {
std::cerr << "Could not open c-output.txt\n";
return 1;
}
const std::size_t written = std::fwrite(data, 1, size, file);
const int close_status = std::fclose(file);
if (written != size || close_status != 0) {
std::cerr << "Could not finish writing c-output.txt\n";
return 1;
}
return 0;
}
제공된 런타임 사례는 성공적으로 완료되었으며 콘솔 출력은 없었습니다. 코드는 줄바꿈을 포함한 data의 문자를 c-output.txt에 씁니다. "w" 모드는 파일을 만들거나 기존 내용을 잘라냅니다.
결론
일반 텍스트에는 std::ofstream과 <<를 사용하세요. 기존 내용을 유지하면서 끝에 추가하려면 std::ios::app을, 기존 내용을 바꾸려면 std::ios::trunc을 선택합니다. 길이를 아는 버퍼에는 write를 사용하고, C 스타일 입출력 작업에는 fwrite를 사용하세요. 파일을 연 뒤와 쓴 뒤에 상태를 확인하고, 데이터가 완전히 기록되었는지 알아야 한다면 닫을 때 발생하는 오류도 확인하세요.
FAQ
-
파일이 열렸는지 어떻게 확인하나요? 스트림을 직접 확인하거나(
if (!file)) 파일을 연 직후is_open()을 호출하세요. 쓰기 전에 실패를 처리해야 합니다. -
기존 내용을 바꾸지 않고 파일 끝에 추가하려면 어떻게 하나요? 출력 스트림을
std::ios::app으로 여세요. 쓰는 내용은 매번 파일 끝에 추가됩니다. -
C++에서 존재하지 않는 파일을 만들 수 있나요? 출력 스트림이나
"w"모드의fopen은 상위 디렉터리가 있고 프로세스에 권한이 있으면 파일을 만들 수 있습니다. 상위 디렉터리가 없거나 권한이 부족하면 파일 열기에 실패합니다. -
여러 줄은 어떻게 쓰나요?
<<로 줄바꿈 문자를 삽입하거나write에 전달하는 버퍼에 줄바꿈 문자를 포함하세요.write와fwrite는 줄 끝 문자를 자동으로 추가하지 않습니다. -
파일을 닫아야 하나요? 파일 스트림은 소멸할 때 닫히지만, 완료 시점을 명확히 하려면
close()를 직접 호출할 수 있습니다. 쓰기 완료 여부가 중요하다면 닫은 뒤 스트림 상태를 확인하세요. C의FILE*은fclose를 호출하고 반환값을 확인해야 합니다.