HOWTO · C++
Como escrever em um arquivo em C++
Este artigo demonstra como escrever num ficheiro em C++. Aprenda sobre fluxos de ficheiros e os diferentes modos de abertura, e veja exemplos claros para gerir eficazmente as operações com ficheiros nos seus programas C++. Quer precise de acrescentar dados ou de substituir o conteúdo existente, este guia ajuda-o.
Nesta página
Use std::ofstream com o operador de inserção (<<) para escrever texto comum num ficheiro. Abra-o com std::ios::app para acrescentar dados no fim, ou use std::ios::trunc se quiser substituir o conteúdo existente. Para escrever um número conhecido de caracteres ou bytes, use a função-membro write de um fluxo; fwrite é a alternativa equivalente ao estilo de C.
Fluxos de ficheiro em C++
Os fluxos de ficheiro ligam um programa C++ a um ficheiro identificado por um nome. Inclua <fstream> e crie um std::ofstream para escrever; use std::fstream quando o mesmo fluxo precisar de permitir leitura e escrita. O operador de inserção é prático para texto formatado, e um carácter de nova linha na cadeia inicia outra linha no ficheiro. Verifique o estado do fluxo depois de o abrir e de escrever, pois um caminho aparentemente válido pode estar inacessível ou o dispositivo de armazenamento pode não estar disponível.
Execute este exemplo:
#include <fstream>
#include <iostream>
int main() {
std::ofstream file("example.txt");
if (!file) {
std::cerr << "Could not open example.txt\n";
return 1;
}
file << "Hello, C++!\n";
file << "File output is ready.\n";
file.close();
if (!file) {
std::cerr << "Could not finish writing example.txt\n";
return 1;
}
std::cout << "Wrote example.txt\n";
return 0;
}
Wrote example.txt
A mensagem é apresentada na consola; as duas linhas escritas através de file ficam guardadas em example.txt. Abra o ficheiro num editor de texto para verificar o conteúdo. Um std::ofstream apenas de saída, com as opções predefinidas, cria o ficheiro se a pasta que o contém existir e, normalmente, apaga o conteúdo anterior ao abri-lo.
Escrever em ficheiros com diferentes modos
O modo de abertura determina o que acontece aos dados existentes. std::ios::app posiciona cada escrita no fim do ficheiro, o que é útil para registos ou dados que devem ser acumulados. Se o ficheiro ainda não existir, abri-lo para escrita pode criá-lo, desde que o caminho e as permissões o permitam. O exemplo autónomo seguinte escreve uma linha no modo de acrescento; não precisa de um ficheiro example.txt preexistente.
#include <fstream>
#include <iostream>
int main() {
std::ofstream file("example.txt", std::ios::app);
if (!file) {
std::cerr << "Could not open example.txt\n";
return 1;
}
file << "A new log entry\n";
file.close();
if (!file) {
std::cerr << "Could not finish writing example.txt\n";
return 1;
}
return 0;
}
O caso de execução fornecido terminou com sucesso e não produziu saída na consola. O código escreve A new log entry, seguido de uma nova linha, em example.txt. Se o ficheiro já contiver dados, a nova linha é acrescentada depois deles.
Escrever e substituir conteúdo com ios::trunc
std::ios::trunc descarta o conteúdo anterior do ficheiro quando este é aberto. Abrir um std::ofstream para escrita sem std::ios::app tem, normalmente, o mesmo efeito de truncagem; especifique std::ios::trunc quando quiser tornar essa escolha explícita. Não use nenhuma destas formas se precisar de preservar os dados existentes.
#include <fstream>
#include <iostream>
int main() {
std::ofstream file("example.txt", std::ios::trunc);
if (!file) {
std::cerr << "Could not open example.txt\n";
return 1;
}
file << "Current report\n";
file.close();
if (!file) {
std::cerr << "Could not finish writing example.txt\n";
return 1;
}
return 0;
}
O caso de execução fornecido terminou com sucesso e não produziu saída na consola. O código escreve apenas Current report e uma nova linha em example.txt, substituindo o conteúdo anterior.
Escrever num ficheiro com fstream::write
Use a função-membro write do fluxo quando os dados já estiverem num buffer de caracteres e o respetivo comprimento for conhecido. A função recebe um ponteiro para caracteres e a quantidade de caracteres a escrever; não acrescenta um terminador nem uma nova linha. A quantidade é um tamanho de fluxo, pelo que passar data.size() escreve os caracteres guardados na cadeia sem incluir um carácter nulo final. Verifique o estado do fluxo após a chamada para detetar falhas de escrita. Consulte a documentação do cppreference sobre basic_ostream::write para conhecer a interface.
#include <fstream>
#include <iostream>
#include <string>
int main() {
const std::string data = "C++ buffer data\n";
std::fstream file("buffer.txt", std::ios::out | std::ios::trunc);
if (!file) {
std::cerr << "Could not open buffer.txt\n";
return 1;
}
file.write(data.data(), static_cast<std::streamsize>(data.size()));
if (!file) {
std::cerr << "Could not write buffer.txt\n";
return 1;
}
file.close();
if (!file) {
std::cerr << "Could not finish writing buffer.txt\n";
return 1;
}
return 0;
}
O caso de execução fornecido terminou com sucesso e não produziu saída na consola. Escreve em buffer.txt os caracteres de data, incluindo a nova linha que faz parte da cadeia; não escreve um carácter nulo final.
A escrita de caracteres e a escrita de bytes diferem no facto de os dados serem ou não formatados. O operador de inserção converte os valores em texto, enquanto write e fwrite copiam os bytes do buffer sem os formatar. Copiar os bytes, por si só, não garante que cheguem inalterados ao ficheiro: um fluxo aberto em modo de texto pode continuar a traduzir os caracteres de nova linha nas plataformas que usam um fim de linha diferente, como o Windows, que converte \n em \r\n na escrita. Quando os bytes exatos importam, abra o fluxo em modo binário, por exemplo com std::ios::out | std::ios::binary | std::ios::trunc, ou passe "wb" em vez de "w" ao fopen, para que não ocorra nenhuma tradução.
Escrever num ficheiro com a função C fwrite
Para operações de entrada e saída ao estilo de C, fwrite recebe um ponteiro, o tamanho de cada elemento, o número de elementos e um FILE*. O valor devolvido é o número de elementos escritos, e não o número de bytes, a menos que cada elemento tenha tamanho um. Verifique essa quantidade, feche o ficheiro e verifique também o resultado de fclose, pois podem surgir erros de escrita em buffer durante o fecho.
#include <cstdio>
#include <cstring>
#include <iostream>
int main() {
const char data[] = "C file output\n";
const std::size_t size = std::strlen(data);
std::FILE* file = std::fopen("c-output.txt", "w");
if (file == nullptr) {
std::cerr << "Could not open c-output.txt\n";
return 1;
}
const std::size_t written = std::fwrite(data, 1, size, file);
const int close_status = std::fclose(file);
if (written != size || close_status != 0) {
std::cerr << "Could not finish writing c-output.txt\n";
return 1;
}
return 0;
}
O caso de execução fornecido terminou com sucesso e não produziu saída na consola. O código escreve em c-output.txt os caracteres de data, incluindo a nova linha. O modo "w" cria o ficheiro ou apaga o conteúdo anterior.
Conclusão
Para texto comum, use std::ofstream e <<. Escolha std::ios::app para preservar o conteúdo existente e acrescentar dados no fim, ou std::ios::trunc para o substituir. Use write para um buffer com comprimento conhecido e fwrite quando estiver a trabalhar com operações de entrada e saída ao estilo de C. Verifique o estado após abrir e escrever; verifique também os erros de fecho quando for necessário confirmar que os dados foram escritos por completo.
Perguntas frequentes
-
Como posso saber se um ficheiro foi aberto? Verifique diretamente o fluxo (
if (!file)) ou chameis_open()logo após a abertura. Trate a falha antes de tentar escrever. -
Como posso acrescentar dados sem substituir o conteúdo existente? Abra um fluxo de saída com
std::ios::app. Cada escrita é encaminhada para o fim do ficheiro. -
O C++ cria um ficheiro que ainda não existe? Os fluxos de saída e
fopencom o modo"w"podem criá-lo se a pasta que o contém existir e o processo tiver permissão. Se a pasta não existir ou não houver permissões suficientes, a abertura falha. -
Como posso escrever várias linhas? Insira caracteres de nova linha com
<<ou inclua-os no buffer passado awrite. Nemwritenemfwriteacrescentam terminadores de linha automaticamente. -
Devo fechar o ficheiro? Um fluxo de ficheiro é fechado quando é destruído, mas chamar explicitamente
close()pode tornar claro quando a escrita terminou. Se for importante confirmar que os dados foram escritos, verifique o estado do fluxo depois do fecho. Para umFILE*de C, chamefclosee verifique o valor devolvido.