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

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.

[code]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;

}[/code]

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

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.

O que esse programa deveria fazer?

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

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.

[quote=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.[/quote]

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.

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.

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.

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.

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.

:shock:

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

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);
}

[quote=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!
    [/quote]

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.