I am defining a buffered writer in a class I am developing, but having problems with it.
In the class constructor I am defining:
public class RestHandler {
public static BufferedWriter rest_logger;
public RestHandler(parsedXMLConfigData _config, BufferedWriter writer) {
rest_logger = writer;
try {
rest_logger.write("RestHandler instance finished init and ready to receive calls!" + "\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
This works and prints the text to my file. But when I try to use the same rest_logger in another one of my class methods:
#POST
#Path("{subResources: [a-zA-Z0-9_/]+}")
public void postHandler
(
#Context final UriInfo uriInfo,
#PathParam("subResources") String subResources) {
try {
rest_logger.write("TEXT...");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
It gives me a stream closed exception! I should mention that I use this to close the stream:
protected void finalize() throws Throwable {
rest_logger.close();
}
There are several problems with your code:
the rest_logger variable should not be static
you shouldn't initialize it to a new BufferedWriter just to discard it afterwards and reinitialize it with the writer argument (that you have no control on)
you shouldn't ignore exceptions. If you don't know what to do with them, make your methods throw IOException and let the caller decide what to do
you should not use finalizers
you should not close a writer that you have not created. Let the opener of the writer close it.
Other than that, and since your code doesn't make much sense, it's hard to understand what the code is supposed to do.
Removing the exception handlers for clarity, your code does:
rest_logger = new BufferedWriter(new FileWriter("rest_logger.txt"));
rest_logger = writer;
You're throwing away that new BufferedWriter immediately there. It does not make much sense. rest_logger will be set to whatever was handed over to you in that constructor call. When that gets closed, rest_logger will be closed too.
I'm not quite sure I understood your question, BUT:
why exactly are you overwriting your newly created BufferedWriter?
rest_logger = writer;
maybe you should look into that...
Related
Hope someone can shed some light into what I'm doing wrong.
I have a DataLoader class that creates a FileInputStream. Since FileInputStream implements Closeable, I create that instance as part of the try block.
I then pass the newly created stream to a DataManager class. This class opens a file channel and reads data into a singleton class, storing all data into memory blocks. Since FileChannel also implements Closeable, I also instanciate it in the try block
I then invoke this code from a single thread to check every now if there are any filechanges, and when this happens, a new instance of DataLoader is created to rebuild the memory blocks. But this constantly fails due to file locking. This code is part of a Java 1.8 standard application, running on windows 10. Am I assuming wrongly that both file channel and file inputstream close? I added code to invoke the close method in both classes, but with no success. Any help would be greatly appreciated. Thanks in advance.
public class DataManager {
public DataManager(FileInputStream in) throws IOException {
fromInputStream(in);
}
public final void fromInputStream(FileInputStream in) throws IOException {
try (FileChannel ch = in.getChannel()) {
MappedByteBuffer mb = ch.map(MapMode.READ_ONLY, ch.position(), ch.size());
readData(mb); //reads mapped buffer into a byte array, e.g.: mb.get(barray, 0, 1000);
}
}
}
public class DataLoader {
public DataLoader(File binFile) throws FileNotFoundException, IOException {
try (FileInputStream in = new FileInputStream(binFile)) {
DataManager d = new DataManager(in);
} catch (Exception e) {
LOG.error("Something went wrong while loading data.", e);
}
}
}
As suggested in the comments, the issue relies on windows being somewhat stringent regarding the use of FileChannel. I replaced all FileChannel related code with InputStream and the locking behavior disappeared.
I have a sample code here. Will the FileInputStream created by the function, get automatically closed when the code exists the try/catch block of parentFunction ?
Or does it need to be explicitly closed in the someOtherFunction() itself ?
private void parentFunction() {
try {
someOtherFunction();
} catch (Exception ex) {
// do something here
}
}
private void someOtherFunction() {
FileInputStream stream = new FileInputStream(currentFile.toFile());
// do something with the stream.
// return, without closing the stream here
return ;
}
You have to use the resource with try-with-resource block.
Please read docs for AutoCloseable interface: https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header.
It needs to either be explicitly closed in the someOtherFunction() method, or used in a try-with-resources block:
private void someOtherFunction() {
try (FileInputStream stream = new FileInputStream(currentFile.toFile())) {
// do something with the stream.
} // the stream is auto-closed
}
I've been working on a small bit of code and though the rest of the code works, there is an error with the logging system that I've written.
When the method log(String) is called, it throws a NullPointerException.
I thought this might be because the file might not be being created, but I'm not sure what I've done wrong and as far as I can tell the file should be being created (It's not) and even if I create the file and put it into the correct position, the exception is still thrown.
I've been tinkering around with it a bit, so some of it doesn't make sense, it's probably because it was while I was debugging.
Here's the code:
package UI;
import java.io.File;
import java.io.PrintWriter;
public class InputLogger {
//Necessary for interceptor pattern
private static PrintWriter output;
//For testing remove later
private static File logFile;
public InputLogger() {
initiate("log.txt");
}
public InputLogger(String anotherFile) {
initiate(anotherFile);
}
public void initiate(String filename) {
try {
/*File */logFile = new File(filename);
if(!logFile.exists()) {
if(!logFile.createNewFile())
System.err.println("Error creating log file. Please verify that files can be created.");
}
output = new PrintWriter(logFile);
} catch (Exception e) {
System.err.println("Error accessing log file. Please verify that files can be created.");
}
}
public static void log(String action) {
try {
output.println(action);
} catch (Exception e) {
e.printStackTrace(System.out);
System.err.println("Error printing to log file. Please verify that file exists or can be created.");
}
}
public void close() {
output.close();
}
}
I think it might have something to do with the fact that I call it as a static method, but I've been looking around and I can't seem to find an explanation elsewhere.
Edit:
I forgot to actually create an InputLogger object. Thanks guys.
Most likely you forgot to create an InputLogger object. Do this:
InputLogger logger = new InputLogger();
InputLogger.log( "hoooey" );
logger.close();
Not calling close may lose a line or two.
Mixing static with a constructor and proper methods is dangerous, and an antipattern. You might remain with static, with a lazy initialization which gives your program the chance to set the file name. Or, better, avoid the statics and do all in proper methods.
In the method initiate you initialize the output, but in your static method log it's not guaranteed to have been initialized before calling since.
To be safe you should always initialize the required static variables either in the static method or as a field declaration.
In this case in your initiate it is possible to throw an exception prior to the line output = new PrintWriter(logFile) which means output is null
Will this release my resources after being used?
InputStream inputStream;
try (InputStream unverifiedStream = connection.getInputStream()){
inputStream = unverifiedStream;
} catch (Exception e) {
e.printStackTrace();
}
//and use stream here to do other stuff with other streams
That will release your resources (close the stream) and leave you talking to a closed stream.
The assignment to inputStream does not copy the stream object. It copies the reference to the stream object. You now have two different ways to talk to the same object.
Since you are using a try-with-resource statement, and if by "released" you mean "closed" then yes.
Any instance implementing AutoCloseable opened in a try-with-resources statement is .close()d right before catch, so in your case unverifiedStream will be closed before you catch Exception.
It should also be noted that Closeable extends AutoCloseable, so all existing classes implementing Closeable will "magically" work within a try-with-resources statement.
Sample code:
public final class AutoCloseableExample
{
private static final class Foo
implements AutoCloseable
{
#Override
public void close()
throws IOException
{
System.out.println("foo");
throw new IOException();
}
}
public static void main(final String... args)
{
try (
final Foo foo = new Foo();
) {
System.out.println("try block");
} catch (IOException ignored) {
System.out.println("exception!");
} finally {
System.out.println("finally block");
}
}
}
Output:
try block
foo
exception!
finally block
Side note: you should not catch Exception since this also catches all unchecked exceptions (ie, RuntimeException and derivates). Catch more specific exceptions instead.
I haven't tried this, but I don't think it will compile if you try to use inputStream after the try-catch block, because inputStream won't be initialized if connection.getInputStream() throws an exception. Your catch block should assign a value or introduce a different flow of control to take care of that possibility.
If the try block completes normally, inputStream will refer to a closed stream outside the try-catch block, and most implementations will throw an exception on any operation you attempt on the stream.
Is it good to use synchronised on java.io.File Object. When you want to alternatively read and write that File Object using two threads: one for reading and one for writing.
public class PrintChar {
File fileObj;
public void read() {
while (true) {
synchronized (this) {
readFile();
notifyAll();
try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ " throws Exception");
e.printStackTrace();
}
}
}
}
public void write(String temp) {
while (true) {
synchronized (this) {
writeFile(temp);
notifyAll();
try {
wait();
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ " throws Exception");
e.printStackTrace();
}
}
}
}
public void setFileObj(File fileObj) {
this.fileObj = fileObj;
}
public void readFile() {
InputStream inputStream;
try {
inputStream = new FileInputStream(fileObj);
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(inputStream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println(strLine);
}
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeFile(String temp) {
BufferedWriter bw;
try {
bw = new BufferedWriter(new FileWriter(fileObj, true));
bw.write(temp);
bw.newLine();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
final PrintChar p = new PrintChar();
p.setFileObj(new File("C:\\sunny.txt"));
Thread readingThread = new Thread(new Runnable() {
#Override
public void run() {
p.read();
}
});
Thread writingThread = new Thread(new Runnable() {
#Override
public void run() {
p.write("hello");
}
});
Thread Randomizer = new Thread(new Runnable() {
#Override
public void run() {
while (true)
try {
Thread.sleep(500000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ " throws Exception");
e.printStackTrace();
}
}
});
readingThread.start();
writingThread.start();
Randomizer.start();
}
}
In the code above I have used Synchronised(this), Can i use Synchronise(fileObj)??
One More solution I have got from one of my professors is to encapsulate the read and write in objects and push them in a fifo after every operation, if anybody elaborate on this
Edit:
Now that you have added your code, you can lock on fileObj but only if it is not changed. I would move it to the constructor and make it final to make sure that someone doesn't call setFileObj inappropriately. Either that or throw an exception if this.fileObj is not null.
Couple other comments:
Don't use notifyAll() unless you really need to notify multiple threads.
If you catch InterruptedException, I'd quit the thread instead of looping. Always make good decisions around catching InterruptedException and don't just print and loop.
Your in.close(); should be in a finally block.
You can lock on any object you want as long as both threads are locking on the same constant object. It is typical to use a private final object for example:
private final File sharedFile = new File(...);
// reader
synchronized (sharedFile) {
// read from file
}
...
// writer
synchronized (sharedFile) {
// write to file
}
What you can't do is lock on two different File objects, even if they both point to the same file. The following will not work for example:
private static final String SHARED_FILE_NAME = "/tmp/some-file";
// reader
File readFile = new File(SHARED_FILE_NAME);
synchronized (readFile) {
...
}
// writer
File writeFile = new File(SHARED_FILE_NAME);
synchronized (writeFile) {
...
}
Also, just because you are locking on the same File object does not mean that the reading and writing code will work between the threads. You will need to make sure that in the writer that all updates are flushed in the synchronized block. In the reader you probably do not want to use buffered streams otherwise you will have stale data.
In general, locking across I/O is not a great idea. It's better to construct your program such that you guarantee by design that usually a given section of the file is not being concurrently written and read, and only lock if you absolutely must mediate between reads and writes of a given piece of the file.
Usually not. There are much better ways: Use a ReentrantLock
This class already offers the "lock for reading/writing" metaphor. It also correctly handles the case that many threads can read at the same time but only one thread can write.
As other people already mentioned, locking will only work if all threads use the same File instance.
Make sure you flush the output buffers after each write; this will cost some performance but otherwise, you'll get stale reads (read thread won't find data that you expect to be there).
If you want to simplify the code, add a third thread which accepts commands from the other two. The commands are READ and WRITE. Put the commands in a queue and let the 3rd thread wait for entries in the queue. Each command should have a callback method (like success()) which the 3rd thread will call when the command has been executed.
This way, you don't need any locking at all. The code for each thread will be much more simple and easy to test.
[EDIT] Answer based on your code: It would work in your case because everyone uses the same instance of fileObj but it would mix several things into one field. People reading your code would expect the file object to be just the path to the file to read. So the solution would violate the principle of least astonishment.
If you'd argue that it would save memory, then I'd reply with "premature optimization".
Try to find a solution which clearly communicates your intent. "Clever" coding is good for your ego but that's about the only positive thing that one can say about it (and it's not good for your ego to learn what people will say about you after they see your "clever" code for the first time...) ;-)
Queueing off read/write objects to one thread that then performs the operation is a valid approach to something, but I'm not sure what.
Wha it would not do, for example, is to enforce read/write/read/write order as you specified in your earlier question. There is nothing to stop the read thread queueing up 100 read requests.
That could be prevented by making the thread that submits an object wait on it until it is signaled by the read/write thread, but this seems a very complex way of just enforcing read/write order, (assuming that's what you still want).
I'm getting to the state now where I'm not sure what it is you need/want.