Creación de una secuencia FILE * que da como resultado una cadena

4 minutos de lectura

Estoy buscando una manera de pasar en un FILE * a alguna función para que la función pueda escribir en ella con fprintf. Esto es fácil si quiero que la salida aparezca en un archivo real en el disco, por ejemplo. Pero lo que me gustaría en su lugar es obtener toda la salida como una cadena (char *). El tipo de API que me gustaría es:

/** Create a FILE object that will direct writes into an in-memory buffer. */
FILE *open_string_buffer(void);

/** Get the combined string contents of a FILE created with open_string_buffer
    (result will be allocated using malloc). */
char *get_string_buffer(FILE *buf);

/* Sample usage. */
FILE *buf;
buf = open_string_buffer();
do_some_stuff(buf);   /* do_some_stuff will use fprintf to write to buf */
char *str = get_string_buffer(buf);
fclose(buf);
free(str);

los glibc los encabezados parecen indicar que se puede configurar un ARCHIVO con funciones de enlace para realizar la lectura y escritura reales. En mi caso, creo que quiero que el enlace de escritura agregue una copia de la cadena a una lista vinculada, y que haya un get_string_buffer función que calcula la longitud total de la lista, le asigna memoria y luego copia cada elemento en el lugar correcto.

Estoy apuntando a algo que se puede pasar a una función como do_some_stuff sin que esa función necesite saber nada más que tiene un FILE * puede escribir.

¿Hay una implementación existente de algo como esto? Parece algo útil y amigable para C, suponiendo que tenga razón sobre el FILE extensibilidad.

Creacion de una secuencia FILE que da como resultado
quinmars

Si la portabilidad no es importante para usted, puede echar un vistazo a fmemopen y abrir_memstream. Son extensiones GNU, por lo tanto, solo están disponibles en sistemas glibc. Aunque parece que son parte de POSIX.1-2008 (fmemopen y abrir_memstream).

  • open_memstream es exactamente lo que quiero. No estoy seguro de si está utilizando el enfoque de lista enlazada, pero no escribiré grandes cantidades, así que no importa.

    – Edmundo

    16 de noviembre de 2009 a las 19:32

1646967192 929 Creacion de una secuencia FILE que da como resultado
asveikau

No estoy seguro de si es posible extender de forma no portátil FILE objetos, pero si está buscando algo un poco más compatible con POSIX, puede usar pipe y fdopen.

No es exactamente lo mismo que tener un FILE* que devuelve bytes de un búfer, pero ciertamente es un FILE* con contenidos determinados programáticamente.

int fd[2];
FILE *in_pipe;

if (pipe(fd))
{
   /* TODO: handle error */
}

in_pipe = fdopen(fd[0], "r");
if (!in_pipe)
{
   /* TODO: handle error */
}

A partir de ahí, querrá escribir su búfer en fd[1] utilizando write(). Sin embargo, tenga cuidado con este paso, porque write() puede bloquearse si el búfer de la tubería está lleno (es decir, alguien necesita leer el otro extremo), y puede obtener EINTR si su proceso recibe una señal mientras escribe. También tenga cuidado con SIGPIPE, lo que sucede cuando el otro extremo cierra la tubería. Tal vez para su uso es posible que desee hacer el write del búfer en un subproceso separado para evitar el bloqueo y asegúrese de manejar SIGPIPE.

Por supuesto, esto no creará una búsqueda FILE*

1646967192 616 Creacion de una secuencia FILE que da como resultado
Remo.D

No estoy seguro de entender por qué quieres meterte con FILE *. ¿No podría simplemente escribir en un archivo y luego cargarlo en una cadena?

 char *get_file_in_buf(char *filename) {
   char *buffer;
   ... get file size with fseek or fstat ...
   ... allocate buffer ...
   ... read buffer from file ...
   return buffer;
 }

Si solo desea “escribir” texto formateado en una cadena, otra opción podría ser manejar un búfer extensible usando snprintf() (Consulte las respuestas a esta pregunta SO para obtener una sugerencia sobre cómo manejar esto: Reanudar [vf]?nprintf después de alcanzar el límite).

Si, en cambio, desea crear un tipo que se pueda pasar de forma transparente a cualquier función que tome una FILE * hacer que actúen sobre los buffers de cadenas, es un asunto mucho más complejo…

  • Hay buenas razones para querer tal FILE*: Hay muchas bibliotecas que ofrecen sólo FILE*basado en E/S e insiste en leer un archivo, cuando los datos ya pueden estar disponibles en la memoria. Por lo tanto, es deseable poder pasar el búfer de memoria en lugar de escribir en un archivo solo para estas bibliotecas. Desafortunadamente, estas bibliotecas rara vez, o nunca, ofrecen una alternativa a sus FILE*API dependiente.

    – desvanecimiento gris

    6 oct 2011 a las 17:54

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad