[n00b question - Resolvido] Problemas com fwrite no Dev-C++

12 respostas
S
Bom dia a todos, estou tentando escrever um arquivo binário usando C, mas aparentemente o Dev-C++ não interpreta corretamente o fwrite(). Alguém já teve esse problema? Abaixo o código.
int cript(char nmarqini[], char nmarqfin[])
{
	char letra;
	FILE *arqini, *arqfin;
	
	if((arqini = fopen(nmarqini, "r"))
	&& (arqfin = fopen(nmarqfin, "wb")))
	{
		while((letra = fgetc(arqini)) != EOF)
		{
			fwrite(&letra, sizeof(char), 1, arqfin);
		}
		
		fclose(arqini);
		fclose(arqfin);
		
		return 1;
	}
	
	return 0;
}

12 Respostas

V

O devcpp usa uma versão muitíssimo antiga do MinGW e a IDE por si só também é cheia de bugs. Já tentou compilar em algo mais atual, como o Code::Blocks:
http://www.codeblocks.org/

Ou o Visual Studio?
http://www.microsoft.com/express/vc/Default.aspx

S

Pois é!
Já reparei nisso, mas só tenho o Dev-C++ Portable disponível exatamente agora. :frowning:
Mas lendo isso, assumo que deva ser bug do compilador mesmo, já que ele escreve, mas faz uma cópia fiel do arquivo ao invés de transformá-lo em binário.

Agradeço a atenção.

V

O que esse programa deveria fazer?

Qual é o formato do arquivo de entrada e como deveria ser o de saída?

S

Esse programa deveria transformar um arquivo texto para binário. O formato de entrada seria texto puro, sob qualquer extensão, e a saída é um arquivo binário.
Vou tentar compilar no Visual Studio mais tarde para verificar se o erro é meu ou o problema é no compilador mesmo.

T

Stormqueen1990:
Pois é!
Já reparei nisso, mas só tenho o Dev-C++ Portable disponível exatamente agora. :frowning:
Mas lendo isso, assumo que deva ser bug do compilador mesmo, já que ele escreve, mas faz uma cópia fiel do arquivo ao invés de transformá-lo em binário.

Agradeço a atenção.

Não entendi.
O que você entende por “arquivo binário”?
O seu código deveria fazer uma cópia quase fiel do arquivo de entrada, exceto pelo fato que deve converter as sequências \r\n para \n (ou seja, se comportaria como o “dostounix” ou “dos2unix” que existe em alguns sistemas Unix.

S

Binário = não texto.
Quero dizer algo cheio de caracteres ASCII ininteligíveis. Fiz isso algumas vezes na última disciplina de C que cursei na faculdade, e funcionava ok desde que o parâmetro do fopen() para a abertura fosse “wb”, e foi o que tentei fazer aí. Mas não funcionou.
E outra, a cópia não é quase fiel. Ela é fiel. É idêntica.
Se botar em um programa de comparação tipo winmerge ele vai dizer que os arquivos são idênticos.

T

a) O WinMerge deve desprezar a diferença entre arquivos formato Windows (linhas terminadas por ‘\r\n’) e arquivos formato Unix (linhas terminadas por ‘\n’).
b) Você quer criar um arquivo criptografado? Aprenda a usar o OpenSSL ( http://www.openssl.org ). Garanto que você vai ter muitas coisas para se divertir.

S

Vou dar uma olhada.
Masss… esse esquema aí em cima deveria funcionar. Vou dar uma olhada no que já escrevi e ver se tem algo errado.

V

Você não terá caracteres ininteligíveis nesse arquivo, pois está copiando de uma fonte que só tem caracteres inteligíveis. Ou seja, (não) surpreendentemente, a cópia binária de um arquivo texto, também resulta num arquivo texto.

S

:shock:

Bom saber.
Só funciona para gravação direta então?

T

Vou fazer um programa que efetue um XOR de cada byte do arquivo original com 0xFF. Quando você passar o arquivo pelo programa 2 vezes seguidas, irá obter o arquivo original. (Não testei com o Dev-C++ mas sim com o Visual Studio :frowning: )

a) Nunca processe arquivos um byte de cada vez. Isso é lento. Processe vários bytes de cada vez, como faço abaixo.
b) A parte mais chata do C é que ele não tem exceções, portanto você tem de:

  • Ficar checando tudo que é valor de retorno (argh)
  • Tudo que você abriu, feche!
#include <stdio.h>
#include <stdlib.h>

void xorBuf (char bufEntrada[], char bufSaida[], int tam) {
    int i;
    for (i = 0; i < tam; ++i) {
        bufSaida[i] = bufEntrada[i] ^ 0xFF;
    }
}

int cript (const char* arqEntrada, const char* arqSaida) {
    FILE *fEntrada, *fSaida;
    char bufEntrada[1024], bufSaida[1024];
    int nBytes;
    if (!(fEntrada = fopen (arqEntrada, "rb"))) {
        fprintf (stderr, "Nao conseguiu abrir o arquivo de entrada %s\n", arqEntrada);
        return 0;
    }
    if (!(fSaida = fopen (arqSaida, "wb"))) {
        fprintf (stderr, "Nao conseguiu abrir o arquivo de saida %s\n", arqEntrada);
        fclose (fEntrada); // tudo que abriu, feche!
        return 0;
    }
    while ((nBytes = fread (bufEntrada, 1, sizeof(bufEntrada), fEntrada)) > 0) {
        xorBuf (bufEntrada, bufSaida, nBytes);
        fwrite (bufSaida, 1, nBytes, fSaida);
    }
    fclose (fEntrada);
    fclose (fSaida);
    return 1;
}

int main (int argc, char* argv[]) {
    if (argc != 3) {
        fprintf (stderr, "Sintaxe: cript arqEntrada arqSaida\n");
        exit (1);
    }
    if (cript (argv[1], argv[2]) != 1) {
        fprintf (stderr, "Problemas ao efetuar a criptografia.\n");
        exit(1);
    }
    exit (0);
}
S

thingol:
b) A parte mais chata do C é que ele não tem exceções, portanto você tem de:

  • Ficar checando tudo que é valor de retorno (argh)
  • Tudo que você abriu, feche!

Pois é, já sei disso. Também não gosto muito desse negócio de ficar testando e não ter exceções, mas tenho que admitir que há casos em que C é mais prático do que o Java.

Vou tentar fazer algo parecido com o seu código aí em cima.

Agradeço a atenção de vcs rapazes.

Criado 4 de agosto de 2009
Ultima resposta 4 de ago. de 2009
Respostas 12
Participantes 3