2012-02-22 7 views
7

Pracuję z niektórych starszych kod, który wykorzystuje mniej więcej tak:Utwórz mapę strukturalną PLIKU * do bufora?

void store_data(FILE *file); 

Jednak nie chcę, aby zapisać dane na dysku, chcę zapisać go w pamięci (char *buf). Mógłbym edytować cały kod, ale kod przeskakuje w każdym miejscu i fwrite zostaje wywołany w pliku w całym miejscu. Czy istnieje prostszy sposób, na przykład, że mogę zmapować obiekt FILE* do bufora (automatycznie rosnącego)? Nie wiem, całkowity rozmiar danych przed ręką.

Rozwiązanie musi być przenośne.

Odpowiedz

5

Nie można tego zrobić, korzystając wyłącznie z udogodnień dostępnych w standardzie C. Najbliższy można przyjść jest

FILE *scratch = tmpfile(); 
... 
store_data(scratch); 
... 
/* after you're completely done calling the legacy code */ 
rewind(scratch); 
buf = read_into_memory_buffer(scratch); 
fclose(scratch); 

ten ma trafić na dysku, przynajmniej potencjalnie, ale powiedziałbym, że jest to najlepiej jeśli trzeba szeroki przenośność i nie można zmodyfikować kod „starszego”.

W POSIX.1-2008 jest open_memstream, który robi dokładnie to, co chcesz; jednak ta wersja POSIX nie jest jeszcze powszechnie przyjęta. GNU libc (używane w Linuksie i kilku innych) ma to, ale nie jest dostępne na OSX lub * BSD, o ile wiem, a na pewno nie na Windows.

+0

Czy rury mogą być opcją? – orlp

+0

Rury również nie są w standardzie C. Na Unixie, tak, możesz mieć pętlę potoku z powrotem do innego wątku w tym samym procesie, który napisał do bufora pamięci. W systemie Windows teoretycznie można zrobić to samo, ale spodziewałbym się, że będzie to źródło niekończącego się żalu, a nawet na Uniksie uderza mnie to za dużo pracy, ponieważ nie ma większego pożytku z podejścia 'tmpfile'. – zwol

1

Możesz chcieć spojrzeć na fmemopen i open_memstream. Robią coś w kierunku tego, co chcesz.

Od strony man:

open_memstream() funkcja otwiera strumień do zapisu do bufora. Bufor przydzielany jest dynamicznie (jak w malloc (3)), a automati- cally rośnie odpowiednio do potrzeb. Po zamknięciu strumienia wywołujący powinien zwolnić (3) ten bufor.

+1

Zgodnie ze stroną man w moim systemie, funkcje te są zgodne z "POSIX.1-2008" Te funkcje nie są określone w POSIX.1-2001 i nie są szeroko dostępne w innych systemach. " –

+0

@DanFego: Prawda. – Florian

1

Nie wiem, czy to jest pomysł dobry, ale to pomysł.

Możesz "przedefiniować" fwrite używając makra.

#define fwrite(a, b, c) your_memory_write_function(a, b, c) 

Następnie wdrożyć memory_write_function do zapisu danych do automatycznego rosnącym buforem zamiast pliku.

Będziesz musiał zadzwonić pod numer store_data za pomocą wskaźnika do czegoś innego (nie jest to wskaźnik do FILE). Ale jest to możliwe z C, więc nie będziesz mieć żadnych problemów.

0

Możesz zajrzeć do fmemopen(). Jeśli to nie jest dla ciebie dostępne, możesz ewentualnie użyć nazwanego segmentu pamięci wspólnej wraz z fdopen(), aby przekonwertować deskryptor pliku zwrócony przez shm_open() na FILE*.

+0

'fmemopen' nie powoduje automatycznej zmiany rozmiaru bufora pamięci podczas zapisu, więc nie spełnia wymagań PO. – zwol

0

Na jakiej platformie pracujesz? Nie możesz użyć tmpfs? Jeśli otworzysz plik na tmpfs, czy nie jest on, z punktu widzenia jądra, taki sam, jak zwykły plik, ale zapisywany do pamięci?

+0

Kod musi być __portable__, nie korzystam z żadnej konkretnej platformy/OS (duża trójka to dobry start). – orlp

+0

Wielka trójka? To musi być FreeBSD, OpenBSD i NetBSD, prawda? ... Dobrze?? ... (dźwięk świerszczy) ... oh, zwykli ludzie ... – ninjalj

+0

@ninjalj Jesteś * tak * szukasz wojny płomieniowej. Ale myślę, że to całkiem zabawne :-D – mydoghasworms

Powiązane problemy