Avatar billede rwj_defcon1 Nybegynder
21. april 2004 - 11:14 Der er 20 kommentarer og
1 løsning

Dataudveksling via binære data til Java

Hej... jeg står overfor at skulle få java (på en mobiltelefon) og noget C# til at snakke sammen ved at konvertere mine C# objekter om til binær data og sende dem til Java....

Jeg har derfor som start lavet følgende to testprogrammer for at se om jeg kunne få lavet to filer der binært er ens.

C#
****
FileStream fs = new FileStream(@"C:\test.bin", FileMode.CreateNew);
BinaryWriter mitOutput = new BinaryWriter(fs,System.Text.Encoding.UTF8);
mitOutput.Write("Hej med dig");
mitOutput.Write(123);
mitOutput.Write(true);
mitOutput.Write(9.9);
mitOutput.Flush();
mitOutput.Close();
fs.Close();

-------------------------------------------------------

Java
***
FileOutputStream fos = new FileOutputStream(new File "/test.bin"));
DataOutputStream dos = new DataOutputStream(fos);
dos.writeUTF("Hej med dig");
dos.writeInt(123);
dos.writeBoolean(true);
dos.writeDouble(9.9);
dos.flush();
dos.close();
fos.flush();
fos.close();

-------------------------------------------------------

Hvert program i sig selv giver en binær fil, men problemet er at disse to binære filer ikke er ens.

Nogen der har siddet med ligende problemstilling og evt har en løsning, eller skal jeg selv til at lave en encoding-standard?

/Rasmus
Avatar billede arne_v Ekspert
21. april 2004 - 11:24 #1
Der er flere ting der skal være styr på:

1)  at data fylder det samme f.eks. at C# Write(9.9) og Java writeDouble
    udskriver det samme antal bytes

2)  at data er en encoded f.eks. at C# Write(true) og Java writeBoolean(true)
    bruger samme størrlese og værdi for true

3)  at text udskrives med samme encoding, UTF-8 versus ISO-8859-1/CP-1252

4)  at tal udskrives med samme endianness, little endian versus big endian

Du har helt styr på #3. #2 skulle også være OK. #1 er nem at checke ved
at se om filem har forskellig størrelse.

Mit gæt er helt klar #4. Java DataOutputStream udskriver i net order
d.v.s. big endian. Det lyder ikke usandsyneligt at .NET er
Intel x86 centric og derfor bruger little endian.
Avatar billede rwj_defcon1 Nybegynder
21. april 2004 - 11:35 #2
Hmm... Det ser også ud til at være et problem med #1 Java fylder 23byte mens C# fylder 25byte

Ligeledes ser det ud til at rækkefølgen på data'ene bliver byttet om på en eller anden måde (Prøver lige at se om man kan copy-paste dataenen ind her)

JAVA:
-----------------------------
Hej med dig{@#ÌÌÌÌÌÍ
-----------------------------
(her er det især det første tomme tegn der forvirre mig.. det er hex 00, samt )

C#:
-----------------------------
Hej med dig{  ÍÌÌÌÌÌ#@
-----------------------------
(Her sidder #@ til sidst i strengen og ikke som i javas i midten)
Avatar billede rwj_defcon1 Nybegynder
21. april 2004 - 11:37 #3
hmm... forum viser ikke det tomme tegn der er foran java's "Hej"... det er ikke et almindeligt mellemrum (Hex 20, men hex 00 hvad det så end er)
Avatar billede arne_v Ekspert
21. april 2004 - 11:40 #4
Det sidste med double tyder helt klart på et big little endian problem (#4).
Avatar billede arne_v Ekspert
21. april 2004 - 11:45 #5
Java writeUTF prefixer bogstaverne med 2 bytes med længden af strengen

.NET Write String er lidt mere uklar på det område, fra docs:

Remarks
A length-prefixed string represents the string length by prefixing to the string a single byte or word that contains the length of that string.
Avatar billede arne_v Ekspert
21. april 2004 - 12:01 #6
Nu har jeg prøvet at køre dem hos mig. Og der er 2 forskelle:

A) C# prefixer strengen med kun 1 byte - Java prefixer strengen med 2 bytes

B) int og double er big endian i Java og little endian i C#
Avatar billede arne_v Ekspert
21. april 2004 - 12:02 #7
#A er nem at løse:

        dos.writeByte("Hej med dig".length());
        dos.write("Hej med dig".getBytes("UTF-8"));
Avatar billede arne_v Ekspert
21. april 2004 - 12:09 #8
#B int kan fixes med:

        dos.writeInt(revbyte(123));

og

    public static int revbyte(int v) {
        return ((v >> 24) & 0x000000FF) |
            ((v >> 8) & 0x0000FF00) |
            ((v << 8) & 0x00FF0000) |
            ((v << 24)& 0xFF000000);
    }
Avatar billede rwj_defcon1 Nybegynder
21. april 2004 - 12:10 #9
Ang. #B ... jeg prøvede i C# at lave encoding om til big endian og fik en 35byte fil : 

 H e j  m e d  d i g{  ÍÌÌÌÌÌ#@

Og det er jo helt forkert
Avatar billede arne_v Ekspert
21. april 2004 - 12:12 #10
BigEndianUnicode er ikke det samme som big endian int
Avatar billede rwj_defcon1 Nybegynder
21. april 2004 - 12:17 #11
ok.... jeg er ret ny ud i det binære :-) .... prøver lige at lave nogle nye filer udfra dine ændringer i java'en
Avatar billede arne_v Ekspert
21. april 2004 - 12:23 #12
using System;
using System.IO;

class MainClass
{
    public static void Main(string[] args)
    {
        FileStream fs = new FileStream(@"C:\csbin.dat", FileMode.CreateNew);
        BinaryWriter bw = new BinaryWriter(fs,System.Text.Encoding.UTF8);
        bw.Write("Hej med dig".);
        bw.Write(123);
        bw.Write(true);
        bw.Write(9.9);
        bw.Close();
        fs.Close();
    }
}
Avatar billede arne_v Ekspert
21. april 2004 - 12:24 #13
import java.io.*;

public class WriteBin {
    public static int revbyte(int v) {
        return ((v >> 24) & 0x000000FF)
            | ((v >> 8) & 0x0000FF00)
            | ((v << 8) & 0x00FF0000)
            | ((v << 24) & 0xFF000000);
    }
    public static long revbyte(double v) {
        long v2 = Double.doubleToRawLongBits(v);
        return ((v2 >> 56) & 0x00000000000000FFL)
            | ((v2 >> 40) & 0x000000000000FF00L)
            | ((v2 >> 24) & 0x0000000000FF0000L)
            | ((v2 >> 8) & 0x00000000FF000000L)
            | ((v2 << 8) & 0x000000FF00000000L)
            | ((v2 << 24) & 0x0000FF0000000000L)
            | ((v2 << 40) & 0x00FF000000000000L)
            | ((v2 << 56) & 0xFF00000000000000L);
    }
    public static void main(String[] args) throws Exception {
        FileOutputStream fos = new FileOutputStream("C:\\javabin.dat");
        DataOutputStream dos = new DataOutputStream(fos);
        dos.writeByte("Hej med dig".length());
        dos.write("Hej med dig".getBytes("UTF-8"));
        dos.writeInt(revbyte(123));
        dos.writeBoolean(true);
        dos.writeLong(revbyte(9.9));
        dos.close();
        fos.close();
    }
}
Avatar billede arne_v Ekspert
21. april 2004 - 12:24 #14
Outputter ens bytes.

Jeg har lavet fedteriet på Java siden. Det kunne sikkert lige så nemt have
været lavet på C# siden.
Avatar billede rwj_defcon1 Nybegynder
21. april 2004 - 12:27 #15
ok.... det er der jeg skal have det lavet, da det er C# der skal skrive det og java der skal læse det
Avatar billede arne_v Ekspert
21. april 2004 - 12:30 #16
Det vil være ret nemt at lave den Java kode om til at læse i.s.f. at skrive.

int revbyte kan genbruges uændret

double revbyte skal lige justeres
Avatar billede arne_v Ekspert
21. april 2004 - 12:36 #17
import java.io.*;

public class ReadBin {
    public static int revbyte(int v) {
        return ((v >> 24) & 0x000000FF)
            | ((v >> 8) & 0x0000FF00)
            | ((v << 8) & 0x00FF0000)
            | ((v << 24) & 0xFF000000);
    }
    public static double revbyte(long v) {
        long v2 =
            ((v >> 56) & 0x00000000000000FFL)
                | ((v >> 40) & 0x000000000000FF00L)
                | ((v >> 24) & 0x0000000000FF0000L)
                | ((v >> 8) & 0x00000000FF000000L)
                | ((v << 8) & 0x000000FF00000000L)
                | ((v << 24) & 0x0000FF0000000000L)
                | ((v << 40) & 0x00FF000000000000L)
                | ((v << 56) & 0xFF00000000000000L);
        return Double.longBitsToDouble(v2);
    }
    public static void main(String[] args) throws Exception {
        FileInputStream fis = new FileInputStream("C:\\csbin.dat");
        DataInputStream dis = new DataInputStream(fis);
        byte[] b = new byte[dis.readByte()];
        dis.read(b);
        String sv = new String(b, "UTF-8");
        int iv = revbyte(dis.readInt());
        boolean bv = dis.readBoolean();
        double xv = revbyte(dis.readLong());
        dis.close();
        fis.close();
        System.out.println(sv + " " + iv + " " + bv + " " + xv);
    }
}
Avatar billede arne_v Ekspert
21. april 2004 - 12:37 #18
Men du skal holde tungen lige i munden !
Avatar billede arne_v Ekspert
21. april 2004 - 12:37 #19
Og et svar
Avatar billede rwj_defcon1 Nybegynder
21. april 2004 - 12:41 #20
Jeg stoler på dig når du siger det virker.... Du ser ud til at have rigtig godt styr på alt det her.... Jeg prøver og takker på forhånd
Avatar billede arne_v Ekspert
21. april 2004 - 12:43 #21
Du kan jo bare prøve at køre mit C# program og det sidste af mine Java
programmer.

Output er rigtigt.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester