I'm new to Java and I'm porting one of my C++ libraries to Java as a learning experiment. This is not homework (as should be obvious from looking at my code). I have a few questions concerning the following code of my constructor for an ESRI shape file reader.
import java.io.*;
/**
*
* #author Bill
*/
public class ShapeFileReader {
public FileInputStream inStream;
/*
* #param fileName File name string. Must not be null or zero length.
* #throws Exception if file specified by fileName fails to open
*/
public ShapeFileReader(String fileName) throws IOException {
if(fileName == null)
throw new NullPointerException("fileName was null");
if(fileName.length() == 0)
throw new IllegalArgumentException("fileName string length was zero");
File fi = new File(fileName);
if(fi.exists() == false)
throw new IOException("File does not exist: " + fileName);
// Catch-or-specify (this method already throws IOException)
inStream = new FileInputStream(fileName);
}
}
During parameter validation and existence should I be throwing the exceptions as shown? The validation throws unchecked exceptions, and the existence throws checked exceptions. I assume that FileInputStream constructor will also throw an IOException, but I specified that in the method throws clause.
I was considering refactoring the opening of the file to a seperate function, but I figured it would be more useful and simple to do this in the constructor, and also learns me how to control errors here. Besides, any instance of this object will not have a closed/open state. All of these objects are reserved strictly for READING a file only, so they are created on a as-needed basis per file. I will provide a close() method seperately.
Also, from an extensibility point of view, would it be difficult to adapt to reading a file over a network using the FileInputStream with the current constructor? Or should I use a different class and multiple constructors?
Thanks for any and all input.
I wouldn't bother with the exceptions, FileInputStream will throw an exception for you, you're not adding anything other than clutter to your code.
For it to work with the network rather than just a file you'd modify thus:
public class ShapeFileReader {
private final InputStream inStream;
public ShapeFileReader(InputStream inStream) {
this.inStream = inStream;
}
/*
* #param fileName File name string. Must not be null or zero length.
* #throws Exception if file specified by fileName fails to open
*/
public ShapeFileReader(String fileName) throws IOException {
this(new FileInputStream(fileName));
}
Since this has been accepted as the answer I'm editing it as Roland (in the comments) is quite correct and this isn't how I'd have approached the problem.
public class ShapeReader {
public static Shape readShape(InputStream inStream) {
... do the work
}
/*
* #param fileName File name string. Must not be null or zero length.
* #throws Exception if file specified by fileName fails to open
*/
public static Shape readShape(String fileName) throws IOException {
FileInputStream fis = new FileInputStream(fileName);
try {
return readShape(fis);
} finally {
fis.close();
}
}
}
Related
I'm developing a java program that will read a file, for example; PSD file (example.psd), and I'll edit the bytes of the file. How can I call the adobe software and have it read the edited bytes through the java program without having to write out the file?
package sandbox;
import java.io.IOException;
public class Sandbox {
/**
* Example of how to run an executable from Java.
*
* #param args
*/
public static String readFileAsString(String fileName)throws Exception
{
String data = "";
data = new String(Files.readAllBytes(Paths.get(fileName)));
return data;
}
public static void main(String[] args) {
try {
Runtime runTime = Runtime.getRuntime();
String data = readFileAsString("C:\\Users\\pankaj\\Desktop\\example.psd");
String executablePath = "C:\\Users\\sdkca\\AppData\\Local\\Programs\\Adobe\\Adobe.exe";
Process process = runTime.exec(executablePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I can call the adobe, and also read the bytes, how would I tell the adobe to read the bytes?
Take a look here:
Java open file with another program
If there is a default opener for the file in the local OS, then that
Desktop.getDesktop().open(...)
may do the trick
Background: I am trying to parse XML into object using JAXB unmarshaller.
What I've done: I used JAXB itself to generate object classes and wrote some methods to unmarshal xml.
public void xmlParser() {
try {
Acquirer acquirer = (Acquirer) readXml(Constants.XML_PATH);
System.out.println(acquirer.getDate());
} catch (JAXBException | IOException e) {
e.printStackTrace();
}
}
/**
* Initializes of JAXB Context and Unmarshaller.
*/
private static void createContext() {
try {
jaxbContext = JAXBContext.newInstance("com.test.xml.generated");
unmarshaller = jaxbContext.createUnmarshaller();
} catch (JAXBException e) {
e.printStackTrace();
}
}
/**
* This reads the XML file from the resources in ClassPath.
*
* #param xmlFile XML file name as String with relative ClassPath
* #return Unmarashalled XML file
* #throws JAXBException
* #throws IOException
* #throws Exception
*/
public Object readXml(String xmlFile) throws JAXBException, IOException {
if (jaxbContext == null) {
createContext();
}
InputStream stream = getClass().getClassLoader().getResourceAsStream(xmlFile);
BufferedInputStream buffredStream = new BufferedInputStream(stream);
***Error:***
Object obj = unmarshaller.unmarshal(buffredStream);
buffredStream.close();
stream.close();
return obj;
}
Error is in Object obj.....
Exception:
javax.xml.bind.UnmarshalException - with linked exception:
[java.io.IOException: Stream closed]
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:246)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:125)
What I've managed to search: I used xml validator to validate xml and it seems fine. I also saw that someone suggested not to use InputStream and etc.. So I tried using File file = new File(); nothing. Moreover I tried to check auto generated object classes, but didn't find anything suspicious. #XmlElement and Root seems to be defined just fine.
P.S. I have xsd scheme of this xml (I generated all object classes using this xsd). I even used online tools to validate them both and everything seems right.
Constants.XML_PATH = "/Acquirer.xml";
Simply change:
InputStream stream = getClass().getClassLoader().getResourceAsStream(xmlFile);
on:
InputStream stream = getClass().getResourceAsStream(xmlFile);
Because when you use getClass().getClassLoader().getResourceAsStream(xmlFile) then it returns null (does not find the resource) and BufferedInputStream then throws the IOException when providing null instead of input stream instance into constructor.
Error in code:
If that train is removed then also show compiler error as below. I tried a lot to remove that and classify sentence as positive or negative.
An InputStreamFactory in not the same as an InputStream. Here is a simple bit of code that will create an InputStreamFactory for you. (You might say it is an InputStreamFactoryFactory :-) )
public static InputStreamFactory getInputStreamFactory(final File file) throws IOException{
return new InputStreamFactory() {
#Override
public InputStream createInputStream() throws IOException {
return new FileInputStream(file);
}
};
}
see javadocs: https://opennlp.apache.org/documentation/1.7.2/apidocs/opennlp-tools/opennlp/tools/util/InputStreamFactory.html
I have an application which throws this error (happens only with xlsx-files):
java.lang.NullPointerException
at java.io.File.<init>(File.java:222)
at de.mpicbg.tds.core.ExcelLayout.openWorkbook(ExcelLayout.java:75)
The method 'openWorkbook' looks like this:
private void openWorkbook() throws IOException {
File excelFile = new File(fileName);
timestamp = excelFile.lastModified();
// open excel file
if (fileName.endsWith(".xlsx")) {
InputStream excelStream = new BufferedInputStream(new FileInputStream(excelFile));
this.workbook = new XSSFWorkbook((excelStream));
} else {
this.workbook = new HSSFWorkbook(new POIFSFileSystem(new FileInputStream(excelFile)));
}
}
If I execute everything in debug mode, everything goes smoothly and the error message does not appear. I don't have any explanation for this behaviour nor any idea how to fix it.
Can anybody help?
The error message says your fileName is null
If you cannot reproduce this when debugging you can add a log message at the start of you method.
System.out.println("The fileName is `" + fileName+"`");
Instead of using a field which may or may not be set, I suggest you use a parameter.
private void openWorkbook(String fileName) throws IOException {
assert fileName != null;
Is there an existing way to have a FileInputStream delete the underlying file automatically when closed?
I was planning to make my own utility class to extend FileInputStreamand do it myself, but I'm kinda surprised that there isn't something already existing.
edit: Use case is that I have a Struts 2 action that returns an InputStream for file download from a page. As far as I can tell, I don't get notified when the action is finished, or the FileInputStream is not in use anymore, and I don't want the (potentially large) temporary files that are generated to be downloaded left lying around.
The question wasn't Struts 2 specific, so I didn't include that info originally and complicate the question.
There's no such thing in the standard libraries, and not any of the apache-commons libs either , so something like:
public class DeleteOnCloseFileInputStream extends FileInputStream {
private File file;
public DeleteOnCloseFileInputStream(String fileName) throws FileNotFoundException{
this(new File(fileName));
}
public DeleteOnCloseFileInputStream(File file) throws FileNotFoundException{
super(file);
this.file = file;
}
public void close() throws IOException {
try {
super.close();
} finally {
if(file != null) {
file.delete();
file = null;
}
}
}
}
I know this is a fairly old question; however, it's one of the first results in Google, and Java 7+ has this functionality built in:
Path path = Paths.get(filePath);
InputStream fileStream = Files.newInputStream(path, StandardOpenOption.DELETE_ON_CLOSE);
There are a couple caveats with this approach though, they're written up here, but the gist is that the implementation makes a best effort attempt to delete the file when the input stream is closed, and if that fails makes another best effort attempt when the JVM terminates. It is intended for use with temp files that are used solely by a single instance of the JVM. If the application is security sensitive, there are also a few other caveats.
Can you can use File.deleteOnExit() before opening the file ?
EDIT: On you can subclass a FileInputStream that will delete the file on 'close()';
class MyFileInputStream extends FileInputStream
{
File file;
MyFileInputStream(File file) { super(file); this.file=file;}
public void close() { super.close(); file.delete();}
}
I know this is an old question, but I just ran into this issue, and found another answer: javax.ws.rs.core.StreamingOutput.
Here's how I used it:
File downloadFile = ...figure out what file to download...
StreamingOutput so = new StreamingOutput(){
public void write(OutputStream os) throws IOException {
FileUtils.copyFile(downloadFile, os);
downloadFile.delete();
}
ResponseBuilder response = Response.ok(so, mimeType);
response.header("Content-Disposition", "attachment; filename=\""+downloadFile.getName()+"\"");
result = response.build();