Domanda

Devo sviluppare un'applicazione che analizzi un file di registro e invii dati specifici a un server.Deve funzionare sia su Linux che su Windows.

Il problema si presenta quando voglio testare il sistema di log rolling (che aggiunge .1 al nome ne crea uno nuovo con lo stesso nome).Su Windows (non ho ancora testato su Linux) non riesco a rinominare un file che ho aperto con std::ifstream() (accesso esclusivo?) anche se lo apro in "modalità input" (ios::in) .

Esiste un modo multipiattaforma per aprire il file in modo non esclusivo?

È stato utile?

Soluzione

Esiste un modo per aprire il file in modo non esclusivo,

Sì, utilizzando Win32, passando i vari flag FILE_SHARE_Xxxx a CreateFile.

è multipiattaforma?

No, richiede codice specifico della piattaforma.

A causa di fastidiosi problemi di compatibilità con le versioni precedenti (le applicazioni DOS, essendo single-tasking, presuppongono che nulla possa eliminare un file da sotto di esse, ad es.che possono fclose() e poi fopen() senza che nulla vada storto;Win16 ha mantenuto questo presupposto per rendere più semplice il porting delle applicazioni DOS, Win32 ha mantenuto questo presupposto per rendere più semplice il porting delle applicazioni Win16, ed è terribile), Windows per impostazione predefinita apre esclusivamente i file.

L'infrastruttura del sistema operativo sottostante supporta l'eliminazione/rinomina dei file aperti (anche se credo che abbia la restrizione secondo cui i file mappati in memoria non possono essere eliminati, che penso non sia una restrizione trovata su *nix), ma la semantica di apertura predefinita no.

Il C++ non ha idea di nulla di tutto ciò;l'ambiente operativo C++ è molto simile all'ambiente operativo DOS: nessun'altra applicazione viene eseguita contemporaneamente, quindi non è necessario controllare la condivisione dei file.

Altri suggerimenti

Non è l'operazione di lettura che richiede la modalità esclusiva, ma la ridenominazione, perché equivale essenzialmente a spostare il file in una nuova posizione.

Non ne sono sicuro ma non credo che sia possibile farlo.Prova invece a copiare il file e successivamente elimina/sostituisci il vecchio file quando non viene più letto.

La semantica del filesystem Win32 richiede che un file che rinomini non sia aperto (in nessuna modalità) nel momento in cui esegui la ridenominazione.Sarà necessario chiudere il file, rinominarlo e quindi creare il nuovo file di registro.

La semantica del filesystem Unix ti consente di rinominare un file aperto perché il nome del file è solo un puntatore all'inode.

Se stai solo leggendo dal file, so che può essere fatto con Windows API CreateFile.Basta specificare file_share_delete | File_share_read | File_share_write come input su dwsharemode.

Sfortunatamente questo non è multipiattaforma.Ma potrebbe esserci qualcosa di simile per Linux.

Vedi msdn per maggiori informazioni su CreateFile.

MODIFICARE:Solo una breve nota sul commento di Greg Hewgill.Ho appena provato con il materiale FILE_SHARE* (anch'io sii sicuro al 100%).Ed è possibile eliminare e rinominare i file in Windows se si apre in sola lettura e si specificano i parametri FILE_SHARE*.

Mi assicurerei che tu non tenga i file aperti.Ciò porta a cose strane se, ad esempio, la tua app si blocca.Cosa farei:

  1. Riassumi (lettura/scrittura/passaggio a un nuovo file) in una classe e organizza la chiusura del file quando desideri passare a uno nuovo in quella classe.(questo è il modo più accurato e poiché hai già il codice roll-over sei già a metà strada.)
  2. Se devi avere più punti di accesso in lettura/scrittura, hai bisogno di tutte le funzionalità di fstreams e non vuoi scrivere un wrapper completo, allora l'unica soluzione multipiattaforma che mi viene in mente è chiudere sempre il file quando non ti serve e fare in modo che il codice di rollover provi ad acquisire l'accesso esclusivo al file alcune volte quando è necessario eseguire il rollover prima di arrendersi.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top