Лучший способ найти положение в Потоке, где данный последовательность байта запускается

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

, Возможно, я не понимаю полное изображение, но на основе Вашего описания, оно не кажется, что у Вас должна была бы обязательно быть блокировка для каждого отдельного поля. Если у Вас есть ряд полей, просто считаны и записаны через методы считывания и методы set, Вам могла, вероятно, сойти с рук единственная блокировка для этих полей. Там является очевидно потенциальным, что Вы излишне сериализируете операцию своих потоков этот путь. Но снова, на основе Вашего описания, это не кажется на агрессивный доступ к объекту также.

я также предложил бы использовать событие вместо того, чтобы использовать поток для опроса состояния устройства. С механизмом опроса Вы собираетесь быть ударом блокировки каждый раз, когда поток запрашивает устройство. С механизмом события, когда-то состояние изменяется, объект уведомил бы любых слушателей. В той точке Ваш поток 'опроса' (который больше не опрашивал бы) проснется и получит новое состояние. Это будет намного более эффективно.

Как пример...

public class Status
{
    private int _code;
    private DateTime _lastUpdate;
    private object _sync = new object(); // single lock for both fields

    public int Code
    {
        get { lock (_sync) { return _code; } }
        set
        {
            lock (_sync) {
                _code = value;
            }

            // Notify listeners
            EventHandler handler = Changed;
            if (handler != null) {
                handler(this, null);
            }
        }
    }

    public DateTime LastUpdate
    {
        get { lock (_sync) { return _lastUpdate; } }
        set { lock (_sync) { _lastUpdate = value; } }
    }

    public event EventHandler Changed;
}

Ваш поток 'опроса' выглядел бы примерно так.

Status status = new Status();
ManualResetEvent changedEvent = new ManualResetEvent(false);
Thread thread = new Thread(
    delegate() {
        status.Changed += delegate { changedEvent.Set(); };
        while (true) {
            changedEvent.WaitOne(Timeout.Infinite);
            int code = status.Code;
            DateTime lastUpdate = status.LastUpdate;
            changedEvent.Reset();
        }
    }
);
thread.Start();
11
задан Powerlord 24 September 2009 в 14:17
поделиться

3 ответа

Я нашел это решение.

Я провел несколько тестов с файлом ASCII размером 3,050 КБ и 38803 строк . С поиском байтов массива из 22 байтов в последней строке файла я получил результат примерно за 2,28 секунд (в медленном / старая машина).

public static long FindPosition(Stream stream, byte[] byteSequence)
{
    if (byteSequence.Length > stream.Length)
        return -1;

    byte[] buffer = new byte[byteSequence.Length];

    using (BufferedStream bufStream = new BufferedStream(stream, byteSequence.Length))
    {
        int i;
        while ((i = bufStream.Read(buffer, 0, byteSequence.Length)) == byteSequence.Length)
        {
            if (byteSequence.SequenceEqual(buffer))
                return bufStream.Position - byteSequence.Length;
            else
                bufStream.Position -= byteSequence.Length - PadLeftSequence(buffer, byteSequence);
        }
    }

    return -1;
}

private static int PadLeftSequence(byte[] bytes, byte[] seqBytes)
{
    int i = 1;
    while (i < bytes.Length)
    {
        int n = bytes.Length - i;
        byte[] aux1 = new byte[n];
        byte[] aux2 = new byte[n];
        Array.Copy(bytes, i, aux1, 0, n);
        Array.Copy(seqBytes, aux2, n);
        if (aux1.SequenceEqual(aux2))
            return i;
        i++;
    }
    return i;
}
5
ответ дан 3 December 2019 в 08:30
поделиться

If you treat the stream like another sequence of bytes, you can just search it like you were doing a string search. Wikipedia has a great article on that. Boyer-Moore is a good and simple algorithm for this.

Here's a quick hack I put together in Java. It works and it's pretty close if not Boyer-Moore. Hope it helps ;)

public static final int BUFFER_SIZE = 32;

public static int [] buildShiftArray(byte [] byteSequence){
    int [] shifts = new int[byteSequence.length];
    int [] ret;
    int shiftCount = 0;
    byte end = byteSequence[byteSequence.length-1];
    int index = byteSequence.length-1;
    int shift = 1;

    while(--index >= 0){
        if(byteSequence[index] == end){
            shifts[shiftCount++] = shift;
            shift = 1;
        } else {
            shift++;
        }
    }
    ret = new int[shiftCount];
    for(int i = 0;i < shiftCount;i++){
        ret[i] = shifts[i];
    }
    return ret;
}

public static byte [] flushBuffer(byte [] buffer, int keepSize){
    byte [] newBuffer = new byte[buffer.length];
    for(int i = 0;i < keepSize;i++){
        newBuffer[i] = buffer[buffer.length - keepSize + i];
    }
    return newBuffer;
}

public static int findBytes(byte [] haystack, int haystackSize, byte [] needle, int [] shiftArray){
    int index = needle.length;
    int searchIndex, needleIndex, currentShiftIndex = 0, shift;
    boolean shiftFlag = false;

    index = needle.length;
    while(true){
        needleIndex = needle.length-1;
        while(true){
            if(index >= haystackSize)
                return -1;
            if(haystack[index] == needle[needleIndex])
                break;
            index++;
        }
        searchIndex = index;
        needleIndex = needle.length-1;
        while(needleIndex >= 0 && haystack[searchIndex] == needle[needleIndex]){
            searchIndex--;
            needleIndex--;
        }
        if(needleIndex < 0)
            return index-needle.length+1;
        if(shiftFlag){
            shiftFlag = false;
            index += shiftArray[0];
            currentShiftIndex = 1;
        } else if(currentShiftIndex >= shiftArray.length){
            shiftFlag = true;
            index++;
        } else{
            index += shiftArray[currentShiftIndex++];
        }           
    }
}

public static int findBytes(InputStream stream, byte [] needle){
    byte [] buffer = new byte[BUFFER_SIZE];
    int [] shiftArray = buildShiftArray(needle);
    int bufferSize, initBufferSize;
    int offset = 0, init = needle.length;
    int val;

    try{
        while(true){
            bufferSize = stream.read(buffer, needle.length-init, buffer.length-needle.length+init);
            if(bufferSize == -1)
                return -1;
            if((val = findBytes(buffer, bufferSize+needle.length-init, needle, shiftArray)) != -1)
                return val+offset;
            buffer = flushBuffer(buffer, needle.length);
            offset += bufferSize-init;
            init = 0;
        }
    } catch (IOException e){
        e.printStackTrace();
    }
    return -1;
}
4
ответ дан 3 December 2019 в 08:30
поделиться

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

Честно говоря, это будет немного неудобно, что бы вы ни делали: (

3
ответ дан 3 December 2019 в 08:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: