C++ e Java (Arquivos)

O modo de gravação de arquivos em disco em Java e C++ é diferente, a função abaixo grava 1 inteiro em arquivo…

public void gravarInteiro (RandomAccessFile file, int valor){ int x = valor; x = ((x >> 24) & (0xFF) | (x >> 8) & (0xFF00) | (x << 8) & (0xFF0000) | (x << 24) & (0xFF000000)); try { file.writeInt(x); } catch (IOException e) { e.printStackTrace(); } }

Como não tenho muita experiencia, gostaria de saber como faço pra gravar um SHORT e um vetor de caracteres CHAR[].

O arquivo será gravado em Java e lido pelo C++

É interessante criar as seguintes três funções em Java:

public int htoni (int x) { // 4 bytes: C++ = &quot;int&quot; ou &quot;long&quot;
return ((x &gt&gt 24) & (0xFF) | (x &gt&gt   8) & (0xFF00) | (x &lt&lt   8) & (0xFF0000) | (x &lt&lt 24) & (0xFF000000));
}
public short htons (short x) { // 2 bytes: C++ = &quot;short&quot; ou &quot;wchar_t&quot;
return ...;
}
public long htonl (long x) { // 8 bytes: C++ = &quot;long long&quot; ou &quot;__int64&quot;
return ...;
}

Elas "invertem a ordem dos bytes" e são necessárias quando o programa em C++ está rodando em uma plataforma Intel ou AMD e o cara que codificou o programa não se importou com a ordem dos bytes.

Agora, quanto ao array de caracteres, gostaria de saber como é que o programa em C está esperando os dados. Ele espera que os caracteres sejam terminados por um "\0" ou então que haja um indicador de comprimento dos dados?

Se for o primeiro caso, deve ser algo como:

String s = "Gisele da Conceição Zózima Bündchen\0";
byte[] bytes = s.getBytes ("ISO-8859-1");

Se for o segundo, é uma coisa parecida com o primeiro, mas você tem de ver como é que o tal indicador deve ser gravado.

Dê uma olhada na classe ByteBuffer e FileChannel. Você daí não precisa fazer muita álgebra booleana, pode escolher se a ordem vai ser big ou little endian, etc.

Também tivemos que lidar com C++ aqui. A classe ByteBufferWorker em anexo vai te ajudar. Ela possui métodos para leitura de dados unsigned e também para leitura de strings terminadas em /0. Tem também uma função útil para gerar um dump de um ByteBuffer.

O meu problema é que tenho q gravar a seguinte estrutura para ser lida em C++:

typedef struct { char Nome[52]; // nome do usuario WORD Classe; // classe do usuario float ValCH; // valor de um CH DWORD Num; // número de sequencia do usuario }StructReg;

Criei uma classe chamada StructReg para se comportar como a struct e agora preciso gravar os dados num arquivo para ser lido uma unica vez como um bloco (a struct em si). e por isso preciso das conversões… :cry:

/* C++ - estou supondo que você esteja usando #pragma pack(1). Se não estiver usando #pragma pack(1), é necessário preencher com bytes zero cada campo para que ele comece em um endereço múltiplo de 4  */
typedef struct
 {
 	char Nome[52];  		// nome do usuario	
 	WORD Classe; 			// classe do usuario
 	float ValCH; 			// valor de um CH	
 	DWORD Num; 		// número de sequencia do usuario
 }StructReg;
/* Java */
class Util {
    public byte[] htons (short s) {
        byte[] ret = new byte[2];
        ret[0] = (byte) s;
        ret[1] = (byte) (s&gt&gt8);
        return ret;
    }
    public byte[] htoni (int x) {
        byte[] ret = new byte[4];
        ret[0] = (byte) s;
        ret[1] = (byte) (s &gt&gt 8);
        ret[2] = (byte) (s &gt&gt 16);
        ret[3] = (byte) (s &gt&gt 24);
        return ret;
    }
}

class StructReg {
     public String nome; /* 0..51 */
     public short classe; /* 52...53 */
     public float valch;   /* 54...57 */
     public int num;       /* 58...61 */
     /* Converte um StructReg em um array de bytes */
     public byte[] getBytes() throws {
         byte[] retorno = new byte[62];
         byte[] bytesNome = nome.getBytes(&quot;ISO-8859-1&quot;);
         byte[] bytesClasse = htons (classe);
         byte[] bytesValch = htoni (Float.floatToIntBits (valch));
         byte[] bytesNum = htoni (num);
         int pos = 0;
         System.arraycopy (bytesNome, 0, retorno, pos, bytesNome.length);
         pos += bytesNome.length;
         System.arraycopy (bytesClasse, 0, retorno, pos, bytesClasse.length);
         pos += bytesClasse.length;
         System.arraycopy (bytesValch, 0, retorno, pos, bytesValch.length);
         pos += bytesValch.length;
         System.arraycopy (bytesNum, 0, retorno, pos, bytesNum.length);
         pos += bytesNum.length;
         return retorno;
     }
}

Tudo certo, agora só voltando à função:

public void gravarInteiro (RandomAccessFile file, int valor){ int x = valor; x = ((x >> 24) & (0xFF) | (x >> 8) & (0xFF00) | (x << 8) & (0xFF0000) | (x << 24) & (0xFF000000)); try { file.writeInt(x); } catch (IOException e) { e.printStackTrace(); } }

Preciso da função similar que ao invés de gravar inteiro grave short, e consequentemente converta um Inteiro