If you're putting data on the Web, you likely need to compress it first.
As businesses provide more data to the Internet, one common administrative task required for preparing the data is to compress the data into either a zip or a tar file.
The IBM i UNIX environment called QShell provides many capabilities, including the jar and tar commands used to compress data. To enter QShell, go to the command line and type STRQSH to bring up a command line in the UNIX environment. Here, you can try out your commands interactively to check the syntax and behavior of the commands that you are executing. I primarily use QShell for operations that I want to perform in the IFS.
In this TechTip, I will compress a text file named test.xml that I have stored in a public folder off of the root directory of the IFS.
Creating the TAR File
To compress the test.xml file into test_xml.tar, I have chosen to use the standard UNIX archiving command TAR:
tar cf /Public/test_xml.tar /Public/test.xml
•· tar is the UNIX command.
•· c indicates to create a new file.
•· f indicates that the archive will be a file.
•· /Public/test_xml.tar is the destination file name of the archive output (TOFILE in IBM lingo).
•· /Public/test.xml is the source file name of the input file (FROMFILE in IBM lingo).
Creating the ZIP File
To compress the test.xml file into test_xml.zip, I have chosen to use the Java Archiving command JAR:
jar cfM /Public/test_xml.zip /Public/test.xml
•· jar is the UNIX command.
•· c indicates to create a new file.
•· f indicates that the archive will be a file.
•· M indicates that the manifest file should not be created. The JAR command's default behavior will accommodate the jar archive format that would create a manifest file to determine the main class of the Java archive. For the purpose of creating a pure zip archive, you would not want a manifest to be created in the resulting archive file.
•· /Public/test_xml.zip is the destination file name of the archive output (TOFILE in IBM lingo).
•· /Public/test.xml is the source file name of the input file (FROMFILE in IBM lingo).
I strongly recommend that you test your intended archiving commands interactively in QShell before you attempt to code it into your RPG program. This way, if you encounter any problems when running the RPG application, you will know that the problem is in the RPG code, so you're not troubleshooting both the QShell command and the RPG program at the same time.
Coding the QShell commands into RPG
Now that you have the syntax down and you've executed it interactively to make sure that it behaves the way that you expect it to, you can code it into your RPG program to be executed. You do this by using the QCMDEXC command to call the STRQSH command with the QShell command as the parameter.
D STRING S 1000A
D INFILENAME S 1000A
D OUTFILENAME S 1000A
D*
C EXSR ZIP_IT
C*
C EXSR TAR_IT
C*
C EVAL *INLR = *ON
C/EJECT
C**********************************************************************
C* SUBROUTINE: ZIP_IT
C* FUNCTION: EXECUTES HARD-CODED JAR COMMAND IN QSHELL.
C**********************************************************************
C ZIP_IT BEGSR
C EVAL INFILENAME = '/Public/test.xml'
C EVAL OUTFILENAME = '/Public/test_xml.zip'
C* ZIP THE XML FILE
C EVAL STRING = 'STRQSH CMD('
C + '''jar cfM '
C + %TRIM(OUTFILENAME) + ' '
C + %TRIM(INFILENAME)
C + ''')'
C Z-ADD 1000 STRLEN
C CALL 'QCMDEXC'
C PARM STRING
C PARM STRLEN 15 5
C ENDSR
C/EJECT
C**********************************************************************
C* SUBROUTINE: TAR_IT
C* FUNCTION: EXECUTES HARD-CODED TAR COMMAND IN QSHELL.
C**********************************************************************
C TAR_IT BEGSR
C EVAL INFILENAME = '/Public/test.xml'
C EVAL OUTFILENAME = '/Public/test_xml.tar'
C* TAR THE XML FILE
C EVAL STRING = 'STRQSH CMD('
C + '''tar cf '
C + %TRIM(OUTFILENAME) + ' '
C + %TRIM(INFILENAME)
C + ''')'
C Z-ADD 1000 STRLEN
C CALL 'QCMDEXC'
C PARM STRING
C PARM STRLEN 15 5
C ENDSR
Error When Submitting to Batch
OK, everything worked fine when I ran it interactively. So why does it crash when I submit it to batch? When you submit the job to batch, you may get Message ID: RNQ0202, indicating that the call to QCMDEXC ended in error.
In our shop, we typically set up our job queues to run one job at a time to allow multiple jobs to be queued up and run in sequential order. This common batch behavior can be a problem for applications that use QShell from RPG because the job will spawn another job to do the QShell operations. Interactively, this isn't a problem because your interactive subsystem allows multiple jobs to run concurrently. Otherwise, you would be the only one allowed on the system with only one session allowed, and that can't work because you have to let the users on too. So more than one job can run concurrently in the interactive subsystem.
To resolve this problem, I created a new subsystem for running these types of jobs in batch. When I used the Create Subsystem Description (CRTSBSD) command, I set the MAXJOBS field to *NOMAX instead of the typical value of 1. When I created the subsystem, I reused the original batch subsystem name of QBATCH and appended MAX to the end of the new subsystem to become QBATCHMAX so that I remembered its behavior. I wouldn't want the system operator to push a bunch of queued batch jobs over to this new subsystem that were depending on the previous job completing before the next one started. You could end up with all of the jobs running concurrently and your bills being printed before your account balances are updated!
Compressing Multiple Files into One Archive File
So far, we have compressed one file into an archive file to reduce the size of the original file, which reduces the time that it takes to transfer the file across the network. You can also combine multiple files into one destination archive file, which reduces the size and also organizes all of the files together. To do this, you simply keep adding the file names to the end of the command.
Compressing an Entire Directory of Files into One Archive File
You can selectively add individual files to an archive by specifying each file that you wish to add, or you can use wild cards to add all of the files within the specified directory that match the wild card criteria. If you wish to add every file in the directory, you just specify the directory name as the source file. If you wish to only include the XML files, you specify the directory with the *.xml wild card value.
Tar Examples:
Archiving files /Public/test1.xml, /Public/test2.xml, and /Public/test3.xml into /Public/test_xml.tar:
tar cf /Public/test_xml.tar /Public/test1.xml /Public/test2.xml /Public/test3.xml
Archiving the XML files into /Public/test_xml.tar:
tar cf /Public/test_xml.tar /Public/*.xml
Archiving all of the files from the /Public folder into /Public/test_xml.tar:
tar cf /Public/test_xml.tar /Public/
Zip Examples:
Archiving files /Public/test1.xml, /Public/test2.xml, and /Public/test3.xml into /Public/test_xml.zip:
jar cfM /Public/test_xml.zip /Public/test1.xml /Public/test2.xml /Public/test3.xml
Archiving the XML files in the /Public folder into /Public/test_xml.zip:
jar cfM /Public/test_xml.zip /Public/*.xml
Archiving all of the files from the /Public folder into /Public/test_xml.zip:
jar cfM /Public/test_xml.zip /Public/
LATEST COMMENTS
MC Press Online