ReadByte/ReadAsciiCharacter return value on error

Everything else that doesn't fall into one of the other PB categories.
miskox
User
User
Posts: 95
Joined: Sun Aug 27, 2017 7:37 pm
Location: Slovenia

ReadByte/ReadAsciiCharacter return value on error

Post 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.
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
miskox
User
User
Posts: 95
Joined: Sun Aug 27, 2017 7:37 pm
Location: Slovenia

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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. :wink: 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.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Sicro
Enthusiast
Enthusiast
Posts: 538
Joined: Wed Jun 25, 2014 5:25 pm
Location: Germany
Contact:

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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.
Image
Why OpenSource should have a license :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (syntax color scheme) :: RegEx-Engine (compiles RegExes to NFA/DFA)
Manjaro Xfce x64 (Main system) :: Windows 10 Home (VirtualBox) :: Newest PureBasic version
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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
sorry for my bad english
User avatar
Tristano
Enthusiast
Enthusiast
Posts: 190
Joined: Thu Nov 26, 2015 6:52 pm
Location: Italy
Contact:

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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!
The PureBASIC Archives: FOSS Resources:
User avatar
Tristano
Enthusiast
Enthusiast
Posts: 190
Joined: Thu Nov 26, 2015 6:52 pm
Location: Italy
Contact:

Re: ReadByte/ReadAsciiCharacter return value on error

Post by Tristano »

Submitted a new feature request for the GetLastFileError(file) command proposed by @Sicro:

viewtopic.php?f=3&t=74627
The PureBASIC Archives: FOSS Resources:
BarryG
Addict
Addict
Posts: 3294
Joined: Thu Apr 18, 2019 8:17 am

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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).
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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.
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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.
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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.
sorry for my bad english
BarryG
Addict
Addict
Posts: 3294
Joined: Thu Apr 18, 2019 8:17 am

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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.
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: ReadByte/ReadAsciiCharacter return value on error

Post 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.
sorry for my bad english
Post Reply