I'm trying to make a save function for a program I'm working on, and for some reason whenever I run it, it only gets past the first line of the try{} statement.
My code is as appears below.
public void saveGame() {
System.out.println("saveGame");
try
{
System.out.println("try saveGame");
BufferedWriter b = new BufferedWriter(new FileWriter("chardata.txt"));
System.out.println("try saveGame2");
String sp = System.getProperty("line.separator");
System.out.println("try saveGame3");
b.write("Miscellaneous char data here");
b.close();
}
catch(IOException ex)
{
System.out.println("File Writing Error");
}
}
When I run the program, the only lines that get printed are "saveGame" and "try saveGame." There is no "File Writing Error" either, it simply doesn't do anything after the "try saveGame" line. I'm not sure if this is relevant, but I am doing this from a computer at a school, which may have restricted permissions. Any kind of explanation and/or help would be much appreciated.
I think a better way to write your file would be using FileOutputStream and OutputStreamWriter.
Additionaly, you should move your b.close to a finally statement because if an exception is thrown before that b.close was executed, it never will be executed.
public void saveGame() {
System.out.println("saveGame");
try
{
System.out.println("try saveGame");
String path = "./chardata.txt"; //your file path
File file = new File(path);
FileOutputStream fsal = new FileOutputStream(file);
OutputStreamWriter osw = new OutputStreamWriter(fsal);
Writer w = new BufferedWriter(osw);
System.out.println("try saveGame2");
String sp = System.getProperty("line.separator");
System.out.println("try saveGame3");
w.write("Miscellaneous char data here");
}
catch(IOException ex)
{
System.out.println("File Writing Error");
}
finally{
if(w!=null)
w.close();
}
}
Related
I've had this error in the past but never fully understood it. After closing an OutputStream, regardless of the location of the java file or the manner in which it is called, completely screws up all sequential runs or attempts to write to another file, even if a different method of writing to a file is used. For this reason I avoid closing streams even though it is a horrible habit not to. In my program, I created was trying a test case that had a close statement which destroyed all of my previous streams, making it for some reason that they only write to files after the program has been terminated.
I kept the file location open and it writes the Text in the text file at the appropriate time, however the "Preview" panel in Windows does not detect it (which used to happen). Note that this all worked perfectly before the stream was accidentally closed. Is there a manner to reset the stream? I've tried flushing it during the process but is still does not run as it did prior.
Here is the method used to create the file:
protected void createFile(String fileName, String content) {
try {
String fileLoc = PATH + fileName + ".txt";
File f = new File(fileLoc);
if(!f.isFile())
f.createNewFile();
FileOutputStream outputStream = new FileOutputStream(fileLoc);
byte[] strToBytes = content.getBytes();
outputStream.write(strToBytes);
} catch (IOException e) {
e.printStackTrace();
return;
}
}
as well as the method used to read the file:
protected String readFile(String fileName) {
try {
StringBuilder sb = new StringBuilder("");
String fileLoc = PATH + fileName + ".txt";
File f = new File(fileLoc);
if(!f.exists())
return "null";
Scanner s = new Scanner(f);
int c = 0;
while(s.hasNext()) {
String str = s.nextLine();
sb.append(str);
if(s.hasNext())
sb.append("\n");
}
return sb.toString();
} catch(Exception e) {
e.printStackTrace();
return "null";
}
}
I'd be happy to answer any clarification questions if needed. Thank you for the assistance.
without try-resource, you need close in final clause to make sure no leak. Or use Stream.flush() if you need more 'in-time' update.
} catch (IOException e) {
e.printStackTrace();
return;
} finally {
outputStream.close();
}
You need to call flush() on the stream to write the bytes to the stream.
You're currently calling write() by itself, like this:
FileOutputStream outputStream = new FileOutputStream(fileLoc);
outputStream.write(content.getBytes());
What you want to do is this:
FileOutputStream outputStream = new FileOutputStream(fileLoc);
outputStream.write(content.getBytes());
outputStream.flush();
From the Javadoc (https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html#flush--) for OutputStream (where FileOutputStream is an OutputStream), this is what it says for flush():
Flushes this output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination.
Even better would be to close the stream in a finally block, so that no matter what your code always tries to free up any open resources, like this:
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(fileLoc);
outputStream.write(content.getBytes());
outputStream.flush();
} finally {
if (outputStream != null) {
outputStream.close();
}
}
or use automatic resource management, like this:
try (FileOutputStream outputStream = new FileOutputStream(fileLoc)) {
outputStream.write(content.getBytes());
outputStream.flush();
}
I'm trying to develop client-server connection between phone and pc using sockets. During the developing i met a problem and cannnot fix it yet. The problem is with outputstream. I use an ObjectoutputStream to send a String array to client and it works when I use this code:
try
{
// отправка пакета с файлами
DataInputStream dir = new DataInputStream(conn.getInputStream());
OutputStream dos = conn.getOutputStream();
ObjectOutputStream objectOutput = new ObjectOutputStream(dos);
byte messageType = dir.readByte();
switch(messageType) {
case 1:
try {
textArea.append("\nClient sends a command: " + dir.readUTF());
objectOutput.writeObject(results);
objectOutput.close();
} catch(Exception e) {
e.printStackTrace();
}
}
dir.close();
} catch (IOException e) {
......
but when I move ObjectOutputStream to the switcher:
try
{
// отправка пакета с файлами
DataInputStream dir = new DataInputStream(conn.getInputStream());
OutputStream dos = conn.getOutputStream();
byte messageType = dir.readByte();
switch(messageType) {
case 1:
try {
ObjectOutputStream objectOutput = new ObjectOutputStream(dos);
textArea.append("\nClient sends a command: " + dir.readUTF());
objectOutput.writeObject(results);
objectOutput.close();
} catch(Exception e) {
e.printStackTrace();
}
}
dir.close();
} catch (IOException e) {
....
my program freezes. I need to do like this, because i also need to do another commands, like sending and receiving files. Any solutions for this problem?
I've solved a problem. I just use BufferedReader & Writer for it, because it will be also used for transferring files.
So now code works fine and looks like this:
// отправка пакета с файлами
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), ENCODING));
String messageType = br.readLine();
switch(messageType) {
case "connect": {
List<String> results = new ArrayList<String>();
File[] files = new File("C:/Tenzor_Denis/ServerFiles/").listFiles();
//If this pathname does not denote a directory, then listFiles() returns null.
for (File file : files) {
if (file.toString().endsWith(".txt")) {
results.add(file.getName());
}
}
try {
for(int i = 0; i < results.size(); i++) {
bw.write(results.get(i));
bw.newLine();
//textArea.append(" " + results.get(i));
}
textArea.append("\nClient sends a command: " + messageType);
} catch(Exception e) {
e.printStackTrace();
}
bw.close();
br.close();
}
break;
}
}
Thx to all for answers.
Which line does it freeze on? It seems like reading from the input stream causes the output stream to block until everything is consumed. Look at the documentation for your conn object. What class is this? Perhaps moving the dir.readUTF() call before creating the ObjectOutputStream might solve it.
You can't do it either way. Closing the ObjectOutputStream will close the socket. You need to keep it open for the life of the socket. So moving it inside the case is futile anyway.
But your code doesn't make sense. You're writing with ObjectOutputStream, yet all you're reading from the peer is a single byte. If you're writing objects, you need to read objects, with an ObjectInputStream, not a DataInputStream, and when using both object input and output streams you must always construct the ObjectOutputStream first, at both ends to be safe.
Now I am getting compile time error at line 30 and 38 that 'fin' might not have been initialized. but its perfectly to write it this way
import java.io.*;
class CopyFile {
public static void main(String args[]) throws IOException {
int i;
FileInputStream fin;//can't it be done like this?
FileOutputStream fout= new FileOutputStream(args[1]);
try{
//open input file
try{
fin = new FileInputStream(args[0]);
}
catch(FileNotFoundException e){
System.out.println("Input file Not Found");
return;
}
//open output file
try{
fout = new FileOutputStream(args[1]);
}
catch(FileNotFoundException e){
System.out.println("Error Opening File");
}
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("usage: Copyfile From to");
}
try{
do{
i = fin.read();
if(i!= -1)
fout.write(i);
}while(i != -1);
}
catch(IOException e){
System.out.println("file error");
}
fin.close();
fout.close();
}
}
I have seen it many time initialized like this. I think its due to the try blocks.
it might miss the initialization due to being in the try block and hence the error?
The problem is that you're not initializing the FileInputStream fin at all. Your code will look like this to the compiler:
FileInputStream fin;
try {
fin = ...
//more code goes here...
} catch (...) {
//exception handling...
} finally {
fin.close(); //fin is not even null for the compiler
}
In order to make the code work, initialize it at least with a null value and check if fin != null before using the close method.
FileInputStream fin = null;
try {
fin = ...
//more code goes here...
} catch (...) {
//exception handling...
} finally {
if (fin != null) {
fin.close(); //fin is not null, at least the JVM could close it
}
}
More info:
Java: Declaring Variables
Uninitialized variables and members in Java
FileInputStream fin=null;
Assign it null or FileInputStream object.
Local variable need to be assigned to some value before being used.
Though in the first try block, you are initializing fin as fin = new FileInputStream(args[0]);, your nested statements confuse the compiler. Just update your declaration as below:
FileInputStream fin = null;
Dont use try catch for an if and vice versa.
Try/catch is for when things go wrong behind your control and that is no part of normal program flow for example writing to a hard disk that is full....
Use if for normal error checking
In your example check your args array with an if block and then initialize your fin.
private static void deleteProxy(File proxyOld, String host, int port) {
try {
String lines, tempAdd;
boolean removeLine = false;
File proxyNew = new File("proxies_" + "cleaner$tmp");
BufferedReader fileStream = new BufferedReader(new InputStreamReader(new FileInputStream(proxyOld)));
BufferedWriter replace = new BufferedWriter(new FileWriter(proxyNew));
while ((lines = fileStream.readLine()) != null) {
tempAdd = lines.trim();
if (lines.trim().equals(host + ":" + port)) {
removeLine = true;
}
if (!removeLine) {
replace.write(tempAdd);
replace.newLine();
}
}
fileStream.close();
replace.close();
proxyOld.delete();
proxyNew.renameTo(proxyOld);
} catch (Exception e) {
e.printStackTrace();
}
}
Calling the function:
File x = new File("proxies.txt");//is calling a new file the reason why it's being flushed out?
deleteProxy(x, host, port);
Before I run the program the file proxies.txt had data inside of it. However when I run the program it appears to be flushed out. It becomes empty.
I noticed while the program is running, if I move my mouse over the file proxies.txt, Windows displays the "Date Modified" and the time it displays is the current time, or last time the function deleteProxy(...) was executed.
Does anyone know what I'm doing wrong? And why won't the list update instead of appearing to be empty?
Updated code:
private static void deleteProxy(File proxyOld, String host, int port) {
try {
String lines, tempAdd;
boolean removeLine = false;
File proxyNew = new File("proxies_" + "cleaner$tmp");
FileInputStream in = new FileInputStream(proxyOld);
InputStreamReader read = new InputStreamReader(in);
BufferedReader fileStream = new BufferedReader(read);
FileWriter write = new FileWriter(proxyNew);
BufferedWriter replace = new BufferedWriter(write);
while ((lines = fileStream.readLine()) != null) {
tempAdd = lines.trim();
if (lines.trim().equals(host + ":" + port)) {
removeLine = true;
}
if (!removeLine) {
replace.write(tempAdd);
replace.newLine();
}
}
in.close();
read.close();
fileStream.close();
write.close();
replace.close();
if (proxyOld.delete()) {
throw new Exception("Error deleting " + proxyOld);
}
if (proxyNew.renameTo(proxyOld)) {
throw new Exception("Error renaming " + proxyOld);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Running the updated code it deletes proxies.txt just fine but it fails to make the new file:\
Maybe I should find a new method to update a text file, do you have any suggestions?
Your rename operation may not work, as per the File.renameTo() documentation:
Many aspects of the behavior of this method are inherently platform-dependent: The rename operation might not be able to move a file from one filesystem to another, it might not be atomic, and it might not succeed if a file with the destination abstract pathname already exists. The return value should always be checked to make sure that the rename operation was successful.
So basically, you're wiping your old file, and you're not guaranteed the new file will take its place. You must check the return value of File.renameTo():
if(proxyNew.renameTo(proxyOld)){
throw new Exception("Could not rename proxyNew to proxyOld");
}
As for why your renameTo may be failing: you're not closing the nested set of streams that you open to read from the old file, so the operating system may still consider an abstract pathname to exist. Try making sure you close all of the nested streams you open.
Try this:
FileInputStream in = new FileInputStream(proxyOld);
BufferedReader fileStream = new BufferedReader(new InputStreamReader(in));
...
in.close();
i am using the following code to write an array to the file:
FileWriter fstream1=new FileWriter("outx.txt");
BufferedWriter out1= new BufferedWriter(fstream1);
FileWriter fstream2=new FileWriter("outy.txt");
BufferedWriter out2= new BufferedWriter(fstream2);
for(int i=0;i<320*240;i++)
{
out1.write(0+System.getProperty("line.separator"));//
// out1.write("\n");
out2.write(0+System.getProperty("line.separator"));
//out2.write("\n");
}
: here in the above code i am putting all zeros
the file should be containing 76800 lines( 0s) but my file is having only 69932 lines.
what is the problem and if you can suggest some other way to do this.
Did you remember to close the output streams? Your example doesn't list the calls to close(), which should flush the streams as well. BufferedWriter's default behavior is to flush (write) its remaining contents before closing the stream it is buffering.
You should probably add:
out1.close();
out2.close();
It is a very common case when the end of a file is being cut off that you forgot to close the writer used to create the file, especially when you have used a BufferedOutputStream or BufferedWriter that may not flush its buffer (write it to the file) until it has been explicitly flushed (or more commonly, closed).
It is a very good habit to get into to immediately write the close() call after opening the stream, and then write all of your code for working with the stream between the calls. Taking exceptions into account, the standard calls use the following idiom:
Writer myOutWriter = null;
try {
myOutWriter = new BufferedWriter(new FileWriter("..."));
// Write to myOutWriter here
} catch (IOException ioe) {
// Handle any exceptions here
} finally {
try {
if (myOutWriter != null) {
myOutWriter.close();
}
} catch (IOException ioe) {
// Not much you can do here
}
}
The Apache Commons IO Project (http://commons.apache.org/io/) has a nice utility called IOUtils.closeQuietly() that cleans up the finally block by including the try catch, null check, and call to close into one method call. An example using that library would look like this:
Writer myOutWriter = null;
try {
myOutWriter = new BufferedWriter(new FileWriter("..."));
// Write to myOutWriter here
} catch (IOException ioe) {
// Handle any exceptions here
} finally {
IOUtils.closeQuietly(myOutWriter);
}
Add:
out1.flush();
out2.flush();
After the for loop.
It is likely that your program is exiting before the buffers in the BufferedReader have been flushed, a common problem with working with buffered output.
Edit: The more correct solution would be:
public static void main(String[] args) throws IOException {
final String outputString = "0" + System.getProperty("line.separator");
BufferedWriter out1 = null;
BufferedWriter out2 = null;
try {
out1 = new BufferedWriter(new FileWriter("outx.txt"));
out2 = new BufferedWriter(new FileWriter("outy.txt"));
for(int i = 0; i < 320 * 240; i++) {
out1.write(outputString);
out2.write(outputString);
}
out1.flush(); // Not really needed as close will flush, but it is
out2.flush(); // useful for describing the intent of the code
} finally {
closeQuietly(out1);
closeQuietly(out2);
}
}
private static void closeQuietly(Closeable c) {
try {
if (c != null) {
c.close();
}
} catch (Exception e) {
// No-op
}
}
As others have pointed out, it is likely that there is unflushed data in your buffers.
An acceptable way to rewrite your code would be like this:
Writer out1 = new FileWriter("outx.txt");
try {
out1 = new BufferedWriter(out1);
Writer out2 = new FileWriter("outy.txt");
try {
out2 = new BufferedWriter(out2);
for (int i = 0; i < 320 * 240; i++) {
out1.write(0 + System.getProperty("line.separator"));
out2.write(0 + System.getProperty("line.separator"));
}
} finally {
out2.close();
}
} finally {
out1.close();
}
This code:
will flush data via close
will always release file handles via close, even if an error occurs (by using finally)
obeys the contract for the Closeable classes
doesn't muck around with null or swallow exceptions