Binary Reader и Writer открыты одновременно?

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

Другими словами, мне нужно много читать и писать. Я уверен, что это действительно просто, но я просто хотел, чтобы профи...

Возможно ли и приемлемо ли сделать что-то вроде:

BinaryReader br = new BinaryReader (File.OpenRead(path));
BinaryWriter bw = new BinaryWriter (File.OpenWrite(path));
br.dostuff();
bw.dostuff();

Я помню, как столкнулся с какой-то ошибкой конфликтующих потоков файлов, когда экспериментировал с открытием и записью в файлы, и я не уверен, что я сделал, чтобы получить это. Проблема в двух файловых потоках? Могу ли я иметь один поток для чтения и записи?


person mowwwalker    schedule 28.12.2011    source источник
comment
Я думаю, что это грязно. Почему вы делаете это таким образом? Может быть, вы можете объяснить свой сценарий?   -  person Matthias    schedule 28.12.2011


Ответы (1)


Это вполне возможно и желательно. Технически, если ваш метод записи не изменяет длину файла и всегда находится за читателем, это не должно вызывать никаких проблем. На самом деле, с точки зрения API, это желательно, поскольку позволяет пользователю контролировать, откуда читать и куда записывать. (Рекомендуется записывать в другой файл, на случай, если в процессе шифрования произойдет что-то плохое, ваш входной файл не будет испорчен).

Что-то типа:

protected void Encrypt(Stream input, Stream output)
{
    byte[] buffer = new byte[2048];

    while (true)
    {
        // read 
        int current = input.Read(buffer, 0, buffer.Length);
    if (current == 0)
                     break;

        // encrypt
        PerformActualEncryption(buffer, 0, current);

        // write
        output.Write(buffer, 0, current);
    }   
}

public void Main()
{
    using (Stream inputStream  = File.Open("file.dat", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    using (Stream outputStream = File.Open("file.dat", FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
    {
        Encrypt(inputStream, outputStream);
    }
}

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

class MySpecialHashingStream : Stream
{
...
}

protected void Encrypt(Stream input, Stream output)
{
    Stream encryptedOutput = new MySpecialHashingStream(output);
    input.CopyTo(encryptedOutput);
}
person Polity    schedule 28.12.2011
comment
@Walkerneo - можно, но я бы не рекомендовал. Файловые дескрипторы оптимизированы с кэшированием, поиск менее оптимизирован (проведите тест, и вы увидите). Кроме того, моя цель заключалась в том, чтобы обеспечить гибкость и безопасность API, которые вы потеряете при работе только с одним дескриптором файла как для чтения, так и для записи. - person Polity; 28.12.2011
comment
С небольшой модификацией: открытие файла дважды не работает, как описано здесь. Но если поток общий, то уже нормально работает: using (var stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) using (var reader = new BinaryReader(stream)) using (var writer = new BinaryWriter(stream)) { ... } - person Gábor; 11.01.2019