C # Заменить байты в байтах [] - PullRequest
4 голосов
/ 27 февраля 2011

Каков наилучший способ заменить некоторые байты в байтовом массиве ??

Например, у меня есть 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 ]

10 голосов
/ 27 февраля 2011

Вы могли бы запрограммировать это ... попробуйте это для начала ... это, однако, еще не надежно, а не в виде кода, подобного коду ... остерегаясь отдельных ошибок.

    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});
4 голосов
/ 27 февраля 2011

Как насчет Array.Copy?

3 голосов
/ 09 мая 2016

Улучшая код Рене, я создал цикл 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;
}

Этот метод будет работать, но если исходные байты слишком велики, я предпочитаю иметь «оконное отображение»msgstr "функция для обработки байтов от чанка.Иначе это займет огромное количество памяти.

0 голосов
/ 13 июня 2019
    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;
    }

это может быть хороший метод, у меня есть тест на множество кодов.

0 голосов
/ 27 февраля 2018

К сожалению, есть проблемы со всеми постами (как уже отмечалось в комментариях).В этом другом вопросе есть правильный ответ 1002 *

Мне нужно было решение для себя, и я написал следующий код.Это также более гибко при использовании перечислимых и множественных поисковых терминов.

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 голосов
/ 27 февраля 2011

Что-то, что я собрал ... Собираюсь проверить это в ближайшее время. Кредиты от Как преобразовать массив байтов в шестнадцатеричную строку и наоборот?

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