2012-02-22 6 views
7

estoy trabajando con un poco de código heredado que usa algo como esto:¿Hacer FILE * struct map a un buffer?

void store_data(FILE *file); 

Sin embargo, yo no quiero para almacenar los datos en el disco, quiero almacenarlo en la memoria (char *buf). Podría editar todo el código, pero el código salta por todas partes y se llama al archivo fwrite en todo el lugar. Entonces, ¿hay una manera más fácil, por ejemplo, de que pueda asignar un objeto FILE* a un búfer (de crecimiento automático)? No sé el tamaño total de los datos de antemano.

La solución debe ser portátil.

Respuesta

5

No hay forma de hacerlo usando solo las facilidades provistas en el estándar C. Lo más cerca que se puede llegar es

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

Esto dio en el disco, al menos potencialmente, pero yo diría que es la mejor opción si necesita gran portabilidad y no se puede modificar el "código heredado".

En POSIX.1-2008, existe open_memstream, que hace exactamente lo que desea; sin embargo, esta revisión de POSIX aún no ha sido ampliamente adoptada. GNU libc (usado en Linux y algunos otros) lo tiene, pero no está disponible en OSX o * BSD hasta donde yo sé, y ciertamente no en Windows.

+0

¿Las tuberías son una opción? – orlp

+0

Las tuberías tampoco están en el estándar C. En Unix, sí, podría tener un lazo de tubería a otro hilo en el mismo proceso que escribió en un búfer de memoria. En Windows, teóricamente puedes hacer lo mismo, pero esperaría que sea una fuente de dolor interminable, e incluso en Unix esto me parece demasiado trabajo para no obtener demasiada ganancia sobre el enfoque 'tmpfile'. – zwol

1

Es posible que desee mirar fmemopen y open_memstream. Ellos hacen algo en la dirección de lo que quieres.

Desde la página del manual:

El open_memstream() abre una corriente para escribir en un búfer. El búfer se asigna dinámicamente (como con malloc (3)) y automáticamente crece según se requiera. Después de cerrar la secuencia, la persona que llama debe liberar (3) este búfer.

+1

De acuerdo con la página man de mi sistema, estas funciones se ajustan a "POSIX.1-2008. Estas funciones no están especificadas en POSIX.1-2001, y no están ampliamente disponibles en otros sistemas". –

+0

@DanFego: cierto. – Florian

1

No sé si es buena idea, pero es una idea.

Puede "redefinir" fwrite utilizando una macro.

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

A continuación, aplicar memory_write_function para escribir datos en el búfer de crecimiento automático en lugar de un archivo.

Deberá llamar al store_data con un puntero a otra cosa (no un puntero a FILE). Pero eso es posible con C por lo que no tendrá problemas allí.

0

Es posible que desee consultar fmemopen(). Si no está disponible para usted, entonces podría utilizar un segmento de memoria compartida con nombre junto con fdopen() para convertir el descriptor de archivo devuelto por shm_open() a FILE*.

+0

'fmemopen' no modifica automáticamente el tamaño del búfer de memoria al escribir, por lo que no cumple con los requisitos del OP. – zwol

0

¿En qué plataforma se está ejecutando? ¿No puedes usar tmpfs? Si abre un archivo en tmpfs, ¿no es, desde el punto de vista del kernel, el mismo que un archivo normal, pero está escrito en la memoria?

+0

El código tiene que ser __portable__, no me estoy ejecutando en ninguna plataforma/sistema operativo en particular (sin embargo, los tres grandes son un buen comienzo). – orlp

+0

¿Los tres grandes? Eso debe ser FreeBSD, OpenBSD y NetBSD, ¿verdad? ... ¿¿Correcto?? ... (sonido de grillos) ... oh, muchachos comunes ... – ninjalj

+0

@ninjalj Estás * tan * buscando comenzar una guerra de llamas. Pero creo que es bastante divertido :-D – mydoghasworms

Cuestiones relacionadas