Pregunta

Tengo que desarrollar una aplicación que analice un archivo de registro y envíe datos específicos a un servidor.Tiene que ejecutarse tanto en Linux como en Windows.

El problema aparece cuando quiero probar el sistema de registro continuo (que agrega .1 al nombre del crea uno nuevo con el mismo nombre).En Windows (aún no lo he probado en Linux) no puedo cambiar el nombre de un archivo que abrí con std::ifstream() (¿acceso exclusivo?) incluso si lo abro en "modo de entrada" (ios::in) .

¿Existe una forma multiplataforma de abrir archivos de forma no exclusiva?

¿Fue útil?

Solución

¿Hay alguna manera de abrir un archivo de forma no exclusiva?

Sí, usando Win32, pasando los distintos indicadores FILE_SHARE_Xxxx a CreateFile.

¿Es multiplataforma?

No, requiere código específico de la plataforma.

Debido a molestos problemas de compatibilidad con versiones anteriores (las aplicaciones DOS, al ser de una sola tarea, asumen que nada puede eliminar un archivo debajo de ellas, es decir,que pueden fclose() y luego fopen() sin que nada salga mal;Win16 conservó esta suposición para facilitar la transferencia de aplicaciones de DOS, Win32 conservó esta suposición para facilitar la transferencia de aplicaciones de Win16, y es horrible), Windows por defecto abre archivos exclusivamente.

La infraestructura del sistema operativo subyacente admite la eliminación/cambio de nombre de archivos abiertos (aunque creo que tiene la restricción de que los archivos asignados en memoria no se pueden eliminar, lo cual creo que no es una restricción que se encuentra en *nix), pero la semántica de apertura predeterminada no.

C++ no tiene noción de nada de esto;el entorno operativo C++ es muy parecido al entorno operativo DOS: no hay otras aplicaciones ejecutándose simultáneamente, por lo que no es necesario controlar el intercambio de archivos.

Otros consejos

No es la operación de lectura la que requiere el modo exclusivo, es el cambio de nombre, porque esto es esencialmente lo mismo que mover el archivo a una nueva ubicación.

No estoy seguro pero no creo que esto se pueda hacer.Intente copiar el archivo y luego elimine/reemplace el archivo antiguo cuando ya no se lea.

La semántica del sistema de archivos Win32 requiere que el archivo cuyo nombre cambie no esté abierto (en ningún modo) en el momento de cambiar el nombre.Deberá cerrar el archivo, cambiarle el nombre y luego crear el nuevo archivo de registro.

La semántica del sistema de archivos Unix le permite cambiar el nombre de un archivo que está abierto porque el nombre del archivo es solo un puntero al inodo.

Si solo está leyendo el archivo, sé que se puede hacer con la API de Windows CreateFile.Simplemente especifique file_share_delete | File_share_read | File_share_write como la entrada a dwsharemode.

Desafortunadamente esto no es multiplataforma.Pero podría haber algo similar para Linux.

Consulte msdn para obtener más información sobre CreateFile..

EDITAR:Sólo una nota rápida sobre el comentario de Greg Hewgill.Acabo de probar con el material FILE_SHARE* (también estoy 100% seguro).Y es posible eliminar y cambiar el nombre de archivos en Windows si abre solo lectura y especifica los parámetros FILE_SHARE*.

Me aseguraría de no mantener archivos abiertos.Esto lleva a cosas raras si tu aplicación falla, por ejemplo.Lo que haría:

  1. Resuma (leer/escribir/pasar a un nuevo archivo) en una clase y organizar el cierre del archivo cuando desee pasar a uno nuevo en esa clase.(Esta es la forma más sencilla y, como ya tiene el código de sustitución, ya está a mitad del camino).
  2. Si debe tener múltiples puntos de acceso de lectura/escritura, necesita todas las funciones de fstreams y no desea escribir un contenedor completo, entonces la única solución multiplataforma que se me ocurre es cerrar siempre el archivo cuando no lo necesite. y haga que el código de renovación intente adquirir acceso exclusivo al archivo varias veces cuando necesite renovarse antes de darse por vencido.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top