Ошибка времени выполнения чтение после конца потока невозможно

На чтение 2 мин Просмотров 366 Опубликовано 12.01.2021

На чтение 2 мин Просмотров 366 Опубликовано 12.01.2021

Всем доброго времени суток, столкнулся с проблемой

Чтения после конца потока невозможно

Дело в том что я читаю бинарный файл :

И так получилось что numb2 имеет запись в файле поэтому reader2.PeekChar() > -1 больше 1, но вот ndef2 уже нету в файле, и я получаю ошибку чтения после конца потока, может есть более правильный метод инициализации данных в файле, и если дальше записи нет, то просто передать 0 и перейти дальше, либо пропускать и идти дальше, просто не хотелось бы делать что-то вроде:

Или все же придется ставить еще одну проверку, как я написал выше ?
Помогите пожалуйста разобраться.

Приветствую, мне требуется ваша помощь, уже не знаю, что делать, весь интернет перерыл, и всем помогает Position = 0,а мне нет.

Подскажите пожалуйста! Всем спасибо!

  • Вопрос задан более года назад
  • 647 просмотров

Для ReadString() возврат пустой строки, вполне вменяемое поведение.

Например, если бы считывался этот комментарий, то Ваш код не дошёл бы до этой строчки.

Я сейчас сижу проверяю, и наткнулся на одну вещь, вот на этой строке:

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

program fgd;
type f= file of real;
var f1:f;
i,j: byte;
a: array[1..4,1..5] of real;
k: real;
begin
assign (f1,’massiv.txt’);
reset (f1);
for i:=1 to 4 do
for j:=1 to 5 do
begin
read (f1, k);
a[i,j]:=k;
end;
close (f1);
for i:=1 to 4 do
begin
for j:=1 to 5 do write (a[i,j],’ ‘);
writeln;
end;
end.

Pascal.
Program2.pas(18) : Ошибка времени выполнения: Чтение после конца потока невозможно.
В чём ошибка

Здесь легко и интересно общаться. Присоединяйся!

Вы файл заполняли в ручную? Возможно для корректного чтения следует заполнить файл программно.

  • Распечатать

Оцените статью:

  1. 5
  2. 4
  3. 3
  4. 2
  5. 1

(0 голосов, среднее: 0 из 5)

Поделитесь с друзьями!

The testing.res file is 240MB size.
I want to read it. But im getting the error on this line:

int v = br.ReadInt32();

EndOfStreamException
Unable to read beyond the end of the stream

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            R();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        public void R()
        {
            using (var br = new System.IO.BinaryReader(File.Open(@"d:testing.res", FileMode.Open)))
            {
                // 2.
                // Position and length variables.
                int pos = 0;
                // 2A.
                // Use BaseStream.
                int length = (int)br.BaseStream.Length;
                while (br.BaseStream.Position < length)
                {
                    // 3.
                    // Read integer.
                    int v = br.ReadInt32();
                    textBox1.Text = v.ToString();
                }

            }
        }
    }
}

The exception:

System.IO.EndOfStreamException was unhandled
  Message=Unable to read beyond the end of the stream.
  Source=mscorlib
  StackTrace:
       at System.IO.BinaryReader.FillBuffer(Int32 numBytes)
       at System.IO.BinaryReader.ReadInt32()
       at WindowsFormsApplication1.Form1.R() in D:C-SharpBinaryReaderWindowsFormsApplication1WindowsFormsApplication1Form1.cs:line 41
       at WindowsFormsApplication1.Form1..ctor() in D:C-SharpBinaryReaderWindowsFormsApplication1WindowsFormsApplication1Form1.cs:line 19
       at WindowsFormsApplication1.Program.Main() in D:C-SharpBinaryReaderWindowsFormsApplication1WindowsFormsApplication1Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

The testing.res file is 240MB size.
I want to read it. But im getting the error on this line:

int v = br.ReadInt32();

EndOfStreamException
Unable to read beyond the end of the stream

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            R();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        public void R()
        {
            using (var br = new System.IO.BinaryReader(File.Open(@"d:testing.res", FileMode.Open)))
            {
                // 2.
                // Position and length variables.
                int pos = 0;
                // 2A.
                // Use BaseStream.
                int length = (int)br.BaseStream.Length;
                while (br.BaseStream.Position < length)
                {
                    // 3.
                    // Read integer.
                    int v = br.ReadInt32();
                    textBox1.Text = v.ToString();
                }

            }
        }
    }
}

The exception:

System.IO.EndOfStreamException was unhandled
  Message=Unable to read beyond the end of the stream.
  Source=mscorlib
  StackTrace:
       at System.IO.BinaryReader.FillBuffer(Int32 numBytes)
       at System.IO.BinaryReader.ReadInt32()
       at WindowsFormsApplication1.Form1.R() in D:C-SharpBinaryReaderWindowsFormsApplication1WindowsFormsApplication1Form1.cs:line 41
       at WindowsFormsApplication1.Form1..ctor() in D:C-SharpBinaryReaderWindowsFormsApplication1WindowsFormsApplication1Form1.cs:line 19
       at WindowsFormsApplication1.Program.Main() in D:C-SharpBinaryReaderWindowsFormsApplication1WindowsFormsApplication1Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

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

 'Получения блока байт информации
    Public Sub DoRead(ByVal obj As Object)
        Try
            Dim Stream As NetworkStream = myClient.GetStream
            Dim Reader As New BinaryReader(Stream)
            Do
                Dim typeMsg = Reader.ReadByte()
                'Далее смотрим заголовок
                Select Case typeMsg
                    Case 0 'Сообщение
                        Dim tmpName = Reader.ReadString
                        Dim tmpMessage = Reader.ReadString
                        RaiseEvent MessageReceived(Me, tmpName, tmpMessage))
                    Case 11 'Пришла часть файла
                        'Получаем индекс-код загружаемого файла
                        typeMsg = Reader.ReadByte
                        'Считываем размер блока данных
                        Dim SizePart = Reader.ReadInt32
                        'Теперь сам блок
                        Dim byteArray = Reader.ReadBytes(SizePart)
                        'Вызываем событие принятия
                        RaiseEvent FileReceived(Me, typeMsg, byteArray)
                    Case 13 'Ошибка при отправке файла
                        'Получаем индекс-код загружаемого файла
                        typeMsg = Reader.ReadByte
                        'Текст ошибки
                        Dim tmpMessage = Reader.ReadString
                        'Теперь выводим ошибку
                        If BufferTCPFiles.ContainsKey(typeMsg) Then
                            BufferTCPFiles(typeMsg).onError(tmpMessage)
                        End If
                End Select
            Loop While Stream.CanRead
        Catch ex As Exception
            ConnectStatus = False
        End Try
    End Sub

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

Первый вопрос. Когда сервер передает массив байт размером, например, 16000 байт, а клиент принимает его способом, указанным в коде (Reader.ReadBytes(SizePart)), может клиент получить не 16000 байт, а, например,
15000, затем вызвать событие обработки FileReceived и потом начать считывать байт-заголовок. В итоге считывает байт из оставшихся 1000 байт и начинает обрабатывать неправильно? Или он будет пытаться прочитать все байты до конца?

Продолжу дальше. Проблема в обмене файлами. Событие FileReceived обрабатывается в классе приема файла (LoadFileTCP) следующим образом:

       BufferTCPFiles = New Concurrent.ConcurrentDictionary(Of Byte, LoadFileTCP)
       'Событие обработки команд с сервера (принятие массива данных)
       AddHandler UserClient.FileReceived, AddressOf onFileReceived

Изначально создается BufferTCPFiles — так как одновременно могут передаваться несколько файлов, он содержит в себе ключ-значения состоящие из индекс-кода загружаемого файла и классы LoadFileTCP, которые обрабатывают массивы
байт. Когда происходит событие FileReceived — идет поиск нужного класса по индекс-коду и у него вызывается процедура обработки:

Private ThreadLock As New Object
        Private Sub onFileReceived(ByVal sender As ClientVisio, ByVal NumberOf As Byte, ByVal PartArray As Byte())
            'Записываем данные в файл только одним потоком
            SyncLock ThreadLock
                If BufferTCPFiles.ContainsKey(NumberOf) Then
                    BufferTCPFiles(NumberOf).WriteDataToFile(PartArray)
                End If
            End SyncLock
        End Sub

Теперь о самой процедуре обработки массива байт — WriteDataToFile:

        Public Sub WriteDataToFile(ByVal byteArray As Byte())
            Try
		'Количество принятых блоков до отправки подтверждения о приеме
                BlockNow = CByte(BlockNow - 1)

		'fs - это ранее созданный FileStream(pathToFile & "tmp", FileMode.OpenOrCreate, FileAccess.Write)
                fs.Write(byteArray, 0, byteArray.Length)
		'Общее количество байт
                LoadDataCount += byteArray.Length

                'Пора отправлять подтверждение о принятии на сервер?
                If BlockNow <= 0 Then
                    'Отправляем ответ с индекс-кодом файла
                    UserClient.SendFOk(myData.IndexLoad)
		    'Сбрасываем счетчик
                    BlockNow = 10
                End If

		'Если все байты получены (размер файла FullSize сервер присылает перед отправкой файла)
                If LoadDataCount = FullSize Then
                    StatusLoad = False
                    fs.Close()

                    'Это последний блок! 
                    'Теперь переименовываем файл, удаляя предыдущий, если есть
                    If FileIO.FileSystem.FileExists(pathToFile) Then 'Файл существует?
                        FileIO.FileSystem.DeleteFile(pathToFile) 'Удаляем...
                    End If
		    'Данные имени и расширения сервер так-же присылает перед отправкой файла
                    FileIO.FileSystem.RenameFile(pathToFile & "tmp", myData("Имя") & myData("Расширение"))
                    'Сообщаем о загрузке
                    BufferTCPFiles.RaiseNewEvent(myData, TypeEvent.LoadComplete, pathToFile)

		'Если вдруг принято больше, чем нужно
                ElseIf LoadDataCount > FullSize Then
                    StatusLoad = False
                    fs.Close()

                    'Сообщаем об ошибке
                    BufferTCPFiles.RaiseNewEvent(myData, TypeEvent.ErrorLoad, "Переполнение! " & vbCrLf & LoadDataCount & "/" & FullSize)
                End If
            Catch ex As Exception
                Console.WriteConsole("Ошибка: " & ex.Message)
            End Try
        End Sub

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

Второй вопрос. Нужно ли при вызове процедуры записи данных файла — WriteDataToFile — использовать SyncLock? Я его поставил, думая, что если много будет потоков вызывать запись на диск по FileStream, то будет некорректно записаны данные.

Ну и третий вопрос — годится ли сама реализация обработки данных с сервера? Выдает ошибку она или процедура записи на диск? Самое интересное, если компьютер более менее производительный (офисный), тогда ошибок вообще нет. Ошибка приема
файла ТОЛЬКО у компьютеров с медленным жестким диском (с большим временем доступа) или просто у старых компьютеров, у которых ждешь по 2 минуты открытие браузера :) Именно из за этого я решил
использовать SyncLock при вызове процедуры записи данных на диск. Решил, что он не успевает записать данные, а уже пришли новые и они вместе со старыми конфликтуют :)

Буду рад любой помощи )

Понравилась статья? Поделить с друзьями:
  • Ошибка времени выполнения ссылка на объект не указывает на экземпляр объекта паскаль
  • Ошибка входа eso
  • Ошибка времени выполнения процесс не может получить доступ к файлу
  • Ошибка входа bad login clientside cubixworld
  • Ошибка времени выполнения значение было недопустимо малым или недопустимо большим для int32