Exe Datei auslesen und in String schreiben.

Mainclain

Mitglied
Hallo, ich habe ein kleines Problem.
Ich möchte gerne eine exe-Datei Byteweise auslesen und diese Bytes in Hex-Form in ein String bringen.

Das ganze funktionierte in C# ganz gut, hier mein Ansatz von C#:
Code:
byte[] exeByte = System.IO.File.ReadAllBytes("meineExe.exe");
string exe_s = ByteToString(exeByte);

ByteToString sieht wie folgt aus:

Code:
private string ByteToString(byte[] ByteArray)
        {
            System.Text.StringBuilder sb = new StringBuilder();
            foreach (byte b in ByteArray)
                sb.Append(Convert.ToString(b, 16).PadLeft(2, '0'));
            return sb.ToString();
        }

Soo das läuft in wenigen Sekunden durch, alles kein Problem - Nun wollte ich das gleiche in Java hinbekommen.

Code:
File file = new File(filename) ;
long size = file.length() ;
byte[] buf = new byte[(int)size] ;

FileInputStream fis = new FileInputStream(file);
fis.read(buf) ;

String exe = ByteToString(buf);


ByteToString:
Code:
        String sb = "";
        for(byte b : ByteArray)
        {
            sb += padLeft(Long.toHexString(b), 2, "0");
            System.out.print(padLeft(Long.toHexString(b), 2, "0"));
        }

        return sb;

und padLeft:
Code:
      public static String padLeft(String s, int n, String form) {
        if(s.length() >= n)
            return s;

        int len = n - s.length();
        String f = "";
        for(int i = 0; i < len; i++)
        {
            f += form;
        }
        return f+s;
    }
Das dauert aber Stunden bis die Exe geladen ist - Was mich auch nicht wundert, sind immerhin 6 GB^^
Die Exe muss ich allerdings mit regex nach Inhalten durchsuchen und in C# klappt das ganze Wunderbar.


Vll habt ihr ja eine Ahnung, wie man das ganze schneller machen kann und wo da mein Problem liegen könnte.
(Ich denke es ist beim umwandeln zum String zu langsam... Den fis.read(buf) ; läuft recht schnell durch)

Noch einen schönen Abend


PS:
Noch eine kleine Ergänzung:
Die ersten Zeichen des Strings sehen bei Java wie folgt aus:
4d5affffffffffffff90000300000004000000

bei dem C# Programm allerdings
4d5a90000300000004000000
Wo kommen die ffffffffs her? Jemand eine Idee?^^
 
Zuletzt bearbeitet:
vielleicht das hilft:
Java:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

Gruß Attila
 
... und es wäre auch besser (auch in Java) in ByteToString anstatt String ein StringBuilder benutzen.

Gruß Attila
 
Hilft leider nur geringfügig.
Gibt es eine Möglichkeit Regex direkt auf eine Datei anzuwenden, ohne diese komplett einzulesen?

Wichtig wäre dabei eben nur das er es wirklich mit den bytes vergleicht(ansonstn siehts ja irgentwie so aus:
MZ ÿÿ ¸ @
statt
4d5a90000300000004000000)

^^

Achja wegen den StringBuilder... habs versucht aber es gab nen Fehler, wahrscheinlich wurde der String zu lang?^^

java.lang.OutOfMemoryError: Java heap space

Denke also es liegt daran das nicht genügend Arbeitsspeicher verfügbar ist.
Ist immerhin eine 6GB große Datei - Anders gehts leider auch nicht. Da ich mit Regex die gesamte datei durchsuchen muss... naja mit C# gings ja auch irgentwie ^^


Hmm vll liegt es schon am Laden der Datei.
Daran liegt wohl das

FFFFFF90 - Was die datei ja noch größer macht :/
Frag mich woher die FFFFFFs kommen^^





Sooo kleines Update:
Das FF problem hab ich gelöst indem ich die Zeilen einzelnt geladen hab.

Code:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

           String str = "";
            while(bis.available() != 0)
            {
                str += padLeft(Integer.toHexString(bis.read()), 2, "0");
            }

So ist es auch gleich in einem String drin. Problem mit dem heap is noch immer da (Ist ja auch klar, die frage ist eher - Wieso funktionierts bei C#^^)
 
Zuletzt bearbeitet:
Also
Gibt es eine Möglichkeit Regex direkt auf eine Datei anzuwenden, ohne diese komplett einzulesen?
Schau dir mal das Kapitel 17 der JavaInsel an: http://openbook.galileocomputing.de/javainsel9/javainsel_17_001.htm

Zu deinem Performance-Problem:
1. das aneinanderhängen von Strings ist in Java sehr Rechenaufwändig. Wenn man mit größeren Strings arbeitet, nutzt man meist StringBuilder.
2. wegen diesem
java.lang.OutOfMemoryError: Java heap space
Fehler hier: sieh dir mal die JVM-Parameter Xmx und Xms an. Sie werden mit
Code:
java -X
ausgegeben oder sind unter http://download.oracle.com/docs/cd/E13222_01/wls/docs81/perform/JVMTuning.html zu finden.
3. warum musst du eine 6GB große exe-Datei auslesen? so etwas kann es doch eigentlich gar nicht geben… da wäre ja mehr Code drin als in allen bisherigen Windows-Versionen zusammen…
4. Was willst du eigentlich mit der Datei machen? suchst du einen bestimmten HexCode bzw. eine bestimmte ByteFolge? Dann müsstest du die Datei ja nicht komplett einlesen, sondern immer nur den Puffer füllen, "leer-lesen" und wieder füllen….

Soo das läuft in wenigen Sekunden durch, alles kein Problem
Will ich sehen :D selbst auf meiner SSD würde das pure lesen der Datei ca. 40sekunden dauern…
Hast du ne ganze Server-Farm zur Verfügung (mit >>6GB RAM)?
 
Zuletzt bearbeitet:
4. Was willst du eigentlich mit der Datei machen? suchst du einen bestimmten HexCode bzw. eine bestimmte ByteFolge? Dann müsstest du die Datei ja nicht komplett einlesen, sondern immer nur den Puffer füllen, "leer-lesen" und wieder füllen….

Problematisch wird das denn, wenn die Bytefolge genau zwischen zwei Speicherungen steht ;)

Beispiel:
Gesuchte Bytefolge: A7 B3 1C D4
Puffer: B2 B9 A7 B3
Puffer, überschrieben: 1C D4 A5 1E
 
Problematisch wird das denn, wenn die Bytefolge genau zwischen zwei Speicherungen steht ;)

Beispiel:
Gesuchte Bytefolge: A7 B3 1C D4
Puffer: B2 B9 A7 B3
Puffer, überschrieben: 1C D4 A5 1E

Erstmal danke an alle für eure Antworten^^
Bin gerade dabei die Datei wie erwähnt mit einer Schleife zu durchsuchen.
Bisher ist zumindest das regex nicht eingeschlagen^^.
Habe das nun so gelöst, das ich immer 2* 1000Byte abspeicher

Dadurch sollte sich auch eigentlich das von dir erwähnte problen lösen.

Ich setzer die alte Bytefolge mit der neuen zusammen - so durchsuch ich zwar teile doppelt, aber dann ist zumindest das Problem gelöst^^


Was die 6Gb angeht - hab mich natürlich verschrieben sind nur 6MB :D (Ist ja kaum ein unterschied *hust hust*)


So nun gehts... zumindest größtenteils xD


Code:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

           String oldStr = "";

           while(bis.available() != 0)
           {
               String workString = "";

               StringBuilder BtS = new StringBuilder();
               int wS = 0;
               while(wS < 1000 && bis.available() != 0)
               {
                   BtS.append(padLeft(Integer.toHexString(bis.read()), 2, "0"));
                   wS++;
               }
               workString = oldStr + BtS.toString();

               if(oldStr.length() == 0)
               {
                   oldStr = workString;
               }else
               {
                   oldStr = workString.substring(workString.length()/2);
               }

//regex.....
           }

Die 2.While Schleife musste ich setzen, da er sonst irgentwie öfters FFFFFFF eingefügt hat (Ich frag mich nur warum... xD)
 
Zuletzt bearbeitet:
@Matthias Reitinger: du hast Recht, ich hab mich vertan (hab mit 280MBit/s statt 280MB/s gerechnet)

@timestamp: deswegen würde ich nur nach dem ersten Byte suchen und nur dann weitersuchen, wenn es gefunden wurde

@Mainclain: das ganze wäre deutlich performanter, wenn du den gesuchten String von HexCode in ein ByteArray codierst. Dann kannst du die Bytes überprüfen und musst nicht jedes mal Strings erzeugen. So lange du einen BufferedInputStream oder ähnliches verwendest, hast du auch keine probleme mit dem von timestamp angesprochenen Fall.
 
Zurück