# Große Datei mit Regex durchsuchen



## mainclain (5. Jan 2011)

Hallo,
ich stehe seit gestern vor einem Problem, welches ich einfach nicht lösen kann.
Ich möchte eine 6MB große Datei mit Regex durchsuchen - und da ist eben mein Problem.
Zudem ist dies eine exe datei. Und ich möchte die Bytes vergleichen (heißt eine einfache umwandlung in String ist auch nicht möglich.)

Bei C# habe ich dies einfach geöffnet:

```
byte[] exeByte = System.IO.File.ReadAllBytes("meineExe.exe");
string exe_s = ByteToString(exeByte);

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

Also erstmal das ganze in ein Byte-Array geladen und das ganze danach byte für byte in ein String (im Hex-Format) umgewandelt.
Ging bei C# in wenigen Sekunden.


Das gleichte versuchte ich auch in Java:

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


```
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 ganze funktioniert auch - nur bei 6GB ist es unheimlich langsam (Würde mehere Stunden dauern).
Ein StreamBuilder ging leider nicht - heap Exception, klar 6MB in speicher laden...


Nun weiß ich nicht weiter wie ich das ganze durchsuchen soll :/


Liebe Grüße und nen schönen Abend noch ^.^


----------



## kirchrath (6. Jan 2011)

Wie soll denn deine Regexp aussehen? Ich würde bei so einer großen Datenmenge versuchen byteweise bzw. in kleinen Intervallen die Daten einzulesen und direkt überprüfen ob es möglicherweise einen Treffer gibt. Auf keinen Fall würde ich versuchen diese Datenmenge (besonders nicht in Java) in den Speicher zu laden...

Gruß
Kirchrath


----------



## mainclain (6. Jan 2011)

Hallo, also ein Beispiel:

```
"568B7424(.{2})8BC633D2F771(.{2})8B41(.{2})8B149085D274.{2}3972.{2}74.{2}8B1285D275.{2}33C05EC2.{4}8B4424.{2}85C074.{2}8B4A(.{2})"
```
Und genauso sehen die Bytes auch aus.
Als müsste ichs am besten in einer Schleife laden (eventuell immer etwas gröber 100 Zeichen oda so) jedes mal die Bytes einzelnt in Strings umwandeln und dann Regex drüberlaufen lassen?

Naja mal probieren wie das von der Performance Funktioniert.
Danke schonmal für die Anregung werde ich morgen ausprobieren xD


----------



## Iron Monkey (6. Jan 2011)

Hi MainClain!

Ich würde in dem Fall in der Schleife nie mit String jedesmal verknüpfen!

Versuch mal besser mit StringBuffer, z.B.:

Mit StringBuffer geht noch schneller als mit String!


```
StringBuffer sb = new StringBuffer();
        for(byte b : ByteArray)
        {
            sb.append( padLeft(Long.toHexString(b), 2, "0") );
            System.out.print( sb.toString() );
        }
 
        return sb.toString();
```


```
public static String padLeft(String s, int n, String form) {
        if(s.length() >= n)
            return s;
 
        int len = n - s.length();
        StringBuffer f = new StringBuffer();
        for(int i = 0; i < len; i++)
        {
            f.append( form );
        }
        return f.toString()+s;
    }
```

Mit RandomAccesFile kannst du z.B. bei 6 GB besser blockweise ( z.B. Buffer mit 65 kb ) auslesen und verarbeiten! Kannst du ja mal versuchen!

Gruß
Iron Monkey


----------



## mainclain (6. Jan 2011)

Okay nun klappt alles bei mir^^
Bin einzelnd durch gegangen:



```
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.....
           }
```


----------

