Ir ao conteúdo
  • Cadastre-se
Sr. David Almeida

Perda de dados fstream

Recommended Posts

Estou estudando sobre arquivos em C++. O problema é que, leio um arquivo qualquer para uma variável, e após salvar esta variável em um arquivo alguns dados são corrompidos, sendo distorção em imagens e problemas em quebra de linha em arquivos de texto, além de um estranho aumento no tamanho do arquivo...

 

IDE: Code::Blocks

SO: Windows 10 x64

c++11 ISO

 

Segue o código:

 

#include <fstream>
#include <iostream>

using namespace std;

int main ()
{

        ifstream file("ico.jpg");

        file.seekg(0,file.end);
        int siz=file.tellg();

        char value[siz];

        file.seekg(0,file.beg);
        file.read(value,siz);


        ofstream out("out.jpg");
        out.write(value,siz);


    return 0;
}

Desde já, grato.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Certamente um jpg é um arquivo binário. você esta abrindo ele como arquivo de texto plano. Si ao tentar abrir ele com um editor de texto normal você ver um montão de letras estranhas, certamente o arquivo é binario, o que quer dizer que ele é uma representação da memoria ram, ou seja, o que contêm nesse arquivo são chars, ints, floats ou qualquer outro tipo de dado. Até mesmo pode ser uma struct completa enviado ao arquivo. Para poder abrir corretamente esse tipo de arquivo você deveria conhecer a estrutura exata do arquivo. porém se fizer a copia byte a byte pode que funcione abrindo ele como binário e guardando de forma igual, porém isso é uma suposição, eu nem provei nem tenho tempo de faze-lo.

Compartilhar este post


Link para o post
Compartilhar em outros sites
17 horas atrás, vangodp disse:

Certamente um jpg é um arquivo binário. você esta abrindo ele como arquivo de texto plano. Si ao tentar abrir ele com um editor de texto normal você ver um montão de letras estranhas, certamente o arquivo é binario, o que quer dizer que ele é uma representação da memoria ram, ou seja, o que contêm nesse arquivo são chars, ints, floats ou qualquer outro tipo de dado. Até mesmo pode ser uma struct completa enviado ao arquivo. Para poder abrir corretamente esse tipo de arquivo você deveria conhecer a estrutura exata do arquivo. porém se fizer a copia byte a byte pode que funcione abrindo ele como binário e guardando de forma igual, porém isso é uma suposição, eu nem provei nem tenho tempo de faze-lo.

O problema é que o arquivo é lido de forma correta, usando um cout consigo ler todos os Bytes Hexadecimais..., mas já para escrever, alguns dados são estranhamente alterados, e o mesmo acontece com arquivos de texto(estranhamente, com arquivos de texto, só acontece quando há uma quebra de linha, e isto na mesma proporção). Resumindo, o problema, de alguma forma está entre o char usado e o write, porque ao printar os dados dessa array, todos etão corretos, o contrario de quando o arquivo é escrito, que de alguma forma, até o tamanho está diferente da variavel siz usada.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Abre em modo binário.

Citação

ifstream file("ico.jpg", ios::binary);

 

Citação

ofstream out("out.jpg", ios::binary);

Assim dá certo.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
23 horas atrás, MassakiMsk disse:

Abre em modo binário.

 

Assim dá certo.

@MassakiMsk  Estou me sentindo burro por não ter tentado isto... kkk', mas vale um desconto por causa do horário que estava mexendo com isso....

 

Enfim, a solução deu certo tanto para arquivos binários quanto para arquivos de texto. Obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites
5 horas atrás, Sr. David Almeida disse:

Estou me sentindo burro por não ter tentado isto...

O que eu disse, arquivo binário. Se não prestou atenção... :atirador:

Compartilhar este post


Link para o post
Compartilhar em outros sites
14 horas atrás, vangodp disse:

O que eu disse, arquivo binário. Se não prestou atenção... :atirador:

@vangodp Na verdade não tinha entendido direito já que tinha tentando usar em um arquivo de texto e também tinha dado o problema... Aí que entra a parte do texto plano... kkk'

Compartilhar este post


Link para o post
Compartilhar em outros sites

se você abrir qualquer tipo de arquivo com o bloco note pad, e nele sair letras estranhas sem sentido algum, tente abrir como indica MassakiMsk(Modo binário), para isso você deve indicar explicitamente.
Como falei antes... arquivos binários são representações da memória ram em um arquivo. Se guardar um simples int em um arquivo binário, você verá que o tamanho do arquivo é de 4 bytes, ou seja que o arquivo simula a ram e todos os dados ocuparam a mesma quantidade em bytes que ocuparia na ram, por isso você pode copiar esse arquivo, porém para manipular ele você deve conhecer a estrutura tal qual como foi criado, ou seja, a ordem dos tipos de dados. Se eu mandar 1 int, 2 chars, e 1 float, tenho que ler nessa mesma order, pois se tentar ler primeiro 1 char vou pegar literalmente o primeiro char do primeiro int, pois foi um int o primeiro dado que guardei, logo todos os outros dados vão sair corrompidos. Como você faria para arrumar o desastre? Por isso a importância de conhecer a estrutura de um arquivo, conhecer a ordem em que os dados foram mandados ao arquivo, se não você não teria uma mínima possibilidade de manipula-lo com sucesso.


Recomendaria você tentar com arquivos bmp, são relativamente fáceis de carrega-los em memória. Aqui você pode ver como é a estrutura de um arquivo bmp: https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header

 

Nesse link você verá uma tabela dizendo coisas como tamanho do dado usado, e que deve conter nesse dado. Tipo o primeiro campo dice que tem um tamanho em bytes de 2(2bytes), e proporciona a seguinte informação:
The header field used to identify the BMP and DIB file is 0x42 0x4D in hexadecimal, same as BM in ASCII. The following entries are possible:

Que traduzido mais ou menos é:
O campo de cabeçalho usado para identificar o arquivo BMP e DIB é 0x42 0x4D em hexadecimal, o mesmo que BM em ASCII. As seguintes entradas são possíveis:

E os dados que pode guardar são:
 

BM – Windows 3.1x, 95, NT, ... etc.

BA – OS/2 struct bitmap array

CI – OS/2 struct color icon

CP – OS/2 const color pointer

IC – OS/2 struct icon

PT – OS/2 pointer


Então podemos intuir que para guardar BM, BA, CI, etc devemos usar quê? Um array! O "BM" é um array, Igual aos outros dados, "BA", "CI", etc. Vamos ver como reservar memória para isso:

char identificarArquivo[3];

dai você lê os 2 primeiros chars do arquivo e guarde tipo:
identificarArquivo[0] = fgetc();
identificarArquivo[1] = fgetc();
identificarArquivo[2] = '\0';

Esse mesmo dado poderia ser um unsigned short int, e você guardaria o 0x42 0x4D em hexadecimal, pois claramente disse que é o mesmo que BM em ASCII. porém acho mais fácil tratar com arrays, por que podemos fazer coisas como if( identificarArquivo == "BM" ). Ja vê por onde vai o tiro não? Claro que você poderia usar unsigned short int se preferir.


Vamos ver outro dado:
4 bytes -> The size of the BMP file in bytes

Claramente é um int pois guardará o tamanho do arquivo em bytes:
int tamanhoArquivo;

E o seguinte passo é ler um int(4bytes);

 

Não sei se me explico bem e da para entender algo, talvez tudo isso não tenha lhe faça o mínimo sentido. O único que quero deixar claro é que sem saber a estrutura do arquivo binário você jamais poderá tirar nada claro desse arquivo, que traduzido quer dizer que se você não souber como é o arquivo a única operação possível é copiar e colar byte a byte.

 

E para deixar constância, jpg é bem mais complicado de entender que bmp, eles costumam vir codificados, e precisam de um complexo algoritmo para descompressão, acho que nem vale a pena você mexer com eles a não ser que você vai trabalhar com eles em um projeto importantíssimo. Melhor seria usar uma biblioteca para carrega-lo que lhe entregue justo o que você quer que é um array com as informações de cada pixel tipo RGB.

É um tema complicado mas muito interessante.
Bom me piro que já gastei as unhas e nem escrevo bem em português. Sorte

 

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×