Get file name from FileOutputStream
Asked Answered
S

5

46

Is there a way to get the file name from a FileOutputStream or from FileInputStream?

Stradivari answered 8/2, 2011 at 6:7 Comment(0)
F
35

Looks like the answer is no:
http://download.oracle.com/javase/1.4.2/docs/api/java/io/FileOutputStream.html
http://docs.oracle.com/javase/7/docs/api/index.html?java/io/FileOutputStream.html

There are no public methods that return the File or String used in construction of the stream.

EDIT: The same holds for FileInputStream.

Forecast answered 8/2, 2011 at 6:12 Comment(0)
U
16

This feature is not provided by the out-of-the-box File-Input/Output-Stream, but nothing stops you from writing your own subclass that stores the File (or fileName) and provides a getter for it.

I would suggest implementing some FileNameAware interface for this), as I/O Streams are usually referenced with the InputStream / OutputStream abstract classes to avoid coupling your application with specific implementations.

Untangle answered 8/2, 2011 at 6:31 Comment(0)
Z
15

Possible, with reflection: Tom G answer is correct, i.e. there is no API to get the path. However, if you are stuck like me with a framework you cannot change and cannot get the filename by any other mean, you can use reflection to get the path (in my case, I needed that for debugging purposes).

Field pathField = FileOutputStream.class.getDeclaredField("path");
pathField.setAccessible(true);
String path = (String) pathField.get(outputStream);

Obviously, the implementation of FileOutpuStream could change with time and this code could break. Also, I omitted the handling of exceptions in the snippet above for clarity purposes.

Not available in 1.6 and 1.7 Confirmed available in 1.8.

Zounds answered 6/11, 2015 at 17:35 Comment(5)
EJP, you are wrong. There is such a field. I just tested it under Java 1.8.0_112-b16. Full code here:Zounds
import java.io.FileOutputStream; import java.lang.reflect.Field; public class FileOutputStreamTest { public static void main(String args[]) throws Exception { FileOutputStream outputStream = new FileOutputStream("./FileOutputStreamTest.java"); Field pathField = FileOutputStream.class.getDeclaredField("path"); pathField.setAccessible(true); String path = (String) pathField.get(outputStream); System.out.println("path=" + path); } }Zounds
Beside, this is not the point. Your down voting is totally out of place. If "path" would not be there, there would be another field with a different name that would do the same. My point is that it is possible to fetch the information using reflection, though it is not recommended.Zounds
OK, not in JDK 1.6 or .7. And why would there be another field? It doesn't need the path outside the constructor. JDK 1.6 didn't need it.Catfall
EJP, I believe you are right. I checked the code in 1.7 and it is not there. The path name is transient and used to be not required to persist. Starting with 1.8, it is stored in the variable "path", but I have not checked the code to find out why the do this. I stand half corrected and I am glad that we have this "bonus" in 1.8 as it helped me debug my issues. Thank you for your input.Zounds
R
3

This is not possible, even in principle. The assumption of the question is that each file input stream is associated with one file that has one name. The latter assumption is wrong, for POSIX systems. For POSIX systems, a file can have any number of names (hard links), including zero. The case of zero names is quite common for temporary files, to ensure that the temporary file is removed on program exit.

I've written plenty of file IO code, and never needed this functionality. That you are asking for it suggests you have a design flaw. That is, you have an XY problem.

  • There is almost no reason for code to declare the class of a reference to a stream object to be a file stream. IO code can use an InputStream or OutputStteam. Indeed, it should, as part of programming to an interface, and to enable cheap unit testing of your IO code (by enabling use of a simple byte array stream as a mock object).
  • Are you perhaps hoping to use the filename in some log messages? If so, that suggests you are trying to log file IO errors too low in your program hierarchy. Perhaps you are catching IOExceptions too "early", rather than letting them propagate to higher parts of your program, which know that the IO is file IO and know the name of the file.
Runthrough answered 20/11, 2016 at 9:26 Comment(1)
Yes it would be possible in principle and in practice. After all the stream was created pointed at a particular file. Just return that and you're setCosimo
J
2

My answer comes a little late. I hit the same issue when writing some code.

To get around it, I used a FileOutputStream(File file) instead of FileOutputStream(String location) because I can then do file.getAbsolutePath(). See the example snippet below.

String location = "some.relative.path.txt";
File file = new File(location);
FileOutputStream f = new FileOutputStream(file);
String question = "<h3>"+header+"</h3>";
String finalSource = HTMLWrapper.HTML_START+question +htmlContent;
f.write(finalSource.getBytes());
f.flush();
f.close();
System.out.println("The report is now available at"+file.getAbsolutePath());
Jegger answered 28/2, 2014 at 8:6 Comment(1)
Maybe because the File(Out/In)putStream did not matter here as you hold the File. If the method only return a Stream, you have no chance (with direct FileInputStream use) to retrieve the underlying File or the locationNewsworthy

© 2022 - 2024 — McMap. All rights reserved.