На чтение 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) : Ошибка времени выполнения: Чтение после конца потока невозможно.
В чём ошибка
Здесь легко и интересно общаться. Присоединяйся!
Вы файл заполняли в ручную? Возможно для корректного чтения следует заполнить файл программно.
- Распечатать
Оцените статью:
- 5
- 4
- 3
- 2
- 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 при вызове процедуры записи данных на диск. Решил, что он не успевает записать данные, а уже пришли новые и они вместе со старыми конфликтуют
Буду рад любой помощи )