Main Content

Generate Code That Reads Data from a File

This example shows how to generate C code from your MATLAB® code that reads data from a CSV file and stores the data in a table.

Inspect Data File

The goal of this example is to generate code that reads a comma separated values (CSV) file that contains temperature measurements (in units of degrees Celsius) of a furnace taken at various times over a course of several days. The file begins with several lines of description. This is followed by the data listed as comma-separated values in a table format.

type mydata.csv
Temperature of a furnace in degrees Celsius
measured at various times over a course of 
one week
time, temp
19-Aug-2021 10:32:35, 81
20-Aug-2021 10:40:28, 72
22-Aug-2021 10:19:36, 98
23-Aug-2021 11:00:02, 70
24-Aug-2021 10:54:27, 90
25-Aug-2021 11:03:00, 87

Create and Test MATLAB Entry-Point Function

Write a MATLAB® function my_readtable that reads the file mydata.csv, ignores the initial description lines, and creates a MATLAB table containing the datetime and numeric values. Because the MATLAB function readtable is not supported for code generation, this example uses low-level file I/O functions like fopen, fgetl, fscanf, feof, and fclose to open the file, read data, and finally close the file.

type my_readtable.m
function T = my_readtable(filename,numRecords) %#codegen

f = fopen(filename,"r");

% Scan and ignore a variable number of description lines at the beginning
% of the CSV file.
line = fgetl(f);
coder.varsize("line");
while(~ismember(',',line))
    line = fgetl(f);
end

% Table variable names.
names = {'time' 'temp'};

% Initialize variables. Define 'months' cell array that is used to convert
% name of month to serial number of month in the next code block.
i = 1;
months = {'Jan' 'Feb' 'Mar' 'Apr' 'May' 'Jun' 'Jul' 'Aug' 'Sep' 'Oct' 'Nov' 'Dec'};

dateAndTime = repmat(datetime,1,numRecords);
temperature = zeros(1,numRecords);

% Read each line in the CSV file till you reach EOF. Construct an array of
% datetime and double values (for time and temp columns).
while(~feof(f))
    day = fscanf(f,'%u-');
    month_name = string(fscanf(f,'%3c',1));
    month_number = find(month_name == months);
    [result,count] = fscanf(f,'-%u %u:%u:%u, %u');

    % Check that the last fscanf call read all remaining data in the line
    assert(count == 5) 

    year = result(1);
    hour = result(2);
    minute = result(3);
    second = result(4);
    dateAndTime(i) = datetime(year,month_number,day,hour,minute,second);
    temperature(i) = result(5);
    i = i + 1;
end

% Construct the table from the values read in the previous code block.
T = table(dateAndTime',temperature','VariableNames',names);
fclose(f);

end

This entry-point function (top-level MATLAB function for which you generate code) uses these coding patterns that make it suitable for code generation:

  • The size of the character vector line changes as the function reads each line of the initial description. The coder.varsize directive instructs the code generator to produce code that dynamically allocates memory for the variable line.

  • The function hardcodes the column header names 'time' and 'temp' instead of reading them from the CSV file at run time. This is because code generation requires table variable names to be compile-time constants.

  • The variable months is defined as a character array instead of a string array because code generation does not support string arrays.

  • The function preinitializes the arrays dateAndTime and temperature before populating them with actual data (in the while loop).

Run the MATLAB entry-point function.

T_matlab = my_readtable("mydata.csv",6)
T_matlab=6×2 table
            time            temp
    ____________________    ____

    19-Aug-2021 10:32:35     81 
    20-Aug-2021 10:40:28     72 
    22-Aug-2021 10:19:36     98 
    23-Aug-2021 11:00:02     70 
    24-Aug-2021 10:54:27     90 
    25-Aug-2021 11:03:00     87 

Generate and Run MEX

To test the output of code generation inside the MATLAB environment, generate and run a MEX (MATLAB executable) by using the codegen command. A MEX is compliled C/C++ code that you can run inside the MATLAB environment. By default, the codegen command produces a MEX.

In the codegen command, specify the following data types for the input arguments of the function my_readtable:

  • filename is an unbounded variable-length string

  • numRecords is a double scalar

s = "mystring";
t = coder.typeof(s);
t.Properties.Value = coder.typeof('a',[1 inf]);

codegen my_readtable -args {t,0} -report
Code generation successful: To view the report, open('codegen/mex/my_readtable/html/report.mldatx')

The code generator produces the MEX function my_readtable_mex. Run the generated MEX.

T_mex = my_readtable_mex("mydata.csv",6)
T_mex=6×2 table
            time            temp
    ____________________    ____

    19-Aug-2021 10:32:35     81 
    20-Aug-2021 10:40:28     72 
    22-Aug-2021 10:19:36     98 
    23-Aug-2021 11:00:02     70 
    24-Aug-2021 10:54:27     90 
    25-Aug-2021 11:03:00     87 

Generate Standalone Code

Generate a static C library for my_readtable for deployment on target hardware.

codegen -config:lib my_readtable -args {t,0} -report
Code generation successful: To view the report, open('codegen/lib/my_readtable/html/report.mldatx')

The file I/O functions are implemented differently between the MEX and the standalone code. For example, for MEX code generation, the code generator automatically treats fscanf as an extrinsic function. So, the generated MEX dispatches the fscanf calls to the MATLAB engine for execution. If you generate standalone code, the code generator actually produces C/C++ code for the body of the MATLAB fscanf function.

For MEX target, If you want to generate C/C++ code for the body of the MATLAB fscanf function, disable extrinsic function calls by setting the ExtrinsicCalls property of the coder.MexCodeConfig object to false. Alternatively, in the MATLAB Coder app, on the More Settings tab, set Keep extrinsic calls to No.

If you have Embedded Coder®, you can verify the generated standalone code by using Software-In-the-Loop (SIL) or Processor-In-the-Loop (PIL) execution before deployment. For an example, see SIL and PIL Verification for Deployment on Raspberry Pi (Embedded Coder).