#include <iostream>
#include <fstream>
#include <vector>
#include <chrono> // Időmérés teljesítmény-összehasonlításhoz (pl. írás/olvasás ideje)
#include <string>
#include <sstream>
#include <iomanip>
#include <cstdint> // Fix méretű típusok (int32_t, uint64_t), hordozhatóság és pontos méret biztosítása (beágyazott rendszerek)
#include <sys/stat.h> // stat() függvény: fájlméret lekérdezése a fajlmeret() segédfüggvényben
using namespace std;
using namespace chrono; // high_resolution_clock, duration_cast
struct Adat {
int id;
double ertek;
};
// --- Segédek ---
static long long fajlmeret(const string& fajlnev) { // hivatkozást adunk át, és nem módosítjuk.
struct stat st {}; // A <sys/stat.h> könyvtárban definiált stat struktúra,
// amely a fájl metaadatait (méret, jogosultságok, utolsó módosítás ideje stb.) tárolja
if ( stat(fajlnev.c_str(), &st) == 0 ) // st-be töltjük a metaadatokat, stat() fv-el, a pathből C-stílusú nullával lezárt karakterláncot
return (long long)st.st_size; // csinálunk, mert ez C-s függvény
// Ha a hívás sikeres, 0-t ad vissza, mi pedig visszaadjuk a méretet
return -1;
}
static pair<long long, long long> egyezes_ellenorzes(const vector<Adat>& v) {
long long sum_id = 0; // az összes id mező összege.
long long sum_valid_ertekek = 0; // az összes ertek mező összege,
// egészre skálázva (* 1'000'000),
for (const auto& x : v) { // megszokott range-based for hogy a lebegőpontos értékek összehasonlítása egyszerűbb legyen.
sum_id += x.id;
sum_valid_ertekek += (long long)(x.ertek * 1'000'000.0);
}
return { sum_id, sum_valid_ertekek };
}
static vector<Adat> generalas(size_t n) { // a függvény láthatósága csak a forrásfájlra korlátozódjon
vector<Adat> v(n);
for (size_t i = 0; i < n; ++i) v[i] =
{ (int)i, i * 0.666 }; // struct aggregate initialization: egyszerre ad értéket az id és ertek mezőknek.
return v;
}
// --- Bináris írás / olvasás ---
static long long binaris_iras(const string& path, const vector<Adat>& v) { // long long: az írás ideje MILLISZEKUNDUMBAN.
auto t1 = high_resolution_clock::now(); // időmérés kezdete: high_resolution_clock a lehető legnagyobb pontosságú órát használja a rendszerben.
ofstream f(path, ios::binary);
f.write( (char*)v.data(), // a vektor első elemére mutató nyers mutató (Adat*), ofstream::write byte-alapú írást vár
(long long)v.size() * (long long)sizeof(Adat) ); // a vektor elemeinek száma * egy Adat struktúra mérete byte-ban = a teljes adatblokk mérete byte-ban
f.close(); // Ez a hívás egyetlen lépésben kiírja a teljes vektort a fájlba, soronkénti feldolgozás nélkül → nagyon gyors.
auto t2 = high_resolution_clock::now();
return duration_cast<milliseconds>(t2 - t1).count(); // Kiszámolja a két időpont különbségét, duration_cast<milliseconds> → milliszekundumokra kerekítve adja vissza
} // .count() → a milliszekundum-értéket egész számmá konvertálja.
static long long binaris_olvasas(const string& path, vector<Adat>& out) {
auto t1 = high_resolution_clock::now();
ifstream f(path, ios::binary);
f.seekg(0, ios::end); // A fájl-olvasási mutatót a fájl végére állítja, tudjuk meg a fájl teljes hosszát.
long long bytes = (long long)f.tellg();
f.seekg(0, ios::beg); // Vissza az elejére
size_t darab = (size_t)(bytes / (long long)sizeof(Adat)); // Hány Adat struktúra fér a fájlba:?
out.resize(darab); // A vektor méretét beállítja, hogy pontosan ennyi Adat férjen bele.
if (darab > 0) // Ha van legalább 1 rekord, egyetlen read() hívással beolvassa az összeset.
f.read( (char*)out.data(), (long long)darab * (long long)sizeof(Adat) );
f.close();
auto t2 = high_resolution_clock::now();
return duration_cast<milliseconds>(t2 - t1).count();
}
// --- CSV írás / olvasás (szöveges összehasonlítás) ---
static long long csv_iras(const string& path, const vector<Adat>& v) {
auto t1 = high_resolution_clock::now();
ofstream f(path);
f << setprecision(17); // A lebegőpontos számok (double) kiírásának pontosságát 17 számjegyre állítja.
// Ez közel a double típus maximális jelentős számjegyeinek száma, így minimalizálódik a mentés-visszatöltés közbeni kerekítési hiba.
for (const auto& x : v)
f << x.id << "," << x.ertek << "\n"; // Egy sor: id,ertek formátumban kerül a fájlba (CSV – comma-separated values).
f.close();
auto t2 = high_resolution_clock::now();
return duration_cast<milliseconds>(t2 - t1).count();
}
static long long csv_olvasas(const string& path, vector<Adat>& out) {
auto t1 = high_resolution_clock::now();
ifstream f(path);
out.clear();
string line; // ide olvassuk soronként a fájl tartalmát.
out.reserve(1024); // előre lefoglal memóriát 1024 elemnek,
// így csökkentve az újrafoglalások miatti lassulást nagy adathalmaz esetén.
while (getline(f, line)) {
if (line.empty()) continue;
size_t c = line.find(',');
if (c == string::npos) continue; // Ha nincs benne vessző, a sor hibás, és átugorjuk.
int id = stoi(line.substr(0, c));
double ertek = stod(line.substr(c + 1));
out.push_back({ id, ertek });
}
f.close();
auto t2 = high_resolution_clock::now();
return duration_cast<milliseconds>(t2 - t1).count();
}
// --- Való élet: O(1) random hozzáférés egy rekordhoz (pl. telemetria napló) --- Miért O(1)? Nem kell végigolvasni a fájlt — egyetlen seekg és read művelet elég.
static bool bin_kiolvasas(const string& path, size_t index, Adat& ki) {
ifstream f(path, ios::binary);
if (!f) return false;
long long off = (long long)index * (long long)sizeof(Adat);
f.seekg(0, ios::end);
long long meret = (long long)f.tellg();
if (off < 0 || off + (long long)sizeof(Adat) > meret) return false; // Határvizsgálat, negatív pozíció nem lehet (gyakorlatban size_t miatt ez nem fordul elő).
// Ha a kért rekord túlmegy a fájl végén → hibás index → false.
f.seekg(off, ios::beg);
f.read((char*)&ki, sizeof(Adat));
return (bool)f;
}
/*
Használat a main-ben (vázlat):
auto v = generalas(1'000'000);
auto msWB = binaris_iras("adatok.bin", v);
vector<Adat> vb; auto msRB = binaris_olvasas("adatok.bin", vb);
auto msWT = csv_iras("adatok.csv", v);
vector<Adat> vt; auto msRT = csv_olvasas("adatok.csv", vt);
cout << "BIN írás/olvasás: " << msWB << " / " << msRB << " ms, méret: " << fajlmeret("adatok.bin") << " B\n";
cout << "CSV írás/olvasás: " << msWT << " / " << msRT << " ms, méret: " << fajlmeret("adatok.csv") << " B\n";
auto csB = egyezes_ellenorzes(vb), csT = egyezes_ellenorzes(vt);
cout << "egyezes_ellenorzes egyezés? " << (csB == csT ? "igen" : "nem") << "\n";
Adat rec{};
if (bin_kiolvasas("adatok.bin", 123456, rec))
cout << "Random rekord[123456]: id=" << rec.id << " ertek=" << rec.ertek << "\n";
*/