C++ liest und schreibt über Streams: std::cin/std::cout für die Konsole, std::ifstream/std::ofstream für Dateien, std::istringstream/std::ostringstream für Strings. Alle benutzen dieselben Operatoren << und >>.
#include <iostream>
#include <fstream>
#include <string>
#include <filesystem>
int main() {
namespace fs = std::filesystem;
const std::string pfad = "notiz.txt";
{
std::ofstream aus(pfad); // schreiben; Datei wird beim Blockende geschlossen (RAII)
if (!aus) { std::cerr << "kann nicht schreiben\n"; return 1; }
aus << "Zeile 1\n" << "Zeile " << 2 << '\n';
}
{
std::ofstream anhang(pfad, std::ios::app); // anhängen
anhang << "Zeile 3\n";
}
std::ifstream ein(pfad);
if (!ein) { std::cerr << "kann nicht lesen\n"; return 1; }
std::string zeile;
int nr = 0;
while (std::getline(ein, zeile)) std::cout << ++nr << ": " << zeile << '\n';
std::cout << fs::exists(pfad) << ' ' << fs::file_size(pfad) << " Bytes\n";
fs::remove(pfad);
std::ifstream fehlt("gibt-es-nicht.txt");
std::cout << (fehlt.is_open() ? "offen" : "nicht gefunden") << '\n';
return 0;
}Ausgabe
1: Zeile 1 2: Zeile 2 3: Zeile 3 1 24 Bytes nicht gefunden
Dateien werden beim Zerstören des Streams automatisch geschlossen. Prüfe nach dem Öffnen mit if (!stream).
Ganze Datei einlesen
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <iterator>
int main() {
std::ofstream("daten.csv") << "name;alter\nMia;17\nTom;19\nZoe;21\n";
std::ifstream f("daten.csv");
std::stringstream puffer;
puffer << f.rdbuf(); // alles auf einmal
std::string inhalt = puffer.str();
std::cout << inhalt.size() << " Zeichen\n";
f.clear(); f.seekg(0);
std::string kopf; std::getline(f, kopf); // Kopfzeile überspringen
int summe = 0;
std::string zeile;
while (std::getline(f, zeile)) {
std::istringstream zeilenstrom(zeile);
std::string name, alterText;
std::getline(zeilenstrom, name, ';'); // bis zum Trennzeichen
std::getline(zeilenstrom, alterText);
summe += std::stoi(alterText);
}
std::cout << "Summe der Alter: " << summe << '\n';
std::remove("daten.csv");
return 0;
}Ausgabe
32 Zeichen Summe der Alter: 57
Binärdaten
#include <iostream>
#include <fstream>
#include <vector>
int main() {
std::vector<int> z{1, 2, 3, 4, 5};
{
std::ofstream aus("zahlen.bin", std::ios::binary);
aus.write(reinterpret_cast<const char*>(z.data()), static_cast<std::streamsize>(z.size() * sizeof(int)));
}
std::vector<int> neu(5);
std::ifstream ein("zahlen.bin", std::ios::binary);
ein.read(reinterpret_cast<char*>(neu.data()), static_cast<std::streamsize>(neu.size() * sizeof(int)));
std::cout << neu[0] << neu[4] << ' ' << ein.gcount() << " Bytes\n";
std::remove("zahlen.bin");
return 0;
}Ausgabe
15 20 Bytes
Formatieren der Ausgabe
#include <iostream>
#include <iomanip>
#include <format>
int main() {
double pi = 3.14159265;
std::cout << std::fixed << std::setprecision(2) << pi << '\n';
std::cout << std::setw(8) << std::setfill('.') << 42 << '|' << std::left << std::setw(6) << 7 << "|\n";
std::cout << std::hex << 255 << ' ' << std::dec << 255 << ' ' << std::scientific << 12345.678 << '\n';
std::cout << std::format("{:>8.3f}|{:08b}|{:#x}\n", pi, 37, 255);
return 0;
}Ausgabe
3.14 ......42|7.....| ff 255 1.23e+04 3.142|00100101|0xff
Die Manipulatoren (std::setw, std::fixed ...) wirken teils dauerhaft auf den Stream. std::format (C++20) ist handlicher und sicher.
std::filesystem
#include <iostream>
#include <filesystem>
#include <fstream>
#include <vector>
#include <algorithm>
namespace fs = std::filesystem;
int main() {
fs::path wurzel = fs::temp_directory_path() / "kurs_demo"; // / setzt Pfade zusammen
fs::create_directories(wurzel / "unter");
std::ofstream(wurzel / "a.txt") << "eins";
std::ofstream(wurzel / "unter" / "b.txt") << "zweiundzwanzig";
std::vector<std::string> namen;
for (const auto& eintrag : fs::recursive_directory_iterator(wurzel))
if (eintrag.is_regular_file())
namen.push_back(fs::relative(eintrag.path(), wurzel).generic_string() + " (" + std::to_string(eintrag.file_size()) + ")");
std::sort(namen.begin(), namen.end());
for (const auto& n : namen) std::cout << n << '\n';
fs::path p = "/a/b/bild.png";
std::cout << p.filename() << ' ' << p.extension() << ' ' << p.stem() << ' ' << p.parent_path() << '\n';
fs::remove_all(wurzel);
std::cout << fs::exists(wurzel) << '\n';
return 0;
}Ausgabe
a.txt (4) unter/b.txt (14) "bild.png" ".png" "bild" "/a/b" 0
Merke
- Streams:
ifstream(lesen),ofstream(schreiben),stringstream(Strings), alle mit<</>> - RAII schließt Dateien automatisch; Öffnen mit
if (!stream)prüfen - Zeilenweise:
std::getline; Trennzeichen:std::getline(s, teil, ';') - Binär:
std::ios::binary,write,read - Formatieren mit
<iomanip>oder besserstd::format std::filesystemfür Pfade, Ordner, Größen
Aufgabe
Lies eine Textdatei zeilenweise, zähle Zeilen und Wörter und schreibe die Statistik in eine zweite Datei.