ununes
Março 29, 2006, 9:21am
#1
Pessoal, olha que problema estranho em manipulação de arquivos usando c++ e Java:
Tenho um programa em c++ que grava a seguinte struct em arquivo:
struct
{
long Tamanho;
int codigo;
} Cabecalho
A parte de gravação dos dados (após setados os valores) no disco é:
HFILE File;
OFSTRUCT Of;
Cabecalho Dados;
File = OpenFile ( (LPCSTR) Nome.c_str(), &Of, OF_WRITE);
_lwrite(File,(char *)&Dados,sizeof(Dados));
_lclose(File);
E uma função em Java para ler esse arquivo:
private void openFile () {
JFileChooser fileChooser = new JFileChooser ();
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
int result = fileChooser.showSaveDialog(this);
if (result == JFileChooser.CANCEL_OPTION){
System.out.println("Clicado CANEL");
}
File fileName = fileChooser.getSelectedFile();
if (fileName == null || fileName.getName().equals("")){
System.out.println("Erro no nome do arquivo");
}
else {
try {
file = new RandomAccessFile(fileName,"rw");
long tamanho = file.readLong();
int codigo = file.readInt();
System.out.println(tamanho);
System.out.println(codigo);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
O problema todo é que quando a função Java lê o arquivo, os valores encontrados são diferentes dos valores gravados pela função C++.
Alguém sabe por que isso ocorre e principalmente, qual a forma correta de se lêr esses dados?
Obrigado aos que ajudarem…
Ulisses Nunes
Dicas:
a) long do C++ = 4 bytes, long do Java = 8 bytes. Portanto você tem de usar readInt, não readLong
b) Se estiver usando uma máquina Intel ou AMD (ou Via, ou sei lá que compatível com o Pentium que você tem), a ordem dos bytes do C++ é ao inverso da ordem dos bytes do Java. Se em C++ você tiver um int com o valor em hexadecimal 0x12345678 (decimal 305419896), em Java esse valor será lido como 0x78563412 (decimal 2018915346). Ou seja, você vai ter de pegar os bytes e inverter a ordem.
Uma forma de inverter os bytes (embora não seja a mais rápida - eu sei que existem uns truques federais, mas não estou conseguindo encontrá-los com facilidade) é esta (confira por favor, estou fazendo de cabeça)
int x = 0x11223344;
x = ((x >> 24) & 0xFF ) |
(x >> 8) & 0xFF00) |
(x << 8) & 0xFF0000) |
(x << 24) & 0xFF000000));
System.out.println (Integer.toHexString (x)); // deveria imprimir 44332211.
ununes
Março 29, 2006, 2:09pm
#4
Sua função de shift funciona perfeitamente. Se não for abusar muito poderia me passar a mesma para conversão de variaveis long?
O “long” do C++ é o “int” do Java (pelo menos em Windows e Linux 32 bits), portanto não é preciso fazer uma outra função de shift.
ununes
Março 29, 2006, 2:38pm
#6
Funcionou perfeitamente, obrigado pela ajuda.
Agora, tenho outra questão…
e como faria para ler um char[100] que representa o nome do Cliente?? E tipos WORD e DWORD em C++, como são representados em Java?
Att. Ulisses Nunes
char © = byte (Java).
Faça o seguinte: pegue os 100 caracteres © e leia em um array de 100 bytes (Java). Você pode então converter os bytes para uma String usando new String (bytes, “ISO-8859-1”). Como uma string em C termina por ‘\0’, você tem de encontrar o primeiro ‘\0’ nessa string e “podar” a string Java resultante nessa posição (use indexOf).
WORD © = short (Java)
DWORD © = int (Java)
ununes
Março 30, 2006, 10:19am
#8
Aproveitando a aula, fica faltando saber a correspondência em Java dos tipos float e double em C++.
float © = float (Java)
double © = double (Java)
Problema: como a ordem dos bytes é invertida, você teria de “desinverter”, só que o processo é mais complexo. Te digo mais tarde como é que se faz.
thingol
Março 30, 2006, 11:10am
#10
Código em C++ para criar um arquivo com 1 double e 1 float.
#define _CRT_SECURE_NO_DEPRECATE
#define _USE_MATH_DEFINES
#include <cstdio>
#include <cmath>
using namespace std;
int main (int argc, char *argv[]) {
FILE* f = fopen ("teste.bin", "wb");
double dbl = M_PI; // 3.14159265358979323846
float flt = M_E; // 2.71828182845904523536
fwrite (&dbl, sizeof(dbl), 1, f);
fwrite (&flt, sizeof(flt), 1, f);
fclose (f);
}
Código em Java para ler esse arquivo.
import java.io.*;
class DoubleCJava {
public static void main(String[] args) throws Exception {
DataInputStream dis = new DataInputStream (new FileInputStream ("teste.bin"));
long _dbl = dis.readLong();
int _flt = dis.readInt();
dis.close();
_flt = ( (_flt >>> 24 & 0x000000FF)
| (_flt >>> 8 & 0x0000FF00)
| (_flt << 8 & 0x00FF0000)
| (_flt << 24 & 0xFF000000));
_dbl = ( (_dbl >>> 56 & 0x00000000000000FFL)
| (_dbl >>> 40 & 0x000000000000FF00L)
| (_dbl >>> 24 & 0x0000000000FF0000L)
| (_dbl >>> 8 & 0x00000000FF000000L)
| (_dbl << 8 & 0x000000FF00000000L)
| (_dbl << 24 & 0x0000FF0000000000L)
| (_dbl << 40 & 0x00FF000000000000L)
| (_dbl << 56 & 0xFF00000000000000L));
float flt = Float.intBitsToFloat(_flt);
double dbl = Double.longBitsToDouble(_dbl);
System.out.println (dbl); // imprime 3.141592653589793
System.out.println (flt); // imprime 2.7182817
}
}
ununes
Março 30, 2006, 11:12am
#11
Funcionou tudo perfeitamente, obrigado.