API do obsługiwania własnego formatu archiwów

0

Witajcie,

Ostatni wątek zachęcił mnie do odpalenia CLiona. Przyszedł problem, którego samodzielnie nie przeskoczę bo jest to dość skomplikowane. Musze napisać klasę FileStream, która może czytać lub pisać do/z pliku lub archiwum. Nie wiem jak to zrealizować, ponieważ z jednego archiwum może czytać kilka programów albo wątków. Da się w jednym momencie z kilku programów otworzyć plik przez fopen() w trybie rw? Co jesli jeden wątek zapisał by coś do archiwum, albo robił defragmentację, a pozostałe, które by czytały trafiały by do sektorów w archiwum, które zostały przed chwilą przeniesione. Wychodziły by jakieś śmieci. Istnieje coś jak std::mutex tylko na plik? Chcę dopuścić, żeby w jednym momencie programy mogły tylko czytać, a jak by jeden chciał zapisywać to nie mógł by otworzyć pliku i analogicznie jak by jeden pisał do plików to reszta nie mogła by otworzyć, żeby czytać. Nie wiem jak jest to na różnych systemach, interesuje mnie Win, Linux i OS X. W sumie to nie tyczy się tylko archiwów, ale ogólnie wszystkich plików możliwych do otwierania przez moją klasę.

PS. Albo źródło gdzie to można znaleźć.

0

Da się w jednym momencie z kilku programów otworzyć plik przez fopen() w trybie rw?

"rw" to raczej zły pomysł, bo nawet gdyby się dało to oprogramowanie tego będzie koszmarem (co jeśli jeden program chce rozpakować plik a drugi w tym czasie go kasuje?) ale w trybie "r" na pewno się da - a przecież nie każda operacja wiąże się z zapisem.
i tak to zwykle działa: zapis jest na wyłączność, i blokuje dostęp do pliku, a odczyt jest swobodny.
o to się system operacyjny martwi.

0

Troche lipa. Napisalem krotkie programy do testu na Linuchu i nie jest jak bym chciał. src:

 #include <fstream>
#include <iostream>
using namespace std;


int main()
{
    fstream in("file.txt", ios::in | ios::out);
    
    if(!in.is_open())
    {
        cout << "Plik nie może być otwarty w trybie rw" << endl;
        return 1;
    }
    
    cout << "Plik otwarty w trybie rw" << endl;
    in << ".test.";
    cout << "Wpisano tekst" << endl;
    
    while(1){}

    return 0;
}

/* Drugi plik */

#include <fstream>
#include <iostream>
using namespace std;


int main()
{
    fstream in("file.txt", ios::in);
    
    if(!in.is_open())
    {
        cout << "Plik nie może być otwarty w trybie r" << endl;
        return 1;
    }
    
    cout << "Plik otwarty w trybie r" << endl;
    cout << in << endl;

    return 0;
}

Uruchomiłem w jednym momencie nawet dwa programy z odczytem "rw", które zloopowały się. W kolejnym terminalu uruchamialem kilka razy ./r i normalnie czytał z pliku. Wiadomo jakies smieci z poczatku klasy bo niewczytalem tego << do stringa tylko na ofstream od razu, ale plik się otworzył.

0
bajos napisał(a):

Chcę dopuścić, żeby w jednym momencie programy mogły tylko czytać, a jak by jeden chciał zapisywać to nie mógł by otworzyć pliku i analogicznie jak by jeden pisał do plików to reszta nie mogła by otworzyć, żeby czytać. Nie wiem jak jest to na różnych systemach, interesuje mnie Win, Linux i OS X. W sumie to nie tyczy się tylko archiwów, ale ogólnie wszystkich plików możliwych do otwierania przez moją klasę.

http://en.cppreference.com/w/cpp/thread/shared_mutex ( C++17, ale jest również w boost'cie )

1

Interesują Cię wywołania:
....na GNU/Linux:

man 2 flock
man 2 fcntl
man 3 lockf

Tymi wywołaniami zablokujesz cały plik i/lub tylko jego część od/do określonego bajtu. Dodatkowo masz 2 typy blokad. Na wyłączność i uznaniową.

To samo dla MS Windows https://msdn.microsoft.com/pl-pl/library/windows/desktop/aa365204(v=vs.85).aspx

Ja bym jednak przemyślał problem. Lepiej (chyba) jest mieć częściowo rozpakowaną strukturę (choćby lokalnie dla zakresu wywołań) i na żądanie zwracać w pełni spakowane archiwum (poza tym że archiwizacja to nie kompresja).

1 użytkowników online, w tym zalogowanych: 0, gości: 1