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.
Related
I want to create a file (outside of the workspace) so that everyone who opens my program has his own Textfile.
Currently I have to following Code:
private static final File m_dataFile = new File("C:\\temp\\MainPlayersLoginData.txt");
private static FileWriter writer;
private static Scanner reader;
public static void setMainPlayersLoginData(String name, String password) {
try {
if (!m_dataFile.exists()) {
createDirectory();
}
writer = new FileWriter(m_dataFile);
writer.write(name + "\n" + password);
writer.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void createDirectory() {
System.out.println("creating directory: " + m_dataFile.getName());
boolean result = false;
try {
m_dataFile.mkdirs();
result = true;
} catch (SecurityException se) {
}
if (result) {
System.out.println("DIR created");
}
}
With this code, the program creates a folder temp as planned, but creates a folder named "MainPlayersLoginData.txt" in it instead of a textfile. In addition I get a FileNotFoundException with the message "Access denied" when initialising the FileWriter.
I tried using m_datafile.mkdir() instead of m_datafile.mkdirs() but this time I get a FileNotFoundException with the message "The system cannot find the specified path" and the folder temp isnt created.
Edit: If i create the folder and the Textfile on my own, everything works fine.
I am writing a file into a directory. There might be the chance that the directory becomes unreachable.
What I want to do is..
As the code is writing to the file, if the directory becomes unreachable or a file not found exception is thrown I want it to keep checking if the directory exists and continue where I left off after the directory exists again.
After some time if the directory does not come back up then I would shut the program down.
My problem is that when a file not found exception is thrown the program just shuts down all together. Here is my code:
public class BusStopsProcessor implements Runnable
{
private BlockingQueue<Bus<buses>> busQueue;
private Bus<buses> BusObject;
public BusStopsProcessor(BlockingQueue<Bus<buses>> busQueue)
{
this.busQueue = busQueue;
}
#Override
public void run()
{
try
{
String path = "C:\\Users\\Me\\Documents\\";
File file = new File(path + "busStopsFile.txt");
FileWriter fw = new FileWriter(file, true);
CSVWriter writer = new CSVWriter(fw, '|', CSVWriter.NO_QUOTE_CHARACTER);
while(true)
{
BusObject = busQueue.take();
//each bus object should have a bus date if it does not then it is a
//poison bus object.
if(BusObject.getBusDate() != null)
{
createBusFile(BusObject, writer);
else
{
try
{
//Finished processing bus stops so close writer.
writer.close();
fw.close();
break;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
e.printStackTrace();
}
catch (FileNotFoundException e)
{
//If a FILENOTFOUND exception is thrown here I want
//my code to be able to pick up where I left off
e.printStackTrace();
logger.warn(e.getMessage());
}
catch (IOException e)
{
e.printStackTrace();
}
}
Here is the method that I want to keep checking if the directory exists. If the file is being written into and all of a sudden the directory goes down. I dont want to repeat the same information in the file I want it to continue to write from where it left off but I just cant figure out how to do that. thank you.
private void createBusFile(Bus<buses> aBusObject, CSVWriter writer) throws InterruptedException
{
//Get bus information here
for(Bus<buses> busStop : aBusObject.getBusStops())
{
busNumber = busStop.getBusNumber();
busArrivalTime = busStop.getBusArrivalTime();
busStop = busStop.getBusStop();
String[] busFields = {busNumber, busDate, busStop};
//If a file not found exception is thrown here I want it to keep checking if the directory exists. And pick up from where I left off
writer.writeNext(busFields);
}
}
}
I'm working on appending objects to a binary file. My professor has provided an "appendable" output stream class for us to use on this assignment, and from my understanding this is what should prevent a corrupted header. However, I'm still getting a corrupted header when I attempt to open the binary file. The name of the file is test.dat and as far as I can tell the program writes the data just fine, but as soon as I try reading from it everything goes out the window.
fileName is a data field in the same class these methods are defined in and is defined as follows File filename = new File("test.dat");
If anyone could point me in the right direction that would be fantastic! Thanks in advance
My Code
/**
Writes a pet record to the file
#param pets The pet record to write
*/
public static void writePets(PetRecord pet){
AppendObjectOutputStream handle = null;
try{
handle = new AppendObjectOutputStream(new FileOutputStream(fileName, true));
handle.writeObject(pet);
handle.flush();
} catch (IOException e){
System.out.println("Fatal Error!");
System.exit(0);
} finally {
try{
handle.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
/**
Reads all pets from the file so long as the user continues to enter "next"
*/
public static void readPets(){
Scanner keys = new Scanner(System.in);
String input = "";
ObjectInputStream handle = null;
PetRecord pet = null;
try{
handle = new ObjectInputStream(new FileInputStream(fileName)); // stack trace points here
do{
try{
pet = (PetRecord) handle.readObject();
System.out.println("\n" + pet);
System.out.println("[*] type \"next\" to continue");
input = keys.nextLine();
} catch (IOException e){
System.out.println("\t[*] No More Entries [*]");
e.printStackTrace();
break;
}
} while (input.matches("^n|^next"));
handle.close();
} catch (ClassNotFoundException e){
System.out.println("The dat file is currupted!");
} catch (IOException e){
System.out.println("\t[*] No Entries! [*]");
e.printStackTrace();
}
}
Provided class:
public class AppendObjectOutputStream extends ObjectOutputStream
{
// constructor
public AppendObjectOutputStream( OutputStream out ) throws IOException
{
// this constructor just calls the super (parent)
super(out);
}
#Override
protected void writeStreamHeader() throws IOException
{
// this forces Java to clear the previous header, re-write a new header,
// and prevents file corruption
reset();
}
}
Stack Track:
java.io.StreamCorruptedException: invalid stream header: 79737200
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:808)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:301)
at UIHandle.readPets(UIHandle.java:381)
at UIHandle.list(UIHandle.java:79)
at UIHandle.command(UIHandle.java:103)
at UIHandle.mainUI(UIHandle.java:40)
at UIHandle.main(UIHandle.java:405)
Turns out it helps if you make sure a file exits before appending to it.
The problem wasn't with reading the file, but attempting to append to a file when it wasn't there. The fix was a simple if/else to check to see if the file existed. If it doesn't exist then write the file as usual, if it does exist then use the custom append class.
/**
Writes a pet record to the file
#param pet The pet record to write
*/
public static void writePet(PetRecord pet){
if (fileName.exists()){
AppendObjectOutputStream handle = null;
try{
handle = new AppendObjectOutputStream(new FileOutputStream(fileName, true));
handle.writeObject(pet);
handle.flush();
} catch (IOException e){
System.out.println("Fatal Error!");
System.exit(0);
} finally {
try{
handle.close();
} catch (IOException e){
e.printStackTrace();
}
}
} else {
ObjectOutputStream handle = null;
try{
handle = new ObjectOutputStream(new FileOutputStream(fileName));
handle.writeObject(pet);
handle.flush();
} catch (IOException e){
System.out.println("Fatal Error!");
System.exit(0);
} finally {
try{
handle.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
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);
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.