I'm having some trouble when reading from a .config file in a Java application.
I have a module, let's call it Configuration_Reader that implements the next interface:
Interface
int getDelayValue();
int getRepValue();
...
For example, the getDelayValue() implementation is as follows:
Implementation
InputStream fis = new FileInputStream(
new File("").getAbsolutePath()+"/config/config.properties");
props.load(fis);
fis.close();
PropertyConfigurator.configure(props);
...
public int getDelayValue() {
return getIntProperty("delayValue");
}
There's no error nor exception when reading the value, but my issue is that if I update the value on the config file and call the getDelayValue() function again, it always returns the original value the property had when I launched the application. So, it is not updating (I assume it is not reading the file again) even if debugging I can see that the function is being called appropriately.
Any tips? Thanks in advance
You need to reload the config file to see the changes, i.e. this code
InputStream fis = new FileInputStream(
new File("").getAbsolutePath()+"/config/config.properties");
props.load(fis);
fis.close();
PropertyConfigurator.configure(props);
needs to run again, after the config has changed.
If you're using Java 7 you can use a WatchService to detect if the file has changed.
Another alternative would be to reload the config file every time a config value is accessed, but I wouldn't recommend this if the value is accessed frequently or concurrently from multiple threads.
Related
i'm developing an application that has to reboot the system after a file has been uploaded and verified. The file system is on an sd card, so it must be synced to be sure the uploaded file has actually been saved on the device.
I was wondering if java.io.file.Files.copy does the sync or not.
My code runs like this:
public int save(MultipartFile multipart) throws IOException {
Files.copy(multipart.getInputStream(), file, standardCopyOption.REPLACE_EXISTING);
if (validate(file)) {
sync(file); <-- is it useless?
reboot();
return 0;
} else {
Files.delete(file);
return -1;
}
}
I tried to find a way to call sync on the fs in the nio package, but the only solution that i've found is:
public void sync(Path file) {
final FileOutputStream fos = new FileOutputStream(file.toFile());
final FileDescriptor fd = fos.getFD();
fd.sync();
}
which relies on old java.io.File .
If you look at the source code for Files.copy(...), you will see that it doesn't perform a sync(). In the end, it will perform a copy of an input stream into an output stream corresponding to the first 2 arguments passed to Files.copy(...).
Furthermore, the FileDescriptor is tied to the stream from which it is obtained. If you don't perform any I/O operation with this stream, other than creating a file with new FileOutputStream(...), there will be nothing to sync() with the fie system, as is the case with the code you shared.
Thus, the only way I see to accomplish your goal is to "revert" to the old-fashioned java.io API and implement a stream-to-stream copy yourself. This will allow you to sync() on the file descriptor obtained from the same FileOutputStream that is used for the copy operation.
I'll say the copy operation is depending on your OS JRE code, so if you want to be sure of the file Copy at OS level, continue to explicitly call the sync() method.
This was because SYNC and DSYNC were annoyingly omitted from StandardCopyOption enum, yet were provided in StandardOpenOption enum for file targets, so you need to use FileChannel and SeekableByteChannel if supported by FileSystemProvider, like :
Set<? extends OpenOption> TARGET_OPEN_OPTIONS = EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
FileChannel.out = target.getFileSystem().provider().newFileChannel(target, TARGET_OPEN_OPTIONS);
SeekableByteChannel = Files.newByteChannel(source, StandardOpenOption.READ);
out.transferFrom(source, 0, source.size());
out.force(boolean metadata); // false == DSYNC, true == SYNC
Using java.io.FileOutputStream.getFD().sync() is an obsolete "solution", because you lose all support for NIO2 FileSystems, like the often bundled ZipFileSystem, and it can still fail if not supported by the native class implementations or OS!
Using DSYNC or SYNC when opening an OutputStream via a FileSystemProvider is another option, but may cause premature flushing of a FileSystem cache.
I decided to post a new question on this since none of the existing posts lead to me a solution. Mine is a Spring Boot application and here is the service:
public String fetchPrediction(MultipartFile file) throws IOException, InterruptedException {
File convFile = new File( System.getProperty("user.dir")+"/"+file.getOriginalFilename());
convFile.setWritable(true);
file.transferTo(convFile);
INDArray array = new CustomerLossPrediction().generateOutput(convFile);
Files.delete(Paths.get(convFile.getPath()));
return array.toString();
}
File deletion isn't happening and it gets stored at user home directory:
Found that the file is being used by the Java process. How can I delete this file once execution is completed? Is there a better approach here rather than writing to a file? Some of you would bring up writing to OutputStream here, but note that I need to work with MultipartFile in order to have file upload functionality.
I don't know if that's possible but I think you can rename the file to a randomly generated string then afterwards lock, read, unlock then delete the renamed file. In theory, another program could guess the filename and read the file just after it's unlocked but before it is deleted. But in practice, you'll probably be fine.
I am trying to open a file for reading or create the file if it was not there.
I use this code:
String location = "/test1/test2/test3/";
new File(location).mkdirs();
location += "fileName.properties";
Path confDir = Paths.get(location);
InputStream in = Files.newInputStream(confDir, StandardOpenOption.CREATE);
in.close();
And I get java.nio.file.NoSuchFileException
Considering that I am using StandardOpenOption.CREATE option, the file should be created if it is not there.
Any idea why I am getting this exception?
It seems that you want one of two quite separate things to happen:
If the file exists, read it; or
If the file does not exist, create it.
The two things are mutually exclusive but you seem to have confusingly merged them. If the file did not exist and you've just created it, there's no point in reading it. So keep the two things separate:
Path confDir = Paths.get("/test1/test2/test3");
Files.createDirectories(confDir);
Path confFile = confDir.resolve("filename.properties");
if (Files.exists(confFile))
try (InputStream in = Files.newInputStream(confFile)) {
// Use the InputStream...
}
else
Files.createFile(confFile);
Notice also that it's better to use "try-with-resources" instead of manually closing the InputStream.
Accordingly to the JavaDocs you should have used newOutputStream() method instead, and then you will create the file:
OutputStream out = Files.newOutputStream(confDir, StandardOpenOption.CREATE);
out.close();
JavaDocs:
// Opens a file, returning an input stream to read from the file.
static InputStream newInputStream(Path path, OpenOption... options)
// Opens or creates a file, returning an output stream that
// may be used to write bytes to the file.
static OutputStream newOutputStream(Path path, OpenOption... options)
The explanation is that OpenOption constants usage relies on wether you are going to use it within a write(output) stream or a read(input) stream. This explains why OpenOption.CREATE only works deliberatery with the OutputStream but not with InputStream.
NOTE: I agree with #EJP, you should take a look to Oracle's tutorials to create files properly.
I think you intended to create an OutputStream (for writing to) instead of an InputStream (which is for reading)
Another handy way of creating an empty file is using apache-commons FileUtils like this
FileUtils.touch(new File("/test1/test2/test3/fileName.properties"));
I am new to programming, I need help in understanding the difference between 2 ways of creating a fileinputstream object for reading files. I have seen examples on internet, some have used first one and others second one. I am confused which is better and why?
FileInputStream file = new FileInputStream(new File(path));
FileInputStream file = new FileInputStream(path);
Both are fine. The second one calls the first implicitly.
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
If you have a reference to the file which should be read, use the former. Else, you should probably use the latter (if you only have the path).
Don't use either in 2015. Use Files.newInputStream() instead. In a try-with-resources statement, at that:
final Path path = Paths.get("path/to/file");
try (
final InputStream in = Files.newInputStream(path);
) {
// do stuff with "in"
}
More generally, don't use anything File in new code in 2015 if you can avoid it. JSR 203, aka NIO2, aka java.nio.file, is incomparably better than java.io.File. And it has been there since 2011.
The FileInputStream Class has three constructors. Described in the official documentation:
FileInputStream(File file)
Creates a FileInputStream by opening a connection to an actual file, the file named by the File object file in the file system.
FileInputStream(String name)
Creates a FileInputStream by opening a connection to an actual file, the file named by the path name name in the file system.
FileInputStream(FileDescriptor fdObj)
Creates a FileInputStream by using the file descriptor fdObj, which represents an existing connection to an actual file in the file system.
As you see here there is no real difference.
Actually they both have the same way to open a file. The first constructor calls
SecurityManager.checkRead(File.getPath())
And the second one uses the same checkRead() as
SecurityManager.checkRead(name)
if you want use
FileInputStream file = new FileInputStream(new File(path));
for create FileInputStream need more time, if I don't mistake, because this constructor doing some checks with security manager
There is not much difference between the two , as
FileInputStream file = new FileInputStream(path)
implicitly calling other.
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
But to make better use of two available constructors, we can use constructor taking File argument when there is already a File object so we will be avoiding creation of another file object which will be created implicitly If we are using another constructor
Secondly, It is better to create FileinputStream object only after checking the existence of file which can be checked by using file.exists() in that case we can avoid FileNotFoundException.
I have to edit the existing file named root.propertis and update it without saving in to another file
Following is the sample proprety file.
root.label.getmore=Mehr Apps
root.msg.apps=Apps
root.label.2.2=Coupons
root.label.35.2=MSNBC
root.label.43.2=PBS Kids
root.label.47.2=Yahoo! Digest
I have to update the string in the file "root.label.43.2=PBS Kids" to "root.label.43.2=Updated"
But i need to save in the same file (root.propertis )by repalcing the string root.label.43.2=PBS Kids.No need to update the changes in another properties file.
Use java.util.Properties:
File f = new File("root.properties");
FileInputStream fis = new FileInputStream(f);
Properties p = new Properties();
p.load(fis);
fis.close();
p.setProperty("root.label.43.2", "Updated");
The call p.store() to save to a file.
Note exception handling has been omitted.
You could use the following sequence to change Properties load the properties with load(), setProperty(key,value) and finally call store() to write it back.
Reading and writing a .properties file can easily be achieved by using the Properties class (see javadoc).
So you can
Read the file into a Properties instance using the Properties#load method
Update the Properties instance using the Properties#setProperty method
Write the Properties to file using the Properties#store method