español - libreria fstream c++
¿La función tellg() da el tamaño incorrecto del archivo? (3)
Hice un proyecto de muestra para leer un archivo en un búfer. Cuando uso la función tellg (), me da un valor mayor que el que la función de lectura realmente se lee del archivo. Creo que hay un error.
Aquí está mi código:
EDITAR:
void read_file (const char* name, int *size , char*& buffer)
{
ifstream file;
file.open(name,ios::in|ios::binary);
*size = 0;
if (file.is_open())
{
// get length of file
file.seekg(0,std::ios_base::end);
int length = *size = file.tellg();
file.seekg(0,std::ios_base::beg);
// allocate buffer in size of file
buffer = new char[length];
// read
file.read(buffer,length);
cout << file.gcount() << endl;
}
file.close();
}
principal:
void main()
{
int size = 0;
char* buffer = NULL;
read_file("File.txt",&size,buffer);
for (int i = 0; i < size; i++)
cout << buffer[i];
cout << endl;
}
tellg
no informa el tamaño del archivo, ni el desplazamiento desde el principio en bytes. Reporta un valor de token que luego se puede usar para buscar el mismo lugar, y nada más. (Ni siquiera se garantiza que pueda convertir el tipo en un tipo integral).
Al menos según la especificación de idioma: en la práctica, en los sistemas Unix, el valor devuelto será el desplazamiento en bytes desde el principio del archivo, y en Windows, será el desplazamiento desde el principio del archivo para los archivos abiertos en modo binario . Para Windows (y la mayoría de los sistemas que no son Unix), en modo de texto, no hay una asignación directa e inmediata entre lo que tellg
y el número de bytes que debe leer para llegar a esa posición. Bajo Windows, todo con lo que puede contar es que el valor no será menor que el número de bytes que debe leer (y en la mayoría de los casos reales, no será mucho mayor, aunque puede ser hasta dos veces más) ).
Si es importante saber exactamente cuántos bytes puede leer, la única manera de hacerlo de manera confiable es mediante la lectura. Deberías poder hacer esto con algo como:
file.ignore( std::numeric_limits<std::streamsize>::max() );
std::streamsize length = file.gcount();
file.clear(); // Since ignore will have set eof.
file.seekg( 0, std::ios_base::beg );
Finalmente, otros dos comentarios concernientes a su código:
Primero, la línea:
*buffer = new char[length];
no debe compilar: ha declarado que el buffer
es un char*
, por lo que el *buffer
tiene el tipo char
y no es un puntero. Teniendo en cuenta lo que parece estar haciendo, es probable que desee declarar el buffer
como un char**
. Pero una solución mucho mejor sería declararlo como std::vector<char>&
o std::string&
. (De esa manera, no tiene que devolver el tamaño también, y no perderá memoria si hay una excepción).
Segundo, la condición de bucle al final es incorrecta. Si realmente quieres leer un personaje a la vez,
while ( file.get( buffer[i] ) ) {
++ i;
}
debe hacer el truco Una mejor solución probablemente sería leer bloques de datos:
while ( file.read( buffer + i, N ) || file.gcount() != 0 ) {
i += file.gcount();
}
o incluso:
file.read( buffer, size );
size = file.gcount();
EDIT: Acabo de notar un tercer error: si no abre el archivo, no se lo dice a la persona que llama. Como mínimo, debe establecer el size
en 0 (pero es probable que sea mejor un manejo más preciso de los errores).
void read_file (int *size, char* name,char* buffer)
*buffer = new char[length];
Estas líneas se parecen a un error: crea una matriz de caracteres y la guarda en el búfer [0]. Luego lees un archivo al búfer, que aún no está inicializado.
Necesitas pasar el buffer
por puntero:
void read_file (int *size, char* name,char** buffer)
*buffer = new char[length];
O por referencia, que es la forma en c ++ y es menos propensa a errores:
void read_file (int *size, char* name,char*& buffer)
buffer = new char[length];
...
fseek(fptr, 0L, SEEK_END);
filesz = ftell(fptr);
hará el archivo si el archivo se abrió a través de fopen
usando ifstream,
in.seekg(0,ifstream::end);
dilesz = in.tellg();
haría similar