Fstream non riesce a creare il nuovo file

Sto usando un file Manager per un progetto in modo che la lettura e la scrittura è meno di una seccatura per me. O sarebbe, se non ho tempo di debug. Quindi, questo comfort di classe, in realtà mi ha causato stress e del tempo. Impressionante.

Il problema sembra essere il fstream. Prima di proseguire ulteriormente, qui è la struttura del mio FileManager di classe.

class FileManager : Utility::Uncopyable
{
public:
    FileManager();

    void open(std::string const& filename);
    void close();

    void read(std::string& buffer);
    void write(std::string const& data);

private:
    std::fstream stream_;
};

Molto semplice. Il buffer è caricato con i dati durante la funzione, il parametro di dati è quello di essere scritto in un file. Prima lettura e la scrittura, è necessario aprire il file o il rischio di ottenere un grande, grasso eccezione in faccia. Un po ‘ come quello che sto ottenendo ora.

Scenario: una Semplice riga di comando per la registrazione di un utente, quindi la scrittura dei dati su file. Chiedo un nome e una password. Il nome è copiato e aggiunto con .txt (nome del file). Quindi sembra che questo:

void SessionManager::writeToFile(std::string const& name, 
                                 std::string const& password)
{
    std::string filename = name + ".txt";
    std::string data;
    data += name +", " +password;

    try
    {
        fileManager_->open(filename);
        fileManager_->write(data);
        fileManager_->close();
    } 
    catch(FileException& exception)
    {
        /* Clean it up. */
        std::cerr << exception.what() << "\n";
        throw;
    }
}

Problema: l’apertura ha esito negativo. Il file non viene creato, e durante la scrittura ottengo un’eccezione per il fatto di non disporre di un file aperto.

FileManager::open() funzione:

void FileManager::open(std::string const& filename)
{
    if(stream_.is_open())
        stream_.close();

    stream_.open(filename.c_str());
}

e scrivere

void FileManager::write(std::string const& data)
{
    if(stream_.is_open())
        stream_ << data;
    else
        throw FileException("Error. No file opened.\n");
}

Tuttavia, se creo il file in anticipo, quindi non ha problemi di apertura del file. Tuttavia, quando ho di controllo, il valore di default std::ios::openmode è std::ios::in | std::ios::out. Posso creare il file proprio bene quando ho solo tag std::ios::out, ma voglio mantenere il flusso in un stato di lettura/scrittura.

Come posso realizzare questo?

OriginaleL’autore IAE | 2011-01-26

6 Replies
  1. 7

    Metodo migliore:

    void FileManager::open(std::string const& filename)
    {
        using std::ios_base;
        if( stream_.is_open() )
            stream_.close();
    
        stream_.open( filename.c_str() ); //...try existing file
        if( !stream_.is_open() ) //...else, create new file...
            stream_.open(filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc);
    }

    In modo che il codice di test per un file esistente e, se non lo crea.

    OriginaleL’autore AtesComp

  2. 3

    Non è possibile utilizzare std::ios::in su un file non esistente. Utilizzare

    std::ios::in | std::ios::out | std::ios::trunc

    invece (ma assicurarsi che non esiste o non verrà troncato a zero byte).

    OriginaleL’autore Daniel Gehriger

  3. 3

    Come posso realizzare questo?

    std::ofstream file("file.txt");
    file << data;

    Non è più semplice?

    “ma io voglio mantenere il flusso in uno stato di lettura/scrittura.”
    Devo ammettere che non riesco a vedere il punto in questo FileManager classe, ma l’OP ha voglia di una lettura/scrittura stream.

    OriginaleL’autore wilhelmtell

  4. 3

    Devi chiamare fstream::open, con un esplicito openmode argomento di

    ios_base::in | ios_base::out | ios_base::trunc

    Altrimenti open avrà esito negativo a causa di ENOENT.

    Tabella 95 del progetto di C++ standard elenchi di file possibili modalità aperte e il loro equivalente in stdio. Il valore di default, ios_base::out | ios_base::in è r+. Quello che ho elencato sopra è equivalente a w+. ios_base::out | ios_base::app è equivalente a a. Tutte le altre combinazioni che coinvolgono ios_base::app non sono validi.

    (A rischio di essere derisi: si potrebbe passare per stdio e utilizzare il file in modalità a+, in cui si legge dall’inizio, e aggiunge alla fine.)

    Dal C++11, ios_base::app da solo è permesso, e l’equivalente di “un”. Vedere la Tabella 132 in C++11 o C++14 per la tabella aggiornata.

    OriginaleL’autore Fred Foo

  5. 2

    Che il modo in cui la biblioteca opera: std::ios::in | std::ios::out apre l’equivalente di stdio‘s "r+", che è solo di aprire un file esistente. Non credo che c’è una modalità che consente di fare ciò che si desidera, avrete a noi un OS specifico per chiamare o controllare il file per l’esistenza (di nuovo, che utilizza un sistema operativo specifico per chiamata) e aprirlo in un modo o l’altro a seconda se è già esistente.

    Modifica: ho dato per scontato che non volete che il file troncato se esiste già. Come altri hanno notato, se sei felice di troncare qualsiasi file esistente quindi in | out | trunc è un’opzione.

    OriginaleL’autore Tim Martin

  6. 1

    Basta avere la vostra funzione per aprire

    void FileManager::open(std::string const& filename)
    {
        using std::ios_base;
        if(stream_.is_open())
            stream_.close();
    
        stream_.open(filename.c_str(), ios_base::in | ios_base::out | ios_base::trunc);
    }

    se questa è la modalità che si richiedono.

    Non c’è modo magico per aprire un file in lettura/scrittura creandolo se non esiste, ma non troncare (la rimozione del suo contenuto), se lo fa. Si hanno a che fare, in più passaggi.

    OriginaleL’autore CashCow

Lascia un commento