C#替换Byte []中的字节

时间:2011-02-27 11:21:19

标签: c# replace byte

替换字节数组中某些字节的最佳方法是什么?

例如,我有bytesFromServer = listener.Receive(ref groupEP);,我可以BitConverter.ToString(bytesFromServer)将其转换为可读格式,以返回

的内容
48 65 6c 6c 6f 20 
74 68 65 72 65 20 
68 65 6c 70 66 75 
6c 20 70 65 6f 70 
6c 65   

我想将“68 65 6c”中的内容替换为“68 00 00”(仅作为示例)。字节[]上没有.Replace()。

是否有一种简单的方法可以将其转换回字节[]?

任何帮助表示赞赏。谢谢!

6 个答案:

答案 0 :(得分:10)

你可以对它进行编程....尝试这个开始...然而这不是强大而不是像代码一样的生产...要知道一个一个错误我没有完全测试这个...

    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;
    }

实施为扩展方法

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

用法常规方法:

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

扩展方法用法:

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

答案 1 :(得分:4)

Array.Copy怎么样?

答案 2 :(得分:3)

改进了rene的代码,我为它创建了一个while循环来替换所有出现的代码:

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;
}

这个方法可行,但是如果源字节太大,我更喜欢使用“窗口”函数来按块处理字节块。否则它将占用大量内存。

答案 3 :(得分:0)

我拼凑的东西......很快就要测试了。来自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;
    }

答案 4 :(得分:0)

不幸的是,所有帖子都存在问题(正如评论中已经指出的那样)。 this other question

中有正确的答案

我需要一个解决方案,所以我自己写了下面的代码。这在使用可枚举和多个搜索替换术语时也更灵活。

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;
    }
}

答案 5 :(得分:-1)

class NCApp(tk.Tk):
    def __init__(...):
        self.profession = tk.StringVar()
        ...
    def setProfession(self, given_profession):
        self.profession.set(given_profession)
    def getProfession(self):
        return self.profession

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.label = tk.Label(self, textvariable=controller.getProfession())
        self.label.pack(pady=10, padx=10)
        ...

这可能是一个好方法,我已经对很多代码进行了测试。