Session 12: File operations


Objectives

In this session we will learn the following:

  1. Writing formatted output to Scilab console
  2. Reading data from files into Scilab variables
  3. Writing formatted output to a file

Introduction

Scilab file operations are similar to those in C programming language. If you are familiar with file operations in C, you will find it easy to perform file operations in Scilab. But this session does not assume you know C.

For both input and output, you will find a set of three similar functions - output to standard output (or input from standard input), output to (or input from) a file and output to (or input from) a string.

To write to (or read from) a file, it is necessary to first open the file for writing (or reading), perform the write (or read) operations and finally close the file.

Functions Used

mopen(), mprintf(), mfprintf(), msprintf(), mfscanf(), msscanf()

Output Functions

Output to Standard Output (Scilab Console) - mprintf()

Let us first write scalar values first and then see how to write matrices.

-->mprintf("%5d, %12.3f\n", 120, 1234.55)
  120,     1234.55

Notice what happened:

  1. To the function mprintf(), we provided three arguments. First, a string containing formatting specifications ("%5d, %12.3f\n"). Second is an integer (120). Third is a real number (1234.55)
  2. The formatting specification contains two format placeholders, namely, %5d and %12.3f. Format placeholders begin with the %. Rest of the formatting specification string are output as they are.
  3. %5d corresponds to the second argument to mprintf(), namely 120. It outputs 120 as an integer (%d), formatting it is a width of 5 places (%5d)
  4. %12.3f can be understood as follows - 12 is the width, 3 is the precision (number of decimal places) and f corresponds to a float (real number).
  5. If there are two placeholders in the formatting specification string, it must be followed by two values with the matching data type as in the formatting specification.

To print out values of a matrix, the format specification string must be able to print one full row of the matrix. This specification will be used for each row of the matrix until all rows are printed. It is an error to provide too few or too many  placeholders in the format specification string than the number of columns being printed. Let us see an example:

-->a = [1 2 3 4; 5 6 7 8];
-->mprintf("%5.2f,%5.2f,%5.2f,%5.2f\n", a)
 1.00, 2.00, 3.00, 4.00
 5.00, 6.00, 7.00, 8.00
-->b = [10 11; 20 21; 30 31]; // 3x2 matrix
-->mprintf("%5.2f,%5.2f,%5.2f,%5.2f\t%8.3f,%8.3f\n", a, b)
 1.00, 2.00, 3.00, 4.00          10.000,  11.000
 5.00, 6.00, 7.00, 8.00          20.000,  21.000

Note that only two rows of matrix b are printed and not all the three. When printing values from more than one matrix, only that many rows are printed as the minimum number of rows in the matrices being printed. In the abov case, a is of size 2x4 and b is of size 3x2. Hence only 2 rows are printed from each matrix. The formatting specification string must contain enough placeholders required to print all the columns of all matrices being printed, which is 4 + 2 = 6 in the above case.

Output to a String - msprintf()

Function msprintf() is similar to mprintf(), except that the output is sent to a string variable (for storage and subsequent output) instead of to the standard output. The above output statements could be rewritten for output to a string as follows:

-->n = 20; s1 = msprintf("Number of items = %d\n", n);
-->disp(s1)
 Number of items = 20
a = [1 2 3 4; 5 6 7 8];
-->s2 = msprintf("%5.2f,%5.2f,%5.2f,%5.2f\n", a)
-->disp(s2)
! 1.00, 2.00, 3.00, 4.00 !
!                        !
! 5.00, 6.00, 7.00, 8.00 !

Output to a File - mfprintf()

Function mfprintf() send the output to a file. Its use is similar to mprintf() and msprintf(), except that:

  1. The file to which output is to be sent must first be opened using the mopen() function. If this function call is successful, it returns a file descriptor which must be used in all subsequent write operations to the file. It requires two input arguments:
    1. A string containing the name of the file to be opened (test.dat in the example below. It is a good idea to check your current working directory).
    2. A string specifying the type of file operation to be performed on the file after opening (other possibility is "r" for reading).
  2. The mfprintf() takes one argument more than mprintf() and msprintf(). The first argument must be the file descriptor obtained with the mfopen() function.
  3. When all output to the file are complete, the file must be closed using mclose() function.

-->n = 20; a = [1 2 3 4; 5 6 7 8];
-->fd = mopen("test.dat", "w"); // Creates a new file or opens an existing file and truncates to zero length
-->mfprintf(fd, "Number of items = %d\n", n)
-->mfprintf(fd, %5.2f,%5.2f,%5.2f,%5.2f\n", a)
-->mclose(fd)

Note the current working directory, then search and open the file test.dat in an editor. It will containg the following lines:

Number of items = 20
 1.00, 2.00, 3.00, 4.00
 5.00, 6.00, 7.00, 8.00

Input Functions

Input functions parse and convert text input into data as prescribed in the format specification string, the opposite of what the output functions do (which is converting data into text output).

Input from Standard Input - mscanf()

The input functions are used as follows:

-->[n, a, b, c] = mscanf("%d%f%f)
5 12.5 -2.5
 c  =
   -2.5
 b  =
    12.5
 a  =
    5

Number of placeholders in the format specification string indicate the number of values expected to be input. The first output argument n on the left hand side of the function mscanf() is the number of values read. It is -1 if values input are fewer than the number of placeholders in the format specification string.

The above example is what is called the multiple left hand side (LHS) syntax. This is to be used when you want to read in multiple values with one mscanf() function. If you want to read in only one value, the syntax for single LHS is simpler:

-->x = mscanf("%f")
10.5
 x  =
    10.5

To read in multiple lines (that is matrices with a known number of rows), the function call for a single LHS value is as follows:

-->x = mscanf(2, "%f %f %f")
-->1.1  1.2  1.3
-->2.1  2.2  2.3
 x  =
    1.1   1.2   1.3
    2.1   2.2   2.3

Reading multiple lines with multiple LHS is possible if each variable has only one column. Reading multiple values on the LHS, each with multiple columns is not possible. Here is how we read values into two variables, namely, a and b, each having a single column and 3 rows:

-->[n, a, b] = mscanf(3, "%f %f")
-->1.1 1.2
-->2.1 2.2
-->3.1 3.2
 b  =
    1.2
    2.2
    3.2
 a  =
    1.1
    2.1
    3.1
 n  =
    2

Using msscanf() and mfscanf() proceed along similar lines.

Input from a String - msscanf()

Function msscanf() reads the input from a string rather than the standard input (as mscanf() does). The input arguments for msscanf() are:

  1. First input argument is the number of lines to be read for each LHS, but is optional.
  2. Second input argument is the string from which input is to be read.
  3. Third input argument is the format specification string

-->[n, a, b, c] = msscanf('5 12.5 -2.5', "%d %f %f")
 c  =
   -2.5
 b  =
    12.5
 a  =
    5
// Initialize the string containing input data
-->s = ['1.1 1.2 1.3'; '2.1 2.2 2.3'];
// Single LHS of size 2x3
-->x = msscanf(2, s, "%f %f %f")
 x  =
    1.1   1.2   1.3
    2.1   2.2   2.3

Input from a File - mfscanf()

Operations are:

  1. Open the file for reading
  2. read from file and convert to data as specified by the format specification string
  3. Close the file

-->//Prepare some sample data for writing
-->x = [0:%pi/16:%pi]'; y = sin(x);
-->// Write data to a file for subsequent reading
-->fd = mopen("sine.dat", "w")
 fd  =
     1
-->mfprintf(fd, "%f %f\n", x, y)
-->mclose(fd)
-->// Open the file sine.dat for reading
-->fd = mopen("sine.dat", "r")
 fd  =
     1
-->// Clear data before reading
-->clear x y
-->[n, x, y] = mfscanf(-1, fd, "%f %f");
-->mclose(fd)

To read until end of file, the number of lines to be read is set to -1.

Summary

  1. To write to (or read from) a file, the file must first be opened in the write (or read) mode. File must be closed after all write (or read) operations are complete. There is no need for a open or close function to write to (or read from) the standard input or a string.
  2. For writing:

    1. Any number of variables can be written out from one mprintf(), msprintf() or mfprintf() function call.
    2. The format specification string must be sufficient to print one full line of all the variables being written.
    3. There is no need to specify the number of rows to be written. The number of lines written is the smallest of the number of lines amongst the variables being written.
  3. For reading:
    1. One or more variables can be read from one mscanf(), msscanf() or mfscanf() function call. When reading multiple variables from a single function call, the first output argument is the number of variables read.
    2. If the number of input variables is fewer than the number of output variables specified on the LHS, variables without input values are set to null matrices.
    3. When reading variables, the number of lines to be read must be specified as the first input argument. If the first input argument is not an integer, it is assumed that one line is to be read.

Task Discussion