By using createNewFile method and delete method of the File class I successfully generate files from my program. But there is an annoying warning message after the compilation process. My question is how can I remove that warning messages without using #SUPPRESSWARNIGN. Because when I do inspection for my code I see a probable bug warnings which are caused by these 2 methods. Yes, by using #SuppressWarning warnings and probable bug messages go away.
I do not know if it is related with the Java version but in any case I am using Java 8. I did the research for this problem, could not find anything on the internet. I saw people on the internet used these 2 methods in the same way I used. May be they ignored the warning messages. But I do not want to.
Here is my code :
private void createAFile() throws IOException {
String outputFileName = getFileName();
String outputPathName = getFilePath();
String fullOutputPath = outputPathName + "/" + outputFileName;
output = new File(fullOutputPath);
if(output.exists()){
output.delete(); //this returns a boolean variable.
}
output.createNewFile(); //this also return a boolean variable.
}
Warnings are :
Warning:(79, 20) Result of 'File.delete()' is ignored.
Warning:(84, 16) Result of 'File.createNewFile()' is ignored.
Thank you
If you want to avoid these messages you can provide logging for the case when these method return false.
Something like this
private static Logger LOG = Logger.getLogger("myClassName");
// some code
if (!output.delete()) {
LOG.info("Cannot delete file: " + output);
}
These look like warnings generated from a code check tool . What i would do is this :
boolean deleted,created; // both should be instantiatd to false by default
if(output.exists()){
deleted = output.delete(); //this returns a boolean variable.
}
if(deleted){
created = output.createNewFile();
}
if(!deleted||!created){
// log some type of warning here or even throw an exception
}
Related
I am trying to write a unit test to test IOException handling in some code. I thought I would be able to create an IOException by removing permissions from a file and trying to delete it. But it looks like the file gets deleted anyway. 1st question is that the expected behavior? If so it seems like a big security hole to me. Second question is anyone have a suggestion on how to create an IOException on either of the two methods Files.delete() or commons.io FileUtils.deleteDirectory(). Following is the unit test code, I have tried both Files.delete on a file and FileUtils.deleteDirectory on a directory. In the latter case I get a fileNotFound exception. The second assertion always fails. Using a debugger I stopped the code and made sure the permissions on unwriteable were 000. I am running java 11 on Redhat 7.
public void testIOException() throws IOException {
binPath.toFile().mkdirs();
Path unwriteablePath = Paths.get(binPath.toString(), "unwriteable");
Path writeablePath = Paths.get(binPath.toString(),"writeable");
File unwriteable = unwriteablePath.toFile();
unwriteable.createNewFile();
File writeable = unwriteablePath.toFile();
writeable.createNewFile();
Assertions.assertTrue(unwriteable.exists());
Assertions.assertTrue(writeable.exists());
Set<PosixFilePermission> perms =
Files.readAttributes( unwriteablePath, PosixFileAttributes.class).permissions();
//make file unwriteable
perms.remove(PosixFilePermission.OWNER_WRITE);
perms.remove(PosixFilePermission.GROUP_WRITE);
perms.remove(PosixFilePermission.OTHERS_WRITE);
perms.remove(PosixFilePermission.OWNER_READ);
perms.remove(PosixFilePermission.GROUP_READ);
perms.remove(PosixFilePermission.OTHERS_READ);
Files.setPosixFilePermissions(unwriteablePath, perms);
Assertions.assertFalse(unwriteable.canWrite());
// Deleter deleter = new Deleter(mockConfig);
// deleter.run();
try {
Files.delete(Paths.get(unwriteable.getAbsolutePath()));
} catch (IOException e) {
System.out.println("Got expected exception");
}
Assertions.assertFalse(writeable.exists());
Assertions.assertTrue(unwriteable.exists());
}
}
I have written a function which takes in a BufferedImage and compares it to a pre-existing image in my hard drive checking if they are same or not.
public boolean checkIfSimilarImages(BufferedImage imgA, File B) {
DataBuffer imgAdata = imgA.getData().getDataBuffer();
int sizeA = imgAdata.getSize();
BufferedImage imgB = null;
try {
imgB = ImageIO.read(B);
} catch (IOException ex) {
Logger.getLogger(SupportClass.class.getName()).log(Level.SEVERE, null, ex);
}
DataBuffer imgBdata = imgB.getData().getDataBuffer();
int sizeB = imgBdata.getSize();
if(sizeA == sizeB) {
for(int i = 0; i < sizeA; i++) {
if (imgAdata.getElem(i) != imgBdata.getElem(i)) {
return false;
}
}
}
return true;
}
This throws IOException "Cant read input file". Idk why this is happening. I am calling the function like this...
while(support.checkIfSimilarImages(currentDisplay, new File(pathToOriginalImage)) == false) {
System.out.println("Executing while-loop!");
bot.delay(3000);
currentDisplay = bot.createScreenCapture(captureArea);
}
where,
String pathToOriginalImage = "C:\\Users\\Chandrachur\\Desktop\\Home.jpg";
I can see that the path is valid. But as I am testing it for File.exists() or File.canRead() or File.absoluteFile().exists() inside the checkIfSimilarImages function and everything is returning false.
I have researched my question here and tried out these suggestions:
It is not only for this location, I have tried a variety of other locations but in vain. Also it is not a problem where I have hidden file extensions and the actual file might be Home.jpg.jpg .
The only thing that might be is that permissions might be different. I dont really know how to verify this, but there is no reason it should have some permission which is not readable by java. It is just another normal jpg file.
Can it be because I am passing the file object reference into a function so in this process somehow the reference is getting modified or something. I just dont know. I am running out of possibilities to test for...
The whole stack trace is as follows:
javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1301)
at battlesbot.SupportClass.checkIfSimilarImages(SupportClass.java:77)
at battlesbot.AutomatedActions.reachHomeScreen(AutomatedActions.java:72)
at battlesbot.BattlesBot.main(BattlesBot.java:22)
Exception in thread "main" java.lang.NullPointerException
at battlesbot.SupportClass.checkIfSimilarImages(SupportClass.java:81)
at battlesbot.AutomatedActions.reachHomeScreen(AutomatedActions.java:72)
at battlesbot.BattlesBot.main(BattlesBot.java:22)
C:\Users\Chandrachur\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 11 seconds)
I am on Windows 10, IDE is NetBeans.
UPDATE:
Huge thanks to #k5_ . He told me to paste this in path and it worked.
"C:/Users/Chandrachur/Desktop/Home.jpg";
It seems some invisible characters were in the path. But I still don't understand what that means.
Usually this kind of problem lies with access problem or typos in the filename.
In this case there were some invisible unicode characters x202A in the filename. The windows dialog box, the file path was copied from, uses them for direction of writing (left to right).
One way of displaying them would be this loop, it has 4 invisible characters at the start of the String. You would also see them in a debugger.
String x = "C:\\Users\\Chandrachur\\Desktop\\Home.jpg";
for(char c : x.toCharArray()) {
System.out.println( c + " " + (int) c);
}
I have a situation where before I process an input file I want to check if certain information is setup in the database. In this particular case it is a client's name and parameters used for processing. If this information is not setup, the file import shall fail.
In many StackOverflow pages, the users resolve handling EmptyResultDataAccessException exceptions generated by queryForObject returning no rows by catching them in the Java code.
The issue is that Spring Integration is catching the exception well before my code is catching it and in theory, I would not be able to tell this error from any number of EmptyResultDataAccessException exceptions which may be thrown with other queries in the code.
Example code segment showing try...catch with queryForObject:
MapSqlParameterSource mapParameters = new MapSqlParameterSource();
// Step 1 check if client exists at all
mapParameters.addValue("clientname", clientName);
try {
clientID = this.namedParameterJdbcTemplate.queryForObject(FIND_BY_NAME, mapParameters, Long.class);
} catch (EmptyResultDataAccessException e) {
SQLException sqle = (SQLException) e.getCause();
logger.debug("No client was found");
logger.debug(sqle.getMessage());
return null;
}
return clientID;
In the above code, no row was returned and I want to properly handle it (I have not coded that portion yet). Instead, the catch block is never triggered and instead, my generic error handler and associated error channel is triggered instead.
Segment from file BatchIntegrationConfig.java:
#Bean
#ServiceActivator(inputChannel="errorChannel")
public DefaultErrorHandlingServiceActivator errorLauncher(JobLauncher jobLauncher){
logger.debug("====> Default Error Handler <====");
return new DefaultErrorHandlingServiceActivator();
}
Segment from file DefaultErrorHandlingServiceActivator.java:
public class DefaultErrorHandlingServiceActivator {
#ServiceActivator
public void handleThrowable(Message<Throwable> errorMessage) throws Throwable {
// error handling code should go here
}
}
Tested Facts:
queryForObject expects a row to be returned and will thrown an
exception if otherwise, therefore you have to handle the exception
or use a different query which returns a row.
Spring Integration is monitoring exceptions and catching them before
my own code can hand them.
What I want to be able to do:
Catch the very specific condition and log it or let the end user know what they need to do to fix the problem.
Edit on 10/26/2016 per recommendation from #Artem:
Changed my existing input channel to Spring provided Handler Advice:
#Transformer(inputChannel = "memberInputChannel", outputChannel = "commonJobGateway", adviceChain="handleAdvice")
Added support Bean and method for the advice:
#Bean
ExpressionEvaluatingRequestHandlerAdvice handleAdvice() {
ExpressionEvaluatingRequestHandlerAdvice advice = new ExpressionEvaluatingRequestHandlerAdvice();
advice.setOnFailureExpression("payload");
advice.setFailureChannel(customErrorChannel());
advice.setReturnFailureExpressionResult(true);
advice.setTrapException(true);
return advice;
}
private QueueChannel customErrorChannel() {
return new DirectChannel();
}
I initially had some issues with wiring up this feature, but in the end, I realized that it is creating yet another channel which will need to be monitored for errors and handled appropriately. For simplicity, I have chosen to not use another channel at this time.
Although potentially not the best solution, I switched to checking for row counts instead of returning actual data. In this situation, the data exception is avoided.
The main code above moved to:
MapSqlParameterSource mapParameters = new MapSqlParameterSource();
mapParameters.addValue("clientname", clientName);
// Step 1 check if client exists at all; if exists, continue
// Step 2 check if client enrollment rules are available
if (this.namedParameterJdbcTemplate.queryForObject(COUNT_BY_NAME, mapParameters, Integer.class) == 1) {
if (this.namedParameterJdbcTemplate.queryForObject(CHECK_RULES_BY_NAME, mapParameters, Integer.class) != 1) return null;
} else return null;
return findClientByName(clientName);
I then check the data upon return to the calling method in Spring Batch:
if (clientID != null) {
logger.info("Found client ID ====> " + clientID);
}
else {
throw new ClientSetupJobExecutionException("Client " +
fileNameParts[1] + " does not exist or is improperly setup in the database.");
}
Although not needed, I created a custom Java Exception which could be useful at a later point in time.
Spring Integration Service Activator can be supplied with the ExpressionEvaluatingRequestHandlerAdvice, which works like a try...catch and let you to perform some logic onFailureExpression: http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html#expression-advice
Your problem might be that you catch (EmptyResultDataAccessException e), but it is a cause, not root on the this.namedParameterJdbcTemplate.queryForObject() invocation.
As part of my plugin i have a clear chat command and at the end of the blank messages there is an option to display text. My problem is that the PlaceHolderAPI isn't working as it should.
Command Code:
if (label.equalsIgnoreCase("clearchat") || label.equalsIgnoreCase("mcc")) {
if (p.hasPermission("mystic.chat.admin.clearchat")) {
for (int i = 0; i < getConfig().getInt("clearChat.blankLines"); i++) {
Bukkit.broadcastMessage(" ");
}
for (String s : getConfig().getStringList("clearChat.endMessage")) {
s = PlaceholderAPI.setPlaceholders(p, s);
// This is here to check if the PlaceHolderAPI even knows there is place holders in it
p.sendMessage(String.valueOf(PlaceholderAPI.containsPlaceholders(s)));
Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', s));
}
return true;
} else {
p.sendMessage(ChatColor.RED + "You are lacking the required permission node!");
return true;
}
}
Config File section:
clearChat:
blankLines: 256
endMessage:
- '&bChat was cleared by %player_name%'
When i run the command "/mcc" or "/clearchat" it always says false (for not recognizing any placeholders) and none of the place holders are replaced.
I do have the API correctly in the build path, and the command words perfectly, other than the place holders not converting.
I feel as if im making a stupid mistake, or that im doing this the complete wrong way...
You shouldn't need to use another api using p.getName() should suffice then using String.replace to replace the %name%
You are using the API wrong
You did this
s = PlaceholderAPI.setPlaceholders(p, s);
If the API would throw an error if there are no placeholders just surround that line with a try{} catch (Exception e) then send it to the player
p.sendMessage(s);
There is no need for the String.valueOf(s) as the API [is expected to] return a String, anyways setting the String s = PlaceholderAPI.setPlaceholders(p, s); will cast whatever object is there to a string.
The filesystem AirportHDD is mounted (AFP) from the beginning and the file exists when I start this little program.
I tried to figure out the whole day why the following is not working, but couldnt find any solution:
public static void main(String[] arguments)
{
while(1==1)
{
File f=new File(
"/Volumes/AirportHDD/test/lock.csv");
System.out.println(f.exists());
AmySystem.sleep(100);
}
}
the output is:
true, true, ...
as soon as I remove the file from a different computer (AirportHDD is a mounted harddisk over network) then the output keeps saying:
true, true, ...
when I open the finder and goto this directory the output changes to: false, false, ...
when the file is added again (via another pc) the output is still:
false, false, ...
but if you open the finder again and click on the directory and finder shows the existing file, the output changes suddenly to: false, true, true, true, ...
NOTE:
also all other file operations like opening for read are failing as long as java 'thinks' the file is not there
if the program itself is creating and deleting the files then problem is not occurring
just found out while testing that with samba sharing everything is ok, but with AFP it just wont work
is there a way to tell java to do the same thing as finder, like a refresh, or do not try to cache, whatever?
I think you might be looking for the WatchService. Oracle was also kind enough to provide a tutorial.
Because the longevity of these links aren't guaranteed, I'll edit in an example code in a couple of minutes. I just wanted to let you know I think I found something in case you want to start looking at it for yourself.
UPDATE
Following the linked tutorial, I came up with code like this. I'm not sure it'll work (don't have time to test it), but it might be enough to get you started. The WatchService also has a take() method that will wait for events, which means you could potentially assume the file's existence (or lack thereof) based on the last output you gave. That will really depend on what this program will be interacting with.
If this works, good. If not, maybe we can figure out how to fix it based on whatever errors you're getting. Or maybe someone else will come along and give a better version of this code (or better option altogether) if they're more acquainted with this than I am.
public static void main(String[] arguments) {
Path path = Paths.get("/Volumes/AirportHDD/test/lock.csv");
WatchService watcher = FileSystems.getDefault().newWatchService();
WatchKey key = null;
try {
key = path.register(watcher,
ENTRY_CREATE,
ENTRY_DELETE);
} catch (IOException x) {
System.err.println(x);
}
while(true) {//I tend to favor this infinite loop, but that's just preference.
key = watcher.poll();
if(key != null) {
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind == OVERFLOW || kind == ENTRY_DELETE) {
System.out.println(false);
}
else if (kind == ENTRY_CREATE) {
System.out.println(true);
}
}//for(all events)
}//if(file event occured)
else {
File f=new File(path);
System.out.println(f.exists());
}//else(no file event occured)
AmySystem.sleep(100);
}//while(true)
}//main() method
Here is a JUnit test that shows the problem
The problem still happens using Samba on OSX Mavericks. A possible reason
is explaned by the statement in:
http://appleinsider.com/articles/13/06/11/apple-shifts-from-afp-file-sharing-to-smb2-in-os-x-109-mavericks
It aggressively caches file and folder properties and uses opportunistic locking to enable better caching of data.
Please find below a checkFile that will actually attempt to read a few bytes and forcing a true file access to avoid the caching misbehaviour ...
JUnit test:
/**
* test file exists function on Network drive
* #throws Exception
*/
#Test
public void testFileExistsOnNetworkDrive() throws Exception {
String testFileName="/Volumes/bitplan/tmp/testFileExists.txt";
File testFile=new File(testFileName);
testFile.delete();
for (int i=0;i<10;i++) {
Thread.sleep(50);
System.out.println(""+i+":"+OCRJob.checkExists(testFile));
switch (i) {
case 3:
// FileUtils.writeStringToFile(testFile, "here we go");
Runtime.getRuntime().exec("/usr/bin/ssh phobos /usr/bin/touch "+testFileName);
break;
}
}
}
checkExists source code:
/**
* check if the given file exists
* #param f
* #return true if file exists
*/
public static boolean checkExists(File f) {
try {
byte[] buffer = new byte[4];
InputStream is = new FileInputStream(f);
if (is.read(buffer) != buffer.length) {
// do something
}
is.close();
return true;
} catch (java.io.IOException fnfe) {
}
return false;
}
The problem is the network file system AFP. With the use of SAMBA everything works like expected.
Maybe the OS returns the wrong file info in OSX with the use of AFP in these scenarios.