Page 1 of 2
ReadByte/ReadAsciiCharacter return value on error
Posted: Thu Apr 04, 2019 3:19 pm
by miskox
Manual says for ReadByte:
Code: Select all
Returns the read byte or zero if there was an error.
and for ReadAsciiCharacter
Code: Select all
Returns the read ascii character or zero if there was an error.
Shouldn't it return negative* value or value >255 if there is an error? But how could this value be returned (ReadByte has .b and ReadAsciiCharacter has .a type)?
Because byte read from the file can have a value of zero?
Thanks.
Saso
* don't see it as .b type (-128 to +127), only as a value between 0 and 255.
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Thu Apr 04, 2019 4:38 pm
by Sicro
Use
Loc() to determine whether
ReadByte() was successful:
Code: Select all
If CreateFile(0, GetTemporaryDirectory() + "test")
For i = 1 To 10
WriteByte(0, i)
Next
FileSeek(0, 0)
Repeat
oldPos = Loc(0)
value = ReadByte(0)
newPos = Loc(0)
If oldPos <> newPos
Debug value
Else
Debug "ReadByte: Error"
Break
EndIf
ForEver
CloseFile(0)
Else
Debug "File could not be created!"
EndIf
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Fri Apr 05, 2019 7:16 am
by miskox
Thanks for the solution but the problem remains - return value should be returned correctly. I think that the application should just rely on 'errorlevel'* and should not include ten, hundred, thousands of lines of code to do the errorchecking.
Saso
* return value whatever we call it
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Fri Apr 05, 2019 2:45 pm
by Sicro
miskox wrote:Thanks for the solution but the problem remains
Of course, only the PureBasic developers can change that. We can only create workarounds.
miskox wrote:I think that the application should just rely on 'errorlevel'* and should not include ten, hundred, thousands of lines of code to do the errorchecking.
You're exaggerating.

The error checking code is very small in this case.
Shouldn't it return negative* value or value >255 if there is an error? But how could this value be returned (ReadByte has .b and ReadAsciiCharacter has .a type)?
Because byte read from the file can have a value of zero?
The problem is that the function returns only one value and the value range is already exhausted and therefore no more value can be reserved for an error. You already realized that. Using a value outside the valid value range of the return type is not a good idea, because the value swaps when an overflow occurs:
Code: Select all
value.b = 127+1 ; Value is over valid value range (byte: -128 to +127)
Debug value ; -128 -- No error recognizable, because the value is in the valid value range
It would probably be best if the read functions had one more parameter to which you could pass an address to a variable that receives the error code:
Code: Select all
value = ReadByte(file, @error)
If error = #False
Debug value
Else
Debug "Error"
EndIf
Or a new function:
Code: Select all
value = ReadByte(file)
If GetLastFileError(file) = #PB_FileError_None
Debug value
Else
Debug "Error"
EndIf
We can discuss which variant is better and then create a feature request.
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Fri Apr 05, 2019 3:37 pm
by mk-soft
I don't see any problems here.
It only depends on how the value is viewed. Signed or Unsigned.
PB have the var type ASCII (var.a) and UNICODE (var.u)
The type var.a is the same as Unsigned Byte and the type var.u the same as unsigned word. PB also sees this as unsigned.
Code: Select all
Define var1.a = 254
If var1 >= 128
Debug "Ok"
EndIf
Define var2.u = 40000
If var2 >= 32768
Debug "ok"
EndIf
So there is not much to do to read the file as byte array (Unsigned).
Code: Select all
Macro ReadUnsignedByte(File)
ReadAsciiCharacter(File)
EndMacro
Macro ReadUnsignedWord(File)
ReadUnicodeCharacter(File)
EndMacro
Dim UnsignedByte.a(20)
cnt = 0
file.s = OpenFileRequester("Open Any File", "", "", 0)
If Bool(file)
If ReadFile(0, file)
While Not Eof(0) And cnt <= 20
old_loc = Loc(0)
UnsignedByte(cnt) = ReadUnsignedByte(0)
If Loc(0) <= old_loc
Debug "Error read byte"
Break
EndIf
cnt + 1
Wend
EndIf
; Output
For index = 0 To cnt - 1
Debug "Index " + index + " = " + UnsignedByte(index)
Next
EndIf
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Fri Apr 05, 2019 7:00 pm
by Sicro
@mk-soft:
The topic here is not about signed/unsigned bytes. The point is that the
ReadByte() function in the PB help says that in the case of an error, the zero value is returned:
PB help => ReadByte() wrote:Returns the read byte or zero if there was an error.
However, the zero value is not always an error, but can also be a normal value.
So I showed the thread creator a workaround that uses
Loc() to determine whether
ReadByte() was successful or not. But the thread creator thinks that the workaround code is too much code and checking whether
ReadByte() was successful or not should be easier.
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Fri Apr 05, 2019 9:07 pm
by Josh
@ miskox:
A ReadByte can only return a variable of type Byte. So it doesn't matter which value is returned, because every read value can occur in the file.
You just have to make sure that you don't read beyond the end of the file. Shouldn't be too complicated.
Code: Select all
CreateFile (0, GetTemporaryDirectory() + "test")
For i = 1 To 10
WriteByte (0, i)
Next
FileSeek (0, 0)
While Not Eof(0)
Debug ReadByte (0)
Wend
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sat Feb 15, 2020 4:09 pm
by Tristano
@miskox is right, I also found the error return description in the Documentation quite confusing, and had to search the forum to work out how it works.
@Sicro, thanks for the solution, I wouldn't have thought of it.
So, on the one hand the Documentation is correct when it mentions that it always returns 0 in case of error; what it doesn't clarify is how to distinguish when a returned 0 is an error or just the read value.
I like @Sicro proposal for a new feature that adds a GetLastFileError(file) command to check if the last file operation for any given file was successful or encountered an error — it would be similar to C's ferror(FILE *stream) function. Defintely, it would spare all the workaround code doing all the Loc() checks, and keep the code more readable.
I'll create a post and add it to the new features wishlist!
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sat Feb 15, 2020 4:22 pm
by Tristano
Submitted a new feature request for the
GetLastFileError(file) command proposed by @Sicro:
viewtopic.php?f=3&t=74627
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sun Feb 16, 2020 2:15 am
by BarryG
I agree with miskox. ReadByte() shouldn't blindly return 0 for error because binary files have 0 in them. How will we know if 0 was the actual data byte read, or an error?
Workarounds are nice but not the solution, because the fact remains that ReadByte() is fundamentally flawed, and needs fixing to return a different value for a read error. This should be -1, because no file has a byte value of -1 (as seen in any hex editor: all byte values are $00 to $FF).
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sun Feb 16, 2020 7:52 am
by #NULL
-1 in a byte.b is $ff.
There is no fix via a different return value, you need a different error handling strategy.
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sun Feb 16, 2020 8:00 am
by #NULL
#NULL wrote:There is no fix via a different return value, you need a different error handling strategy.
PB could pack the value byte and an error byte together in a long or quad and the user can then extract them with a bit mask again, but I already see the bug reports coming even if it would be documented.
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sun Feb 16, 2020 9:18 am
by Josh
I am always shocked that it is so difficult to read and interpret a text by some people.
Sure, the help is not perfect, but what is so difficult to understand about the sentence 'Returns the read byte or zero if there was an error'? I can't see anywhere in the help something like 'If zero is returned, an error was a detected'. And excuse me, if someone thinks that a return value of -1 or any other value will change something, then there is much more he hasn't understood.
If you want a check for errors, few lines of code are required, no matter if Pb adds some additional functions or not. Check for the end of the file and all is fine. Of course, there are plenty of other ways to check for the end of a file, but that depends on the file you are working on and you have to know how the file is structured.
What Pb might do better is that with the 'Loc' always the calculated value is returned after a read access, so this value is not terminated with 'Lof'. Then you can check afterwards if the file was read over the end of the file.
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sun Feb 16, 2020 12:56 pm
by BarryG
Josh wrote:what is so difficult to understand about the sentence 'Returns the read byte or zero if there was an error'? I can't see anywhere in the help something like 'If zero is returned, an error was a detected'.
You do realize that
"zero if there was an error" and
"if zero is returned, an error was a detected" mean the same thing, right? So yes, the help
does say that. You just quoted it.
Re: ReadByte/ReadAsciiCharacter return value on error
Posted: Sun Feb 16, 2020 1:25 pm
by Josh
Barry, that's the problem. Something is interpreted from a sentence that is simply not true, fragments are torn out from a sentence that completely ignore the context. Why you don't write the whole sentence as it appears in the help? Maybe because then your argument won't hold up from the start?
If 'Returns the read byte or zero if there was an error' means the same thing to you as 'If zero is returned, an error was a detected', then I feel sorry for you. The same bullshit as your claim that a byte value in a file cannot contain -1.