getMethod return null java - java

I wrote getMethod in the file MovieReader and if I print this method inside this file everything is working well.
import java.io.BufferedReader; // scanner
import java.io.FileReader;
public class MovieReader {
private static String text;
public static void main(String args[]) throws Exception {
FileReader file = new FileReader("C:/Users/krystian/Desktop/filmDateBaseProject/movies.txt");
BufferedReader reader = new BufferedReader(file);
text = "";
String line = reader.readLine();
while(line != null) {
text+= line +"\n";
line=reader.readLine();
}
reader.close();
System.out.println(getText()); // This method works
}
public static String getText() {
return text;
}
}
But when I'm trying to call this method from other file it's printing null
public class Userr{
public static void main(String args[]){
MovieReader user = new MovieReader();
System.out.println(user.getText());
}
}
Can you help me with it?

In the MovieReader class you load the file and fill the contents of text in the main() method. When you create a new MovieReader object, the main() method is not executed, so the text field is not initialized.
You can create a static loader method in MovieReader and move the code from main() to there, like this:
public static void loadMovieInfo() {
FileReader file = new FileReader("C:/Users/krystian/Desktop/filmDateBaseProject/movies.txt");
... // rest of the code
reader.close();
}
Just call this before trying to call getText():
MovieReader.loadMovieInfo();
System.out.println(MovieReader.getText());
If you want the file to be loaded and the content of text to be filled when the object is created, you can turn text into an instance variable and load the file info in the MovieReader constructor.
Example:
public class MovieReader {
private String text;
public MovieReader() {
FileReader file = new FileReader("C:/Users/krystian/Desktop/filmDateBaseProject/movies.txt");
BufferedReader reader = new BufferedReader(file);
this.text = "";
String line = reader.readLine();
while(line != null) {
this.text += line +"\n";
line=reader.readLine();
}
reader.close();
}
public String getText() {
return this.text;
}
}
Then this should work:
MovieReader user = new MovieReader();
System.out.println(user.getText());
Also, a couple of observations:
Static methods belong to the class (not to a particular object), and should be called with the name of the class:
MovieReader.getText()
You should use a StringBuilder (docs here) instead of String concatenation to fill the contents of the text variable.

Try this one.
import java.io.BufferedReader; // scanner
import java.io.FileReader;
public class MovieReader {
private static String text;
public static String getText() {
FileReader file = new FileReader("C:/Users/krystian/Desktop/filmDateBaseProject/movies.txt");
BufferedReader reader = new BufferedReader(file);
text = "";
String line = reader.readLine();
while(line != null) {
text+= line +"\n";
line=reader.readLine();
}
reader.close();
System.out.println(getText()); // This method works
return text;
}
}
public class Userr{
public static void main(String args[]){
MovieReader user = new MovieReader();
System.out.println(user.getText());
}
}

The fast and dirty fix: Call the MovieReader.main method.
The longer answer, how you should actually do it:
You probably come from a scripting background like python. What you did here was to create two scripts, basically, wrapped in classes. When you call java, you have one class as entry point, whose main method is called.
So you created one script that loads a file, and another script that reads it, and your expectation is that both main methods are called. You need to go back to design!
The better way would be to only have a minimal main() in MovieReader, and instead have a method like readMovies(), which the main() calls. Then have User.main() call that method as well, before calling getText().
Don't put all the logic in main

First of all, you should call static getText() method with class name.
MovieReader.getText()
Second, default value of static string:
It's initialized to null if you do nothing, as are all reference types.
As, you are not doing anything that's why the value of text is null.
Refer the following fixed code:
MovieReader class
public class MovieReader {
private static String text;
public static void main(String args[]) throws Exception {
FileReader file = new FileReader("C:/Users/krystian/Desktop/filmDateBaseProject/movies.txt");
BufferedReader reader = new BufferedReader(file);
text = "";
String line = reader.readLine();
while(line != null) {
text+= line +"\n";
line=reader.readLine();
}
reader.close();
System.out.println(getText()); // This method works
}
public static String getText() {
return text;
}
}
Userr class:
public class Userr{
public static void main(String args[]){
try {
MovieReader.main(null);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(MovieReader.getText());
}
}

Assuming that you are running the main() method of Userr class.
main() method and getText() method of the class MovieReader are independent of each other. If you are calling getText() method, it will return the value of text variable without any operations on it, cos operations of main() method [ of MovieReader class ] are not going to execute. That's why you are not getting intended result.
try to re factor your code as below.
public class Movie {
public static void main(String[] args) {
MovieReader user = new MovieReader();
String file = "C:/Users/krystian/Desktop/filmDateBaseProject/movies.txt";
System.out.println(user.getText(file));
}
}
and the MovieReader class,
class MovieReader {
private String text;
String getText(String fileName) {
FileReader file;
file = null;
try {
file = new FileReader(fileName);
BufferedReader reader = new BufferedReader(file);
text = "";
String line = reader.readLine();
while (line != null) {
text += line + "\n";
line = reader.readLine();
}
reader.close();
return text;
} catch (FileNotFoundException ex) {
Logger.getLogger(MovieReader.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(MovieReader.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
file.close();
} catch (IOException ex) {
Logger.getLogger(MovieReader.class.getName()).log(Level.SEVERE, null, ex);
}
}
return null;
}
}
its always a good practice to use exception handling.

Related

Unit testing a constructor method

I'm having trouble getting my head round how to unit test a constructor method.
I need to check an error is being thrown. The constructor is:
#Autowired
public BankDetailsValidator() {
try {
logDebugMessage("BankDetailsValidator() constructor");
loadModulusWeightTable();
loadSortCodeSubstitutionTable();
} catch (final IOException e) {
throw new BankDetailsValidationRuntimeException("An error occured loading the modulus weight table or sort code substitution table", e);
}
}
To test this, I need to have the loadModulusWeightTable or loadSortCodeSubstitutionTable throw and IOException.
private void loadModulusWeightTable() throws IOException {
modulusWeightTable.clear();
logDebugMessage("Attempting to load modulus weight table " + MODULUS_WEIGHT_TABLE);
final InputStream in = new FileInputStream(MODULUS_WEIGHT_TABLE);
br = new BufferedReader(new InputStreamReader(in));
try {
String line;
while ((line = br.readLine()) != null) {
final String[] fields = line.split("\\s+");
modulusWeightTable.add(new ModulusWeightTableEntry(fields));
}
logDebugMessage("Modulus weight table loaded");
}
finally {
br.close();
}
}
I was trying to use Spy to have the buffered file reader return a IOException but couldn't get it working due to it being in the constructor.
public class BankDetailsValidatorTest {
#Spy
private BufferedReader mockBufferReader;
#InjectMocks
private CDLBankDetailsValidator testSubject;
#Test(expected = IOException.class)
public void testIOErrorLogging() throws Exception{
when(mockBufferReader.readLine()).thenThrow(new IOException());
testSubject = new CDLBankDetailsValidator();
}
}
I think that class BankDetailsValidator should be refactored. In such scenarios you should extract code responsible for reading data to separate class and inject it to BankDetailsValidator as constructor parameter. After that you could test that reader separately and of course test BankDetailsValidator with mocked reader.
Here's how you could refactor your code:
#Autowired
public BankDetailsValidator(Collection<ModulusWeightTableEntry> table) {
try {
logDebugMessage("BankDetailsValidator() constructor");
this.modulusWeightTable.addAll(table);
loadModulusWeightTable();
loadSortCodeSubstitutionTable();
} catch (final IOException e) {
throw new BankDetailsValidationRuntimeException("An error occured loading the modulus weight table or sort code substitution table", e);
}
}
which removes the loading from file part to maybe a #Configuration.
#Configuration
class WeightTableConfiguration {
#Bean
ModulusWeightTable loadFromFile(#Value("${mwt.filename}") String filename) {
Collection<ModulusWeightTableEntry> table = new ArrayList<>();
logDebugMessage("Attempting to load modulus weight table " + filename);
try (InputStream in = new FileInputStream(filename);
br = new BufferedReader(new InputStreamReader(in))) {
String line;
while ((line = br.readLine()) != null) {
final String[] fields = line.split("\\s+");
table.add(new ModulusWeightTableEntry(fields));
}
logDebugMessage("Modulus weight table loaded");
}
return table;
}
}
Now you can test your validator separately from the loading code, and create a separate test configuration providing a manually created weight table.
Or you parameterize your constructor with a Supplier<WeightTable> and put the loading code into the get() method of an implementing #Component class.

How to use a Path object as a String

I'm looking to try and create a Java trivia application that reads the trivia from separate question files in a given folder. My idea was to use the run() method in the FileHandler class to set every text file in the folder into a dictionary and give them integer keys so that I could easily randomize the order at which they appear in the game. I found a simple chunk of code that is able to step through the folder and get the paths of every single file, but in the form a Path class. I need the paths (or just the names) in the form a String class. Because I need to later turn them into a file class (which excepts a String Constructor, not a Path). Here is the chunk of code that walks through the folder:
public class FileHandler implements Runnable{
static Map<Integer, Path> TriviaFiles; //idealy Map<Integer, String>
private int keyChoices = 0;
public FileHandler(){
TriviaFiles = new HashMap<Integer, Path>();
}
public void run(){
try {
Files.walk(Paths.get("/home/chris/JavaWorkspace/GameSpace/bin/TriviaQuestions")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
TriviaFiles.put(keyChoices, filePath);
keyChoices++;
System.out.println(filePath);
}
});
} catch (FileNotFoundException e) {
System.out.println("File not found for FileHandler");
} catch (IOException e ){
e.printStackTrace();
}
}
public static synchronized Path getNextValue(){
return TriviaFiles.get(2);
}
}
There is another class named TextHandler() which reads the individual txt files and turns them into questions. Here it is:
public class TextHandler {
private String A1, A2, A3, A4, question, answer;
//line = null;
public void determineQuestion(){
readFile("Question2.txt" /* in file que*/);
WindowComp.setQuestion(question);
WindowComp.setAnswers(A1,A2,A3,A4);
}
public void readFile(String toRead){
try{
File file = new File("/home/chris/JavaWorkspace/GameSpace/bin/TriviaQuestions",toRead);
System.out.println(file.getCanonicalPath());
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
question = br.readLine();
A1 = br.readLine();
A2 = br.readLine();
A3 = br.readLine();
A4 = br.readLine();
answer = br.readLine();
br.close();
}
catch(FileNotFoundException e){
System.out.println("file not found");
}
catch(IOException e){
System.out.println("error reading file");
}
}
}
There is stuff I didn't include in this TextHandler sample which is unimportant.
My idea was to use the determineQuestion() method to readFile(FileHandler.getNextQuestion).
I am just having trouble working around the Path to String discrepancy
Thanks a bunch.
You can simply use Path.toString() which returns full path as a String. But kindly note that if path is null this method can cause NullPointerException. To avoid this exception you can use String#valueOf instead.
public class Test {
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
Path path = Paths.get("/my/test/folder/", "text.txt");
String str = path.toString();
// String str = String.valueOf(path); //This is Null Safe
System.out.println(str);
}
}
Output
\my\test\folder\text.txt

Proper way to use Generics in this example?

FileReader fileReader = null;
Object reader = null;
String dataRow = null;
fileReader = new FileReader(new File(fileLocation));
if (extension.equals("csv"))
{
reader = new CSVReader(fileReader);
}
else
{
reader = new BufferedReader(fileReader);
}
while (null != (dataRow = reader.readLine()))
{
...
}
The idea is to use different types depending on the file type in order to remove duplicated code. However, I get an error on the last line, since reader is type Object. Thanks for the help.
Maybe you could make 2 methods:
public String read(CSVReader c){
return c.readLine();
}
public String read(BufferedReader br){
return br.readLine();
}
Then, in your current code:
if(extension.equals("csv"))
dataRow = read(new CSVReader(fileReader));
else
dataRow = read(new BufferedReader(fileReader));
This overloading would remove the need for a wrapper class.
If you really want to use a wrapper class, I recommend having this somewhere:
public interface MyIO{
public String readLine();
}
public class MyBr extends BufferedReader implements MyIO{}
public class MyCSV extends CSVReader implements MyIO{}
Then, in your code:
MyIO reader;
if(extension.equals("csv"))
reader = new MyCSV(fileReader);
else
reader = new MyBr(fileReader);
You'd notice that both are the same number of lines of code and (in my opinion) the methods are easier to follow.
Just answering to point out that it is certainly possible to use generics even if your types are not cooperative. You'll just have to define specializations for each type separately. I'll just put a sketch in Java 8 here. Not sure what you mean by 'Proper way', there are pros and cons to everything...especially in Java.
Somewhat simpler way, putting generic code in a common superclass:
interface GenericExample {
interface InputGenericCode<Input> {
/**
* This is implemented in subtypes.
*
* #param x
* #return
*/
String readLine(Input x);
default void genericAlgorithm(Input x) {
// algorithm expressed generically here...
for (;;) {
String lineString = readLine(x);
System.out.println("" + lineString);
}
}
}
public class BufferedReaderInputGenericCode implements InputGenericCode<BufferedReader> {
#Override
public String readLine(BufferedReader x) {
try {
return x.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
public class CSVReaderInputGenericCode implements InputGenericCode<CSVReader> {
#Override
public String readLine(CSVReader x) {
return x.readLine();
}
}
static class CSVReader {
public CSVReader(FileReader fileReader) {
throw new RuntimeException("implement this");
}
public String readLine() {
throw new RuntimeException("implement this");
}
}
public static void main(String fileLocation, String extension) {
FileReader fileReader = openFile(fileLocation);
if (extension.equals("csv")) {
CSVReader reader = new CSVReader(fileReader);
new CSVReaderInputGenericCode().genericAlgorithm(reader);
} else {
BufferedReader reader = new BufferedReader(fileReader);
new BufferedReaderInputGenericCode().genericAlgorithm(reader);
}
// dataRow = reader.readLine();
}
public static FileReader openFile(String fileLocation) {
FileReader fileReader = null;
try {
fileReader = new FileReader(new File(fileLocation));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
return fileReader;
}
}
More complex way:
interface GenericExample {
/**
* All generic operations.
*
* #author jonasn
*
* #param <Input>
*/
interface InputGenerics<Input> {
String readLine(Input x);
}
interface InputGenericCode {
public static <Input> void genericAlgorithm(Input x, InputGenerics<Input> generics) {
// algorithm expressed generically here...
for (;;) {
String lineString = generics.readLine(x);
System.out.println("" + lineString);
}
}
}
static class CSVReader {
public CSVReader(FileReader fileReader) {
// TODO Auto-generated constructor stub
}
public String readLine() {
throw new RuntimeException("not implemented");
}
}
public class CSVReaderInputGenerics implements InputGenerics<CSVReader> {
#Override
public String readLine(CSVReader x) {
return x.readLine();
}
}
public class BufferedReaderInputGenerics implements InputGenerics<BufferedReader> {
#Override
public String readLine(BufferedReader x) {
try {
return x.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
}
public static void main(String fileLocation, String extension) {
// String fileLocation = "whatever";
// String extension = "";
FileReader fileReader = null;
// Object reader = null;
String dataRow = null;
try {
fileReader = new FileReader(new File(fileLocation));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
if (extension.equals("csv"))
{
CSVReader reader = new CSVReader(fileReader);
InputGenericCode.genericAlgorithm(reader, new CSVReaderInputGenerics());
}
else
{
BufferedReader reader = new BufferedReader(fileReader);
InputGenericCode.genericAlgorithm(reader, new BufferedReaderInputGenerics());
}
// dataRow = reader.readLine();
}
}

fill a file inside a inner class

I'm quiet new to java and I'm not even sure if the title makes any sense.
Anyway how do I gain access to a file inside of onStatus?
I'm just trying to write into a file in that function so in the code below "T_file.length()" the "T_file" cannot be resolved.
public static void main (){
foo("file_name");
}
foo(String fileName)
{
try{
final File T_file = new File (fileName);
final FileWriter fw = new FileWriter(fileName);
final BufferedWriter bw = new BufferedWriter (fw);
}catch (IOException e){}
StatusListener listener = new StatusListener(){
public void onStatus(Status status){
if (T_file.length() > 100){
System.out.println ("I have access here");
}
}
}
}
"T_file.length()" the "T_file" cannot be resolved
This is because T_file is not in the scope of onStatus. You declare T_file in the foo method, but then create a new StatusListener in which you redefine the onStatus, but the compiler still see StatusListener as an other class.
A workaround would be to declare the variable globally in your class, then access it specifying the name of your Class.this.T_file. Here an example :
public class Foo {
File T_file;
public static void main (){
new Foo("file_name");
}
Foo(String fileName)
{
T_file = new File (fileName);
StatusListener listener = new StatusListener(){
public void onStatus(Status status){
if (Foo.this.T_file.length() > 100){
System.out.println ("I have access here");
}
}
};
}
}
This example would compile.
Notice that I added a ; at the end of the StatusListener, else it would not compile.

How to call instance method in static method

So what am I trying to do is to read a .txt file and add some record on it using eclipse. I set my resource which I named it as "fileName" as private and when I try to call it in main method, there is some error. Here is my code:
public class FileController {
private String fileName;
public FileController() {
}
public FileController(String fileName) {
fileName = "student.txt";
}
public void readLine() {
try {
FileReader fr = new FileReader(fileName);
Scanner sc = new Scanner(fr);
// read in the file line by line
while (sc.hasNextLine()) {
System.out.println(sc.nextLine());
}
fr.close();
} catch (FileNotFoundException exception) {
System.out.println("The file " + fileName + " was not found.");
} catch (IOException exception) {
System.out.println(exception);
}
}
public void writeLine() {
try {
// create the PrintWriter
FileWriter fw = new FileWriter(fileName, true);
BufferedWriter bw = new BufferedWriter(fw);
PrintWriter outFile = new PrintWriter(bw);
// write value out to the file
outFile.println("Coke is nice");
outFile.println("Diet Coke is even better cos won't put on weight =)");
// close the file
outFile.close();
System.out.println("File created: " + fileName);
} catch (IOException exception) {
System.out.println(exception);
}
}
public static void main(String[] args) {
FileController fs = new FileController();
fs.readLine();
fs.writeLine();
}
}
Anybody can give me some clues? These codes keep giving me NullPointerException error. I know it's from the FileController fs = new FileController() that line, but I do not know how to call instance method in static method.
Try:
public FileController() {
fileName = "student.txt";
}
public FileController(String fileName) {
this.fileName = filename;
}
I think your constructor should look like this:
public FileController(String fileName) {
this.fileName = fileName;
}
And the no-arg constructor like this:
public FileController() {
this("student.txt");
}
FileController fs = new FileController();
should be
FileController fs = new FileController("fileName");
You should also edit you constructor like this.Since class variable fileName and parameter name in constructor has same name you must have to use "this" keyword for assignment .
public FileController(String fileName) {
this.fileName = fileName;
}
If the parameter name and the class variable name is different you can do this.
public FileController(String name) {
fileName = name;
}
You are not passing the name of the file in the constructor. You should pass a valid file name in there for your logic to work properly
You need to call your constructor with an argument, or your default constructor should provide a default filename, for instance, in your main:
FileController fs = new FileController("somefile.txt")
And your constructor needs to be changed to:
public FileController(String filename) {
this.fileName = filename;
}
And you could change your default constructor:
public FileController() {
this("someDefaultFile.txt");
}
Keep in mind that the later option only makes sense if there is a default file to look for, otherwise you should explicitly pass the name of the file.
Instance methods can be accessed in static methods using the object reference of the class whose method you are trying to invoke.
Hence using new keyword as you have rightly pointed out will resolve your issue.
Problem is by calling new FileController(); you didn't initialized fileName field.
You probably wanted your constructors look like this:
public FileController() {
this.fileName = "student.txt";
}
public FileController(String fileName) {
this.fileName = fileName;
}
Then will be calling new FileController(); legit.

Categories