javadirectoryftpftp-clientcd

FTPClient path/directory change. Multiple directories in single FTPClient InputStream connect. Unknown parser type: "/Path" is current directory


FTPClient.changeWorkingDirectory & changeToParentDirectory(). How to change directory in ftpCient. In explorer the ftp path looks like this ftp://192.168.10.20. once entering this, I can see folders COMPLETED, FAILURE and QRCODEGENERATE. In my java code first I'm entering inside FAILURE folder and getting the respective file. And this process is successfully done. After getting it I want to enter into COMPLETED folder, I mean the directory path has to be changed like this /FAILURE to COMPLETED but it's getting error. I shared the Console error at the bottom.

I can get the value if I close the connection and open again. But I dont want to do like that. I want to change the directory with out closing the connection.

1.First I'm getting into FAILURE and I'm accessing a file and its contents.

2.Then I'm going back to COMPLETED and I want to access the files and its contents.

Here is my JAVA code

InputStream is = null;
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
strDir= "FAILURE";
ftpClient.printWorkingDirectory();
String[] ftpList=ftpClient.listNames();
//Here I'm listing the folders present in parent directory
for(int i =0; i<ftpList.length;i++)
{
    String ftpFilsList=ftpList[i];
    System.out.println(".........::::::::::"+ftpFilsList);
}

//getting into Failure Folder and fetching file

ftpClient.changeWorkingDirectory(ftpClient.printWorkingDirectory()+strDir);
System.out.println("prnt#WorkingDir"+ftpClient.printWorkingDirectory());
is =ftpClient.retrieveFileStream(filename+".json");

int i=0;
String valuesinside="";
while((i = is.read())!=-1)
{
    //valuesinside+=valuesinside+i;
    char c = (char)i;
    valuesinside+=Character.toString(c);
    ftpfilelist=valuesinside;
}
//Successfully Fetched file and its contents
                
//change the directory to COMPLETED Folder
                
String strFullFileName = "";
File fileJson=null;
int intfilecount=00;
String strFileCount="";
strDir = "COMPLETED";
                
ftpClient.changeToParentDirectory();//To go back to previos directory
System.out.println("PARENRT+++++:::::"+ftpClient.printWorkingDirectory());//This shows null
ftpClient.changeWorkingDirectory(strDir);
ftpClient.printWorkingDirectory();
System.out.println("COMPLETED+++++:::::"+ftpClient.printWorkingDirectory());//Shows "/COMPLETED" in the console. but not getting the files.
FTPFile[] fileJsonReader=ftpClient.listFiles(ftpClient.printWorkingDirectory()); 
for(FTPFile ftpFile:fileJsonReader)
{
    String strJsonFileName=null;
    strJsonFileName=ftpFile.getName();
    System.out.println("strJsonFileName:::+++++"+strJsonFileName);
    String strBillNoFile=strJsonFileName.substring(0, strJsonFileName.lastIndexOf("-"));//-01
    System.out.println("strBillNoFile+++++::::::"+strBillNoFile);
    strBillNoFile=strBillNoFile+".json";
    System.out.println("strBillNoFile:::::+++++"+strBillNoFile);
    if(strBillNoFile.equalsIgnoreCase(filename.getName()))
    {
        
        intfilecount=intfilecount+1;
    }
 }

In console I'm getting error like this. You can see the list of folders shown first.

.....................:::::::::::::::COMPLETED
.......................:::::::::::::::FAILURE
.......................:::::::::::::::QRCODEGENERATE
prnt#WorkingDir/FAILURE
PARENT+++++:::::::null
COMPLETED+++++:::::/COMPLETED
org.apache.commons.net.ftp.parser.ParserInitializationException: Unknown parser type: "/COMPLETED" is current directory.
at org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory.createFileEntryParser(DefaultFTPFileEntryParserFactory.java:132)
    at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:2263)
    at org.apache.commons.net.ftp.FTPClient.listFiles(FTPClient.java:2046)
    at com.restService.FtpJson.FTPAuthJSONReader(FtpJson.java:130)
    at com.restService.JsonFailCompleted.getMessage(JsonFailCompleted.java:27)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:124)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:167)
    at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:219)
    at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:469)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:391)
    at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:80)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:253)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:232)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:366)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:319)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:209)
    at com.thetransactioncompany.cors.CORSFilter.doFilter(CORSFilter.java:244)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:610)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503)
    at java.lang.Thread.run(Unknown Source)

please help me to solve this. Thanks in advance

Solution

-----Just closed the inputStream is.close() and Boolean result = ftpClient.completePendingCommand();

Throws nullPointerException in InputStream

is =ftpClient.retrieveFileStream(filename+".json"); here if the folder doesn't have the requested file name, it throws NullPointerException. How to handle it without changing retrieveFileStream?


Solution

  • Update:

    It looks like the issue is caused because you use this method retrieveFileStream();, which needs some extra processes and the server either disconnects or behaves oddly once it is finished. Here is the key part information from the api referance:

    retrieveFileStream - Returns an InputStream from which a named file from the server can be read. If the current file type is ASCII, the returned InputStream will convert line separators in the file to the local representation. You must close the InputStream when you finish reading from it. The InputStream itself will take care of closing the parent data connection socket upon being closed.

    To finalize the file transfer you must call completePendingCommand and check its return value to verify success. If this is not done, subsequent commands may behave unexpectedly.

    So you need to close the steam is.close(); then use ftpClient.completePendingCommand();. Once this is done, you can check if the connection is still alive if(ftp.isConnected() == true){...} and if not then you can reconnect ftp.connect(...); then move onto your next command to change the working directory.

    //Open the stream
    is =ftpClient.retrieveFileStream(filename+".json");
    
    //Process the stream data
    int i=0;
    String valuesinside="";
    while((i = is.read())!=-1)
    {
        //valuesinside+=valuesinside+i;
        char c = (char)i;
        valuesinside+=Character.toString(c);
        ftpfilelist=valuesinside;
    }
    
    //Close the stream and complete the command
    is.close();
    Boolean result = ftpClient.completePendingCommand();
    
    //check if connection is alive
    if(ftp.isConnected() == false){
        //reconnect here with your server details
        //...
    }
    
    //Now move onto the next commands
    ftpClient.changeToParentDirectory();/
    ftpClient.changeWorkingDirectory("COMPLETED");
    System.out.println("PARENRT+++++:::::"+ftpClient.printWorkingDirectory());
    

    Alternatly you could use a different method where you manage the stream manually rather than using the API, for example you could do retrieveFile(fileName, outputStream);.

    The ParserInitializationException error:

    If you are interested more about other reasons why the error happens then see here at the apache FTPClient docs:

    ParserInitializationException - Thrown if the parserKey parameter cannot be resolved by the selected parser factory. In the DefaultFTPEntryParserFactory, this will happen when parserKey is neither the fully qualified class name of a class implementing the interface org.apache.commons.net.ftp.FTPFileEntryParser nor a string containing one of the recognized keys mapping to such a parser or if class loader security issues prevent its being loaded.