I'm am trying to upload a file into mainframe server using FTP. My code is below
FTPClient client = new FTPClient();
InputStream in = null;
FileInputStream fis = null;
try {
client.connect("10.10.23.23");
client.login("user1", "pass123");
client.setFileType(FTPClient.BINARY_FILE_TYPE);
int reply ;
reply = client.getReplyCode();
System.out.println("Reply Code:"+reply);
if(FTPReply.isPositiveCompletion(reply)){
System.out.println("Positive reply");
String filename ="D:\\FILE.txt";
in = new FileInputStream(filename);
client.storeFile("FILE.TXT", in);
client.logout();
fis.close();
} else {
System.out.println("Negative reply");
}
} catch(final Throwable t){
t.printStackTrace();
}
The code gets struck in client.storeFile("FILE.TXT", in);
I am unable to debug. Please suggest ways / solutions.
First there is what Lukas said fis is null, but I have a bunch of other questions. What is FTPClient? It is not sun.net.ftp.FtpClient as that class has no store() method. Other things to consider is logging into the mainframe, where I work you can't just grab files off the mainframe without first logging in. There can be more things to consider but lets start there.
You don't appear to be changing to a specific directory before uploading the file. There are two ways of changing directories on the Mainframe. If you need to upload to a PDS you would execute a command like the following from with in the windows ftp client.
cd USERID.DATASET.PREFIX
If you need to upload a file to the USS subsystem you would execute a command like the following.
cd '/direone/dirtwo'
Have you checked that user1 has access permissions to ftp? It is possible to grant those on a very granular level so that you can list files and submit jobs, but not put files.
The fact that it dies right after your SEND seems like that might be a good candidate. I would call your RACF / ACF2 / Whatever-security-product person you have and ask them.
first remove the file extension from the file name
enclose the resultant file name after trimming within single quotes
now put the above string as the first parameter of storeFile() method
Related
I need to write a custom batch File renamer. I've got the bulk of it done except I can't figure out how to check if a file is already open. I'm just using the java.io.File package and there is a canWrite() method but that doesn't seem to test if the file is in use by another program. Any ideas on how I can make this work?
Using the Apache Commons IO library...
boolean isFileUnlocked = false;
try {
org.apache.commons.io.FileUtils.touch(yourFile);
isFileUnlocked = true;
} catch (IOException e) {
isFileUnlocked = false;
}
if(isFileUnlocked){
// Do stuff you need to do with a file that is NOT locked.
} else {
// Do stuff you need to do with a file that IS locked
}
(The Q&A is about how to deal with Windows "open file" locks ... not how implement this kind of locking portably.)
This whole issue is fraught with portability issues and race conditions:
You could try to use FileLock, but it is not necessarily supported for your OS and/or filesystem.
It appears that on Windows you may be unable to use FileLock if another application has opened the file in a particular way.
Even if you did manage to use FileLock or something else, you've still got the problem that something may come in and open the file between you testing the file and doing the rename.
A simpler though non-portable solution is to just try the rename (or whatever it is you are trying to do) and diagnose the return value and / or any Java exceptions that arise due to opened files.
Notes:
If you use the Files API instead of the File API you will get more information in the event of a failure.
On systems (e.g. Linux) where you are allowed to rename a locked or open file, you won't get any failure result or exceptions. The operation will just succeed. However, on such systems you generally don't need to worry if a file is already open, since the OS doesn't lock files on open.
// TO CHECK WHETHER A FILE IS OPENED
// OR NOT (not for .txt files)
// the file we want to check
String fileName = "C:\\Text.xlsx";
File file = new File(fileName);
// try to rename the file with the same name
File sameFileName = new File(fileName);
if(file.renameTo(sameFileName)){
// if the file is renamed
System.out.println("file is closed");
}else{
// if the file didnt accept the renaming operation
System.out.println("file is opened");
}
On Windows I found the answer https://stackoverflow.com/a/13706972/3014879 using
fileIsLocked = !file.renameTo(file)
most useful, as it avoids false positives when processing write protected (or readonly) files.
org.apache.commons.io.FileUtils.touch(yourFile) doesn't check if your file is open or not. Instead, it changes the timestamp of the file to the current time.
I used IOException and it works just fine:
try
{
String filePath = "C:\sheet.xlsx";
FileWriter fw = new FileWriter(filePath );
}
catch (IOException e)
{
System.out.println("File is open");
}
I don't think you'll ever get a definitive solution for this, the operating system isn't necessarily going to tell you if the file is open or not.
You might get some mileage out of java.nio.channels.FileLock, although the javadoc is loaded with caveats.
Hi I really hope this helps.
I tried all the options before and none really work on Windows. The only think that helped me accomplish this was trying to move the file. Event to the same place under an ATOMIC_MOVE. If the file is being written by another program or Java thread, this definitely will produce an Exception.
try{
Files.move(Paths.get(currentFile.getPath()),
Paths.get(currentFile.getPath()), StandardCopyOption.ATOMIC_MOVE);
// DO YOUR STUFF HERE SINCE IT IS NOT BEING WRITTEN BY ANOTHER PROGRAM
} catch (Exception e){
// DO NOT WRITE THEN SINCE THE FILE IS BEING WRITTEN BY ANOTHER PROGRAM
}
If file is in use FileOutputStream fileOutputStream = new FileOutputStream(file); returns java.io.FileNotFoundException with 'The process cannot access the file because it is being used by another process' in the exception message.
Hi I am trying to get the returned file path by my JNLP file chooser. Here's my code.
I don't know how and where to get the file path. is it from fileContents? fileConents.getfilepath something like that?
try {
if (fileOpenService==null) {
fileOpenService = (FileOpenService)ServiceManager.
lookup("javax.jnlp.FileOpenService");
}
fileContents = fileOpenService.openFileDialog(path, xtns);
} catch(UnavailableServiceException use) {
use.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
}
Thanks in advance!
According to http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html
You can call other methods on the File object, such as
getPath, isDirectory, or exists to obtain information about the file.
You can also call other methods such as delete and rename to change
the file in some way. Of course, you might also want to open or save
the file by using one of the reader or writer classes provided by the
Java platform. See Basic I/O for information about using readers and
writers to read and write data to the file system.
It is for security reasons that a FileContents will not return a path. The JRE asked the user if our app. could access the content of that file, not it's path.
It is a bit like the brower/HTML based file upload field. Some browsers provide the entire path, while more typically it is just the content/name.
So I pushed my java app to a server, pretty excited about that.
Now I want to test something, how can I save the posted data to my servlet to a file, and the filename should be a unique guid.
I have this so far:
public class TestServlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, IOException {
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
throws javax.servlet.ServletException, IOException {
PrintWriter printWriter = response.getWriter();
printWriter.print("hello, world from testservlet!");
}
}
So assuming the http posted data (say around 50K) will be posted to the field 'payload', how can I grab the posted text, and save it to a file, with the filename being a GUID.
Does java have a construct to clean up an open file, like in c#:
using(var file = new ....)
{
// write to file
}
That closes the connection and cleans up memory etc.
Also, do I need to set special permissions for tomcat to save this file?
I just set things up by default right now (just playing around on a VPS) using ubuntu 11, installed tomcat6.
Thanks.
You can user request to read the "payload", see the API doc for ServletRequest:
request.getParameter("payload");
You can use File to create the file, see AP doc:
File newFile = new File("fileName");
boolean isCreated = newfile.createNewFile();
You can write to the file as follows,
BufferedWriter out = new BufferedWriter(new FileWriter(newFile));
out.write(payLoad);
out.close();
For GUID you see this Create a GUID in Java
And for the clean up, you don't have to worry about it in Java, it's Garbage Collector ( What is the garbage collector in Java? ) does it for you automatically when the reference goes out of scope.
But you should close the resources like out.close to release it back to the system when you are done with it.
Also, do I need to set special permissions for tomcat to save this file?
You do not need to do that because tomcat is just a server, it's more related to the file system (OS). I use Glassfish on Unix and I don't need to do anything like that to create file.
Now I want to test something, how can I save the posted data to my servlet to a file, and the filename should be a unique guid.
Use File#createTempFile() to create a file with an unique ID in the given folder.
File file = File.createTempfile("prefix-", ".ext", "/path/to/files");
// ...
See also:
Saving uploaded file in specific location
Does java have a construct to clean up an open file, like in c#: using?
Only in Java 7 which is already been out for some time.
try (FileWriter writer = new FileWriter(file)) {
writer.write(content);
}
which is equivalent to
FileWriter writer = null;
try {
writer = new FileWriter(file);
writer.write(content);
} finally {
if (writer != null) writer.close();
}
See also:
"using" keyword in java
Also, do I need to set special permissions for tomcat to save this file?
The user who has started Tomcat should indeed have the file write permissions on the given directory.
In the future please ask separate questions in separate SO questions.
Java 7 has a new try with resources construct that will take care of closing the file for you. Otherwise... just close the file; no big deal.
As far as "special permissions", as long as the user Tomcat is running under can access the directory in question, there's no issue. I'd recommend against storing it under the webapp directories, though (and if it's deployed as a war you may not be able to anyway). Keep uploaded files in a known, but separate, directory.
I am trying to open a file i just created in my code (so i am sure that the file exists)
The code is like this:
File file = new File(filename);
file.createNewFile();
BufferedWriter bw = new BufferedWriter(new FileWriter(file));
...
bw.close();
try {
Desktop desktop = null;
if (Desktop.isDesktopSupported()) {
desktop = Desktop.getDesktop();
}
desktop.open(file);
} catch (Exception e) {
...
}
But as the title says i get a "java.io.IOException: The system cannot find the path specified" from the desktop.open(file) istruction.
The problem surely is that the file pathname contains spaces (which are translated into "%20"). Is there a way to avoid this?
I found the real problem.
It wasn't either the %20 as i supposed.
I just hadn't the privileges to directly access the file location. It's a bit complicated to explain...
i'm just sorry i coulnd't figure out the real problem before.
Thanks for your suggestions anyway!
Are you using an IDE? What is inside the variable 'filename' (it's actual contents). Line two is unnecessary.
Is the error from the stack trace pointing to BufferedWriter bw = new BufferedWriter(new FileWriter(file)); or desktop.open(file);
EDIT:
You can also try the following code
File myCSVFile; //reference to your csv file here
String execString = "excel " + myCSVFile.getAbsolutePath();
Runtime run = Runtime.getRuntime();
try {
Process pp = run.exec(execString);
} catch(Exception e) {
e.printStackTrace();
}
The java.io error is appearing because it's failing to open the file. The code above will force excel open with your file as the argument. You'll need to set your environment variable to ensure that the command 'excel' in the command line opens the Excel application.
If you're planning on releasing this application for use you can ensure that excel is installed by checking the registry, then checking the install location of Excel from there.
Try to open a different file with other applications and see if other file types are supported. As Clarisse said, IOException is thrown from the 'open' method if the specified file has no associated application or the associated application fails to be launched. If the specified file doesn't exists IllegalArgumentException is thrown, which is not in your case. If for some reason opening a CSV file with Desktop doesn't work for you, try using krslynx approach. Same can be found here. You can quickly assemble a test application for opening anything on your machine using the code found here
In the Desktop javadoc it's written :
IOException - if the specified file has no associated application or the associated application fails to be launched
So are you sure your filetype has a default application associated ?
As krslynx says, file.createNewFile() is unnecessary. However file.mkdirs() may be necessary instead, if the intermediate directories don't exist yet.
EDIT: it's not clear from your question whether this is happening in new FileWriter() or in Desktop.open(). Please clarify.
I am working on an Android application that depends on an ELF binary:
our Java code interacts with this binary to get things done. This
runtime needs to be started and terminated on Application startup and
application exit / on demand.
Questions:
I am assuming that we will be able to execute this binary using the
Runtime.exec() API. Is there any constraints as to where I
need to be putting my library in the folder structure? How would the system runtime locate this executable? Is there some sort of class path setting?
Since the application has dependencies on this Runtime, I was
thinking of wrapping it around a service so that it can be started or
stopped as required. What is the best way to handle such executables
in Android project?
What are other alternatives, assuming that I do not have source code for this executable?
Please advice.
Thanks.
1) No, there should be no constrains, besides those that access system files and thus require root. The best place would be straight to /data/data/[your_package_name] to avoid polluting elsewhere.
2) A very thorough discussion about compiling against native libraries can be found here: http://www.aton.com/android-native-libraries-for-java-applications/ . Another option is a cross-compiler for arm (here is the one used to compile the kernel, it's free: http://www.codesourcery.com/sgpp/lite/arm ). If you plan to maintain a service that executes your cammand, be warned that services can be stopped and restarted by android at any moment.
3) Now, if you don't have the source code, I hope that your file is at least compiled as an arm executable. If not, I don't see how you could even run it.
You will execute the file by running the following commands in your java class:
String myExec = "/data/data/APPNAME/FILENAME";
Process process = Runtime.getRuntime().exec(myExec);
DataOutputStream os = new DataOutputStream(process.getOutputStream());
DataInputStream osRes = new DataInputStream(process.getInputStream());
I know nothing about your executable, so you may or may not need to actually get the inputStream and outputStream.
I am assuming that running adb to push the binary file is out of the question, so
I was looking for a neat way to package it. I found a great post about including an executable in your app. Check it out here:
http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App
The important part is this one (emphasis mine):
From Android Java app, using assets folder
Include the binary in the assets folder.
Use getAssets().open(FILENAME) to get an InputStream.
Write it to /data/data/APPNAME (e.g. /data/data/net.gimite.nativeexe), where your application has access to write files and make it executable.
Run /system/bin/chmod 744 /data/data/APPNAME/FILENAME using the code above.
Run your executable using the code above.
The post uses the assets folder, insted of the raw folder that android suggests for static files:
Tip: If you want to save a static file in your application at compile time, save the file in your project res/raw/ directory. You can open it with openRawResource(), passing the R.raw. resource ID. This method returns an InputStream that you can use to read the file (but you cannot write to the original file).
To access the data folder, you can follow the instructions here:
http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
Also, there's the File#setExecutable(boolean); method that should works instead of the shell command.
So, putting everything together, I would try:
InputStream ins = context.getResources().openRawResource (R.raw.FILENAME)
byte[] buffer = new byte[ins.available()];
ins.read(buffer);
ins.close();
FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(buffer);
fos.close();
File file = context.getFileStreamPath (FILENAME);
file.setExecutable(true);
Of course, all this should be done only once after installation. You can have a quick check inside onCreate() or whatever that checks for the presence of the file and executes all this commands if the file is not there.
Let me know if it works. Good luck!
Here is a complete guide for how to package and run the executable. I based it on what I found here and other links, as well as my own trial and error.
1.) In your SDK project, put the executable file in your /assets folder
2.) Programmatically get the String of that files directory (/data/data/your_app_name/files) like this
String appFileDirectory = getFilesDir().getPath();
String executableFilePath = appFileDirectory + "/executable_file";
3.) In your app's project Java code: copy the executable file from /assets folder into your app's "files" subfolder (usually /data/data/your_app_name/files) with a function like this:
private void copyAssets(String filename) {
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
Log.d(TAG, "Attempting to copy this file: " + filename); // + " to: " + assetCopyDestination);
try {
in = assetManager.open(filename);
Log.d(TAG, "outDir: " + appFileDirectory);
File outFile = new File(appFileDirectory, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(IOException e) {
Log.e(TAG, "Failed to copy asset file: " + filename, e);
}
Log.d(TAG, "Copy success: " + filename);
}
4.) Change the file permissions on executable_file to actually make it executable. Do it with Java calls:
File execFile = new File(executableFilePath);
execFile.setExecutable(true);
5.) Execute the file like this:
Process process = Runtime.getRuntime().exec(executableFilePath);
Note that any files referred to here (such as input and output files) must have their full path Strings constructed. This is because this is a separate spawned process and it has no concept of what the "pwd" is.
If you want to read the command's stdout you can do this, but so far it's only working for me for system commands (like "ls"), not the executable file:
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
process.waitFor();
Log.d(TAG, "output: " + output.toString());
For executing binary file starting from Android 10 it's only possible from read-only folder. It means that you should pack binary with your app. Android doc
Put android:extractNativeLibs="true" into AndroidManifest;
Put your binary to src/main/resources/lib/* directory, where * – stands for architecture of CPU, for instance armeabi-v7a;
Use code like this for executing:
private fun exec(command: String, params: String): String {
try {
val process = ProcessBuilder()
.directory(File(filesDir.parentFile!!, "lib"))
.command(command, params)
.redirectErrorStream(true)
.start()
val reader = BufferedReader(
InputStreamReader(process.inputStream)
)
val text = reader.readText()
reader.close()
process.waitFor()
return text
} catch (e: Exception) {
return e.message ?: "IOException"
}
}
Here is discussion with answer from android team on reddit.
I've done something like this using the NDK. My strategy was to recompile the program using the NDK and write some wrapper JNI code that called into the program's main function.
I'm not sure what the lifecycle of NDK code is like. Even services that are intended to be long-running can be started and stopped by the system when convenient. You would probably have to shutdown your NDK thread and restart it when necessary.