0

I am trying to edit the hex code of a file. The code in C# needs to find either the decoded text i.e., 1004 or the corresponding hex 31 30 30 34 and replace with string 2113 or either the corresponding hex 32 31 31 33

I have tried to edit the string directly using:-

string test = File.ReadAllText("tram.png");
Regex id = new Regex("1004");
string idre = id.Replace(test, "2113", 1);
File.WriteAllText("tram.png", idre);

Also tried Byte method

Byte[] test = File.ReadAllBytes("tram.png");             
Byte[] id = new Regex("1004");             
Byte[] idre = id.Replace(test, "2113", 1);
File.WriteAllBytes("tram.png", idre);

It says 'byte[]' does not contain a definition for 'Replace' and Cannot implicitly convert type 'System.Text.RegularExpressions.Regex' to 'byte[]'

Can you tell me what am I doing wrong please?

  • 4
    PNG is not a text file. You need to read the file bytes. – Wiktor Stribiżew Jul 29 '20 at 14:25
  • @WiktorStribiżew Yah, I also tried with other text files. But, it just doesn't work. I am still not able to figure out the byte method though. I tried `Byte[] test = File.ReadAllBytes("tram.png"); Byte[] id = new Regex("1004"); Byte[] idre = id.Replace(test, "2113", 1); File.WriteAllBytes("tram.png", idre);` And, it gives me an error that Bye doesn'thave replace defined. – droidtaber Jul 29 '20 at 14:31
  • 1
    The `Replace` methods work on strings not bytes. You need to use a different scheme. Please [edit] the question to explain the problem more clearly and explain what you have tried. – AdrianHHH Jul 29 '20 at 14:38
  • 1
    Sure, regex only works on text data. You need to convert byte to strings, run the regex and then convert back. – Wiktor Stribiżew Jul 29 '20 at 14:40
  • Use `File.ReadAllBytes`, then [replace the appropriate bytes in that byte array](https://stackoverflow.com/questions/5132890/c-sharp-replace-bytes-in-byte), then use `File.WriteAllBytes`. – Joe Sewell Jul 29 '20 at 14:41
  • @AdrianHHH Tried the two methods in the question. I have updated it. – droidtaber Jul 29 '20 at 14:42
  • @JoeSewell I tried that and when I try to add the extension method as in the answer,it just gives me extension method must be defined in a non-generic static class. Tried adding static, tried adding under namespace created a namespace, etc., but none work. The hex replace has to take place as part of a button click event. – droidtaber Jul 29 '20 at 14:45
  • Then make sure you understand what an extension method is. Similarly, with the second way you posted in your question, you said you were getting errors because `Byte[]` doesn't have a `Replace` method and `Regex` cannot be assigned to a `Byte[]` variable. You should read up on these topics to have a better understanding of C#, for this and future questions you come across. Ex: [Extension methods](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods), [Types](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/) – Joe Sewell Jul 29 '20 at 14:53
  • You may end up corrupting the file if you do this - firstly there is a chance that your sequence of bytes could naturally occur in a binary file (1 in 2^32 chance is small but not zero). Secondly, I believe in a PNG file data blocks have CRC check codes in them which will no longer match if you start editing bytes. – PaulF Jul 29 '20 at 14:55

1 Answers1

2

You can't use regex on bytes. You can look for the pattern manually and just replace those elements in the array:

byte[] bytes = File.ReadAllBytes("tram.png");

for (int i = 0; i < bytes.Length - 4; ++i)
{
    if (bytes[i] == 31 && bytes[i + 1] == 30 && bytes[i + 2] == 30 && bytes[i + 3] == 34)
    {
        bytes[i] = 32;
        bytes[i + 1] = 31;
        bytes[i + 2] = 31;
        bytes[i + 3] = 33;

        i += 3;  // Skip the new bytes for efficiency.
    }
}

File.WriteAllBytes("tram.png", bytes);
itsme86
  • 19,266
  • 4
  • 41
  • 57
  • I tried this code, but it says Invalid real literal if the code had a letter in it, like `2E` – droidtaber Jul 29 '20 at 14:58
  • @droidtaber If you want to use hex instead of decimal, you have to prefix it with `0x`, (e.g. `0x2E`). – itsme86 Jul 29 '20 at 14:59
  • This worked! But, there's a small issue. I was running `id.Replace(test, "2113", 1);` cause there are two instances of the same hex in the document. Anyway to limit to first instance? – droidtaber Jul 29 '20 at 15:11
  • @droidtaber Yes, just replace the `i += 3;` line with `break;`. – itsme86 Jul 29 '20 at 15:20
  • 1
    Can't thank you enough! Have been trying to fix this for more than a day now. BTW, in the above code, it should be `bytes` with the example instead of `test`. Have a nice day! Thanks a lot again. – droidtaber Jul 29 '20 at 15:24