C # Попытка заменить байт при использовании класса MemoryStream - PullRequest
3 голосов
/ 09 сентября 2011

Я получаю текстовый файл из мэйнфрейма, и иногда в середину текстовых строк вводится 0x0D.

Программист предыдущих версий создал метод, используя класс FileStream.Этот метод работает нормально, но на прохождение всего файла уходит около 30 минут.

Я подумал о том, чтобы передать необходимые строки текста (около 25 строк) в метод, чтобы уменьшить время обработки.

Я работал с классом MemoryStream, но у меня возникла проблема, когда он не находит управляющий код 0x0D.

Вот текущий метод FileStream:

private void ReplaceFileStream(string strInputFile)
{
    FileStream fileStream = new FileStream(strInputFile, FileMode.Open, FileAccess.ReadWrite);
    byte filebyte;

    while (fileStream.Position < fileStream.Length)
    {
        filebyte = (byte)fileStream.ReadByte();
        if (filebyte == 0x0D)
        {
            filebyte = 0x20;
            fileStream.Position = fileStream.Position - 1;
            fileStream.WriteByte(filebyte);
        }
    }
    fileStream.Close();
}

и вот метод MemoryStream:

private void ReplaceMemoryStream(string strInputLine)
{
    byte[] byteArray = Encoding.ASCII.GetBytes(strInputLine);
    MemoryStream fileStream = new MemoryStream(byteArray);

    byte filebyte;

    while (fileStream.Position < fileStream.Length)
    {
        filebyte = (byte)fileStream.ReadByte();
        if (filebyte == 0x0D)
        {
            filebyte = 0x20;
            fileStream.Position = fileStream.Position - 1;
            fileStream.WriteByte(filebyte);
        }
    }
    fileStream.Close();
}

Поскольку я не использовал класс MemoryStream до этого, я не настолько знаком с ним.Любые советы или идеи?

Ответы [ 2 ]

3 голосов
/ 09 сентября 2011

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

private void ReplaceFileStream(string strInputFile)
{
    byte[] fileBytes = File.ReadAllBytes(strInputFile);
    bool modified = false;
    for(int i=0; i < fileBytes.Length; ++i)
    {
        if (fileByte[i] == 0x0D)
        {
            fileBytes[i] = 0x20;
            modified = true;
        }
    } 

    if (modified)
    {
        File.WriteAllBytes(strInputFile, fileBytes);
    }
}

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

private void ReplaceFileStream(string strInputFile)
{
    string tempFile = Path.GetTempFileName();
    try
    {
        using(FileStream input = new FileStream(strInputFile,
            FileMode.Open, FileAccess.Read))
        using(FileStream output = new FileStream(tempFile,
            FileMode.Create, FileAccess.Write))
       {
           byte[] buffer = new byte[4096];
           bytesRead = input.Read(buffer, 0, 4096);
           while(bytesRead > 0)
           {
                for(int i=0; i < bytesRead; ++i)
                {
                    if (buffer[i] == 0x0D)
                    {
                        buffer[i] = 0x20;
                    }
                }

                output.Write(buffer, 0, bytesRead);
                bytesRead = input.Read(buffer, 0, 4096);
            }
            output.Flush();
        }

        File.Copy(tempFile, strInputFile);
    }
    finally
    {
        if (File.Exists(tempFile))
        {
            File.Delete(tempFile);
        }
    }
}
2 голосов
/ 09 сентября 2011

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

в противном случае ваш код выглядит нормально, я бы использовал использование MemoryStream, чтобы убедиться, что оно закрыто и расположено, что-то вроде этого:

using(var fileStream = new MemoryStream(byteArray))
{

  byte filebyte;

 // your while loop...

}

глядя на ваш код Я не уверен на 100%, что изменения, внесенные вами в поток памяти, будут сохранены; На самом деле я думаю, что если вы не сохраните его после изменений, ваши изменения будут потеряны. Я могу ошибаться в этом, но вы должны проверить и посмотреть, если он не сохраняется, вы должны использовать StreamWriter, чтобы сохранить его после изменений.

...