User Tools

Site Tools


k6:k6.2:start

6.2.0 Stream Input-Output Functions

The following sections introduce you to stream input-output functions. Examples supplement the descriptions.

6.2.0.1 OPEN

Stream = OPEN FileName [ FOR [ READ | INPUT ] [ WRITE | OUTPUT ] [ CREATE | APPEND ] [ WATCH ] ]

Opens a stream for reading, writing, creating or adding data - optionally also for watching. The stream must exist or the keyword CREATE must also be used.

  • If the keyword CREATE is specified, the stream is created. If it already exists, it will be deleted first.
  • If the keyword APPEND is specified, the stream pointer is moved to the end of the stream immediately after opening.
  • If the keywords READ or WRITE are specified, the inputs and outputs are not buffered.
  • If the keywords INPUT or OUTPUT are specified, the inputs and outputs are buffered.
  • If the keyword WATCH is specified, the stream is monitored by the interpreter via the select(2) system call:
    • If at least one byte can be read from the file, the File_Read() event is triggered.
    • If at least one byte is written to the file, the File_Write() event is triggered.

6.2.0.2 CLOSE

CLOSE [ # ] hStream
hStream.Close()

Both statements close an open stream. These statements never fail. When you have a process stream open, it closes its standard input - just as if you were typing the key combination CTRL+D in a terminal. Standard input and standard output refer to the data channels in a console.

6.2.0.3 OPEN STRING

Stream = OPEN STRING [ aString ] [ FOR [ READ ] [ WRITE ] ]

Use the OPEN STRING command to access a string with the stream interface.

  • If the string aString is opened for reading, the string argument aString must be specified! Then the content of the string is accessed sequentially.
  • Reading a string stream is always possible.
  • If the string aString is opened for writing, an internal string stream buffer collects all written data.

If you set the tag property with a value - like hStringStream.Tag = “open” - after opening, then you have the possibility to check if the StringStream has already been closed.

6.2.0.4 CLOSE StringStream

String = CLOSE [ # ] StringStream

Closing a string stream returns the complete contents of the internal string stream buffer.

Example

' Gambas class file
 
Public sLog As String
Public hLogStream As Stream
Public fTemperature As Float
 
Public Sub Form_Open()
  hLogStream = Open String sLog For Write
  SetLogHeader()
  LogTimer.Delay = 1 * 1000
  LogTimer.Start()
End
 
Public Sub btnReadFromStreamString_Click()
  TextArea1.Text = Close #hLogStream
  hLogStream = Open String sLog For Write
  SetLogHeader()
End
 
Public Sub SetLogHeader()
  Write #hLogStream, "PROTOKOLL" & gb.NewLine
  Write #hLogStream, "Datum: " & Format(Now, "dd. mmmm yyyy") & gb.NewLine
  Write #hLogStream, String$(38, "-") & gb.NewLine
End
 
Public Sub LogTimer_Timer()
 
' fTemperature = Round(RS232_Value,-2)
  fTemperature = Round(Rnd(19, 20), -1)
 
  Write #hLogStream, Format(Now, "hh:nn:ss") & "  |  " & "T = " & Str(fTemperature) & " °C"
  Write #hLogStream, gb.NewLine
 
End

For practical use, you can also read the randomly generated temperature values in the above example by the temperature values of an RS232 interface with temperature sensor.

This is what a protocol extract looks like:

PROTOKOLL
Datum: 08. November 2018
--------------------------
09:36:31  |  T = 19,7 °C
09:36:32  |  T = 20,0 °C
09:36:33  |  T = 19,1 °C
09:36:34  |  T = 19,2 °C
09:36:35  |  T = 20,0 °C
09:36:36  |  T = 19,9 °C

6.2.0.5 WRITE

  • (a) WRITE [ # wStream , ] Expression AS Datatype
  • (b) WRITE [ # wStream , ] WString [ , Length ]
  • (c) WRITE [ # wStream , ] Pointer , Length

(a) Writing data of a specific data type

The first syntax writes an expression to the stream wStream by using its binary representation.

  • If wStream is not specified, the standard output is used.
  • When writing a string, the length of the string is sent before the content of the string.
  • The data type of the expression can be one of the following: NULL, Boolean, Byte, Short, Integer, Long, Pointer, Single, Float, Date, String, Variant, any Array or Collection, or any Structure.
  • If Expression is a Collection, an Array or a Structure, then its contents are written recursively.
  • When writing a structure, the structure type must be specified as the data type.
  • If an unsupported data type is written or a circular reference is detected, then an error is raised.
  • This command uses the byte order of wStreams to write the data.

Example

You can save a string array to a file and export it that way. An array is written serialised to a file via Write. The content of the file has a gambas-specific file format:

Public hFile As File
Public aNames As String[]
...
' Data export
If Dialog.SaveFile() Then Return
hFile = Open Dialog.Path For Write Create
Write #hFile, aNames As ARRAY
Close #hFile

(b) Writing the contents of a string

The second syntax writes a specified number of bytes - specified by the Length value - from the string wString to the specified stream.

If the stream is not specified, the standard output is used.If Length is not specified, the length of wString is used.

(c) Writing the memory content

The third syntax writes a specified number of bytes - specified by the Length value - from the Pointer memory address to the specified stream.

  • If the stream is not specified, the standard output is used.
  • If Length is not specified, the length of wStream is used.

6.2.0.6 PRINT

PRINT [ # hStream , ] Expression [ { ; | ;; | , } Expression ... ] [ { ; | ;; | , }  ]

The instruction writes the contents of Expression to the stream hStream.

  • If hStream is not specified, then the standard output is used.
  • The standard output can be redirected by the OUTPUT TO instruction.
  • You can convert the expressions to strings by using the Str$ function.
  • If there is no semicolon or comma after the last expression, then an end-of-line character is inserted after the last expression. The end-of-line character can be defined with the property Stream.EndOfLine.
  • If the semicolon is doubled, a space is inserted between the expressions.
  • If a comma is used instead of a semicolon, a tab character (ASCII code 9) is inserted to separate the expressions.

6.2.0.7 READ

(a)	Variable = READ [ # rStream ] AS Datatype
(b)	Variable = READ [ # rStream , ] iLength

(a) Read data of a specified data type *. * The first syntax reads the stream as a data stream whose type is specified by Datatype.

  • If the stream rStream is not specified, the standard input is used.
  • The returned datatype can be one of the following types: NULL, Boolean, Byte, Short, Integer, Long, Pointer, Single, Float, Date, String, Variant, any Array, Collection or Structure.
  • When reading a string, the length of the string must precede the string content in the stream data.
  • If the stream content cannot be read, an error is raised.

Example

If an array was written serialised into a (file) stream via Write, the array can be read from it with Read:

Public hFile As File
Public aNames As String[]
...
' Data import
If Dialog.OpenFile() Then Return
hFile = Open Dialog.Path For Read
aNames = Read #hFile As ARRAY
Close #hFile

(b) Read the contents of a stream

  • The second syntax reads from the stream rStream a number of bytes specified by the Length argument and returns it as a string.
  • If iLength is negative, then at most (-Length) bytes are read until the end of the stream.
  • If the stream is not specified, the standard input is used.

Example

Public sTemperatureDigit As String
 
hRS232 = New SerialPort As "hRS232"
 
Public Sub hRS232_Read()
  sTemperatureDigit  = Read #hRS232, Lof(hRS232)
End

6.2.0.8 LINE INPUT

LINE INPUT [ # hStream , ] Variable

Reads a line of text from the text stream into a string variable.

If the stream hStream is not specified, then the standard input is used. The complete line is always read - with the exception of the end-of-line character. By default, it is the constant gb.Unix, which represents a single Chr$(10) character. The end-of-line character can be defined with the Stream.EndOfLine property.

  • Do not use LINE INPUT … to read from binary files, as you are not using them for a line structure. Use READ instead.
  • Do not use this command inside the Read event of a process that is not necessarily sending a new line because it is issuing a prompt, for example. It will block forever and wait for the line break. For example, the shell sends a command prompt to signal that it is ready to receive a new command. This prompt is usually not terminated by a NewLine, which is why a programme - if it uses LINE INPUT - cannot read this prompt. The implied readiness of the shell to continue is lost.

Example 1

Public Sub AddTextToFile(FilePath As String, Text As String)
 
  Dim hFile As File
 
  Try hFile = Open FilePath For Append
  Print #hFile, Text
 
  Finally
    If Exist(FilePath) Then Close #hFile
  Catch
    Message.Error("Error:\n" & Error.Text & " in " & Error.Where)
 
End
 
Public Function GetTextFromFile(FilePath As String) As String
 
  Dim hFile As File
  Dim sLine, Text As String
 
  Try hFile = Open FilePath For Read
 
  While Not Eof(hFile)
    Line Input #hFile, sLine
    Text &= sLine & "\n"
  Wend
 
  Return Text
 
  Finally
    If Exist(FilePath) Then Close #hFile
  Catch
    Message.Error("Error:\n" & Error.Text & " in " & Error.Where)
 
End
 
Public Sub btnAddTextToFile_Click()
 
  Dim sLogDir As String
 
  sLogDir = Desktop.DataDir &/ "gambasbook" &/ Application.Name
  If Not Exist(sLogDir) Then Shell.MkDir(sLogDir)
 
  AddTextToFile(sLogDir &/ "rs232.log", "Time = " & Format(Now, "hh:nn:ss"))
  Catch
    Message.Error("Error:\n" & Error.Text & " in " & Error.Where)
 
End
 
Public Sub btnGetTextFromFile_Click()
 
  Dim sLogPath As String
 
  sLogPath = Desktop.DataDir &/ "gambasbook" &/ Application.Name &/ "rs232.log"
  txaLog.Text = GetTextFromFile(sLogPath)
 
End

Example 2

Characters are read in via standard input (terminal) to control the MediaPlayer. Notes can be found at: http://www.mplayerhq.hu/DOCS/man/de/mplayer.1.html.

' Gambas module file
 
Public mPlayer As New MediaPlayer
 
Public Sub Main()
 If mPlayer Then mPlayer = Null
 Start()
End
 
Public Sub Start()
 
  mPlayer = New MediaPlayer
  mPlayer.URL = "http://mp3channels.webradio.rockantenne.de/classic-perlen"
 
  mPlayer.Play()
  mPlayer.Audio.Volume = 1.0
 
  Print #File.Out, ""
  Print #File.Out, "-------------------------------------"
  Print #File.Out, "Instructions for use"
  Print #File.Out, "-------------------------------------"
  Print #File.Out, "+  ▶ Audio.Volume ▲"
  Print #File.Out, "-  ▶ Audio.Volume ▼"
  Print #File.Out, "p  ▶ Player.Pause"
  Print #File.Out, "r  ▶ Player.Run (After a pause)"
  Print #File.Out, "m  ▶ Audio.Mute (off/on)"
  Print #File.Out, "q  ▶ Player.Stop"
  Print #File.Out, "-------------------------------------"
  Print #File.Out, "Each command is followed by <ENTER>."
  Print #File.Out, "-------------------------------------"
  Print #File.Out, ""
 
End
 
Public Sub Application_Read()
 
  Dim sInput As String
  Dim fDeltaVolume As Float
 
  If mPlayer.Audio.Volume > 1.1 Then
    fDeltaVolume = 1.0
  Else
    fDeltaVolume = 0.1
  Endif
 
  Line Input #File.In, sInput
 
  Select Case sInput
    Case "q"
      mPlayer.Stop()
      Quit
    Case "p"
      mPlayer.Pause()
    Case "r" ' run
      mPlayer.Play()
    Case "m" ' toggle switch: mute on/mute off
      mPlayer.Audio.Mute = Not mPlayer.Audio.Mute
    Case "+"
      If mPlayer.Audio.Volume > 0.09 And mPlayer.Audio.Volume < 9.0 Then
         mPlayer.Audio.Volume += fDeltaVolume
      Endif
    Case "-"
      If mPlayer.Audio.Volume > 0.2 And mPlayer.Audio.Volume < 10.0 Then
         mPlayer.Audio.Volume -= fDeltaVolume
      Endif
  End Select
 
End

In this example, characters are output to standard output (File.Out) and read from standard input (File.In). The standard error output is not used.

6.2.0.9 INPUT FROM STREAM

INPUT FROM sStream
  • Redirects the standard input to the stream sStream.
  • The standard input is used by INPUT, READ, LINE INPUT, Eof and Lof if you do not specify a stream argument.
  • Calls to this instruction can be nested.

6.2.0.10 INPUT FROM DEFAULT

INPUT FROM DEFAULT

Redirects the standard input to the state before the last redirection.

6.2.0.11 OUTPUT TO STREAM

OUTPUT TO sStream
  • Redirects the standard output to the stream sStream.
  • The standard output is used by PRINT and WRITE if you do not specify a stream argument.
  • Calls to this statement can be nested.

6.2.0.12 OUTPUT TO DEFAULT

OUTPUT TO DEFAULT

Redirects the standard output to the state before the last redirection.

6.2.0.13 ERROR TO STREAM

ERROR TO eStream

Redirects the standard error output to the stream eStream. The standard error output is used by the ERROR and DEBUG instructions. Calls to the instruction can be nested.

6.2.0.14 ERROR TO DEFAULT

ERROR TO DEFAULT

Redirects the standard output to the state before the last redirection.

6.2.0.15 SEEK

SEEK [ # ] hStream , iPosition

Positions the stream pointer for the next read/write. If iPosition is negative, then the stream pointer is moved to a location relative to the end of the file. To move the stream pointer to the end of a file, you must use the Lof(hStream) function.

Example

A text file is read in different ways. After variant 1, the stream pointer is set back to the beginning (position 0) and the file is read out completely again after a second variant:

  hFile = Open $sCurrentFilePath For Input
 
' Variant 1
  hFile = Open $sCurrentFilePath For Input
  While Not Eof(hFile)
    Line Input #hFile, sLine
    sContent = sContent & sLine & gb.NewLine
  Wend
 
  sContent = sContent & gb.NewLine
 
' Variant 2
  seek">Seek #hFile, 0
  For Each sLine In hFile.Lines
    sContent = sContent & sLine & gb.Lf
  Next
 
  sContent = sContent & gb.NewLine

6.2.0.16 Seek

iPosition = Seek ( Stream )

Returns the current value of the stream pointer of the specified stream. The return value iPosition is an integer number of type Long. Note: Many stream types, such as process or socket, do not have a stream pointer.

6.2.0.17 LOCK

hStream = LOCK sPath

Use LOCK and the specified path sPath to achieve a system-wide stream lock. If the specified stream is already locked by another process (advisory look), the command will fail. You can unlock a locked stream with the command UNLOCK.

Example

To safely prevent a second programme start, you can place a system-wide lock on a (pseudo) file. If another programme is started, an error is triggered in (YX) because a lock already exists. Do not forget to release the lock when you exit the programme.

' Gambas class file
 
Public hLockFile As File
Public sFilePath As String
 
Public Sub _new()
 
  sFilePath = Desktop.DataDir &/ "lock.lock"
  Try hLockFile = Lock sFilePath ' <--- Step 1 (XY)
  If Error Then
     Message.Warning(Subst("&1 '&2' &3", ("There is already an instance of"), Application.Name, "!"))
     FMain.Close()
  Endif
 
End
 
' Main program ...
 
Public Sub Form_Close()
    Try Unlock hLockFile ' <--- Step 2
    FMain.Close()
End

6.2.0.18 LOCK WAIT

Stream = LOCK Path fWait Delay
  • Locks a stream for a specified time fWait.
  • The delay is specified in seconds. The type of fWait is Float.
  • If the delay has passed before the lock is acquired, the command fails - an error is raised.

6.2.0.19 UNLOCK

UNLOCK [ # ] Stream

Unlocks a stream previously locked by a LOCK command. Closing the stream also automatically unlocks the stream.

6.2.0.20 EOF (end of file)

Result = Eof ( [ hStream AS Stream ] ) AS Boolean

The function returns TRUE when the end of the stream has been reached.

If hStream is not specified, the standard input is used.The behaviour of Eof() depends on the stream blocking mode: (1) If the stream is in non-blocking mode, then Eof() returns the function value True if at least one byte can be read from the stream. (2) If, on the other hand, the stream is in blocking mode, Eof() first waits for data before checking whether anything can be read.

  hFile = Open $sCurrentFilePath For Input
  While Not Eof(hFile)
    Line Input #hFile, sLine
    sContent = sContent & sLine & gb.NewLine
  Wend

6.2.0.21 LOF (length of file)

Length = Lof ( hStream AS Stream ) AS Long
  • Returns the length of the open stream hStream if hStream is a regular file.
  • On the other hand, if hStream is not a regular file, such as a socket, then the number of bytes that can be read simultaneously is returned.

6.2.0.22 FLUSH

FLUSH [ [ # ] Stream ]

The data of a buffered stream is output immediately - the buffer is emptied. If no stream is specified, the data of any open stream is output. However, you cannot use the flush instruction to request data from another process if you want to read its data from a stream.

Example

The prompt “Enter your name: ” is to be displayed in the terminal and the cursor is to remain - as usual - in the same line for entering the answer. This is accomplished by the double semicolon after the print instruction. It outputs a space and suppresses the line break that Print normally appends to the output. Now, however, terminals are line-buffered. This means that the Gambas programme receives the printed string and buffers it until it reads the next end-of-line character. Only then is the data sent to the terminal. Since the line break is missing after the print instruction in *** due to the double semicolon, you would not see a prompt in the terminal (without flush), although the Gambas programme is already at the line input instruction and waiting for input. Why don't you try it without flush and just type your name blindly. It will work, but you won't see the prompt until after the second print instruction, which returns an end-of-line! With Flush you tell Gambas to print the data immediately. This will make the programme work as expected.

' Gambas module file
 
Public Sub Main()
 
  Dim sName As String
 
  Print "Enter your name:";; ' ***
  Flush
 
  Line Input sName
  Print "Good to know that you are " & sName;
  Print
 
End

Programme start in the project directory:

hans@mint-183 ~/GB3BUCH/6K_Stream/6.2.0_Stream-Input-Output-Funktionen/Projekte/Flush $ gbr3 flush.gambas
Enter your name: Mister Red
Good to know that you are Mister Red

6.2.0.23 NAMED PIPE

hStream = PIPE sPipeName FOR [ READ ] [ WRITE ] [ WATCH ]
hStream = OPEN PIPE sPipeName FOR [ READ ] [ WRITE ] [ WATCH ]
  • Opens a named pipe for reading, writing or both.
  • If the named pipe does not exist, it is created automatically.
  • If the named pipe was opened successfully, a stream object is returned to the variable hStream.

A detailed description of Named Pipes can be found in Chapter 6.2.2.

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k6/k6.2/start.txt · Last modified: 13.01.2022 (external edit)

Page Tools