I'm trying to read a file. so in my class 'Skanner' i have a field that looks like this:
private Reader reader, readerX;
Now I initialized these fields in the contructor:
public Skanner()
{
try
{
Reader readerX = new FileReader("aliceinwonderland.txt");
Reader reader = new BufferedReader(readerX);
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
but when I try to use the fields in methods of class Skanner, I get a null-pointer exception. If I instead use reader.read() in the try block of the constructor that doesn't give any problems. Why can't I call reader.read() outside the scope where I initiated it?
You're hiding the instance members by redeclaring them in the method. Remove the Reader type declarations from the code you posted.
the problem is the Reader object is only available in your contructor which is
public Skanner()
{
try
{
Reader readerX = new FileReader("aliceinwonderland.txt");
Reader reader = new BufferedReader(readerX);
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if you would like to access them outside the constructor you need to declare them outside the constructor
Reader readerX;
Reader reader;
public Skanner()
{
try
{
readerX= new FileReader("aliceinwonderland.txt");
reader = new BufferedReader(readerX);
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void someMethod(){
//is now available
// make sure you use new Skanner() first before calling this method or it will result to NPE(null pointer exception) because the initialization of reader is in the constructor
reader.read();
}
and if you want to access them outside the class use the public access modifier.
Related
i am new to java and i am learning deserialization and while doing so i am getting classcastexception
I did serialization at one class and deserialization at another
serialization
zipfile f = new zipfile(30,"kavin");
ArrayList<zipfile> a = new ArrayList<zipfile>(101);
a.add(f);
String file = "def.txt";
try {
FileOutputStream fi = new FileOutputStream(file);
ObjectOutputStream s = new ObjectOutputStream(fi);
s.writeObject(f);
System.out.println(f.age);
s.close();
fi.close();
} catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
deserialization
String file = "def.txt";
try {
FileInputStream fi = new FileInputStream(file);
ObjectInputStream s = new ObjectInputStream(fi);
f=(deserialization)s.readObject();
System.out.println(f.age);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
output
Exception in thread "main" java.lang.ClassCastException: demo2.zipfile cannot be cast to demo2.deserialization
at demo2.deserialization.main(deserialization.java:69)
The following must be kept in mind when dealing with Serialization:
If a parent class has implemented Serializable interface then child class doesn’t need to implement it but vice-versa is not true.
Only non-static data members are saved via Serialization process.
Static data members and transient data members are not saved via Serialization process. So, if you don’t want to save the value of a non-static data member then make it transient.
The constructor of the object is never called when an object is deserialized.
Associated objects must be implementing the Serializable interface.
Try to look thru your code and find if one of the above-mentioned cases is the problem.
For more help, refer to the source at - Serialization in Java
I'm trying to get a thread to run for a swing application on button click, but the value isn't updating.
It supposed to grab the computer name I'm searching, but in order for the value to update I have to launch a new instance of the GUI.
I created a thread, but for some reason it's not working. Any help is appreciated.
(t.start is at end of code block)
searchComputerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Thread t = new Thread("my non EDT thread") {
public void run() {
//my work
testLabel.setText(CN);
}
};
String line;
BufferedWriter bw = null;
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(tempFile));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// String lineToRemove = "OU=Workstations";
String s = null;
Process p = null;
/*
* try { // p = Runtime.getRuntime().exec(
* "cmd /c start c:\\computerQuery.bat computerName"); } catch
* (IOException e1) { // TODO Auto-generated catch block
* e1.printStackTrace(); }
*/
try {
p = Runtime.getRuntime().exec("c:\\computerQuery.bat");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
StringBuffer sbuffer = new StringBuffer();
BufferedReader in = new BufferedReader(new InputStreamReader(p
.getInputStream()));
try {
while ((line = in.readLine()) != null) {
System.out.println(line);
// textArea.append(line);
String dn = "CN=FDCD111304,OU=Workstations,OU=SIM,OU=Accounts,DC=FL,DC=NET";
LdapName ldapName = new LdapName(dn);
String commonName = (String) ldapName.getRdn(
ldapName.size() - 1).getValue();
}
ComputerQuery.sendParam();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InvalidNameException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally
{
try {
fw.close();
}
catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
try {
in.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ComputerQuery.sendParam();
t.start();
}
});
UPDATE
private void threadStart() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
testLabel.setText(CN);
}
});
And I put the method here
JButton searchComputerButton = new JButton("Search");
searchComputerButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
threadStart();
String line;
Be aware of the Swing Thread https://docs.oracle.com/javase/tutorial/uiswin/concurrency/
Have a look here:
http://www.javamex.com/tutorials/threads/invokelater.shtml
You must enqueue your JLabel update method invocation using the Method
SwingUtilities.invokeLater(???).
Following example does it
Further more i think that is has something to do with the .batch file invocations. Have a look here: How do I run a batch file from my Java Application?
Runnable task = new UpdateJob("Query: " + i);
SwingUtilities.invokeLater(task);
To make it more understandable.
Swing manages all draw-Operations, within one Thread.
It provides a queue. If you call a method from outside of that queue the behaviour is completely unpredictable.. NullPointer... RuntimeExc....
But if you call SwingUtilities.invokeLater(...) your method will be enqueued into the Swing-Queue and invoked as soon as possible!
UPDATE due to comment:
check your mainthread (GUI)
check your threads.
when a sub-thread (e.g a ActionListener) want to call JLabel::setText
it has to use the method SwingUtils::InvokeLater("...");
That means invokeLater() has to be call within all threads which not directly belong to the main threads.
UPDATE due to Question
In my oppinion you current't code doesn't need SwingUtilities.invok.. at all.
Did you change the Code assigned to you your question.
I'm new in semaphore and i have any questions. I have a thread which start and read lines from text file A and write them in to other text file B. I wrote this code, but I'm not sure whether thread block critical section and sync properly. Because and others threads can operation with these files.
public static void main(String[] args) {
Thread thread = new Thread(new ThreadManager());
thread.start();
}
Thread class:
public class ThreadManager extends Thread {
private Semaphore semaphore;
public ThreadManager() {
this.semaphore = new Semaphore(1);
}
public void run() {
try {
this.semaphore.acquire();
BufferedReader br = null;
String line;
String fileNme = "threadLog.txt";
ArrayList<String> fileLines = new ArrayList<String>();
int numLine = 0;
File outFile = new File("$$$$$$$$.tmp");
// input
FileInputStream fis = null;
PrintWriter out = null;
try {
fis = new FileInputStream(fileNme);
// output
FileOutputStream fos = new FileOutputStream(outFile);
out = new PrintWriter(fos);
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
BufferedReader in = new BufferedReader(new InputStreamReader(fis));
try {
while ((line = in.readLine()) != null) {
fileLines.add(line);
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (!fileLines.isEmpty()) {
int middleLine = (int) Math.round(fileLines.size() / 2);
fileLines.add(middleLine, Thread.currentThread().getName());
for (int i = 0; i < fileLines.size(); i++) {
out.println(fileLines.get(i));
}
out.flush();
out.close();
try {
in.close();
new File(fileNme).delete();
outFile.renameTo(new File(fileNme));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.semaphore.release();
} catch (InterruptedException e3) {
// TODO Auto-generated catch block
e3.printStackTrace();
}
}
You cannot guarantee synchronized access to a file, given only its filename, using semaphores or synchronized blocks (or whatever). Any other thread (or process) can still open, read, or modify that file, e.g. by creating its own FileOutputStream and passing the same file name.
While you could certainly structure your code to encourage synchronized access to a file, at least within your process, you cannot guarantee it. So you'll have to make some assumptions about the possibility of other processes accessing your file, and define (and document) some rules as to how other threads can access the file and adhere to them.
It looks like you're just making a temporary file so you could also consider File.createTempFile() to reduce the possibility of the same file name being used; adding uniqueness to the file name could help.
While I could definitely go into more detail about specific options, though, your precise use isn't clear from your question, and without more information, the best I can tell you is that synchronization primitives can't be used to 100% guarantee that nothing else is accessing that file at the same time - you have to consider your situation and find a balance between providing this protection through code vs. good documentation and sticking to rules that you define.
By the way, a semaphore with 1 permit is the same as a mutex, in which case you might find that synchronized blocks provide a more appealing syntax.
Also don't forget about ReadWriteLock, another useful tool depending on your access patterns and performance requirements.
I have this class:
class Tester{
final String rigaFile=riga;
final BufferedReader r=new BufferedReader(reader2);
fr.getList().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
// fr.getLabel().setText(fr.getList().getSelectedValue().toString());
while(rigaFile!=null)
{
String[] parts=rigaFile.split("\t");
for(int i=0;i<dim;i++)
{
if(listaPath.get(i).equals(parts[1]) && parts[1].substring(parts[1].lastIndexOf('/')+1, parts[1].length()).equals(fr.getList().getSelectedValue().toString()))
{
fr.getLabel().setText(fr.getList().getSelectedValue().toString());
}
}
try {
rigaFile=r.readLine();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
});
}
}
The variable "rigaFile" throws the following error:
"The final local variable rigaFile can not be assigned, since it is defined in an enclosing type".
Any suggestion for this ?
Inner classes can only access variables of the surrounding class when they are final. This means you can't change the reference. Since strings in java are immutable, you can't change its value as well.
One possible solution is using a final StringBuilder instead of a String and change its content inside your anonymous inner class.
final StringBuilder rigaFile = new StringBuilder(riga);
...
try {
rigaFile.setLength(0);
rigaFile.append(r.readLine());
} catch (IOException e1) {
You also have to change your while condition, since rigaFile will never be null. To get the string value of rigaFile you may write rigaFile.toString().
Below is the code snippet, I am trying to invoke the usingClass method using REFLECTION. Calling the usingClass() method directly(w/o reflection) works when I pass an object of type Child, though when I try to achieve the same thing using Reflection it throws NoSuchMethodFoundException. Would like to understand if I am missing something or is there any logic behind this? Please help
package Reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestMethodInvocation {
/**
* #param args
*/
public static void main(String[] args) {
TestMethodInvocation test = new TestMethodInvocation();
Child child = new Child();
Parent parent = (Parent)child;
Class<? extends Parent> argClassType = parent.getClass();
Class<? extends TestMethodInvocation> thisClassType = test.getClass();
test.usingClass(child);
Method methodToCall;
try {
methodToCall = thisClassType.getDeclaredMethod("usingClass", argClassType);
methodToCall.invoke(test, parent);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void usingClass(Parent p){
System.out.println("UsingClass: " + p.getClass());
}
}
Output is as below.
UsingClass: class Reflection.Child
java.lang.NoSuchMethodException: Reflection.TestMethodInvocation.usingClass(Reflection.Child)
at java.lang.Class.getDeclaredMethod(Unknown Source)
at Reflection.TestMethodInvocation.main(TestMethodInvocation.java:20)
The reason your code does not work is that getClass() is dynamically bound. Casting to Parent does not affect the runtime type of your object and so the variables child and parent contain the same class object.
Unless you explicitly query your instance for its parent class via getGenericSuperclass() or something similar, you will have to use the static way mentioned by dystroy.
You should use
methodToCall = thisClassType.getDeclaredMethod("usingClass", Parent.class);
because the precise exact class of parent (which is Child), is used at runtime and the type of the variable holding it changes nothing.
Another (too heavy) way to solve it would be :
Class<? extends Parent> argClassType2 = (new Parent()).getClass();
...
methodToCall = thisClassType.getDeclaredMethod("usingClass", argClassType2);