Opening Text File in DataStage BASIC
Posted: Wed Sep 14, 2005 4:07 pm
I had posted this earlier, but in the ADN downloads area as a DSX file. A few people report that they don't have ADN access and would like it here. It shows the full drama that you should go through when opening a text file. The code is good with any version of DataStage from 1.0 through 8.7.
Documentation (from the General tab)
Arguments:
Pathname pathname of the file to be opened using OpenSeq
OpenMode "R" = open for reading (file must exist), "W" = open for writing
WriteMode "O" = overwrite existing file, "A" = append to existing file. Ignored if OpenMode = "R".
LogEvents "Y" = generate warnings into caller's job log (default), "N" = do not log warnings
Returns:
file handle file opened successfully
anything else file not opened successfully
If the file is not opened successfully, system variable @User.Return.Code contains text of log event, whether or not that event was logged.
The return value may be the operating system error code, the DataStage user number of a process that already has the file open, or a DataStage error code.
Testing
======
This routine can not be tested in the conventional manner in the Test Grid, because it is not legal to display a file variable (the error message is "improper data type".
To test the routine in the grid, toggle the TESTING token near the top of the code from $UNDEFINE TESTING to $DEFINE TESTING then recompile and test.
Once your testing is complete, toggle the TESTING token back from $DEFINE TESTING to $UNDEFINE TESTING and recompile.
Example
=======
Code: Select all
FUNCTION OpenSequentialFile(PathName, OpenMode, WriteMode, LogEvents)
$COPYRIGHT "Copyright (c) 2002, Ray Wurlod. All rights reserved."
$* This code may be used freely with the above copyright notice intact."
$UNDEFINE TESTING
RoutineName = "OpenSequentialFile"
* Initialize variables
Ans = @NULL
ErrMsg = ""
* Check that no arguments are unassigned or null. If they are, return without attempting to open file.
If Unassigned(Pathname)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with Pathname argument unassigned."
End
If Unassigned(OpenMode)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with OpenMode argument unassigned."
End
If Unassigned(WriteMode)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with WriteMode argument unassigned."
End
If Unassigned(LogEvents)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with LogEvents argument unassigned."
End
If IsNull(Pathname)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with null Pathname argument."
End
If IsNull(OpenMode)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with null OpenMode argument."
End
If IsNull(WriteMode)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with null WriteMode argument."
End
If IsNull(LogEvents)
Then
ErrMsg<-1> = "Function " : RoutineName : " invoked with null LogEvents argument."
End
* If the ErrMsg variable is still empty, there is no problem thus far.
If Len(ErrMsg) > 0
Then
* There is one line in the log event for each error encountered.
Call DSLogWarn(ErrMsg, RoutineName)
@User.Return.Code = ErrMsg
End
Else
Ans = 0
* Default values replace illegal values silently
If Index("RW", OpenMode, 1) = 0 Then OpenMode = "W"
If Index("AO", WriteMode, 1) = 0 Then WriteMode = "O"
If Index("YN", LogEvents, 1) = 0 Then LogEvents = "Y"
* Attempt to open the file for sequential access. Handle all possible errors.
OpenSeq Pathname To Ans
On Error
ErrMsg = "Error opening " : Quote(Pathname) : ". ErrorCode = " : Status() : "."
End
Locked
ErrMsg = "File " : Quote(Pathname) : " in use by user number " : Status() : "."
End
Then
If OpenMode = "W"
Then
@User.Return.Code = 0
If WriteMode = "O"
Then
WeofSeq Ans ; * truncate file (so overwriting can occur)
End
Else
Seek Ans,0,2
Else
ErrMsg = "Unable to position to end of " : Quote(Pathname) : "."
End ; * Seek
End ; * if WriteMode = "O"
End ; * if OpenMode = "W"
End
Else
If Status() = 0
Then
If OpenMode = "W"
Then
@User.Return.Code = 0
NULL ; * file opened OK for writing, does not yet exist
End
Else
@User.Return.Code = 2 ; * "file does not exist"
ErrMsg = Quote(Pathname) : " can not be opened for reading because it does not exist."
End ; * if OpenMode = "W"
End
Else
@User.Return.Code = Status()
ErrMsg = Quote(Pathname) : " does not appear to be a file that can be opened."
End
End ; * end of OpenSeq statement
If Len(ErrMsg) > 0
Then
@User.Return.Code = ErrMsg
If LogEvents = "Y"
Then
Call DSLogWarn(ErrMsg, RoutineName)
End
End
End
$IFDEF TESTING
If FileInfo(Ans,0)
Then
CloseSeq Ans
Ans = (If Len(ErrMsg) Then "Bad Test" Else "File variable " : Quote(Pathname))
End
$ENDIF
RETURN(Ans)Documentation (from the General tab)
Arguments:
Pathname pathname of the file to be opened using OpenSeq
OpenMode "R" = open for reading (file must exist), "W" = open for writing
WriteMode "O" = overwrite existing file, "A" = append to existing file. Ignored if OpenMode = "R".
LogEvents "Y" = generate warnings into caller's job log (default), "N" = do not log warnings
Returns:
file handle file opened successfully
anything else file not opened successfully
If the file is not opened successfully, system variable @User.Return.Code contains text of log event, whether or not that event was logged.
The return value may be the operating system error code, the DataStage user number of a process that already has the file open, or a DataStage error code.
Testing
======
This routine can not be tested in the conventional manner in the Test Grid, because it is not legal to display a file variable (the error message is "improper data type".
To test the routine in the grid, toggle the TESTING token near the top of the code from $UNDEFINE TESTING to $DEFINE TESTING then recompile and test.
Once your testing is complete, toggle the TESTING token back from $DEFINE TESTING to $UNDEFINE TESTING and recompile.
Example
=======
Code: Select all
DEFFUN OpenSequentialFile(filename, openmode, writemode, logevents) CALLING "DSU.OpenSequentialFile"
MyFile = "/usr/mydir/sample.txt"
* Open file for reading
FileVariable = OpenSequentialFile(MyFile, "R", "A", "Y")
If FileInfo(FileVariable, 0)
Then
* file opened for reading
End
Else
* file not opened, routine logged warning
Reason = @User.Return.Code
End