This chapter describes the File class, which provides methods and properties for reading from and writing to external files and discusses the following topics:
Data type of a file object
Scope of a file object
File security considerations
File access interruption recovery
Plain text files
Automatic PeopleCode generation
File layout error processing
File class built-in functions
File class methods
File class properties
File layout examples
Multiple file layouts
See Also
Constructing File Layouts and Performing Data Interchanges
PeopleTools supports reading and writing to plain text files, and to files that have a format based on a File Layout definition that has been created in PeopleSoft Application Designer.
If the file is a plain text file, data is read or written using text strings.
If the file is based on a File Layout, you can use text strings, rowset, or record objects.
This simplifies reading, writing, and manipulating hierarchical transaction data with PeopleCode.
File layout methods and properties are noted as such in their descriptions.
See Also
Constructing File Layouts and Performing Data Interchanges
The File Object is an instance of the File class. A file object is declared using the File data type. For example,
Local File &MYFILE;
This creates an object &MYFILE of the class File.
A file object can only be instantiated from PeopleCode. This object can be used anywhere you have PeopleCode, that is, in message subscription PeopleCode, Component Interface PeopleCode, record field PeopleCode, and so on.
A file object is passed to and returned from PeopleCode functions and methods as a reference, so the file object is never copied; rather, alternate identifiers are used to refer to the same object. Any change made to a file using one identifier has the same effect as it would with any other identifier for that file.
In the following code example, two variables, &F1 and F2, are declared by using the data type File. The file is opened using the GetFile built-in function. Next, &F1 is assigned to &F2. This does not copy &F1 to &F2. Instead, &F1 and &F2 both refer to the same object. Therefore, in the last step when &F2 is closed, &F1 is closed too.
Local File &F1, &F2; &F1 = GetFile("somefile.txt", "R"); &F2 = &F1; &F2.Close(); /* Now &F1 is also closed. */
See Also
When you’re using file objects in PeopleCode that might run on a server, you must be aware of some security concerns. The underlying system doesn’t provide security checks on access to the files. Instead, the PeopleCode programs use whatever authority the server process has, and not that of the user. This means you must write your PeopleCode program to prevent the user from reading or writing files that they should not. In particular, be especially wary of opening files where any part of the filename is derived from user input.
You can use the GetPosition or SetPosition methods to minimize the loss of work in the event of a system failure during file access. To use them and recover from access interruptions, you must access the file in Update mode using the GetFile built-in function or the Open method, specifying the mode parameter "U". You need to use this mode in anticipation of possible interruptions if you want to recover from them later.
To start reading or writing from the beginning of a file, use SetPosition to set a read/write position of 0, immediately after you open the file in Update mode.
Warning! In Update mode, any write operation clears the file of all data that follows the position you set.
When reading from or writing to a file, use GetPosition periodically to determine your current byte position in the file. This establishes a checkpoint to which you can return after a failure. You must save the checkpoint value in a separate file or a database so you can retrieve it later. How often you save a checkpoint depends on your requirements: the less work you want to redo, the more frequent your checkpoints should be. You may also want to save information identifying the data you’re reading or writing at the time.
After a failure interrupts your file access, reopen the file in Update mode. You can then retrieve the last checkpoint value you saved, and use SetPosition to apply that value. Your read/write position in the file is the position of the last checkpoint, and you can continue reading or writing from there.
Use the Update mode with GetPosition and SetPosition only for recovering from interruptions as described here, or for starting at the beginning of the file again.
Note. Currently, the effect of the Update mode is not well defined for Unicode files. Use the Update mode only on files stored with a non-Unicode character set.
See Also
To read and write from plain text files involves reading and writing strings of data. These text strings can be manipulated with built-in string functions, like RTrim, Find, Replace, and so on.
Note. If your data is hierarchical in nature, or based on existing PeopleSoft records or pages, use a File Layout definition for reading and writing your data, rather than doing it line by line (or field by field.)
The following example creates an array of array of string, then reads in two files, one into each "column" of the array. The Names file contains names; the Numbers file contains employee numbers. The ReadLine method reads each successive line in a file, until it reaches the end of the file.
Notice that the first file is opened using the GetFile function. The second file is not opened using GetFile, but rather with the Open method. After the data is read into the array, you can do processing on the data. The end of the program writes the changes back to the files, using the WriteLine method, which includes a system end of line character at the end of every line.
Local array of array of string &BOTH; Local File &MYFILE; Local string &HOLDER; /* Create empty &BOTH array */ &BOTH = CreateArrayRept(CreateArrayRept("", 0), 0); /* Read first file into first column */ &MYFILE = GetFile("names.txt", "R"); While &MYFILE.ReadLine(&HOLDER); &BOTH.Push(&HOLDER); End-While; /* read second file into second column */ &MYFILE.Open("numbers.txt", "R"); &LINENO = 1; While &MYFILE.ReadLine(&HOLDER); If &LINENO > &BOTH.Len Then /* more number lines than names, use a null name */ &BOTH.Push(CreateArray("", &HOLDER)); Else &BOTH[&LINENO].Push(&HOLDER); End-If; &LINENO = &LINENO + 1; End-While; /* if more names than numbers, add null numbers */ For &LINENO = &LINENO to &BOTH.Len &BOTH[&LINENO].Push(""); End-For; &MYFILE.Close(); /* do processing with array */ /* write data back to files */ &MYFILE1 = GetFile("names.txt", "A"); &MYFILE2 = GetFile("numbers.txt", "A"); /* loop through array and write to files */ For &I = 1 To &BOTH.Len &STRING1 = &BOTH[&I][1]; &MYFILE1.writeline(&STRING1); &STRING2 = &BOTH[&I][2]; &MYFILE2.writeline(&STRING2); End-For; &MYFILE1.Close(); &MYFILE2.Close();
See Also
After you create a File Layout definition, you can use PeopleCode to access it. This PeopleCode can be long and complex. Rather than write it directly, you can drag and drop the File Layout definition from Application Designer Project View into an open PeopleCode edit pane. This is primarily used for importing data. Application Designer analyzes the definition and generates initial PeopleCode as a template, which you can modify to meet your requirements.
The following is just a snippet of the code that is generated:
Function EditRecord(&REC As Record) Returns boolean ; Local integer &E; REM &REC.ExecuteEdits(%Edit_Required + %Edit_DateRange + %Edit_YesNo + %Edit_TranslateTable + %Edit_PromptTable + %Edit_OneZero); &REC.ExecuteEdits(%Edit_Required + %Edit_DateRange + %Edit_YesNo + %Edit_OneZero); If &REC.IsEditError Then For &E = 1 To &REC.FieldCount &MYFIELD = &REC.GetField(&E); If &MYFIELD.EditError Then &MSGNUM = &MYFIELD.MessageNumber; &MSGSET = &MYFIELD.MessageSetNumber; &LOGFILE.WriteLine("****Record:" | &REC.Name | ", Field:" | &MYFIELD.Name ); &LOGFILE.WriteLine("****" | MsgGet(&MSGSET, &MSGNUM, "")); End-If; End-For; Return False; Else Return True; End-If; End-Function; . . .
See Also
Constructing File Layouts and Performing Data Interchanges
If an error occurs on any field in any record of a rowset object populated with the ReadRowset method, the rowset object’s property IsEditError returns True. For example, you can use the method ExecuteEdits on a record, to verify that the data in the record is valid (has the correct format, the right data type, and so on.) This type of error is indicated by the IsEditError.
In some instances, however, the rowset object won’t receive the error; in that case the file object’s IsError property returns True. To discover all field errors, check both properties after executing ReadRowset.
To determine which field has the error, you must examine the EditError property of every field in the rowset to find the one returning True. You can then examine that field’s MessageSetNumber and MessageNumber properties to determine the relevant error message. The following example shows how this might be done:
&MYFILE.Open(&SOMENAME, "R"); &MYFILE.SetFileLayout(FILELAYOUT.SOMELAYOUT); &MYROWSET = &MYFILE.ReadRowset(); If &MYFILE.IsError Then For &I = 1 to &MYROWSET.ActiveRowCount If &MYROWSET.GetRow(&I).IsEditError Then &ROW = &MYROWSET.GetRow(&I); For &J = 1 to &ROW.RecordCount If &ROW.GetRecord(&J).IsEditError Then &REC = &ROW.GetRecord(&J); For &K = 1 to &REC.FieldCount If &REC.GetField(&K).EditError Then /* Examine the field’s MessageSetNumber and MessageNumber properties, and respond accordingly */ End-If; End-For; End-If; End-For; End-If; End-For; End-If; &MYFILE.Close();
Note. Only field errors set the IsError, IsEditError, or EditError properties. All other errors triggered by File class methods terminate the PeopleCode program.
See Also
In this section, we discuss the File class methods. The methods are discussed in alphabetical order.
Syntax
Close()
Description
The Close method discards any changes that haven’t been written to the external file, disassociates the file object from the external file, releases all resources connected with the file object, and causes the file object to go out of scope.
You cannot use any methods or properties on the object after it is closed. You must get another file object (using the GetFile function) and instantiate another file object after you use Close.
Parameters
None.
Returns
None.
Example
&MYFILE.Open("somefile.txt", "W", %FilePath_Relative); &MYFILE.WriteLine("Some text."); &MYFILE.Close();
See Also
File class: Open method, IsOpen property.
Syntax
CreateRowset()
Description
The CreateRowset method is a file layout method. It instantiates a PeopleCode rowset object containing one unpopulated row, based on the file layout definition specified with SetFileLayout.
Note. You must specify a file layout using the SetFileLayout method before using CreateRowset, otherwise it returns NULL.
See File class: SetFileLayout method.
After the empty rowset object has been created, you can use Rowset class methods such as Select or Fill, and built-in functions such as GetLevel0 or GetRowset, to populate the rowset with data. After the rowset contains data, you can use the method WriteRowset to write the data to a file.
Don’t use CreateRowset when reading from a file. Instead, use the ReadRowset method to instantiate and populate rowsets with data from the file.
Parameters
None.
Returns
An empty rowset object.
Example
&SOMEROWSET = &MYFILE.CreateRowset();
The following rowset is created from a file object, then populated with data using the GetLevel0 function:
&FILEROWSET = &MYFILE.CreateRowset(); &FILEROWSET = GetLevel0(); &MYFILE.WriteRowset(&FILEROWSET, True);
The following rowset is created from a file object, then populated with data using Fill method:
&FILEROWSET = &MYFILE.CreateRowset(); &NUM_READ = &FILEROWSET.Fill("where MYRECORD = :1", &UVAL);
See Also
File class: ReadRowset method, SetFileLayout method, WriteRowset method.
Syntax
Delete()
Description
Use the Delete method to delete an open file. You cannot delete a closed file.
Parameters
None.
Returns
None.
Example
/* Open a temporary file. Use the "N" parameter to ensure the file is new. */ &MyFile = GetFile("temp.txt", "N"); /* do processing using the temporary file */ /* delete the temporary file */ &MyFile.Delete();
See Also
File class: Open method, Close method.
Syntax
GetPosition()
Description
The GetPosition method returns the current read or write position in the external file. GetPosition works only with a file that was opened in Update mode. This method is designed to be used in combination with the SetPosition method to establish checkpoints for restarting during file access.
Note. Currently, the effect of the Update mode and the GetPosition and SetPosition methods is not well defined for Unicode files. Use the Update mode only on files stored with a non-Unicode character set.
Parameters
None.
Returns
A number representing the current read or write position in the file.
Note. When you use ReadRowset to read from a file in Update mode, the CurrentRecord property returns, the entire record just read. The current read/write position is at the end of the CurrentRecord, that is, just past the end of the rowset.
Example
The following example opens a file in Update mode, and saves the current position after each read operation:
&MYFILE.Open(&SOMENAME, "U"); If &MYFILE.IsOpen Then while &MYFILE.ReadLine(&SOMESTRING) &CURPOS = &MYFILE.GetPosition(); /* Save the value of &CURPOS after each read, and process the contents of each &SOMESTRING */ End-While; End-If; &MYFILE.Close();
See Also
File class: Open method, SetPosition method.
File Access Interruption Recovery
Syntax
GetString([Strip_Line_Terminator])
Description
Use the GetString method to return the entire file as a single string.
Note. After this method completes successfully, the original file is deleted.
You can specify whether the resulting string is to include the line terminator characters or not by using the Strip_Line_Terminator parameter. The default value for this parameter is false, which means the resulting string includes the line terminator characters at the end of each line.
For example on a Unix system, with a line terminator of a LF, the resulting string includes not only the data for each line, but the LF character as well.
Parameters
Strip_Line_Terminator |
Specify whether the line terminators are to be stripped or not. |
Returns
A single string containing the entire contents of the file.
Example
The following example creates a file on a Windows system, then retrieves it as a single line of text.
Note. The file is destroyed on successful completion of this method.
Local File &File = GetFile("c:\temp\junk\something.txt", "W", %FilePath_Absolute) /* write a bunch of > 2048 length lines */ Local string &piece, &input; Local integer &I; &piece = "123456789-"; While Len(&piece) < 2048 &piece = &piece | &piece; End-While; &File.WriteString(&piece); &File.WriteString(&piece); &File.WriteString(&piece); &input = &File.GetString( True); &File.Close(); Local string &pieces = &piece | &piece | &piece; /* Note that the result of this message should indicate &pieces is the same as &input */ MessageBox(0, "", 0, 0, "&piece = &input: Len(&pieces)=" | Len(&pieces) | " Len(&input)=" | Len(&input) | " Same? " | (&pieces = &input));
See Also
File class: ReadLine method, WriteLine method, WriteRaw method.
Syntax
Open(filespec, mode [, charset] [, pathtype])
Description
The Open method associates the file object with an external file for input or output.
You can use the GetFile function to access an external file, but each execution of GetFile instantiates a new file object. If you plan to access only one file at a time, you need only one file object. Use GetFile to instantiate a file object for the first external file you access, then use Open to associate the same file object with as many different external files as you want. You need to instantiate multiple file objects with GetFile only if you expect to have multiple files open at the same time.
If the file object is currently associated with a file, that file is first closed.
If you specify a relative path, that path is appended to the path specified by an environmental variable, if the variable exists, in a particular order. This means if the first environmental variable in order is found, that is the one that's used. If it isn't found, the next one is searched for, and if found, is used, and so on.
If Open is called from Application Engine when running standalone, that is, when not within an application server domain), the following environmental variables are valid, and are searched for in the following order:
PS_FILEDIR[\relative_path]
PS_SERVDIR\Files[\relative_path]
If the code is not running on an application server, the following environmental variables are valid, and are searched for in the following order:
PS_FILEDIR[\relative_path]
PS_SERVDIR\Files[\relative_path]
TEMP[\relative_path]
The PS_FILEDIR environmental variable is not initialized and set to a path automatically. If you want to use this environmental variable, you must set it yourself.
Note. Your system security should verify if a user has the correct permissions before allowing access to a drive (for example, if a user changes their TEMP environmental variable to a network drive they don’t normally have access to, your system security should detect this.)
Parameters
filespec |
Specify the name, and optionally, the path, of the file you want to open. |
mode |
A string indicating the manner in which you want to access the file. The mode can be one of the following: "R" (Read mode): opens the file for reading, starting at the beginning. "W" (Write mode): opens the file for writing. Warning! When you specify Write mode, any existing content in the file is discarded and is overwritten. Note. Currently, the effect of the Update mode and the GetPosition and SetPosition methods is not well defined for Unicode files. Use the Update mode only on files stored with a non-Unicode character set. "E" (Conditional "exist" read mode): opens the file for reading only if it exists, starting at the beginning. If it doesn’t exist, Open has no effect. Before attempting to read from the file, use the IsOpen property to confirm that it’s open. "N" (Conditional "new" write mode): opens the file for writing, only if it doesn’t already exist. If a file by the same name already exists, Open has no effect. Before attempting to write to the file, use the IsOpen property to confirm that it’s open. You can insert an asterisk (* ) in the filename to ensure that a new file is created. The system replaces the asterisk with numbers starting at 1 and incrementing by 1, and checks for the existence of a file by each resulting name in turn. It uses the first name for which a file doesn’t exist. In this way you can generate a set of automatically numbered files. If you insert more than one asterisk, all but the first one are discarded. |
charset |
A string indicating the character set you expect when you read the file, or the character set you want to use when you write to the file. You can abbreviate Unicode UTF-16 to "U" and the host operating system's default non-Unicode (sometimes referred to as the ANSI character set) to “A”. All other character sets must be spelled out in full, for example, ASCII, THAI, or UTF8. If non-Unicode (“A”) is specified, or you don't specify a character set, the character set used is dependent on the application server configuration. On a Windows application server, the default non-Unicode character set is dependent on the Windows ANSI Codepage (ACP) which can be checked using the DOS command chcp. On a Unix application server, the default non-Unicode character set is specified in the application server configuration file, psappsrv.cfg, and can be modified using PSADMIN. You can also use a record field value to specify the character set (for example, RECORD.CHARSET.) A list of supported character set names valid for this argument can be found in Enterprise PeopleTools 8.46 PeopleBook: PeopleSoft Global Technology. See Character Sets in the PeopleSoft Pure Internet Architecture. Note. If you attempt to read data from a file using a different character set than was used to write that data to the file, the methods used generate a runtime error or the data returned is unusable. When a file is opened for reading using the “U” charset argument, GetFile expects the file to begin with a Unicode Byte Order Mark (BOM), otherwise known as a sentinal. This mark indicates whether the file is written in big endian order or little endian order. A BOM consisting of the hex value 0xFEFF indicates a big endian file, a BOM consisting of the hex value 0xFFEF indicates a little endian file. If the Unicode UTF-16 file being opened does not start with a BOM, an error is returned. The BOM is automatically stripped from the file when it is read into the buffers by GetFile. When a file is opened for writing using the “U” charset argument, the Unicode BOM is automatically written to the start of the file, dependent on whether the application server hardware platform operates in little endian or big endian mode. Byte Order Marks are not expected or supported for files in other character sets, including UTF8. Note. When working with XML documents, specify UTF8 for charset. |
pathtype |
If you have prepended a path to the file name, use this parameter to specify whether the path is an absolute or relative path. The valid values for this parameter are:
If you don’t specify pathtype the default is %FilePath_Relative. If the path is an absolute path, whatever path you specify is used verbatim. You must specify a drive letter and the complete path. You can’t use any wildcards when specifying a path. The Component Processor automatically converts platform-specific separator characters to the appropriate form for where your PeopleCode program is executing. On a WIN32 system, UNIX "/" separators are converted to "\", and on a UNIX system, WIN32 "\" separators are converted to "/". |
Note. The syntax of the file path does not depend on the file system of the platform where the file is actually stored; it depends only on the platform where your PeopleCode is executing.
Returns
None.
Example
The following example opens an existing Unicode file for reading:
&MYFILE.Open(&SOMENAME, "E", "U"); If &MYFILE.IsOpen Then while &MYFILE.ReadLine(&SOMESTRING) /* Process the contents of each &SOMESTRING */ End-While; &MYFILE.Close(); End-If;
The following example opens a numbered file for writing in ANSI format, without overwriting any existing files:
&MYFILE.Open("C:\temp\item*.txt", "N", %FilePath_Absolute); If &MYFILE.IsOpen Then &MYFILE.WriteLine("Some text."); &MYFILE.Close(); End-If;
See Also
File class: IsOpen property, SetPosition method, GetPosition method, Close method.
File Access Interruption Recovery
Syntax
ReadLine(string)
Description
The ReadLine method reads one line of text from the external file. The line includes the newline character, but ReadLine strips out the newline character and inserts the result into the string variable string.
When ReadLine is executed, it moves the starting point for the next read operation to the end of the text just retrieved, so each line in the file can be read in turn by subsequent ReadLine operations. When no more data remains to be read from the file, ReadLine returns False, and clears the string variable of any content.
Parameters
string |
A string variable that receives the input text. |
Returns
A Boolean value: True if the method succeeds, False otherwise. The return value is not optional, it is required.
Example
The following example reads a file called &MYFILE and puts each line as a separate element in an array.
Local File &MYFILE; Local array of string &MYARRAY; Local string &TEXT; &MYFILE = GetFile("names.txt", "R"); &MYARRAY = CreateArrayRept("", 0); While &MYFILE.ReadLine(&TEXT); &MYARRAY.Push(&TEXT); End-While; &MYFILE.Close();
See Also
File class: GetString method, ReadRowset method, WriteString method, WriteLine method.
Syntax
ReadRowset()
Description
The ReadRowset method is a file layout method. It instantiates a PeopleCode rowset object based on the file layout definition, then populates the rowset with one transaction from the file. A transaction is considered to be one instance of level zero data contained in a file record, plus all of its subordinate data. If you put more than one segment at level zero, each segment is read in sequence.
Note. You must specify a file layout using the SetFileLayout method before using ReadRowset, otherwise it will return NULL.
When ReadRowset is executed, it moves the starting point for the next read operation to the beginning of the next rowset, so each transaction in the file can be read in turn by subsequent ReadRowset operations. When no more data remains to be read from the file, ReadRowset returns NULL.
If you’re using the SetFileId method with ReadRowset to process an input file based on multiple file layouts, ReadRowset returns NULL when it reads a FileId file record (line) between the rowsets.
When ReadRowset returns NULL, you can use the IsFileId property to determine if you’ve reached the end of the file or a FileId record.
Note. When using ReadRowset, if a value in the file exceeds the defined length in the file layout, it is ignored. The given record field is flagged with an edit error which can be programmatically checked.
If the ReadRowset encounters a line in the file containing the FileId, and the lines following this are not a new rowset, the process considers it to be an invalid FileId. You can specify whether to ignore the invalid record or terminate the PeopleCode with the IgnoreInvalidId property.
Note. If you’re using the SetFileId method with ReadRowset to process an input file based on multiple layouts, FileId file records between the rowsets are considered to be valid file records, and won’t generate any errors, regardless of the state of the IgnoreInvalidId property.
See File class: SetFileLayout method.
Considerations for Using Dates With ReadRowset
Single digits in dates in the form MMDDYY or MMDDYYYY must be padded with zeros. That is, if the date in your data is February 3, 2000, the form must be:
02/03/2000
or
02/03/00
The following is not valid.
2/3/00
Considerations Using XML With ReadRowset
If all of the fields in the file layout are not present in the XML, no data is written to the database. If there are additional tags in the XML, they are ignored.
Parameters
None.
Returns
A populated rowset.
Example
The following example reads and processes an entire file. The data in the file is based on a single File layout definition:
&MYFILE.GetFile(&SOMENAME, "R"); If &MYFILE.SetFileLayout(FILELAYOUT.SOMELAYOUT) then &SOMEROWSET = &MYFILE.ReadRowset(); While &SOMEROWSET <> NULL /* Process the contents of each &SOMEROWSET */ &SOMEROWSET = &MYFILE.ReadRowset(); End-While; End-If; &MYFILE.Close();
See Also
File class: CurrentRecord property, IgnoreInvalidId property, GetString method, ReadLine method, SetFileLayout method, WriteRecord method, WriteRowset method.
Syntax
SetFileId(fileid, position)
Description
The SetFileId method is a file layout method. If your input file contains data based on more than one File Layout definition, you must use this method in combination with the CurrentRecord and IsNewFileId properties and the ReadRowset method to process the file correctly.
Note. SetFileId, CurrentRecord and IsNewFileId don’t apply to CSV and XML format input files. You can use only FIXED format files to implement multiple file layouts.
See File class: CurrentRecord property, IsNewFileId property, ReadRowset method.
At each point in the input file where the structure of the rowset changes, there must be an extra line in the file containing the file record (line), the FileId file record (line), that signifies that the change. Each FileId file record must have the following components:
A value that designates it as a Fileid. Only one FileId value is necessary throughout the file, such as "999".
A name field that identifies the file layout needed for the rowset that follows. This field could contain the name of the file layout as it’s defined in PeopleSoft Application Designer.
These lines containing the FileId are not part of any rowset. They can contain other information, which will be disregarded by the system. The FileId identifier and the file layout names aren’t automatically stored anywhere; they exist only in the input file’s FileId file records and in the PeopleCode.
To process an input file that requires multiple file layouts:
Use SetFileLayout to specify the file layout definition to use.
If you’re specifying the initial file layout for this file, it doesn’t have to be the correct one. You can determine the correct file layout to use for the first rowset during a subsequent step.
Use SetFileId to specify the value of the FileId field, fileid, that’s used throughout the file to designate FileId file records.
Note. After each execution of SetFileLayout, the SetFileId setting is disabled. Be sure to re-specify the FileId value if you expect the file layout to change, so the system continues looking for the next FileId file record.
Use ReadRowset to read the next rowset from the file.
The current file record is also stored in the CurrentRecord property as a string. The PeopleCode process determines whether it’s the beginning of a new rowset, or a FileId file record according to the fileid you specified. If it’s a FileId file record, the process sets the IsNewFileId property to True; if not, it sets the IsNewFileId property to False.
Note. If this is the first execution of ReadRowset on the file, it returns NULL upon encountering the initial FileId file record, but still stores that file record in CurrentRecord and sets IsNewFileId accordingly.
If the rowset returned isn’t NULL, process that rowset as necessary.
If IsNewFileId is False, go back to step 3 to continue reading rowsets from the file. If IsNewFileId is True, examine CurrentRecord to determine which new file layout to use, and go back to step 1.
You can repeat this procedure one rowset at a time, proceeding through the remainder of the input file. When ReadRowset returns NULL, no more rowset data is available.
Parameters
fileid |
Specify the value of the FileId field used in the current file. |
position |
Specify the column in the FileId file record where the FileId field starts. The default is 1. |
Returns
None.
Example
&rsFile = &MYFILE.ReadRowset(); &CurrentRecord = &MYFILE.CurrentRecord; &IsNewFileID = &MYFILE.IsNewFileId; If &MYFILE.IsNewFileId Then &FILELAYOUT = FindFileID(&CurrentRecord); &MYFILE.SetFileLayout(@("FileLayout." | &FILELAYOUT)); &MYFILE.SetFileId("999", 1); End-If;
See Also
File class: CurrentRecord property, IsNewFileId property, ReadRowset method, SetFileLayout method.
Constructing File Layouts and Performing Data Interchanges
Syntax
SetFileLayout(FILELAYOUT.filelayoutname)
Description
The SetFileLayout method is a file layout method. It associates a specific file layout definition with the file object executing this method, providing easy access to rowset data. The file object must be associated with an open file. With file layout definitions, you can read and write rowsets as easily as strings. If the file object isn’t open or the definition doesn’t exist, SetFileLayout fails.
You must execute SetFileLayout before you can use any other file layout methods or properties with a file object, otherwise those methods and properties return NULL or False.
Note. All provided PeopleTools records that have a prefix of PSFLD are related to file layout definitions.
Parameters
filelayoutname |
Specify as a string the name of an existing file layout definition created in PeopleSoft Application Designer. |
Returns
A Boolean value: True if the method succeeds, False otherwise.
Example
The following example opens a data file, associates a file layout definition with it, reads and processes the first rowset from it, and closes the file.
&MYFILE.Open(&SOMENAME, "E"); If &MYFILE.SetFileLayout(FILELAYOUT.SOMELAYOUT) then &SOMEROWSET = &MYFILE.ReadRowset(); /* Process the contents of &SOMEROWSET */ Else /* Error - SetFileLayout failed */ End-If; &MYFILE.Close();
See Also
File class: CurrentRecord property, CreateRowset method, ReadRowset method, IgnoreInvalidId property, WriteRowset method.
Constructing File Layouts and Performing Data Interchanges
Syntax
SetPosition(position)
Description
The SetPosition method sets the current read or write position in the external file associated with the file object executing this method. SetPosition works only with a file, which is opened in Update mode, and is designed to be used in combination with the GetPosition method to recover from interruptions during file access.
To start reading or writing from the beginning of a file, you must use SetPosition to set a read/write position of 0, immediately after you open the file in Update mode.
Parameters
position |
The byte position in the file at which you want to continue reading or writing. This should either be 0 or a value you previously obtained with the GetPosition method and saved in a separate file or a database. |
Warning! In Update mode, any write operation clears the file of all data that follows the position you set.
Note. Use SetPosition only for recovering from file access interruptions. Supplying your own value for SetPosition isn’t recommended, except for position 0.
Returns
None.
Example
The following example reopens a file in Update mode, and sets the read position to the last saved checkpoint:
&MYFILE = GetFile(&SOMENAME, "U"); If &MYFILE.IsOpen Then /* Retrieve the value of the last saved checkpoint, &LASTPOS */ &MYFILE.SetPosition(&LASTPOS); while &MYFILE.ReadLine(&SOMESTRING) /* Process the contents of each &SOMESTRING */ End-While; &MYFILE.Close(); End-If;
Note. Currently, the effect of the Update mode and the GetPosition and SetPosition methods is not well defined for Unicode files. Use the Update mode only on files stored with a non-Unicode character set.
See Also
File class: GetPosition method, Open method.
File Access Interruption Recovery
Syntax
SetRecTerminator(Terminator)
Description
The SetRecTerminator method is a file layout method.
Use this method to specify the string of characters that indicate the end of a file record. Read operations use the value of SetRecTerminator to determine where each file record ends and the next one starts, and write operations append the value of SetRecTerminator to each record written.
This value defaults to the newline character appropriate to the platform where the file is being stored:
a linefeed on UNIX systems
a carriage return/linefeed combination on Windows systems
You need to specify a different record terminators only if you anticipate that part of the data in a file field that includes the newline character used on the storage platform; you must assign the record terminator a unique string that you know does not appear in a file field.
If you set the record terminator to Null ("") you eliminate linefeeds or carriage returns.
Parameters
Terminator |
Specify the value you want used for the record terminator. |
Returns
None.
Example
&File = GetFile(......); if &File.IsOpen then /* set the terminator to be NULL */ Local String &Term = ""; &File.SetRecTerminator(&Term);
Syntax
WriteLine(string)
Description
The WriteLine method writes one string of text, string, to the output file associated with the file object executing this method, followed by a newline character appropriate to the platform where the file is being written. To build a single line using multiple strings, use the WriteString method.
Parameters
string |
The string of text to be written. |
Returns
None.
Example
The following example adds a line of text to an existing file:
&MYFILE.Open("somefile.txt", "A"); &MYFILE.WriteLine("This is the last line in the file."); &MYFILE.Close();
The following example converts a file where the fields are separated with tabs into a file where the fields are separated with commas.
Local File &TABFILE, &CSVFILE; Local string &FILE_NAME, &DATA, &NEWDATA; &FILE_NAME = "Test.txt"; &TAB = Char(9); &TABFILE = GetFile(&FILE_NAME, "r"); &FileName = &TABFILE.Name; &POS = Find(".", &FileName); &NEWFILE_NAME = Substring(&FileName, 1, &POS) | "dat"; &CSVFILE = GetFile(&NEWFILE_NAME, "N", %FilePath_Absolute); If &TABFILE.IsOpen And &CSVFILE.IsOpen Then While &TABFILE.ReadLine(&DATA); &NEWDATA = Substitute(&DATA, &TAB, ","); &CSVFILE.WriteLine(&NEWDATA); End-While; &TABFILE.Close(); &CSVFILE.Close(); End-If;
See Also
File class: GetString method, ReadLine method, WriteString method, WriteRaw method.
Syntax
WriteRaw(RawBinary)
Description
The WriteRaw method writes the contents of RawBinary to a file. This can be used for writing images, messages, or other types of raw binary data to a file.
Parameters
RawBinary |
Specify the raw binary to be written to the file. |
Returns
None.
Example
The following example writes employee photos (GIF files) from a record to a file.
Local File &FILE; Local Record &REC; Local SQL &SQL; &REC = CreateRecord(Record.EMPL_PHOTO); &SQL = CreateSQL("%SelectAll(:1)", Record.EMPL_PHOTO); &FILE = GetFile("C:\temp\EMPL_PHOTO.GIF", "w", "a", %FilePath_Absolute); While &SQL1.Fetch(&REC) &FILE.WriteRaw(&REC.EMPLOYEE_PHOTO.Value); End-While; &FILE.Close();
See Also
File class: WriteLine method, WriteString method.
Syntax
WriteRecord(record)
Description
The WriteRecord method is a file layout method. It writes the contents of the record object record, to the output file. (Remember, a record object contains only one row of data from an SQL table.)
You can use this method to build a transaction in the output file, one file record at a time, without having to instantiate and populate a rowset object. You can apply this method to any record whose structure and name matches that of a record defined in the current file layout.
Note. You must execute the SetFileId method from the file object before using WriteRecord, otherwise it returns False.
See File class: SetFileLayout method.
Note. When you're writing text to an XML file, special HTML characters, such as ampersands, lesser than or greater than symbols, and so on, are automatically converted to valid XML character string, such as &.
Considerations Using XML With File Definition Tags
File Definition Tags have no effect when importing data. However, generally, during export, the File Definition Tag is added at the start and end of the data to create a valid XML file.
The one exception is when the file to which the data is being written during export has been opened in append mode. At that time, the file definition tag is not taken into consideration.
Considerations Using XML with File Definitions
If your file layout is defined as XML, WriteRecord doesn't add the closing tag for the record. You must write it yourself using the WriteLine method. This is because the code has no way of knowing when you want to write children records following the record just written out.
The following code shows an example of using WriteLine:
Local File &MYFILE; &MYFILE = GetFile("XMLrecord.txt", "A"); If &MYFILE.IsOpen Then If &MYFILE.SetFileLayout(FILELAYOUT.RECORDLAYOUT) Then &LN = CreateRecord(RECORD.QA_INVEST_LN); &SQL2 = CreateSQL("%Selectall(:1)", &LN); While &SQL2.Fetch(&LN) WriteRecord(&LN); WriteLine("</QA_INVEST_LN>"); /* Add the closing tag */ End-While; Else /* do error processing - filelayout not correct */ End-If; Else /* do error processing - file not open */ End-If; &MYFILE.Close();
Parameters
record |
Specify the name of an existing record object to be written. You can use Rowset class methods such as GetField and built-in functions such as GetRecord to populate the record with data before writing it to the file. |
Returns
A Boolean value: True if the method succeeds, False otherwise. This value is optional.
Example
The following example appends all the data in a record to an existing file:
Local File &MYFILE; &MYFILE = GetFile("record.txt", "A"); If &MYFILE.IsOpen Then If &MYFILE.SetFileLayout(FILELAYOUT.VOL_TEST) Then &LN = CreateRecord(RECORD.VOLNTER_ORG_TBL); &SQL2 = CreateSQL("%Selectall(:1)", &LN); While &SQL2.Fetch(&LN) &MYFILE.WriteRecord(&LN); End-While; Else /* do error processing - filelayout not correct */ End-If; Else /* do error processing -; file not open */ End-If; &MYFILE.Close();
See Also
File class: CreateRowset method, ReadRowset method, SetFileLayout method, WriteRowset method.
Syntax
WriteRowset(rowset [, Write_Data])
Description
The WriteRowset method is a file layout method. It writes the contents of a rowset object, rowset, to the output file associated with the file object executing this method. Regardless of whether the rowset contains just one or more than one transaction (level zero row), executing this method once writes the entire contents of the rowset to the output file.
Note. You must execute the SetFileLayout method from the file object before using WriteRowset, otherwise it returns False.
See File class: SetFileLayout method.
WriteRowset writes a rowset to a file only if the data in the component buffer has changed. You must specify the WriteData parameter as True if you want the WriteRowset method to force the rowset to be written to the file even if the buffer has not been changed.
Note. When you're writing text to an XML file, special HTML characters, such as ampersands, lesser than or greater than symbols, and so on, are automatically converted to valid XML character string, such as &.
Considerations Using Fixed Length Files With Numeric Fields
All numeric fields are right-justified in when writing to fixed length files. In addition, zeros are padded to the right after the decimal point if required.
Considerations Using XML With File Definition Tags
File Definition Tags have no effect when importing data. However, generally, during export, the File Definition Tag is added at the starting and end of the data to create a valid XML file.
The one exception is when the file to which the data is being written during export has been opened in append mode. At that time, the file definition tag is not taken into consideration.
Parameters
rowset |
Specify the name of an existing rowset object that was instantiated with the File class CreateRowset or ReadRowset method. You can use Rowset class methods such as Select and built-in functions such as GetLevel0 to populate the rowset with data before writing it to the file. |
WriteData |
Specify whether to write the rowset data to the file whether or not the data in the buffer has changed. This parameter takes a Boolean value: True, write the data to the buffer regardless, False, only write the data if changed. The default value for this parameter is False. |
Returns
A Boolean value: True if the method succeeds, False otherwise.
Example
Local File &MYFILE; Local Rowset &FILEROWSET; &MYFILE = GetFile("c:\temp\EMP_CKLS.txt", "A", %FilePath_Absolute); If &MYFILE.IsOpen Then If &MYFILE.SetFileLayout(FILELAYOUT.EMPL_CHECKLIST) Then &FILEROWSET = &MYFILE.CreateRowset(); &FILEROWSET = GetLevel0(); &MYFILE.WriteRowset(&FILEROWSET, True); Else /* file layout not found, do error processing */ End-If; Else /* file not opened, do error processing */ End-if; &MYFILE.Close();
See Also
File class: CreateRowset method, ReadRowset method, SetFileLayout method, WriteRecord method.
Syntax
WriteString(string)
Description
The WriteString method writes one string of text to the output file associated with the file object executing this method, without any newline character. Each string written extends the current line in the file.
You can start a new line by using the WriteLine method to write the last part of the current line. WriteLine always adds a newline character appropriate to the platform where the file is being written, whether you supply a character string of any length, or a null string.
Parameters
string |
A string variable containing the text to be written. |
Returns
None.
Example
The following example opens an empty file, writes two lines of text to it without a final newline, and closes it:
&MYFILE.Open("somefile.txt", "W"); &MYFILE.WriteString("This is the first "); &MYFILE.WriteString("line in the file."); &MYFILE.WriteLine(""); &MYFILE.WriteString("This second line is not terminated."); &MYFILE.Close();
See Also
File class: ReadLine method, WriteLine method, WriteRaw method.
In this section, we discuss each File Class property.
Description
This property is a file layout property. This property returns the current record as a string. The CurrentRecord property is used in combination with the SetFileId and ReadRowset methods and IsNewFileId property when reading files that contain data based on multiple file layouts.
If the ReadRowset method returns NULL, either the current record is a FileId record or the end of file has been reached. The IsNewFileId enables you to determine which. If it is a FileId, you can parse the string returned by CurrentRecord to determine the file layout definition to be used.
Note. SetFileId, CurrentRecord, and IsNewFileId don’t apply to CSV and XML format input files. You can implement multiple file layouts only with FIXED format files.
This property is read-only.
Example
&RECSTRING = &MYFILE.CurrentRecord;
See Also
File class: SetFileId method, ReadRowset method, IsNewFileId property.
Description
This property is a file layout property that’s used in combination with the ReadRowset method. It returns a Boolean value that specifies whether file records with invalid FileIds are ignored. Each time ReadRowset is executed, it may encounter a file record that doesn't qualify as part of the rowset because its File ID isn’t part of the current file layout, or because it occurs in an invalid position in the rowset. If IgnoreInvalidId is False, the PeopleCode program terminates; if IgnoreInvalidId is True, ReadRowset ignores the invalid file record. The default value is True.
This property is read-write.
Example
&MYFILE.IgnoreInvalidId = False;
See Also
File class: ReadRowset method.
Description
This property is a file layout property. It returns a Boolean value indicating whether a field error condition was generated by the last file layout method executed. If an error condition was generated, IsError returns True; if not, IsError returns False. The default value is False.
This property is read-only.
Example
The following example shows where IsError would be used:
&MYFILE.Open(&SOMENAME, "R"); &MYFILE.SetFileLayout(FILELAYOUT.SOMELAYOUT); &MYROWSET = &MYFILE.ReadRowset(); If &MYFILE.IsError Then /* Examine the EditError property of each field in the rowset to find the one with the error, and respond accordingly */ End-If; &MYFILE.Close();
See Also
Description
This property is a file layout property. It returns a Boolean value indicating whether a FileId file record has been encountered. When the ReadRowset method reads a transaction from an input file, it examines the current file record following the transaction. If that file record is a FileId file record, IsNewFileId returns True; if not, IsNewFileId returns False.
IsNewFileId is used in combination with the SetFileId method and CurrentRecord property when reading files that require multiple file layouts.
Note. SetFileId, CurrentRecord, and IsNewFileId don’t apply to CSV and XML format input files. You can use only FIXED format files to implement multiple file layouts.
This property is read-only.
Example
&MYFILE.SetFileLayout(FILELAYOUT.SOMELAYOUT) then /* Set the first layout */ &MYFILE.SetFileId("999", 1); /* Set the FileId */ &SOMEROWSET = &MYFILE.ReadRowset(); /* Read the first rowset */ While &SOMEROWSET <> NULL If &MYFILE.IsNewFileId Then /* Examine &MYFILE.CurrentRecord for the next layout */ /* Set the next layout */ &MYFILE.SetFileId("999", 1); /* Set the FileId */ End-If; /* Process the current &SOMEROWSET */ &SOMEROWSET = &MYFILE.ReadRowset(); /* Read the next rowset */ End-While;
See Also
File class: ReadRowset method, SetFileId method, CurrentRecord property.
Description
This property returns a Boolean value indicating whether the file is open. If the file object is open, IsOpen returns True; if not, IsOpen returns False.
This property is read-only.
Example
The following example opens a file, writes a line to it, and closes it:
&MYFILE.Open("item.txt", "W"); If &MYFILE.IsOpen Then &MYFILE.WriteLine("Some text."); &MYFILE.Close(); End-If;
Description
This property returns as a string the name of the external file. If no file is currently associated with the file object, Name returns a NULL string.
This property is read-only.
Example
&TMP = &MYFILE.Name;
If your data is hierarchical in nature, or based on existing PeopleSoft records or pages, you want to use a File Layout definition for reading and writing your data, rather than doing it line by line (or field by field.)
For example, suppose you wanted to write all the information from a record to a file. You can use the WriteRecord method to write all the data from the record, instead of having to loop through every field, find the value, and write it to the file.
In addition, you could write all the information from a transaction (or several transactions) from a page to a file. Each transaction can be considered a rowset. A rowset can contain more than one record and is generally composed in a hierarchical structure. You could create a File Layout definition that has the same structure as the page (or component), and use the WriteRowset method. If you have a file that contains data in the correct format, you can use the ReadRowset method to read the data from the file to the page.
Each file layout is associated with a format. This format specifies the type of data in the files. You specify the format as part of the File Layout Properties. You can only specify one format for a file layout. Available formats are:
FIXED (default)
CSV
XML
The file layout methods and properties use this information to handle each file type in a transparent manner. Generally, you don’t need to do anything different based on file type. Any exceptions are noted in the documentation.
Note. Unlike other PeopleTools definitions, records and field are copied to a File Layout definition. There are no pointers. This means if you change a record definition (add or remove a field) you must change the File Layout definition also. The changes are not automatically propagated. This is why the documentation refers to these elements as file records, file fields, and so on, to show that they are no longer part of the original definition they were created from.
See Using Standalone Rowsets for more examples of writing from and reading to files using File Layout and standalone rowsets.
See Also
Constructing File Layouts and Performing Data Interchanges
In the following example, the File Layout definition is based on the record ABSENCE_HISTORY, and looks like this:
Example File Layout definition (ABS_HIST)
You should note the following about the using the WriteRecord method:
Not all the fields in the File Layout definition and the record have to match. The WriteRecord method, like all File Layout methods, applies only to the like-named fields. If there are additional fields in the record or in the File Layout definition, they are ignored.
The WriteRecord method writes only to like-named records. If you rename a record after you use it to create a File Layout definition, you must rename it to the exact same name in your File Layout. Because WriteRecord writes like-named records, the same file layout definition can contain more than one record.
The WriteRecord method takes a record object as its parameter. A populated record object references a single row of data in the SQL table. This is why a SQL Fetch statement is used in a condition around the WriteRecord method. This fetches every row of data from the SQL table, then writes it to the file.
The following code writes the ABSENCE_HIST record to the file record.txt.
Local Record &RecLine; Local File &MYFILE; Local SQL &SQL2; &MYFILE = GetFile("record.txt", "A"); If &MYFILE.IsOpen Then If &MYFILE.SetFileLayout(FileLayout.ABS_HIST) Then &RecLine = CreateRecord(RECORD.ABSENCE_HIST); &SQL2 = CreateSQL("%Selectall(:1)", &RecLine); While &SQL2.Fetch(&RecLine) &MYFILE.WriteRecord(&RecLine); End-While; Else /* do error processing -; filelayout not correct */ End-If; Else /* do error processing -; file not open */ End-If; &MYFILE.Close();
If you wanted to write only changed records to the file, you could add the following code that is set in bold font:
While &SQL2.Fetch(&RecLine) If &RecLine.IsChanged Then &MYFILE.WriteRecord(&RecLine); End-If; End-While;
The following is the first part of a sample data file created by the previous code. The field format is FIXED:
8001 VAC 09/12/1981 09/26/1981 14 0 P Y 8001 VAC 03/02/1983 03/07/1983 5 0 P Y 8001 VAC 08/26/1983 09/10/1983 13 0 P Y 8105 CNF 02/02/1995 ??/??/ 0 0 U N 8516 MAT 06/06/1986 08/01/1986 56 0 P Y 8516 SCK 08/06/1988 08/07/1988 1 0 P Y 8516 VAC 07/14/1987 07/28/1987 14 0 P Y 8553 JUR 12/12/1990 12/17/1990 5 0 Local Jury Duty P N 8553 MAT 02/20/1992 10/01/1992 224 0 Maternity Leave U N 8553 MAT 08/19/1994 03/01/1995 194 0 Maternity-2nd child U Y 8553 PER 04/15/1993 04/19/1993 4 0 U N Personal Day required 8553 SCK 01/28/1987 01/30/1987 2 0 Hong Kong Flu P N 8553 SCK 08/02/1988 08/03/1988 1 0 Sick P N 8553 SCK 09/12/1995 09/13/1995 1 0 P N 8641 VAC 06/01/1988 06/15/1988 14 0 P Y 8641 VAC 07/01/1989 07/15/1989 14 0 P Y G001 MAT 07/02/1991 09/28/1991 88 0 3-month Maternity leave P Y Maternity will be paid as 80% of Claudia's current salary.
If a record in the File Layout definition has a File Record ID, each line in the file referencing this record is prefaced with this number. The File Record ID is not a field in the data itself. It is also referred to as the rowid. File Record IDs can be useful when the file you’re producing refers to more than one record.
File Record IDs can be used only with File Layout definitions that have a type of FIXED. If a File Layout definition has only one level then File Record IDs can be omitted. But for File Layout definitions with more than one level, you must use File Record IDs.
The following is sample file, produced with the same code, but with a File Record ID of 101 added:
101 8001 VAC 09/12/1981 09/26/1981 14 0 P Y 101 8001 VAC 03/02/1983 03/07/1983 5 0 P Y 101 8001 VAC 08/26/1983 09/10/1983 13 0 P Y 101 8105 CNF 02/02/1995 ??/??/ 0 0 U N 101 8516 MAT 06/06/1986 08/01/1986 56 0 P Y 101 8516 SCK 08/06/1988 08/07/1988 1 0 P Y 101 8516 VAC 07/14/1987 07/28/1987 14 0 P Y 101 8553 JUR 12/12/1990 12/17/1990 5 0 Local Jury Duty P N 101 8553 MAT 02/20/1992 10/01/1992 224 0 Maternity Leave U N 101 8553 MAT 08/19/1994 03/01/1995 194 0 Maternity-2nd child U Y 101 8553 PER 04/15/1993 04/19/1993 4 0 U N Personal Day required 101 8553 SCK 01/28/1987 01/30/1987 2 0 Hong Kong Flu P N 101 8553 SCK 08/02/1988 08/03/1988 1 0 Sick P N 101 8553 SCK 09/12/1995 09/13/1995 1 0 P N 101 8641 VAC 06/01/1988 06/15/1988 14 0 P Y 101 8641 VAC 07/01/1989 07/15/1989 14 0 P Y 101 G001 MAT 07/02/1991 09/28/1991 88 0 3-month Maternity leave P Y Maternity will be paid as 80% of Claudia's current salary.
Note. File positions start at 1, not 0. When you specify a File Record ID, make sure that the starting position of the Record ID is greater than 0.
This following example uses the same File Layout definition as the previous example. The file format is CSV. The fields are separated by commas and delimited by double-quotes.
"8001","VAC","09/12/1981","09/26/1981","14","0","","P","Y","" "8001","VAC","03/02/1983","03/07/1983","5","0","","P","Y","" "8001","VAC","08/26/1983","09/10/1983","13","0","","P","Y","" "8105","CNF","02/02/1995","??/??/","0","0","","U","N","" "8516","MAT","06/06/1986","08/01/1986","56","0","","P","Y","" "8516","SCK","08/06/1988","08/07/1988","1","0","","P","Y","" "8516","VAC","07/14/1987","07/28/1987","14","0","","P","Y","" "8553","JUR","12/12/1990","12/17/1990","5","0","Local Jury Duty","P","N","" "8553","MAT","02/20/1992","10/01/1992","224","0","Maternity Leave","U","N","" "8553","MAT","08/19/1994","03/01/1995","194","0","Maternity-2nd child","U","Y","" "8553","PER","04/15/1993","04/19/1993","4","0","","U","N","Personal Day required" "8553","SCK","01/28/1987","01/30/1987","2","0","Hong Kong Flu","P","N","" "8553","SCK","08/02/1988","08/03/1988","1","0","Sick","P","N","" "8553","SCK","09/12/1995","09/13/1995","1","0","","P","N","" "8641","VAC","06/01/1988","06/15/1988","14","0","","P","Y","" "8641","VAC","07/01/1989","07/15/1989","14","0","","P","Y","" "G001","MAT","07/02/1991","09/28/1991","88","0","3-month Maternity leave","P","Y","Maternity will be paid as 80% of Claudia's current salary."
To read in the previous CSV file we use the following PeopleCode. It reads the file into a temporary record. First each line of the file is read into a string. The string is split into an array, with the value of each field in the array becoming an element in the array. The value of each field in the record is assigned a value from the array. After additional processing (for example, converting strings into dates or numbers, verifying data, and so on) the record can be inserted into the database. To insert the final data into the database, this code must be associated with a PeopleCode event that allows database updates, that is, SavePreChange, WorkFlow, SavePostChange, and so on. This code could also be used as part of an Application Engine program.
Local File &MYFILE; Local Record &REC; Local array of string &ARRAY; &MYFILE = GetFile("c:\temp\vendor.txt", "R", %FilePath_Absolute); &REC = CreateRecord(RECORD.ABS_HIST_TEST); &ARRAY = CreateArrayRept("", 0); If &MYFILE.IsOpen Then If &MYFILE.SetFileLayout(FILELAYOUT.ABS_HIST) Then While &MYFILE.ReadLine(&STRING); &ARRAY = Split(&STRING, ","); For &I = 1 To &REC.FieldCount &REC.GetField(&I).Value = &ARRAY[&I]; End-For; /* do additional processing here for converting values */ &REC.Insert(); End-While; Else /* do error processing - filelayout not correct */ End-If; Else /* do error processing - file not open */ End-If; &MYFILE.Close();
Note. You can't read a file that contains a thousands separator for numeric fields. You must strip out the separator before you try to read in the file.
In the following example, the File Layout definition is based on the component EMPL_CHECKLIST, and looks like this:
Example File Layout definition (EMPL_CHECKLIST)
Here’s the structure of the component EMPLOYEE_CHECKLIST:
EMPLOYEE_CHECKLIST Component structure
Note that:
Every field in the two structures don’t have to match (that is, every field or record that’s in the file layout doesn’t have to be in the component, and vice versa.)
The two structures must be the same. That is, if the component has PERSONAL_DATA at level zero, and EMPL_CHECKLIST at level one, the file layout must have the same hierarchy.
The following example uses the previous File Layout definition to copy data from the EMPL_CHECKLIST page into a file.
The CreateRowset function creates an empty rowset that has the structure of the file layout definition. The GetRowset function is used to get all the data from the component and copy it into the rowset. The GetLevel0 function copies all like-named fields to like-named records. The WriteRowset method writes all the component data to the file. Because this code runs on the server, an absolute file path is used.
See GetRowset.
Example
The following is the PeopleCode for this example.
Local File &MYFILE; Local Rowset &FILEROWSET; &MYFILE = GetFile("c:\temp\EMP_CKLS.txt", "A", %FilePath_Absolute); If &MYFILE.IsOpen Then If &MYFILE.SetFileLayout(FILELAYOUT.EMPL_CHECKLIST) Then &FILEROWSET = &MYFILE.CreateRowset(); &FILEROWSET = GetLevel0(); &MYFILE.WriteRowset(&FILEROWSET, True); Else /* file layout not found, do error processing */ End-If; Else /* file not opened, do error processing */ End-if; &MYFILE.Close();
The following is a sample data file created by the previous code:
8113 Frumman,Wolfgang 08/06/1999 000001 8219 Going to London office 100 000015 I 08/06/1999 200 000030 I 08/06/1999 300 000009 I 08/06/1999 400 000001 I 08/06/1999 500 000011 I 08/06/1999 600 000002 I 08/06/1999 700 000021 I 08/06/1999 800 000024 I 08/06/1999 900 000004 I 08/06/1999 1000 000006 I 08/06/1999 09/06/1999 000004 7707 What to do after he arrives 100 000022 I 08/06/1999 200 000008 I 08/06/1999 300 000018 I 08/06/1999 400 000019 I 08/06/1999 8101 Penrose,Steven 07/06/1999 000006 8229 New hire 1 000033 I 08/06/1999 2 000034 I 08/06/1999 3 000035 I 08/06/1999 4 000036 I 08/06/1999 5 000037 I 08/06/1999 6 000038 I 08/06/1999 7 000039 I 08/06/1999 8 000040 I 08/06/1999 9 000041 I 08/06/1999 10 000042 I 08/06/1999
When you create the File Layout definition, you can choose for each field whether to inherit a value from a higher level record field. If a value is inherited, it is written only once to the file, the first time it's encountered.
In the previous data example, there are three records: PERSONAL_DATA, EMPL_CHECKLIST, and EMPL_CHKLST_ITM. The field EMPLID is on all three records, but is written to the file only the first time a new value is encountered. So, the value for EMPLID is inherited by EMPL_CHECKLIST, and the value for EMPL_CHKLST_ITM is inherited from PERSONAL_DATA. The field CHECKLIST_DT is on EMPL_CHECKLIST and EMPL_CHKLST_ITM. However, the field value appears only once, in the parent record, and not in the child record.
If a record in the File Layout definition has a File Record ID, each line in the file referencing this record will be prefaced with this number. The File Record ID is not a field in the data itself. It is also referred to as the rowid. File Record IDs can be useful when the file being created refers to more than one record. File Record IDs can be used only with File Layout definitions that have a type of FIXED.
The following is sample file, produced with the same code, but with a File Record IDs added to all the records. 001 was added to the first level, 002 to the second, and 003 to the third.
001 8113 Frumman,Wolfgang 002 08/06/1999 000001 8219 Going to London office 003 100 000015 I 10/13/1999 003 200 000030 I 10/13/1999 003 300 000009 I 10/13/1999 003 400 000001 I 10/13/1999 003 500 000011 I 10/13/1999 003 600 000002 I 10/13/1999 003 700 000021 I 10/13/1999 003 800 000024 I 10/13/1999 003 900 000004 I 10/13/1999 003 1000 000006 I 10/13/1999 002 09/06/1999 000004 7707 What to do after he arrives 003 100 000022 I 10/13/1999 003 200 000008 I 10/13/1999 003 300 000018 I 10/13/1999 003 400 000019 I 10/13/1999 001 8101 Penrose,Steven 002 10/13/1999 000006 8229 New hire 003 1 000033 I 10/13/1999 003 2 000034 I 10/13/1999 003 3 000035 I 10/13/1999 003 4 000036 I 10/13/1999 003 5 000037 I 10/13/1999 003 6 000038 I 10/13/1999 003 7 000039 I 10/13/1999 003 8 000040 I 10/13/1999 003 9 000041 I 10/13/1999 003 10 000042 I 10/13/1999
The following program reads all the rowsets from a file and updates a work scroll with that data. The work scroll isn’t hidden on the page: it’s created in the Component buffer from existing records using CreateRowset. The structure of the work scroll and the file layout are identical: that is, they’re composed of two records, and the names of the records in the file layout are exactly the same as the names of the record definitions.
Local File &CHARTINPUT_F; Local Rowset &INPUT_ROWSET, &TEMP_RS, &WORK_DATA; Local Record &WRK_DATA; &filename = "c:\temp\test.txt"; If FileExists(&filename, %FilePath_Absolute) Then &CHARTINPUT_F = GetFile(&filename, "R", "A", %FilePath_Absolute); Else Exit; End-If; &CHARTINPUT_F.SetFileLayout(FileLayout.CHART_INFO); /* Create rowset to be read into NOTE that you have to start at LOWEST level of rowset */ &TEMP_RS = CreateRowset(RECORD.CHART_ITEM); &WORK_DATA = CreateRowset(RECORD.CHART_DATA, &TEMP_RS); &INPUT_ROWSET = CreateRowset(RECORD.CHART, &WORK_DATA); While &INPUT_ROWSET <> Null &INPUT_ROWSET = &CHARTINPUT_F.ReadRowset(); &INPUT_ROWSET.CopyTo(&WORK_DATA); /* do processing -- Though file may contain more than one level zero Component processor only allows one level zero at a time */ End-While;
The following are considerations for when you use rowsets with files.
Although you can create a File Layout definition with more than four levels of hierarchy, a rowset created from Component buffer data can contain only four levels (level zero through 3). Any additional levels of data are ignored.
ReadRowset populates the rowset with one transaction from the file. (A transaction is considered to be one instance of level zero data contained in a file record, plus all of its subordinate data.) WriteRowset writes one transaction to a file.
You can also use PeopleCode in an Application Engine program to either write to or read from files. This example isn't a proper Application Engine program: it contains the PeopleCode only for opening and reading from a file. However, it's included here as starting point for your own Application Engine programs.
Here is the Application Engine program:
Application Engine example program
Here is the PeopleCode in the step 1.
Local File &FILE; Local Record &REC; Local Rowset &FRS; &FILE = GetFile("TEST.txt", "R"); &REC = CreateRecord(Record.QEPC_FILE_REC); &SQL = CreateSQL("%Insert(:1)"); If Not &FILE.IsOpen Then Error ("TEST: failed file open"); Else If Not &FILE.SetFileLayout(FileLayout.QEPC_FILE_REC) Then Error ("TEST: failed SetFilelayout"); Else &FRS = &FILE.ReadRowset(); While &FRS <> Null &FRS.GetRow(1).QEPC_FILE_REC.CopyFieldsTo(&REC); &SQL.execute(&REC); &FRS = &FILE.ReadRowset(); End-While; End-If; &FILE.Close(); End-If;
The example Application Engine program reads the following CSV file:
"TEST2","1ST","01/01/1901",10 "TEST2","2ND","01/01/1902",20 "TEST2","3RD","01/01/1903",30 "TEST2","4TH","01/01/1904",40
Note that the last field has no qualifier.
The File Layout used to read this record has the following form:
QEPC_FILE_REC File Layout
The properties for the QEPC_FILE_REC File Layout are as follows:
File Layout Definition Properties
Note that the Definition Qualifier is double-quotes ("), while the separator is a comma.
Remember, the last field didn't have a qualifier. To account for that, the field properties for this field must be edited, and a blank must be put in the Field Qualifier property.
File layout Field Properties
See Understanding PeopleSoft Application Engine.
In the previous examples, the input file contained rowsets based on a single File Layout definition. However, PeopleTools provides the functionality to process input files containing rowsets that require several different File Layouts.
Note. You can use only FIXED format files to implement multiple file layouts.
See the SetFileId method for details about handling multiple file layouts.
In this section, we discuss how to:
Read multiple file layouts.
Write multiple file layouts.
See File class: SetFileId method.
If your input file contains data based on more than one File Layout, it must contain an indicator, called a FileId that specifies:
When a different File Layout definition should be used.
Which File Layout definition should be used.
The FileId must be specified on a separate line and must precede every rowset that requires a layout different from the previous rowset. It isn’t considered part of the rowset.
In the following example, the file contains two FileId lines; they use a file record ID that distinguishes them from the rowset data—in this case, "999".
999 PRODUCT /* The following rowset uses the PRODUCT layout */ 001 /* Level 0 record data */ 101 /* level 1 record data */ 201 /* Level 2 record data */ 201 /* Level 2 record data */ 999 ORDER /* The following two rowsets use the ORDER layout */ 001 /* Level 0 record data */ 111 /* Level 1 record data */ 111 /* Level 1 record data */ 001 /* Level 0 record data */ 111 /* Level 1 record data */ 111 /* Level 1 record data */
The FileId can contain any information you want that indicates which file layout to use; the "PRODUCT" and "ORDER" fields shown are just examples.
To read this file, you should do the following in your program:
Use the SetFileId method to specify the file record ID value.
Use the ReadRowset method to read the data.
Check if the rowset is NULL.
NULL indicates you’ve reached either the end of the file or a new rowset.
Use the IsNewFileId property to check if the next line is a FileId file record (line).
If IsNewFileld is False, you’ve reached the end of the file.
If IsNewFileld is True, use the CurrentRecord property to determine which File Layout to use next.
The following example reads rowsets from a file. When it finds a new rowset (indicated by &IsNewFileld returning True) the value of &CurrentRecord is passed to a function that reads and evaluates the line, then returns the name of the new file layout. (The code for the function FindFileId is included at the start of the example.)
Local File &MYFILE; Local Rowset &rsFile; Local Record &rSomeRec1, &rSomeRec2; Local SQL &SQL1; Function FindFileID(&CurrentRecord As string) Returns string ; Evaluate RTrim(Substring(&CurrentRecord, 5, 50)) When "SOME_REC1" &FILELAYOUT = "SOME_REC1"; When "SOME_REC2" &FILELAYOUT = "SOME_REC2"; End-Evaluate; Return &FILELAYOUT; End-Function; &rSomeRec1 = CreateRecord(Record.SOME_REC1); &rSomeRec2 = CreateRecord(Record.SOME_REC2); &SQL1 = CreateSQL("%Insert(:1)"); &MYFILE = GetFile("c:\temp\MULTI_FILE.out", "R", %FilePath_Absolute); rem Set temporary first file layout; &MYFILE.SetFileLayout(FileLayout.SOME_REC1); &MYFILE.SetFileId("999", 1); rem Read rowset to find actual first file ID; &rsFile = &MYFILE.ReadRowset(); &CurrentRecord = &MYFILE.CurrentRecord; &IsNewFileID = &MYFILE.IsNewFileId; If &MYFILE.IsNewFileId Then &FILELAYOUT = FindFileID(&CurrentRecord); &MYFILE.SetFileLayout(@("FileLayout." | &FILELAYOUT)); &MYFILE.SetFileId("999", 1); End-If; rem Read first 'real' rowset; &rsFile = &MYFILE.ReadRowset(); &CurrentRecord = &MYFILE.CurrentRecord; &IsNewFileID = &MYFILE.IsNewFileId; While &rsFile <> Null Or &IsNewFileID If &MYFILE.IsNewFileId Then &FILELAYOUT = FindFileID(&CurrentRecord); &MYFILE.SetFileLayout(@("FileLayout." | &FILELAYOUT)); &MYFILE.SetFileId("999", 1); If &IsNewFileID Then &rsFile = &MYFILE.ReadRowset(); &CurrentRecord = &MYFILE.CurrentRecord; &IsNewFileID = &MYFILE.IsNewFileId; End-If; End-If; Evaluate &FILELAYOUT When "SOME_REC1" &rsFile(1).SOME_REC1.CopyFieldsTo(&rSomeRec1); &rSomeRec1.ExecuteEdits(%Edit_Required); If Not &rSomeRec1.IsEditError Then &SQL1.Execute(&rSomeRec1); End-If; Break; When "SOME_REC2" &rsFile(1).SOME_REC2.CopyFieldsTo(&rSomeRec2); &rSomeRec2.ExecuteEdits(%Edit_Required); If Not &rSomeRec2.IsEditError Then &SQL1.Execute(&rSomeRec2); End-If; End-Evaluate; &rsFile = &MYFILE.ReadRowset(); &CurrentRecord = &MYFILE.CurrentRecord; &IsNewFileID = &MYFILE.IsNewFileId; End-While; &MYFILE.Close();
See File class: SetFileId method, ReadRowset method, IsNewFileId property.
If you’re writing files that contain data based on more than one File Layout definition, consider the following points:
If the file is going to a third-party vendor, you should work with the third-party to determine what their requirements are for specifying the different data formats.
If the file is going to be used by another PeopleSoft system, you must add the FileId between each rowset that requires a different layout. FileId file records are not part of any rowset. They should be designed so they won’t be mistaken for part of a rowset. You can create and write them to the file in many ways. The following are suggestions:
Build each line as a string, using any of the built-in string manipulation functions, then write them to the file using the File class WriteLine or WriteString methods.
Design a file layout consisting of a single file record definition for the FileId file records, then build the records using Record Class methods and functions, and write them to the file using the WriteRecord method.
The following code example writes each record from the level one scroll on a page to the file using a different File Layout. Between each WriteRowset the File ID file record is written to the file, describing the new File Layout being used.
Local File &MYFILE; Local Rowset &FILEROWSET; Local Record &REC1, &REC2; Local SQL &SQL; &MYFILE = GetFile("c:\temp\Records.txt", "W", %FilePath_Absolute); If &MYFILE.IsOpen Then If &MYFILE.SetFileLayout(FileLayout.TREE_LEVEL) Then &REC1 = CreateRecord(Record.PSTREELEVEL); &FILEROWSET = &MYFILE.CreateRowset(); &SQL = CreateSQL("%Selectall(:1)", &REC1); /* write first File ID to file */ &MYFILE.WriteLine("999 FILE LAYOUT 1"); While &SQL.Fetch(&REC1) &REC1.CopyFieldsTo(&FILEROWSET.GetRow(1).PSTREELEVEL); &MYFILE.WriteRowset(&FILEROWSET, True); End-While; Else /* file layout not found, do error processing */ End-If; If &MYFILE.SetFileLayout(FileLayout.TREE_USERLEVEL) Then &REC2 = CreateRecord(Record.TREE_LEVEL_TBL); &FILEROWSET = &MYFILE.CreateRowset(); &SQL = CreateSQL("%Selectall(:1)", &REC2); /* write second File ID to file */ &MYFILE.WriteLine("999 FILE LAYOUT 2"); While &SQL.Fetch(&REC2) &REC2.CopyFieldsTo(&FILEROWSET.GetRow(1).TREE_LEVEL_TBL); &MYFILE.WriteRowset(&FILEROWSET); End-While; Else /* file layout not found, do error processing */ End-If; Else /* file not opened, do error processing */ End-If; &MYFILE.Close();
See File class: WriteLine method, WriteString method, WriteRecord method.
See Record Class.