Read / Extract ZIP Files - PeopleCode Example

In this tutorial, we will discuss how to Read / extract a ZIP file in PeopleSoft with a PeopleCode example. If you are looking to ZIP a file in PeopleCode, you should refer to our earlier tutorials. We will be using java.util.zip.ZipInputStream to read a ZIP file in PeopleSoft, and then extract every entry inside the ZIP file to a file on disk using the methods available in Java, extended to PeopleCode. The high level steps to extract a ZIP file in PeopleCode are documented below: 

Steps to Extract ZIP Files in PeopleCode
Steps to Extract ZIP Files in PeopleCode

The ZIP File we want to read and extract is shown in the screenshot below:

Sample ZIP Input File to Extract in PeopleCode
Sample ZIP Input File to Extract in PeopleCode

The output we are looking for when we extract this file, should be like the following as shown below:

C:\temp\dir1 ------- /* Create Directory in PeopleCode */
C:\temp\dir2 ------- /* Create Directory in PeopleCode */
C:\temp\dir1\source.log ----- /* Extract File into the directory */
C:\temp\dir2\source.sql ----- /* Extract File into the directory */


We have to create two directories in PeopleCode and place the input files into this directory, all in a generic fashion. Let us now get started with this tutorial.

1. Read ZIP File as ZipInputStream


In this step, we create a JavaObject in PeopleCode that will read the input ZIP file as an object of type java.util.zip.ZipInputStream . In order to create a ZipInputStream, you have to pass an object of type InputStream as a parameter. So, we create a FileInputStream object that will point to the physical zip file on the disk, and pass this to the code. The PeopleCode snippet is shown below:

Local JavaObject &InputZipReader = CreateJavaObject("java.util.zip.ZipInputStream", CreateJavaObject("java.io.FileInputStream", "c:\temp\TESTER.zip"));


2. Read First ZIP Entry


There is no direct method available in ZipInputStream to read the number of entries in the ZIP file. So, we read the first entry using getNextEntry method, which returns a ZipEntry back to us. ZipEntry is defined in java.util.zip.ZipEntry, if you are keen to read as a reference.

Local JavaObject &EntryForZipFile = &InputZipReader.getNextEntry();

3. Extract Directories in PeopleCode


Now, when you extract a ZIP file in PeopleCode, you need to find a way to know if the extracted entry is a directory. If it is a directory, then you need to create a directory in the file system, so that you can put the files into the right folder. You use isDirectory method in ZipEntry to check if the entry is a directory. If it is a directory, then you use getName method to get the name of the directory, and create a directory in File System by using mkdir method available in java.io.File. The PeopleCode segment is shown below:

   If (&EntryForZipFile.isDirectory()) Then
      Local JavaObject &dir = CreateJavaObject("java.io.File", &EntryForZipFile.getName());
      Local boolean &b = &dir.mkdir();


4. Extract Bytes from ZIP File


If the entry is a non directory (i.e. File) then you have to read the bytes from the entry and write the bytes read to a file on disk. Note, that when you use getNextEntry method, the stream is automatically positioned at the beginning of the entry data. So, to read bytes from the entry, all you have to do is to use read method, and read the bytes to a byte array in PeopleCode. You have to recursively do this, until all bytes from the Zip entry is read. You will learn about this, when you see the full PeopleCode example. For now, here is a split segment;

Local JavaObject &ByteBufferArray = CreateJavaArray("byte[]", 1024); /* Create Byte Array to read Zip entry bytes */
Local number &NumberOfBytes; /* Variable to loop through number of bytes */

.................
.................

&NumberOfBytes = &InputZipReader.read(&ByteBufferArray); /* Read First set into byte array */
      
      While &NumberOfBytes > 0 /* Loop until all bytes are read */
      /* Here, we will write code to write the bytes read to a file on disk */
         &NumberOfBytes = &InputZipReader.read(&ByteBufferArray); /* Read next set of bytes */
      /* We exit the loop when all bytes are read */   
      End-While;
/* We have to close the entry at the end, so that the stream becomes ready to read next entry */      
&InputZipReader.closeEntry();      

Note that at the end of the process, we are invoking a closeEntry method, that closes the current entry and moves the pointer to read the next entry.

5. Write ZIP Entry to Disk


Now, while you are reading bytes from every ZIP file as per Step 4, you can write the entry to disk, by creating a FileOutputStream object and pass the base directory / Entry path details to it. Then you can use the write method to write the bytes to the output stream, that you have read in step 4. The PeopleCode snippet is shown below:

      Local JavaObject &out = CreateJavaObject("java.io.FileOutputStream", "c:\temp\" | &EntryForZipFile.getName(), True);
      ......
      ......
      &out.write(&ByteBufferArray, 0, &NumberOfBytes);

6. Read / Extract All Other ZIP Entries


We repeat steps 3, 4 and 5 in a loop until all the entries in the ZIP files are read. The method getNextEntry returns NULL, when there are no more entries to be read in the input file. So, we make use this factor as a looping condition to read all the entries. Inside the loop, we handle directories and files as discussed earlier. ( refer code below )

7. Close Input ZIP File


At the end of step 6, we are done extracting the ZIP file completely. So, we can now close the input ZIP file by using the close method in ZipInputStream class. This step closes the input stream and releases memory back.


Complete PeopleCode – Read / Extract ZIP File


The complete PeopleCode snippet to read / extract ZIP file is shown below. Note that we have handled directories and files separately, as we found that in some cases, the directories are read after the file is read. You can tweak the code to suit to your needs and get rid of the directories code section completely, if you don’t want it.

/* Extract ZIP Files in PeopleCode - Example */
Local JavaObject &InputZipReader = CreateJavaObject("java.util.zip.ZipInputStream", CreateJavaObject("java.io.FileInputStream", "c:\temp\TESTER.zip"));
Local JavaObject &EntryForZipFile = &InputZipReader.getNextEntry();
Local JavaObject &ByteBufferArray = CreateJavaArray("byte[]", 1024);
Local number &NumberOfBytes;

/* Create all directories first */
While &EntryForZipFile <> Null
   If (&EntryForZipFile.isDirectory()) Then
      Local JavaObject &dir = CreateJavaObject("java.io.File", "c:\temp\" | &EntryForZipFile.getName());
      Local boolean &b = &dir.mkdir();
   End-If;
   &EntryForZipFile = &InputZipReader.getNextEntry();
End-While;
&InputZipReader.close();

/* You can combine the code if required. I have split the code as Java read files first and directories next in some cases */
/* Now we handle files */

&InputZipReader = CreateJavaObject("java.util.zip.ZipInputStream", CreateJavaObject("java.io.FileInputStream", "c:\temp\TESTER.zip"));
&EntryForZipFile = &InputZipReader.getNextEntry();

While &EntryForZipFile <> Null
   If (&EntryForZipFile.isDirectory()) Then
      /* do nothing */
   Else
      Local JavaObject &out = CreateJavaObject("java.io.FileOutputStream", "c:\temp\" | &EntryForZipFile.getName(), True);
      &NumberOfBytes = &InputZipReader.read(&ByteBufferArray);
      While &NumberOfBytes > 0
         &out.write(&ByteBufferArray, 0, &NumberOfBytes);
         &NumberOfBytes = &InputZipReader.read(&ByteBufferArray);
      End-While;
      /* You can read the file into PeopleSoft at this stage if required */
      &InputZipReader.closeEntry();
   End-If;
   &EntryForZipFile = &InputZipReader.getNextEntry();
End-While;


This code produces the same output as shown in the expected output section earlier. That completes our tutorial to extract ZIP files in PeopleCode. Feel free to discuss any questions that you have on this in the comments section of this blog.

No comments:

Post a Comment