2012-02-22 12 views
7

Sto lavorando con un certo codice legacy che utilizza qualcosa di simile:Rendi FILE * struct map in un buffer?

void store_data(FILE *file); 

Tuttavia, non voglio per memorizzare i dati sul disco, voglio conservare in memoria (char *buf). Potrei modificare tutto il codice, ma il codice salta dappertutto e fwrite viene chiamato sul file dappertutto. Quindi c'è un modo più semplice, ad esempio di mappare un oggetto FILE* a un buffer (a crescita automatica)? Non conosco la dimensione totale dei dati prima mano.

La soluzione deve essere portatile.

risposta

5

Non c'è modo di farlo utilizzando solo le funzioni fornite nello standard C. Il più vicino si può venire è

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); 

Ciò ha colpito il disco, almeno potenzialmente, ma io direi che è la soluzione migliore se avete bisogno di un'ampia portabilità e non si può modificare il "codice legacy".

In POSIX.1-2008, c'è open_memstream, che fa esattamente ciò che si desidera; tuttavia, questa revisione di POSIX non è ancora ampiamente adottata. GNU libc (usato su Linux e pochi altri) ce l'ha, ma non è disponibile su OSX o * BSD per quanto ne so, e certamente non su Windows.

+0

Le pipe sono forse un'opzione? – orlp

+0

I tubi non sono nello standard C neanche. Su Unix, sì, si potrebbe avere un loop pipe di nuovo su un altro thread nello stesso processo che ha scritto su un buffer di memoria. Su Windows, puoi teoricamente fare la stessa cosa, ma mi aspetterei che fosse una fonte di dolore senza fine, e anche su Unix questo mi sembra un lavoro troppo impegnativo per non avere molti vantaggi rispetto all'approccio 'tmpfile'. – zwol

1

Si potrebbe voler guardare fmemopen e open_memstream. Fanno qualcosa nella direzione di ciò che vuoi.

Dalla pagina man:

L'open_memstream() apre un flusso per la scrittura di un buffer. Il buffer viene allocato dinamicamente (come con malloc (3)), e automati- cally cresce come richiesto. Dopo aver chiuso il flusso, il chiamante deve libero (3) questo buffer.

+1

In base alla pagina man sul mio sistema, queste funzioni sono conformi a "POSIX.1-2008" Queste funzioni non sono specificate in POSIX.1-2001 e non sono ampiamente disponibili su altri sistemi. " –

+0

@DanFego: vero. – Florian

1

Non so se è un'idea buona , ma è un'idea.

È possibile ridefinire "fwrite utilizzando una macro.

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

quindi implementare memory_write_function per scrivere i dati per il buffer crescente auto invece di un file.

Avrete bisogno di chiamare store_data con un puntatore a qualcos'altro (non un puntatore a FILE). Ma è possibile con C così non avrai problemi.

0

Si consiglia di esaminare fmemopen(). Se questo non è disponibile, è possibile utilizzare un segmento di memoria condivisa denominato insieme a fdopen() per convertire il descrittore di file restituito da shm_open() a FILE*.

+0

'fmemopen' non ridimensiona automaticamente il buffer di memoria in scrittura, quindi non soddisfa i requisiti dell'OP. – zwol

0

Su quale piattaforma stai correndo? Non puoi usare tmpfs? Se apri un file su tmpfs, non è, dal punto di vista del kernel, lo stesso di un normale file, ma scritto in memoria?

+0

Il codice deve essere __portable__, non sto girando su nessuna piattaforma/sistema operativo particolare (i primi tre sono comunque un buon inizio). – orlp

+0

I tre grandi? Deve essere FreeBSD, OpenBSD e NetBSD, giusto? ... Destra?? ... (suono di grilli) ... oh, gente comune ... – ninjalj

+0

@ninjalj Sei * così * che cerca di iniziare una guerra di fuoco. Ma penso che sia abbastanza divertente MrGreen – mydoghasworms