C# Replace bytes in Byte[]

后端 未结 6 908
日久生厌
日久生厌 2020-12-06 14:01

What is the best way to replace some bytes in a byte array??

For instance i have bytesFromServer = listener.Receive(ref groupEP); and i can do Bit

相关标签:
6条回答
  • 2020-12-06 14:07

    How about Array.Copy?

    0 讨论(0)
  • 2020-12-06 14:17
        public static byte[] ReplaceBytes(byte[] src, byte[] search, byte[] repl)
        {
            if (repl == null) return src;
            int index = FindBytes(src, search);
            if (index < 0) return src;
            byte[] dst = new byte[src.Length - search.Length + repl.Length];
            Buffer.BlockCopy(src, 0, dst, 0, index);
            Buffer.BlockCopy(repl, 0, dst, index, repl.Length);
            Buffer.BlockCopy(src, index + search.Length, dst, index + repl.Length,src.Length - (index + search.Length));
            return dst;
        }
    
        public static int FindBytes(byte[] src, byte[] find)
        {
            if(src==null|| find==null|| src.Length==0|| find.Length == 0 || find.Length> src.Length) return -1;
            for (int i = 0; i < src.Length - find.Length +1 ; i++)
            {
                if (src[i] == find[0])
                {
                   for(int m=1;m< find.Length;m++)
                   {
                        if (src[i + m] != find[m]) break;
                        if (m == find.Length - 1) return i;
                   }
                }
            }
            return -1;
        }
    

    this may be a good method , i have test in lots of codes.

    0 讨论(0)
  • 2020-12-06 14:19

    Unfortunately there are issues with all of the posts (as already pointed out in comments). There is a correct answer in this other question

    I needed a solution so for myself and wrote the following code. This is also more flexible in using enumerable and multiple search replace terms.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    
    public class ByteTools
    {
        static void ByteReplaceTests()
        {
            var examples = new(string source, string search, string replace)[]
                {
                    ("bababanana", "babanana", "apple"),
                    ("hello guys", "hello", "hello world"),
                    ("apple", "peach", "pear"),
                    ("aaaa", "a", "abc"),
                    ("pear", "pear", ""),
                    ("good morning world", "morning", "morning"),
                    ("ababab", "ab", "ababab"),
                    ("ababab", "abab", "ab"),
                    ("", "aa", "bb"),
                };
    
            int i = 0;
            foreach (var (source, search, replace) in examples)
            {
                var stringReplaceResults = source.Replace(search, replace);
    
                var sourceByte = Encoding.ASCII.GetBytes(source);
                var searchByte = Encoding.ASCII.GetBytes(search);
                var replaceByte = Encoding.ASCII.GetBytes(replace);
                //converts string values to bytes, does the replace, then converts back to string
                var byteReplaceResults = Encoding.ASCII.GetString(
                    ByteReplace(sourceByte, (searchByte, replaceByte)).ToArray());
    
                Console.WriteLine($"{i}: {source}, {search}, {replace}");
                Console.WriteLine($"       String.Replace() => {stringReplaceResults}");
                Console.WriteLine($"       BytesReplace()   => {byteReplaceResults}");
                i++;
            }
        }
    
        static IEnumerable<byte> ByteReplace(IEnumerable<byte> source, params (byte[] search, byte[] replace)[] replacements)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (replacements == null)
                throw new ArgumentNullException(nameof(replacements));
            if (replacements.Any(r => r.search == null || r.search.Length == 0))
                throw new ArgumentOutOfRangeException(nameof(replacements), "Search parameter cannot be null or empty");
            if (replacements.Any(r => r.replace == null))
                throw new ArgumentOutOfRangeException(nameof(replacements), "Replace parameter cannot be null");
    
            var maxMatchSize = replacements.Select(r => r.search.Length).Max();
            var bufferSize = maxMatchSize * 2;
            var buffer = new byte[bufferSize];
            int bufferStart = 0;
            int bufferPosition = 0;
    
            byte[] nextBytes()
            {
                foreach ((byte[] search, byte[] replace) in replacements)
                {
                    if (ByteStartsWith(buffer, bufferStart, bufferPosition - bufferStart, search))
                    {
                        bufferStart += search.Length;
                        return replace;
                    }
                }
    
                var returnBytes = new byte[] { buffer[bufferStart] };
                bufferStart++;
                return returnBytes;
            }
    
            foreach (var dataByte in source)
            {
                buffer[bufferPosition] = dataByte;
                bufferPosition++;
    
                if (bufferPosition - bufferStart >= maxMatchSize)
                {
                    foreach (var resultByte in nextBytes())
                        yield return resultByte;
                }
    
                if (bufferPosition == bufferSize - 1)
                {
                    Buffer.BlockCopy(buffer, bufferStart, buffer, 0, bufferPosition - bufferStart);
                    bufferPosition -= bufferStart;
                    bufferStart = 0;
                }
            }
    
            while (bufferStart < bufferPosition)
            {
                foreach (var resultByte in nextBytes())
                    yield return resultByte;
            }
        }
        static bool ByteStartsWith(byte[] data, int dataOffset, int dataLength, byte[] startsWith)
        {
            if (data == null)
                throw new ArgumentNullException(nameof(data));
    
            if (startsWith == null)
                throw new ArgumentNullException(nameof(startsWith));
    
            if (dataLength < startsWith.Length)
                return false;
    
            for (int i = 0; i < startsWith.Length; i++)
            {
                if (data[i + dataOffset] != startsWith[i])
                    return false;
            }
    
            return true;
        }
    }
    
    0 讨论(0)
  • 2020-12-06 14:23

    You could program it.... try this for a start... this is however not robust not production like code yet...beaware of off-by-one errors I didn't fully test this...

        public int FindBytes(byte[] src, byte[] find)
        {
            int index = -1;
            int matchIndex = 0;
            // handle the complete source array
            for(int i=0; i<src.Length; i++)
            {
                if(src[i] == find[matchIndex])
                {
                    if (matchIndex==(find.Length-1))
                    {
                        index = i - matchIndex;
                        break;
                    }
                    matchIndex++;
                }
                else if (src[i] == find[0])
                {
                    matchIndex = 1;
                }
                else
                {
                    matchIndex = 0;
                }
    
            }
            return index;
        }
    
        public byte[] ReplaceBytes(byte[] src, byte[] search, byte[] repl)
        {
            byte[] dst = null;
            int index = FindBytes(src, search);
            if (index>=0)
            {
                dst = new byte[src.Length - search.Length + repl.Length];
                // before found array
                Buffer.BlockCopy(src,0,dst,0, index);
                // repl copy
                Buffer.BlockCopy(repl,0,dst,index,repl.Length);
                // rest of src array
                Buffer.BlockCopy(
                    src, 
                    index+search.Length , 
                    dst, 
                    index+repl.Length, 
                    src.Length-(index+search.Length));
            }
            return dst;
        }
    

    Implement as an extension method

    public void Replace(this byte[] src, byte[] search, byte[] repl)
    {
          ReplaceBytes(src, search, repl);
    }
    

    usage normal method:

    ReplaceBytes(bytesfromServer, 
                 new byte[] {0x75, 0x83 } , 
                 new byte[]{ 0x68, 0x65, 0x6c});
    

    Extension method usage:

    bytesfromServer.Replace(
                 new byte[] {0x75, 0x83 }, 
                 new byte[]{ 0x68, 0x65, 0x6c});
    
    0 讨论(0)
  • 2020-12-06 14:29

    Improving on rene's code, I created a while loop for it to replace all occurences:

    public static byte[] ReplaceBytes(byte[] src, byte[] search, byte[] repl)
    {
        byte[] dst = null;
        byte[] temp = null;
        int index = FindBytes(src, search);
        while (index >= 0)
        {
            if (temp == null)
                temp = src;
            else
                temp = dst;
    
            dst = new byte[temp.Length - search.Length + repl.Length];
    
            // before found array
            Buffer.BlockCopy(temp, 0, dst, 0, index);
            // repl copy
            Buffer.BlockCopy(repl, 0, dst, index, repl.Length);
            // rest of src array
            Buffer.BlockCopy(
                temp,
                index + search.Length,
                dst,
                index + repl.Length,
                temp.Length - (index + search.Length));
    
    
            index = FindBytes(dst, search);
        }
        return dst;
    }
    

    This method will work, but if the source bytes is too huge, I prefer to have a "windowing" function to process the bytes chunk by chunk. Else it will take a huge amount of memory.

    0 讨论(0)
  • 2020-12-06 14:29

    Something i pieced together... Going to test it soon. Credits from How do you convert Byte Array to Hexadecimal String, and vice versa?

         public byte[] ReplaceBytes(byte[] src, string replace, string replacewith)
        {
            string hex = BitConverter.ToString(src);
            hex = hex.Replace("-", "");
            hex = hex.Replace(replace, replacewith);
            int NumberChars = hex.Length;
            byte[] bytes = new byte[NumberChars / 2];
            for (int i = 0; i < NumberChars; i += 2)
                bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            return bytes;
        }
    
    0 讨论(0)
提交回复
热议问题