Directorio de artículos
- E/S
- fluir
- Sistema de herencia de la biblioteca de clases de flujo
- Cuatro objetos de entrada y salida
- Funcionamiento de la corriente ostream
- Funcionamiento de la corriente istream
- flujo de archivos
- abrir un archivo
- modo de apertura de archivos
- modo protegido
- Notas sobre la apertura de archivos
- estado de flujo
- cerrar archivo
- archivo de lectura y escritura
- Leer y escribir archivos binarios
- Puntero de actividad de flujo de archivo actual
- Lectura y escritura aleatoria de archivos seekp y seekg
- Lectura y escritura aleatoria de archivos tellp y tellg
- buscar_dir
- Formateo del flujo de salida
E/S
La entrada y salida de datos (entrada/salida se abrevia como E/S), y la entrada y salida de dispositivos de entrada estándar y dispositivos de salida estándar se conoce como E/S estándar. La entrada y salida de archivos en el disco de almacenamiento externo se conoce como E/S de archivo. La entrada y salida al espacio de almacenamiento de cadena especificado en la memoria se conoce como E/S de cadena.
fluir
El proceso de entrada y salida de datos se puede visualizar como un flujo. Las operaciones que obtienen datos de un flujo se denominan "obtener" (operaciones de entrada). Las operaciones que agregan datos a una secuencia se denominan operaciones de "inserción" (salida).
Sistema de herencia de la biblioteca de clases de flujo
- La biblioteca de clases de flujo tiene dos clases base paralelas: streambuf y clase ios, y todas las clases de flujo usan una de las dos como clase base.
- La clase streambuf proporciona operaciones de bajo nivel en el búfer: configurar el búfer, operar en el puntero del búfer, almacenar/recuperar caracteres en el búfer.
- Las clases ios_base e ios registran el estado de la transmisión y admiten la conversión formateada o sin formato de la entrada/salida del búfer del streambuf.
- strstreambuf: use una cadena para guardar una secuencia de caracteres. Amplía streambuf para realizar operaciones de inserción y extracción de búfer.
- filebuf: use un archivo para guardar secuencias de caracteres. Incluye abrir archivos, leer/escribir y encontrar personajes.
Cuatro objetos de entrada y salida
C++ define cuatro objetos de clase para que los usuarios realicen operaciones de E/S estándar: cin, cout, cerr y clog. cin es un objeto de la clase de flujo istream, que representa el teclado del dispositivo de entrada estándar, y los tres últimos son objetos de la clase de flujo ostream. cout significa monitor de dispositivo de salida estándar. cerr y clog tienen el mismo significado, ambos representan la pantalla del dispositivo de salida del mensaje de error.
Funcionamiento de la corriente ostream
1.operador<<
¿Por qué se puede usar consecutivamente la operación <<? <<El valor de retorno es una referencia a ostream, puede usar <<sobrecarga continuamente. << Proporciona sobrecarga de tipos básicos.
2.poner
La operación put genera un solo carácter y devuelve una referencia a un ostream.
cout.put('A').put('B').put('C');
3.escribir
La operación de escritura genera la longitud especificada del búfer y devuelve una referencia al ostream.
char buf[] = "testing!!!";
cout.write(buf, 8);
Funcionamiento de la corriente istream
1.operador>>
El valor devuelto es una referencia a un istream, que se puede sobrecargar continuamente con >>. >> Proporciona sobrecarga de tipos básicos.
2.obtener
La operación de obtención lee un solo carácter y devuelve un número entero como el código ASCII del carácter.
int ch = cin.get();
cout << ch << endl;
También puede recibir una referencia.
char ch, ch2;
cin.get(ch).get(ch2);
cout << ch << " " << ch2 << endl;
3.getline
La operación getline lee una línea (se encontró con la tecla Intro). Devuelve una referencia al objeto istream. La diferencia entre la operación getline() y >>: getline obtiene una línea completa, y >> se detiene cuando encuentra un espacio.
char buf[10] = {
0 };
cin.getline(buf, 10);
cout << buf << endl;
char buf2[10] = {
0 };
cin >> buf2;
cout << buf2 << endl;
4.leer
La operación de lectura devuelve una referencia a un objeto istream, la iluminación de los caracteres en blanco es correcta y el número especificado de caracteres se lee antes del final.
char buf[10] = {
0 };
cin.read(buf, 5);
cout << buf << endl;
5. echar un vistazo y retroceder
peek mira sin leer; putback agrega un carácter a la secuencia.
char c[10], c2, c3;
c2 = cin.get();
c3 = cin.get();
cin.putback(c2);
cin.getline(&c[0], 9);
cout << c << endl;
flujo de archivos
ofstream, derivado de ostream, se usa para escribir archivos.
ifstream, derivado de istream, se usa para leer archivos.
fstream, derivado de iostream, se usa para leer y escribir archivos.
abrir un archivo
Después de que se haya declarado el objeto de flujo, el archivo se puede abrir usando la función open(). La apertura de un archivo es para establecer una conexión entre la secuencia y el archivo. Prototipo de función:
void open(const char* filename,int mode = ios::out,int prot = _SH_DENYNO);
mode indica el modo de apertura de archivos, modo de protección prot. Hay 5 formas de juzgar si el archivo se abrió con éxito:
#include <iostream>
#include <fstream>
#include <cassert>
using namespace std;
int main()
{
ofstream fout;
fout.open("test.txt");
//1
if (fout.is_open())
{
cout << "succ" << endl;
}
else
cout << "failed" << endl;
//2
if (fout.good())
{
cout << "succ" << endl;
}
else
cout << "failed" << endl;
//3
if (fout)
{
cout << "succ" << endl;
}
else
cout << "failed" << endl;
//4
if (!fout)
{
cout << "failed" << endl;
}
else
cout << "succ" << endl;
//推荐使用断言方式
assert(fout);
fout.close();
return 0;
}
modo de apertura de archivos
método abierto | describir |
---|---|
iso::en | Abrir un archivo para lectura (predeterminado para ifstream) |
iso::fuera | Abra un archivo para escribir (el valor predeterminado para ofstream) |
iso::aplicación | encontrar el final del archivo antes de escribir |
iso::ate | colocar el archivo al final del archivo inmediatamente después de abrir el archivo |
iso::tronco | descartar el contenido del archivo actual |
iso::nocreate (ya no es compatible) | Si el archivo que se va a abrir no existe, llamar a la función open() con esta función no funcionará |
iso::noreplace (ya no se admite) | Si el archivo que se va a abrir ya existe, intentar abrirlo con la función open() devolverá un error |
iso::binario | Abra un archivo en forma binaria, el valor predeterminado es un archivo de texto |
modo protegido
#define _SH_DENYRW 0x10 /* deny read/write mode */拒绝对文件进行读写
#define _SH_DENYWR 0x20 /* deny write mode */拒绝写入文件
#define _SH_DENYRD 0x30 /* deny read mode */拒绝文件的读取权限
#define _SH_DENYNO 0x40 /* deny none mode */读取和写入许可
#define _SH_SECURE 0x80 /* secure mode */共享读取,独占写入
Notas sobre la apertura de archivos
- La apertura de archivos también se puede abrir a través del constructor, por ejemplo:
ofstream fout("test.txt,ios::out");
-
El método de apertura del archivo puede ser una de las constantes de enumeración anteriores o una expresión OR bit a bit compuesta por varias constantes de enumeración.
-
Cuando se utiliza la función de miembro abierto para abrir un archivo, si el archivo especificado por el parámetro de puntero de carácter no existe, se crea el archivo.
-
Cuando el método abierto no contiene la opción ios::ate o ios::app, el puntero del archivo se mueve automáticamente al principio del archivo, es decir, la dirección del byte es 0.
-
En efecto, especificar el modo out de ofstream es equivalente a especificar los modos out y trunc.
-
De forma predeterminada, los objetos fstream se abren tanto en modo de entrada como de salida.
-
No se vacía cuando el archivo se abre tanto con la entrada como con la salida.
-
Si solo se usa el modo de salida sin especificar el modo de entrada, el archivo se vaciará de los datos existentes.
-
Si out y app se especifican al mismo tiempo, no se borrará.
-
Si se especifica el modo trunc al abrir el archivo, el archivo también se borrará independientemente de si se especifica el modo in al mismo tiempo.
estado de flujo
método abierto | describir |
---|---|
ios::buen bit | Todo funciona bien, no se producen errores y no hay fin de entrada |
ios::eofbit | fin de entrada |
ios::fallo | Una operación de E/S falló, principalmente debido a datos ilegales (como una letra encontrada al intentar leer un número). La secuencia se puede seguir utilizando y el bit de falla también se establecerá al final de la entrada. |
ios::malo | Se ha producido un error fatal (quizás físico). la transmisión no estará disponible. |
En correspondencia con cada bit de estado de esta palabra indicadora, la clase ios también proporciona las siguientes funciones miembro para detectar o establecer el estado de la transmisión:
bool rdstate(); //返回流的当前状态标志字
bool eof(); //返回非0值表示到达文件尾
bool fail(); //返回非0值表示操作失败
bool bad(); //返回非0值表示出现错误
bool good(); //返回非0值表示流操作正常
bool clear(int flag=0); //将流的状态设置为flag
Para mejorar la confiabilidad del programa, es necesario detectar si la operación del flujo de E/S es normal en el programa. Cuando se detecta un error en una operación de transmisión, se puede usar el manejo de excepciones para resolver el problema.
cerrar archivo
Cada clase de secuencia de archivos proporciona una función miembro close() para cerrar el archivo. Función: cuando finaliza la operación del archivo abierto, debe cerrarse, de modo que la secuencia del archivo se desconecte del archivo físico correspondiente y pueda garantizar que el contenido salga al búfer del archivo al final, sin importar si esté lleno o no, se escribirá inmediatamente en el archivo físico correspondiente. Después de cerrar el archivo correspondiente a la secuencia de archivos, también puede usar la secuencia de archivos para llamar a la función de miembro abierto para abrir otros archivos. Lo mejor es borrarlo primero.
archivo de lectura y escritura
1.>>和<<
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ofstream fout("test.txt");
fout << "abcd" << " " << 200;
fout.close();
ifstream fin("test.txt");
string s;
int n;
fin >> s >> n;
cout << s << " " << n << endl;
return 0;
}
2. poner y recibir
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;
int main()
{
ofstream fout("test2.txt");
char ch;
assert(fout);
for (int i = 0; i < 26; i++)
{
ch = 'A' + i;
fout.put(ch);
}
fout.close();
ifstream fin("test2.txt");
while (fin.get(ch))
{
cout << ch;
}
return 0;
}
3. leer y escribir
La siguiente es una introducción a la lectura y escritura de archivos binarios.
4. La diferencia entre el modo de texto y el modo binario
Si el archivo se abre como texto, al escribir caracteres, la conversión se realizará cuando se encuentre \n. La plataforma Windows \n se convertirá a \r\n, la plataforma Linux permanecerá sin cambios y el sistema mac \n se convertirá a \r. \r no hacer ninguna conversión. Si el archivo se abre en modo binario, los caracteres se escriben sin conversión. Abrir un archivo como texto también puede escribir datos binarios y abrir un archivo como binario también puede escribir texto. Que los datos escritos sean binarios o texto no tiene nada que ver con el método de apertura, sino con la función utilizada para escribir. Para escribir datos binarios, se debe usar la escritura y se debe leer la lectura correspondiente.
Leer y escribir archivos binarios
Los archivos binarios son diferentes de los archivos de texto y se pueden usar para cualquier tipo de archivo, incluidos los archivos de texto. La lectura y escritura de archivos binarios puede usar la función miembro read() heredada de la clase istream y la función miembro write() heredada de la clase ostream. Utilice la constante de enumeración ios::binary al abrir el archivo, por ejemplo:
ofstream fout("binary.dat",ios::out|ios::binary);
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;
struct Test
{
int a;
int b;
};
int main()
{
Test test = {
100,200 };
ofstream fout("binary.txt", ios::out | ios::binary);
fout.write(reinterpret_cast<char*>(&test),sizeof(Test));
fout.close();
Test test2;
ifstream fin("binary.txt", ios::in | ios::binary);
fin.read(reinterpret_cast<char*>(&test2),sizeof(Test));
cout << test2.a << " " << test2.b << endl;
return 0;
}
Archivo de lectura y escritura cuando la cadena es lo suficientemente larga
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;
struct Test
{
int x;
string a;
string b;
};
int main()
{
Test t1;
t1.x = 100;
t1.a = "asdfsdafasfdasdfasdffsdfsdafadsadsfdfsfdsafdasfdsadfasdsfaasfddsfsadfsdfafdsasadffads";
t1.b = "qwerqwerqrwewqrrqewewrewrqrqewerwqrewqqwerrweqrewqreqwerqwrqewrqweqrwerweqqrwerqwerwesfadsfafdfadsasfasdafsqrw";
ofstream fout("test4.txt", ios::out | ios::binary);
fout.write((char*)(&t1.x),sizeof(int));
int len;
len = t1.a.length();
fout.write((char*)&len, sizeof(int));
fout.write(t1.a.data(), t1.a.length());
len = t1.b.length();
fout.write((char*)&len, sizeof(int));
fout.write(t1.b.data(), t1.b.length());
fout.close();
ifstream fin("test4.txt", ios::in | ios::binary);
Test t2;
fin.read((char*)(&t2.x),sizeof(int));
fin.read((char*)(&len), sizeof(int));
t2.a.resize(len);
fin.read(&t2.a[0], len);
fin.read((char*)(&len), sizeof(int));
t2.b.resize(len);
fin.read(&t2.b[0], len);
cout << t2.x << " " << t2.a << " " << t2.b << endl;
return 0;
}
Puntero de actividad de flujo de archivo actual
Los punteros de flujo de archivos se utilizan para realizar un seguimiento de dónde ocurren las operaciones de E/S. Cada vez que se lee o se escribe un carácter en la transmisión, el puntero de actividad actual avanza. Cuando el método abierto no contiene la opción ios::ate o ios::app, el puntero del archivo se mueve automáticamente al principio del archivo, es decir, la dirección del byte es 0.
Lectura y escritura aleatoria de archivos seekp y seekg
- seekp: Establezca la posición del puntero del flujo de archivos del flujo de archivos de salida.
- seekg: Establezca la posición del puntero del flujo de archivos del flujo de archivos de entrada.
Parámetros de la función: pos nueva posición del puntero del flujo de archivos, apagado necesita valor de desplazamiento, posición de inicio de búsqueda de directorios.
Lectura y escritura aleatoria de archivos tellp y tellg
- tellp: obtiene la posición actual del puntero del flujo del archivo de salida en bytes.
- Tellg: Obtiene la posición actual del puntero del flujo del archivo de entrada en bytes.
El valor de retorno de la función es en realidad un tipo largo.
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
using namespace std;
struct Test
{
int x;
string a;
string b;
};
int main()
{
ifstream fin("test5.txt");
assert(fin);
fin.seekg(2);
char ch;
fin.get(ch);
cout << ch << endl;
fin.seekg(-1, ios::end);
fin.get(ch);
cout << ch << endl;
fin.seekg(0, ios::end);
streampos pos = fin.tellg();
cout << pos << endl;
return 0;
}
buscar_dir
El parámetro dir se usa para ubicar el puntero del flujo de archivos y representa la posición inicial de la búsqueda. Tipos de enumeración definidos en ios:
enum seek_dir{
beg,cur,end};
beg indica la posición inicial del flujo de archivos, cur indica la posición actual del flujo de archivos y end indica la posición final del flujo de archivos.
Formateo del flujo de salida
El formateo de la entrada y salida de datos se controla utilizando los manipuladores proporcionados en los archivos de encabezado del sistema. Simplemente utilícelos como objetos de salida del operador de inserción <<. Como setiosflags, setw, setfill, setprecision, hex, oct, etc.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int n = 64;
double d = 123.45;
double d2 = 0.0187;
//通过操纵子方式进行格式化输出
cout << "====================宽度控制====================" << endl;
cout << n << "#" << endl;
cout << setw(10) << n << "#" << endl; //默认右对齐
cout << setw(10) << n << "#" << n << endl; //宽度控制不会影响下一个输出
cout << "====================对齐控制====================" << endl;
cout << setw(10) << setiosflags(ios::left) << n << "#" << endl; //设置左对齐
cout << setw(10) << n << "#" << endl; //对齐控制影响下一个输出
cout << setw(10) << setiosflags(ios::right) << n << "#" << endl; //设置右对齐
cout << setw(10) << resetiosflags(ios::left) << n << "#" << endl; //取消左对齐
cout << "====================对齐控制====================" << endl;
cout << setw(10) << setfill('?') << n << "#" << endl;
cout << setw(10) << n << "#" << endl; //填充控制影响下一个输出
cout << setw(10) << setfill(' ') << n << "#" << endl;
cout << "====================精度控制====================" << endl;
cout << setprecision(4) << d << endl; //保留四位有效数字
cout << setprecision(2) << d2 << endl;
cout << setiosflags(ios::fixed);
cout << setprecision(4) << d << endl; //保留小数点后四位
cout << setprecision(2) << d2 << endl;
cout << "====================进制输出====================" << endl;
cout << n << endl;
cout << dec << n << endl;
cout << oct << n << endl;
cout << hex << n << endl;
cout << endl;
cout << setiosflags(ios::showbase);
cout << dec << n << endl;
cout << oct << n << endl;
cout << hex << n << endl;
cout << endl;
cout << setbase(10) << n << endl;
cout << setbase(8) << n << endl;
cout << setbase(16) << n << endl;
return 0;
}
El formato se controla llamando a funciones miembro de la secuencia, como setf, unsetf, ancho, relleno, precisión, etc. La ventaja es que mientras configura el formato, puede volver a la configuración anterior, lo cual es conveniente para restaurar la configuración original.
#include <iostream>
using namespace std;
int main()
{
int n = 64;
double d = 123.45;
double d2 = 0.0187;
cout << "====================宽度控制====================" << endl;//宽度控制不会影响下一个输出
cout << n << "#" << endl;
cout.width(10);
cout << n << "#" << endl;
cout << n << "#" << endl;
cout << "====================对齐控制====================" << endl;//对齐控制影响下一个输出
cout.width(10);
cout.setf(ios::left);
cout << n << "#" << endl;
cout.width(10);
cout << n << "#" << endl;
cout.width(10);
cout.unsetf(ios::left);
cout << n << "#" << endl;
cout.width(10);
cout.setf(ios::right);
cout << n << "#" << endl;
cout << "====================对齐控制====================" << endl;//填充控制影响下一个输出
cout.width(10);
cout.fill('?');
cout << n << "#" << endl;
cout.width(10);
cout << n << "#" << endl;
cout.width(10);
cout.fill(' ');
cout << n << "#" << endl;
cout << "====================精度控制====================" << endl;
cout.precision(4);//保留四位有效数字
cout << d << endl;
cout.precision(2);
cout << d2 << endl;
cout.setf(ios::fixed);
cout.precision(4);//保留小数点后四位
cout << d << endl;
cout.precision(2);
cout << d2 << endl;
cout << "====================进制输出====================" << endl;
cout.setf(ios::showbase);
cout << n << endl;
cout.unsetf(ios::dec);
cout.setf(ios::oct);
cout << n << endl;
cout.unsetf(ios::showbase);
cout << n << endl;
return 0;
}