FileItem inputStream to FileInputStream - java

I have a web page with an upload feature which lets you upload a excel file, on hitting upload an Ajax call is fired. From there I get the FileItem input stream and using the method fileItem.getInputStream(), I have another class with a method which I need to pass the file to, which has a FileInputStream parameter. So my question is how do I convert the input stream to a FileInputStream?
A detailed solution would be appreciated as I am a junior developer, so I am still learning.
Many thanks.

From JavaDoc
A FileInputStream obtains input bytes from a file in a file system.
I would suggest two solutions:
The proper one is to change the API and to have InputStream as a parameter. I don't see a reason why you have FileInputStream in your API.
If you don't own the API and cannot change it I'm afraid you will need to save the InputStream to temp file and then create FileInputStream giving a path to this file (it's a suboptimal solution as you first write the file to disk - risking out of space - and then read it and streaming API is designed for reading / writing data on the fly)

If you are using org.apache.commons.fileupload.FileItem interface then your class is probably DefaultFileItem which is a subclass of DiskFileItem. So you can cast FileItem to DiskFileItem. then if you look at the source code of DiskFileItem you'll find that getInputStream() is actually returning a FileInputStream or a ByteArrayInputStream If you get a FileInputStream from DiskFileItem you can pass it directly to your other class. But if you get a ByteArrayInputStream you will have to write the contents to your own temporary file and then open another FileInputStream on this temp file. There is also another method DiskFileItem.getStoreLocation() which seem to return the server side File used for upload, but it may return null if the file is cached in memory.
In conclusion: you cannot be sure that there is going to be a server side file because the upload may be cached in memory. Therefore if you need a FileInputStream elsewhere you will have to create it yourself by creating a temp file. There is an example on how to pipe between two streams here.

//Pass file path/name directly to FileInputStream
FileInputStream input1 = new FileInputStream("input.txt");
//Save file path that has been passed in by the user, into a string variable.
String fileName = args[0];
//pass path to File object
File inputFile = new File(fileName);
//pass file object to FileOutputStream
FileOutputStream output = new FileOutputStream(inputFile);

Related

classLoader.getResourceAsStream returns an empty Stream in Testing

I have a method where I need to read a resource file and pass it to another method as an InputStream. The obvious approach
InputStream is = classLoader.getResourceAsStream("filename.pem");
works fine when actually running the application, but in testing it returns an empty InputStream (filled with zeros). I don't think its a problem with the resource path or anything, because when I use a nonsense path like "filex" (filex does not exist), I get an actual null pointer exception and not an empty stream. Also in debugger the complete file path of the empty Stream points to the correct path, where the file actually is stored (default class root).
Furthermore, with the following workaround it works:
File file = new File(classLoader.getResource("filename.pem").getFile());
String fileS= new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
InputStream is = classLoader.getResourceAsStream("filename.pem");
InputStream is2 = new ByteArrayInputStream(fileS.getBytes(StandardCharsets.UTF_8));
In this example is2 has the actual content of the file in the InputStream, while is has an Stream filled with zeros. I can't quite explain that behaviour. I double checked with 'getClass().getClassLoader().getClass()' if we use some modified ClassLoader in the Application, but it is the original one from sun.misc.Launcher$AppClassLoader.
So my questions are:
Why does the workaround work but not the classic approach?
Why does it fail only in test class?
Is there a way to make it work? The workaround is more lines of code and also need to catch IOException because of the Files.readAllBytes() call.
The only idea I had left: the encoding or charset has something to do with it. But to my knowledge there is no parameter in getResourceAsStream() like Charset or StandardCharsets.
If you open a resource file as a stream, you end up with a BufferedInputStream around a FileInputStream.
The call chain is as follows:
java.lang.ClassLoader#getResource returns an URL
url.openStream() is called
this first opens the Stream; sun.net.www.protocol.file.Handler#createFileURLConnection
then the Stream is connected: is = new BufferedInputStream(new FileInputStream(filename)); in sun.net.www.protocol.file.FileURLConnection#connect
finally you get this is back as InputStream
What you're seeing is the empty internal buffer of the BufferedInputStream, which will be used as soon as you start reading from the InputStream.
See is FileInputStream not buffered and why BufferedInputStream is faster?
If you for example read from the InputStream with all zero's, you will see it does actually contain data:
Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name());
String firstLine = scanner.next();
From https://www.baeldung.com/convert-input-stream-to-string
Your workaround works, because after you've located the file from the resource URL you actually start reading it directly.
So what might be failing in your test; are you not trying to read from the stream in your testcase? How are you using/validating if this inputstream is correct in your test vs the real application? There might be the problem.

How to delete the contents of a file using the FileOutputStream class in Java?

I'm working with the FileOutputStream class in java, but I don't know how to delete "the contents" of a file (the main reason i need overwrite the file).
If you want to delete the contents of the file, but not the file itself, you could do:
PrintWriter pw = new PrintWriter("file.txt");
pw.close();
A few seconds of Googling got me this:
how to delete the content of text file without deleting itself
How to clear a text file without deleting it?
To delete the file completely, do:
File file = new File("file.txt");
f.delete();
Call File.delete() which deletes the file or directory denoted by this abstract pathname.
File f = new File("foo.txt");
if (f.delete()) {
System.out.println("file deleted");
}
The main reason i need overwrite the file ...
One way to do this is to delete the file using File.delete() or Files.delete(Path). The latter is preferable, since it can tell you why the deletion fails.
The other way is to simply open the file for writing. Provided that you don't open in "append" mode, opening a file to write will truncate the file to zero bytes.
Note that there is a subtle difference in the behavior of these two approaches. If you delete a file and then create a new one, any other application that has the same file open won't notice. By contrast, if you truncate the file, then other applications with the file open will observe the effects of the truncation when they read.
Actually, this is platform dependent. On some platforms, a Java application that tries to open a file for reading that another file has open for writing will get an exception.
Yes, you can do it with FileOutputStream. All the answers given say about PrintWriter but the same can be done with FileOutputStream. The int representation of space is 32. So simply pass the file to the instance of FileOutputStream as:
FileOutputStream out = new FileOutputStream(file);
out.write(32);
This will clear the contents of the file. Surely use this only of u want to do it with FileOutputStream only otherwise use PrintWriter.

Need to convert AssetInputStream to FileInputStream

I have implemented a data structure which is working on my computer and now I am trying to port it into my android application. I open a raw .dat resource and get a InputStream but I need to get a FileInputStream:
FileInputStream fip = (FileInputStream) context.getResources().openRawResource(fileID);
FileChannel fc = fip.getChannel();
long bytesSizeOfFileChannel = fc.size();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0L, bytesSizeOfFileChannel);
...
The code above throws the following exception since an InputStream can not be cast to a FileInputStream but that's just what I need:
java.lang.ClassCastException: android.content.res.AssetManager$AssetInputStream cannot be cast to java.io.FileInputStream
All my code is build on using this FileChannel with a FileInputStream so I want to keep using it. Is there a way to go from having an InputStream from context.getResources().openRawResource(fileID) and then convert it into a FileChannel?
Somewhat relevant posts in which I could not find a working solution for my case which android:
How to convert InputStream to FileInputStream
Converting inputStream to FileInputStream?
Using FileChannel to write any InputStream?
A resource isn't a file. Ergo it can't be used as a memory-mapped file. If you have resources that are so enormous they need to be memory-mapped, they probably shouldn't be resources at all. And if they are small, memory mapping brings no advantages.
This might be late, but i think you can indirectly get a FileInputStream from an InputStream. what i suggest is this: get the input stream from resource, then create a temp file,get a FileOutputStream from it. read the InputStream and copy it to FileOutputStream.
now the temp file has the contents of your resource file, and now you can create a FileInputStream from this file.
I don't know if this particular solution is useful to you, but i think it can be used in other situations.
As an example, if your file is in the assets folder, you get an InputStream and then a FileInputStream using this method:
InputStream is=getAssets().open("video.3gp");
File tempfile=File.createTempFile("tempfile",".3gp",getDir("filez",0));
FileOutputStream os=newFileOutputStream(tempfile);
byte[] buffer=newbyte[16000];
int length=0;
while((length=is.read(buffer))!=-1){
os.write(buffer,0,length);
}
FileInputStream fis=new FileInputStream(tempfile);

Method to read XML file and parse it

How to read an XML file saved in the local folder and then use the stream object to parse it?
You can use a FileInputStream (see docs).
File file = new File("C:\\Temp\\myxml.xml");
InputStream stream = new FileInputStream(file)
If you need an URL, you can use file.toURI().toURL() or use a File-URL: file://C:/Temp/myxml.xml
Otherwise, directly go with the FileInputStream as suggest by Jeff.

Where does Java File instance store?

I have a question regarding to the Java File class. When I create a File instance, for example,
File aFile = new File(path);
Where does the instance aFile store in the computer? Or it stores in JVM? I mean is there a temp file stored in the local disk?
If I have an InputStream instance, and write it to a file by using OutputSteam, for example
File aFile = new File("test.txt");
OutputStream anOutputStream = new FileOutputStream(aFile);
byte aBuffer[] = new byte[1024];
while( ( iLength = anInputStream.read( aBuffer ) ) > 0)
{
anOutputStream.write( aBuffer, 0, iLength);
}
Now where does the file test.txt store?
Thanks in advance!
A File object isn't a real file at all - it's really just a filename/location, and methods which hook into the file system to check whether or not the file really exists etc. There's no content directly associated with the File instance - it's not like it's a virtual in-memory file, for example. The instance itself is just an object in memory like any other object.
Creating a File instance on its own does nothing to the file system.
When you create a FileOutputStream, however, that does affect whatever file system you're writing to. The File instance is relatively irrelevant though - you'd get the same effect from:
OutputStream anOutputStream = new FileOutputStream("test.txt");
It will write the file where you specify it with path arguement.
In your case, it will write it in the directory where you run your java class.
If you specify /test/myproject/myfile.txt
it will go in /test/myproject/myfile.txt
If you don't provide a path, it is in the current directory (ie: the directory where java.exe is executed from.) If you provide a full path, it is stored there.
Regardless, it is always stored in the filesystem, not in JVM memory.

Categories