My problem is in the following code.
The problem is that when I call the alreadyUser(String username) if the file doesn't exist on the system already, it gives the FileNotFoundException. I want to get over this error and I can not figure it out.
So at startup of the app the system asks for uname and pass. Then the alreadyUser method is called and it gives the error if the file is not already created hardly (I create it manually for example). And the next time I start the program if the file is already there it must not be switched with new, because the old data will be gone ofc :)
public final class TinyBase {
final static String FILENAME = "KEYVALUES.txt";
static FileOutputStream fos = null;
static FileInputStream fis = null;
protected static void createUser(String username, String password)
protected static boolean loadUser(String username, String password)
protected static boolean alreadyUser(String username) {
String encode = new String(username);
String compare = null;
boolean flag = false; // true - ok no such user ; false - fail username
// already in use
try {
/* ERROR IS HERE */
fis = new FileInputStream(FILENAME);
/* ERROR IS HERE */
byte[] buffer = new byte[fis.available()];
while (fis.read(buffer) != -1) {
compare = new String(buffer);
if (compare.contains(encode)) {
flag = true;
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fis.close();
return flag;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
Check if the file exists using -
File f = new File(filePathString);
if(f.exists()) { /* do something */ }
I guess, what you need according to your snapshot, is to handle FileNotFoundCase properly :
// ....
} catch (FileNotFoundException e) {
Log.d("no settings for the user - assuming new user");
flag = true;
}
BTW, you need to fix your finally block, in case of prior exception your fis may be null, so to avoid NullPointerException you may need an extra check :
if (fis != null) {
fis.close();
}
UPDATE
Here is sketch of what you may need based on my understanding of your problem :
// ... somewhere at startup after username/pass are given
// check if file exists
if (new File(FILENAME).isFile() == false) { // does not exist
fos = new FileOutputStream(FILENAME); // will create
// file for you (not subfolders!)
// write content to your file
fos.close();
}
// by this point file exists for sure and filled with correct user data
alreadyUser(userName);
Related
I have a method that sets a few properties using Java Properties if the config file does not exists in the local drive. However the bad thing I found out was even if I change a few properties in my code, the method just checks if the file exists and does not update the file with new properties.
The other condition is the user might have overwritten one of the property in the config file. So the method that sets the property should not overwrite the values on the config file with my code.
Here is what I did
private void setDefaultConfig() {
try {
if (!checkIfFileExists(configFile)) {
setProperty(configFile, "cfgFile", "cfg.xml");
setProperty(configFile, "type", "emp");
setProperty(configFile, "url", "www.google.com");
}
} catch (Exception e) {
e.printStackTrace();
}
}
setPropertyMethod just sets the property on the specified file.
Now if I add another property in my method the user won't get the new property because I'm just checking if the file exists.
For Eg : If the user changes the "url" property to have "www.yahoo.com" then my code in the setDefaultConfig method should not replace the value with "www.google.com"
Is there any method that can handle this situation?
protected void setProperty(String fileName, String property, String value) {
Properties prop = new Properties();
FileOutputStream fileOut = null;
FileInputStream fileIn = null;
try {
File file = new File(fileName);
if(checkIfFileExists(fileName)) {
fileIn = new FileInputStream(file);
prop.load(fileIn);
}
prop.setProperty(property, value);
fileOut = new FileOutputStream(fileName);
prop.store(fileOut, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (fileOut != null) {
try {
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I'm using this code to read value from a file.
public String getChassisSerialNumber() throws IOException
{
File myFile = new File("/sys/devices/virtual/dmi/id/chassis_serial");
byte[] fileBytes;
String content = "";
if (myFile.exists())
{
fileBytes = Files.readAllBytes(myFile.toPath());
if (fileBytes.length > 0)
{
content = new String(fileBytes);
}
else
{
return "No file";
}
}
else
{
return "No file";
}
return null;
}
I get this error:
java.nio.file.AccessDeniedException: /sys/devices/virtual/dmi/id/chassis_serial
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
at java.nio.file.Files.newByteChannel(Files.java:361)
at java.nio.file.Files.newByteChannel(Files.java:407)
at java.nio.file.Files.readAllBytes(Files.java:3149)
How I can handle this error? Because now I the code stops execution? Is there some better way without interruption the code execution?
You have to use try-catch, either within getChassisSerialNumber() on when calling it. E.g.
try {
getChassisSerialNumber();
} catch (java.nio.file.AccessDeniedException e) {
System.out.println("caught exception");
}
OR
try {
fileBytes = Files.readAllBytes(myFile.toPath());
} catch (java.nio.file.AccessDeniedException e) {
return "access denied";
}
This way your program does not terminate.
For a clean design you should either return null in cases you could not read the file (returning "magic strings like "No file" or "access denied" are no good design, because you cannot differentiate if this string came from the file or not) or catch the exception outside of the method (my first example).
Btw. by just putting the content of the file into the content variable you don't return it (i.e., replace content = new String(fileBytes); with return new String(fileBytes);)
public String getChassisSerialNumber()
{
File myFile = new File("/sys/devices/virtual/dmi/id/chassis_serial");
if (myFile.exists())
{
byte[] fileBytes;
try {
fileBytes = Files.readAllBytes(myFile.toPath());
} catch (java.nio.file.AccessDeniedException e) {
return null;
}
if (fileBytes != null && fileBytes.length > 0)
{
return new String(fileBytes);
}
}
return null;
}
You should catch the exception instead of throwing it. I think that you need to put a try-catch block around the call to the method getChassisSerialNumber.
Something like this should work in your case:
String result = null;
try {
result = getChassisSerialNumber();
} catch (java.nio.file.AccessDeniedException ex) {
// do something with the exception
// you can log it or print some specific information for the user
}
return result; // if the result is null, the method has failed
In order to understand better this kind of things you should have a look to this page
Okay, this is going to be a bit long. So I made a junit test class to test my program. I wanted to test if a method that uses a Scanner to read a file into the program threw and exception, if the file didn't exist like this:
#Test
public void testLoadAsTextFileNotFound()
{
File fileToDelete = new File("StoredWebPage.txt");
if(fileToDelete.delete()==false) {
System.out.println("testLoadAsTextFileNotFound - failed");
fail("Could not delete file");
}
try{
assertTrue(tester.loadAsText() == 1);
System.out.println("testLoadAsTextFileNotFound - passed");
} catch(AssertionError e) {
System.out.println("testLoadAsTextFileNotFound - failed");
fail("Did not catch Exception");
}
}
But the test fails at "could not delete file", so I did some searching. The path is correct, I have permissions to the file because the program made it in the first place. So the only other option would be, that a stream to or from the file is still running. So I checked the method, and the other method that uses the file, and as far as I can, both streams are closed inside the methods.
protected String storedSite; //an instance variable
/**
* Store the instance variable as text in a file
*/
public void storeAsText()
{
PrintStream fileOut = null;
try{
File file = new File("StoredWebPage.txt");
if (!file.exists()) {
file.createNewFile();
}
fileOut = new PrintStream("StoredWebPage.txt");
fileOut.print(storedSite);
fileOut.flush();
fileOut.close();
} catch(Exception e) {
if(e instanceof FileNotFoundException) {
System.out.println("File not found");
}
fileOut.close();
} finally {
if(fileOut != null)
fileOut.close();
}
}
/**
* Loads the file into the program
*/
public int loadAsText()
{
storedSite = ""; //cleansing storedSite before new webpage is stored
Scanner fileLoader = null;
try {
fileLoader = new Scanner(new File("StoredWebPage.txt"));
String inputLine;
while((inputLine = fileLoader.nextLine()) != null)
storedSite = storedSite+inputLine;
fileLoader.close();
} catch(Exception e) {
if(e instanceof FileNotFoundException) {
System.out.println("File not found");
return 1;
}
System.out.println("an Exception was caught");
fileLoader.close();
} finally {
if(fileLoader!=null)
fileLoader.close();
}
return 0; //return value is for testing purposes only
}
I'm out of ideas. Why can't I delete my file?
EDIT: i've edited the code, but still this give me the same problem :S
You have two problems here. The first is that if an exception is thrown during your write to the file, the output stream is not closed (same for the read):
try {
OutputStream someOutput = /* a new stream */;
/* write */
someOutput.close();
The second problem is that if there's an exception you aren't notified:
} catch (Exception e) {
if (e instanceof FileNotFoundException) {
/* do something */
}
/* else eat it */
}
So the problem is almost certainly that some other exception is being thrown and you don't know about it.
The 'correct' idiom to close a stream is the following:
OutputStream someOutput = null;
try {
someOutput = /* a new stream */;
/* write */
} catch (Exception e) {
/* and do something with ALL exceptions */
} finally {
if (someOutput != null) someOutput.close();
}
Or in Java 7 you can use try-with-resources.
Because the File object constructor needs a String to represent the path and considering other reasons, I chose to make a temporary file and when the user wants to save, to take the content of the temporary to the final file and ask the user to give the path at that time.
I have some code I will explain, but for many reasons, I think it's not one of the best solutions to do what I am trying to do.
public String FileSavePath() throws NullPointerException {
boolean acceptable = false;
String theFilepath = null;
do {
theFilepath = null;
File f = null;
JFileChooser FileChooser = new JFileChooser();
if (FileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
theFilepath = FileChooser.getSelectedFile().getAbsolutePath();
f = FileChooser.getSelectedFile();
//System.out.println(theFile);
if (f.exists()) {
int result = JOptionPane.showConfirmDialog(this, "The file exists, overwrite?",
"Existing file", JOptionPane.YES_NO_CANCEL_OPTION);
if (result == JOptionPane.YES_OPTION) {
acceptable = true;
}
}
} else {
acceptable = true;
}
} while (!acceptable);
saved=true;
return theFilepath;
}
And the method is called in the save function this way:
FileChannel sourceChannel=null;
FileChannel targetChannel=null;
try
{
try{
file=new File(FileSavePath());
}
catch(NullPointerException npe)
{
System.exit(0);
}
sourceChannel = new FileInputStream(temp).getChannel();
targetChannel = new FileOutputStream(file).getChannel();
targetChannel.transferFrom(sourceChannel, 0,
sourceChannel.size());
}
catch(IOException ioe)
{
System.out.println(ioe.getMessage());
}
finally
{
try {
if (sourceChannel != null) {
sourceChannel.close();
}
if (targetChannel != null) {
targetChannel.close();
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
Basically the mechanism is the following: All the data is saved to a temporary file. When the user wants to save, a JFileChooser appears and saves the path. Then the final file is iniatialized, the temporary data passed to the final file and that's it. The NPE is important to handle if the user did not chose a valid path or cancelled somewhere during the
What I am not sure of is if my code is efficent or if there were any ways to make it better.
P.S. Please don't bother telling that the exceptions are not handled yet, I know this, but I want to know if the basic idea would efficently do what is should.
I am wondering why I get this warning with the new eclipse Juno despite I think I correctly closed everything. Could you please tell me why I get this warning in the following piece of code?
public static boolean copyFile(String fileSource, String fileDestination)
{
try
{
// Create channel on the source (the line below generates a warning unassigned closeable value)
FileChannel srcChannel = new FileInputStream(fileSource).getChannel();
// Create channel on the destination (the line below generates a warning unassigned closeable value)
FileChannel dstChannel = new FileOutputStream(fileDestination).getChannel();
// Copy file contents from source to destination
dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
// Close the channels
srcChannel.close();
dstChannel.close();
return true;
}
catch (IOException e)
{
return false;
}
}
IF you're running on Java 7, you can use the new try-with-resources blocks like so, and your streams will be automatically closed:
public static boolean copyFile(String fileSource, String fileDestination)
{
try(
FileInputStream srcStream = new FileInputStream(fileSource);
FileOutputStream dstStream = new FileOutputStream(fileDestination) )
{
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
}
}
You won't need to explicitly close the underlying channels. However if you're not using Java 7, you should write the code in a cumbersome old way, with finally blocks:
public static boolean copyFile(String fileSource, String fileDestination)
{
FileInputStream srcStream=null;
FileOutputStream dstStream=null;
try {
srcStream = new FileInputStream(fileSource);
dstStream = new FileOutputStream(fileDestination)
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
} finally {
try { srcStream.close(); } catch (Exception e) {}
try { dstStream.close(); } catch (Exception e) {}
}
}
See how much better the Java 7 version is :)
You should always close in finally because if an exception rise, you won't close the resources.
FileChannel srcChannel = null
try {
srcChannel = xxx;
} finally {
if (srcChannel != null) {
srcChannel.close();
}
}
Note: even if you put a return in the catch block, the finally block will be done.
eclipse is warning you about the FileInputStream and FileOutputStream that you can no longer reference.