Skip to Main Content
  • Questions
  • get file names in a directory not working anymore due to SQJ is no longer supported by 12.2 or later version

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Phong.

Asked: January 08, 2018 - 5:16 pm UTC

Last updated: November 06, 2024 - 2:51 pm UTC

Version: 12.2.1.0

Viewed 10K+ times! This question is

You Asked

Hi Tom,

I have been using your script as listed below to get the list of the file names in a directory and insert them into a global temporary table. Everything was working fine until last week I have upgraded my database to 12.2 and the script is no longer working. I found out that according to the Oracle Doc ID 2310077.1 Starting from Oracle 12.2 release the server-side SQLJ is no longer supported. And in your script at line 19 and 20 there is an insert statement (SQLJ) to insert the file names into DIR_LIST table. It is not working anymore, It causes the java source compiled failed, when I commented out the insert statement then the compile was successful. I still need to have the file names insert into a table, Would you please to show me the alternate way to do that instead of using the embedded SQL which it is no longer supported by 12.2.

Thank you very much in advance.

Regards,
Phong.

ops$tkyte@8i> create or replace
2 and compile java source named "DirList"
3 as
4 import java.io.*;
5 import java.sql.*;
6
7 public class DirList
8 {
9 public static void getList(String directory)
10 throws SQLException
11 {
12 File path = new File( directory );
13 String[] list = path.list();
14 String element;
15
16 for(int i = 0; i < list.length; i++)
17 {
18 element = list[i];
19 #sql { INSERT INTO DIR_LIST (FILENAME)
20 VALUES (:element) };
21 }
22 }
23
24 }
25 /

Java created.

ops$tkyte@8i>
ops$tkyte@8i> create or replace
2 procedure get_dir_list( p_directory in varchar2 )
3 as language java
4 name 'DirList.getList( java.lang.String )';
5 /

and Connor said...

Here is a much easier way that does not use Java at all. An external table with a pre-processor can take care of it.

Check out Adrian Billington's blog post which walks through the code nicely

http://www.oracle-developer.net/display.php?id=513


Rating

  (6 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Avoid SQLJ INSERT

Jonathan Taylor, January 09, 2018 - 12:13 pm UTC

This is an alternative that still does this using a similar Java method, but avoiding SQLJ (since we didn't like the lack of dependency between the table name and the java source).

Instead of inserting into DIR_LIST, getListing() gets the list of files and puts them in an array. nextFileName() is then called to get the files from the array one at a time into PL/SQL (NULL marks the end of the list). (At the time this was written, there wasn't an easy way of returning a Java array to PL/SQL).

If need be, you could still populate DIR_LIST in a PL/SQL package by calling the above methods.

create or replace and compile java source named directorylist as
package yourorganisation.directorylist;

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Arrays;

public class DirectoryList {

    static ArrayList globalFileList;
    /**********************************************************************/
    /*
    Get the listing as a string array, and stores in globalFileList
    */
    public static void getListing (String directory) {
      File path = new File( directory );
      String[] list = path.list();
      /* Convert array to ArrayList (to allow removal of element 0)*/
      globalFileList = new ArrayList (Arrays.asList (list));
    }
    /**********************************************************************/
    /*
    Gets the next name from the list.
    return "" if end of list.
    */
    public static String nextFileName() {
      String fileName="";
      
      if (globalFileList.size()>0) {
        fileName=(String)globalFileList.remove(0);
      }
      
      return(fileName);
    }
}


You would need two PL/SQL procedures defined similar to this:-

  --****************************************************************************
  PROCEDURE     Java_Directory_List_Get
    ( p_Directory_Name          IN      VARCHAR2
    )                           
  AS LANGUAGE JAVA
  NAME 'yourorganisation.directorylist.DirectoryList.getListing(java.lang.String)'
  ;
  --****************************************************************************
  FUNCTION      Java_Directory_List_Next_File
                                RETURN  VARCHAR2
  AS LANGUAGE JAVA
  NAME 'yourorganisation.directorylist.DirectoryList.nextFileName() return java.lang.String'
  ;
  --****************************************************************************  

Connor McDonald
January 10, 2018 - 12:12 am UTC

Thanks for the additional info and for contributing to AskTOM.

Return List as Array

Marcus, January 10, 2018 - 8:58 am UTC

Since the returned string has a length limit that might be exceeded if there are a lot of files in the directory I prefer a solution where I get an array (see the code by Anthony Wilson at
https://asktom.oracle.com/pls/apex/asktom.search?tag=reading-files-in-a-directory-how-to-get-a-list-of-available-files#1565062600346635117 )

This solution does not need a table to select the entries because you can do a simple
  1  select *
  2  from table(util.ls('YOUR_DIR_NAME'))
  3  where name like '%.zip'
  4  and modified >= sysdate - 3
  5* and file_size > 1000000


Connor McDonald
January 12, 2018 - 12:30 am UTC

Agreed, but the external table doesn't need any structures/memory/etc :-)

Is there a concurrency issue?

Marcus, February 27, 2020 - 8:16 am UTC

When more than one user tries to Access the external table at the same time - wouldn't there be a concurrency issue if they both try to set the file location?
Chris Saxon
February 27, 2020 - 11:24 am UTC

Possibly - what exactly are you concerned about?

Concurrency

Marcus, February 27, 2020 - 11:42 am UTC

At the moment I use the Java dir_list that won't work anymore in 12.2. Users can see which files are in different directories they might have to process.
If I implement the External Table solution it might happen that two or more users try to read different directories at the same time.
Of course I could create a table for each directory but this is not my idea of reusable code.
Connor McDonald
March 03, 2020 - 6:25 am UTC

But LOCATION is dynamic in 12.2 and above, eg

SELECT ...  FROM   my_ext_table  EXTERNAL MODIFY (
                 LOCATION 'abc.dat'
               )


so each query has its own control without changing the table DDL

using java based approach

Rajeshwaran, Jeyabal, March 03, 2020 - 10:45 am UTC

As Connor mentioned, it is quite easy to go with External table for this use case, however if you still need a java based approach -similar to SQLJ -Here is an option http://tiny.cc/13pskz

Simple Java Fix

Craig, November 06, 2024 - 1:15 am UTC

Yes, hit this problem upgrading from 12.c to 19c
Simplest approach was to continue with Java approach but replace SQLJ #sql statement with PreparedStatement dynamic style which I found at below:

DirList Java Class for Oracle DB since 12.2 ยท GitHub
https://gist.github.com/hotfix/908ff78b4bdb807c3b514dbdce14a7cd

Chris Saxon
November 06, 2024 - 2:51 pm UTC

Thanks for sharing.

More to Explore

Design

New to good database design? Check out Chris Saxon's full fundamentals class.