File Sorter - fileNotFoundException - java

I am trying to create a program that reads a File, saves the content (words) in an ArrayList, sorts the ArrayList, and then writes the content of the sorted ArrayList back to the File.
I have no idea why, it keeps on giving me a FileNotFoundException or a NullPointerException (both are occurring, it's a bit wierd)...
Here's my code, if anyone can help that would be great.
Thanks.
By the way, the code contains four classes:
DriverClass, View(the GUI), ReadFile, and WriteFile.
You can ignore the comments, I just wrote those for myself - they're pretty obvious. For "field.getText();" let's say the user enters C:\Users\Corecase\Desktop\test.txt I've tried doing C:\\Users\\Corecase\\Desktop\\test.txt) and that doesn't work either.
Thanks again!
public class DriverClass
{
public static void main(String[] args)
{
View open= new View();
}
}
//View
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class View implements ActionListener
{
private JFrame frame = new JFrame("File Sorter");
private JPanel mainPane = new JPanel();
private JPanel textPane = new JPanel();
private JPanel buttonPane = new JPanel();
private JButton sortButton = new JButton("Sort");
private JLabel label = new JLabel("Enter file path: ");
public JTextField field = new JTextField(25);
private Font f = new Font("Trebuchet MS", Font.PLAIN, 20);
public View()
{
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPane);
mainPane.setLayout(new GridLayout(2,1));
mainPane.setBackground(Color.gray);
mainPane.add(textPane);
mainPane.add(buttonPane);
textPane.setLayout(new GridLayout(2,1));
textPane.add(label);
textPane.add(field);
buttonPane.add(sortButton);
field.setFont(f);
sortButton.setFont(f);
label.setFont(f);
sortButton.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == sortButton)
{
ReadFile r = new ReadFile(field.getText());
WriteFile w = new WriteFile(field.getText());
r.openFile();
r.readAndSortFile();
r.closeFile();
w.openFile();
w.writeFile(r.getList());
w.closeFile();
}
}
}
//ReadFile
import java.io.*;
import java.util.*;
public class ReadFile extends View
{
private ArrayList<String> words = new ArrayList<String>();
private String fileName = new String();
private Scanner x;
public ReadFile(String address)
{
fileName = address;
}
public void openFile()
{
try
{
x = new Scanner(new File(fileName));
}
catch(Exception e)
{
field.setText("Could not read file.");
}
}
public void readAndSortFile()
{
while(x.hasNext())
words.add(x.next());
sort();
}
public void closeFile()
{
x.close();
}
public ArrayList<String> sort()
{
String temp = "";
for(int index = 0; index < words.size(); index++)
{
for(int inner = 0; inner < words.size(); inner++)
{
if((words.get(inner)).compareTo(words.get(inner+1)) > 0)
{
temp = words.get(inner);
words.set(inner, words.get(inner + 1));
words.set(inner + 1, temp);
}
}
}
return words;
}
public ArrayList<String> getList()
{
return words;
}
}
//WriteFile
import java.io.*;
import java.util.*;
import java.lang.*;
public class WriteFile extends View
{
private Formatter x;
private String fileName = new String();
public WriteFile(String address)
{
fileName = address;
}
public void openFile()
{
try
{
x = new Formatter(fileName);
}
catch(Exception e)
{
field.setText("Could not write to file.");
}
}
public void writeFile(ArrayList<String> myWords)
{
for(int index = 0; index < myWords.size(); index++)
x.format("%s", myWords.get(index), "\n");//%s means string - in this case ONE string
}
public void closeFile()
{
x.close();
}
}

You have several issues in your code. You are extending View to obtain a reference of the textField 'field'! and that is not the way to go. You should use Exception handling to do this simple task. Also you cannot read and write from/to a file simultaneously! so you need to separate the duties here. When you finish reading the file, close it and open it again with whatever writer you want to use. Final note: You could use FileChooser to obtain the path, and that saves you the need of checking valid inputs! If you want to do the hard way and force the user to input the path manually, you have to add the escape character '/', In your case, a valid path would be C:\\Users\\Corecase\\Desktop\\test.txt
Change the following code in 'View.java'
if (e.getSource() == sortButton)
{
ReadFile r;
try
{
r = new ReadFile(field.getText());
r.readAndSortFile();
WriteFile w = new WriteFile(field.getText());
w.writeFile(r.getList());
}
catch (FileNotFoundException e1)
{
field.setText(e1.getMessage());
e1.printStackTrace();
}
}
and change 'WriteFile.java' to
public class WriteFile
{
private Formatter x;
private String fileName;
public WriteFile(String address) throws FileNotFoundException
{
fileName = address;
try
{
x = new Formatter(fileName);
} catch (Exception e)
{
throw new FileNotFoundException("Could not write to file.");
}
}
public void writeFile(ArrayList<String> myWords)
{
for (int index = 0; index < myWords.size(); index++)
x.format("%s%s", myWords.get(index), System.lineSeparator());
// now you are done writing so close the file.
x.close();
}
}
Change 'ReadFile.java' to
public class ReadFile
{
private ArrayList<String> words;
private String fileName;
private Scanner x;
public ReadFile(String path) throws FileNotFoundException
{
fileName = path;
words = new ArrayList<String>();
try
{
x = new Scanner(new File(fileName));
} catch (Exception e)
{
throw new FileNotFoundException("File Doesn't exist in the place you specified.");
}
}
public void readAndSortFile()
{
while (x.hasNext())
words.add(x.next());
Collections.sort(words);
// Now you are done reading and sorting, so close the file.
x.close();
}
.
.
.
}

There are couple of issue in your code:
ReadFile and WriteFile are extending View, as per the constructor you will have multiple instances of JFrame opened, as you are making the frame visible in your constructor frame.setVisible(true);, ReadFile and WriteFile just need a reference of the JTextField which should be updated, just pass this as a parameter.
Your sort will definitely throw IndexOutOfBoundsException for this line
if ((words.get(inner)).compareTo(words.get(inner + 1)) > 0) {
This line won't work when it reaches the last index, why not use simple Collections.sort(words);
You don't have a check if user has entered path or not, if nothing is entered, you will get NullPointerException in your ReadFile, ideally if file is not found i.e. your scanner is null, don't proceed further. Currently you are showing an error message but your code doesn't stop there, it still tries to read and sort file which is wrong.

i have tried your example and debugged it. I used c:\\dir\\file.text as parameter to the GUI and the file is read properly, so it is not there your problem. The exception i was getting was coming from this code:
for (int index = 0; index < words.size(); index++) {
for (int inner = 0; inner < words.size(); inner++) {
if ((words.get(inner)).compareTo(words.get(inner + 1)) > 0) {
temp = words.get(inner);
words.set(inner, words.get(inner + 1));
words.set(inner + 1, temp);
}
}
}

FileNotFoundException means that the file was not found.
NullPointerException means you tried to dereference a null pointer.
If that doesn't answer your question I don't know what does. StackOverflow is not a debugging service.

Related

How to access value of an abstract method in a different class?

AbstractInputFile is an abstract class and has the following code below:
public abstract class AbstractInputFile {
static final public int MIN_BILLING_CYCLE = 1;
static final public int MAX_BILLING_CYCLE = 12;
private File file;
public AbstractInputFile() {
}
public abstract List<Request> readFile() throws IOException, BarsException;
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
}
CSVInputFileImpl is a subclass of AbstractInputFile, thus inheriting the readFile() method. What it does is it reads the contents of a csv file using a buffered reader, stores it in an arraylist, and returns it.
public List<Request> readFile() throws IOException, BarsException {
List<Request> requests = new ArrayList<>();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
String line = "";
//READ CSV FILE
try {
BufferedReader br = new BufferedReader(new FileReader(getFile()));
int row = 1;
int index = 0;
while ((line = br.readLine()) != null) {
String[] data = line.split(",", 3);
//Validate if billing cycle ranges 1-12
try {
int billingCycle = Integer.parseInt(data[0]);
if(billingCycle <= MAX_BILLING_CYCLE && billingCycle >= MIN_BILLING_CYCLE) {
request.setBillingCycle(billingCycle);
} else {
log.error(BILLING_CYCLE_NOT_ON_RANGE + row);
throw new BarsException(BILLING_CYCLE_NOT_ON_RANGE + row);
}
} catch (BarsException e) {
log.error(INVALID_BILLING_CYCLE + row);
throw new BarsException(INVALID_BILLING_CYCLE + row);
}
//Validate start date
try {
LocalDate startDate = LocalDate.parse(data[1], formatter);
request.setStartDate(startDate);
} catch (DateTimeParseException e) {
log.error(INVALID_START_DATE_FORMAT + row);
throw new BarsException(INVALID_START_DATE_FORMAT + row);
}
//Validate end date
try {
LocalDate endDate = LocalDate.parse(data[2], formatter);
request.setStartDate(endDate);
} catch (DateTimeParseException e) {
log.error(INVALID_END_DATE_FORMAT + row);
throw new BarsException(INVALID_END_DATE_FORMAT + row);
}
row++;
//Add the requests to array list created previously
requests.add(index,new Request(request.getBillingCycle(), request.getStartDate(), request.getEndDate()));
index++;
}
//Validate if file exists
} catch (FileNotFoundException e) {
throw new BarsException(NO_SUPPORTED_FILE);
} catch (IOException e) {
throw new IOException(PATH_DOES_NOT_EXIST);
}
return requests;
}
In another public class FileProcessor, I am instructed to get the array list using List<Request> requests = abstractInputFile.readFile(); but is unable to do so because I am getting the error Non-static method 'readFile()' cannot be referenced from a static context.
public List<Request> execute(File file) throws BarsException {
InputFileFactory fact = InputFileFactory.getInstance();
try {
fact.getInputFile(file);
} catch (BarsException e) {
throw new BarsException(NO_SUPPORTED_FILE);
}
List<Request> requests = AbstractInputFile.readFile();
return requests;
}
My question is: How will I be able to retrieve the arraylist and return it in the execute(file) method? There might be a lot more errors in other areas of the code and logic but I'd appreciate any help and suggestions.
First things first, AbstractInputFile.readFile() can't be called for 2 reasons: readFile() in the AbstractInputFile class is abstract, and it is an instance method.
From what you wrote here, you implement the readFile() method in the subclass, CSVInputFileImpl. Therefore, in this case, your readFile() calls should be based on THIS class, not AbstractInputFile. However, this is still classified as an instance method, meaning you need to first create an instance of CSVInputFileImpl before you can call readFile(). I would correct the code like this (I'm making assumptions that the CSVInputFileImpl class is structured the same as AbstractInputFile, but make sure the file instance var is set):
CSVInputFileImpl csvInputFileImpl = new CSVInputFileImpl();
csvInputFileImpl.setFile(file);
List<Request> requests = csvInputFileImpl.readFile();
return requests;

Why does Scanner nextLine() read one file but not another in the same directory?

I have two files in a directory. Both of them have lines of text in them. According to Notepad++, each line has a CRLF. My ReadFile class reads one file and not the other and not the other.
private FileRead fileRead = new FileRead();
private JobSiteData jobSiteData = new JobSiteData();
private String path = "C:/Users/Antonio/IdeaProjects/JobSearch/websiteTest/";
If I uncomment out the block and comment out the other block it works fine.
#Test
void setAllText_ItReturnsAllLinesFromSite_arrayListOfLinesFromSite() throws IOException {
// ArrayList<String> thisWorks = new ArrayList<>();
// thisWorks = fileRead.getLinesFromFile(path + "allTextTest.txt");
// for (String s : thisWorks) {
// System.out.println(s);
// }
ArrayList<String> thisDoesntWork = new ArrayList<>();
thisDoesntWork = fileRead.getLinesFromFile(path + "goDaddySplitTestAllLines.txt");
for (String s : thisDoesntWork) {
System.out.println(s); // prints "File is empty."
}
}
Here is my FileRead Class.
public class FileRead {
private String fileName;
private ArrayList<String> linesFromFile = new ArrayList<>();
private Scanner fileScanner;
public ArrayList<String> getLinesFromFile(String fileName) {
this.fileName = fileName;
setLinesFromFile();
if (isFileEmpty()) {
linesFromFile.add("File is empty.");
}
return linesFromFile;
}
private void setLinesFromFile() {
File file = new File(fileName);
if (doesFileExist(file)) {
readFile();
closeFileReader();
}
}
private Boolean doesFileExist(File file) {
try {
fileScanner = new Scanner(file);
} catch (FileNotFoundException e) {
linesFromFile.add("File does not exist.");
return false;
}
return true;
}
private void readFile() {
if (fileScanner != null) {
if (!linesFromFile.isEmpty()) {
linesFromFile.clear();
}
while (fileScanner.hasNextLine()) {
linesFromFile.add(fileScanner.nextLine());
}
}
}
private void closeFileReader() {
if (fileScanner != null) {
fileScanner.close();
}
}
private boolean isFileEmpty() {
return linesFromFile.size() == 0;
}
}
UPDATE: I found the issue. For some reason this line in the file is causing the scanner not to read the lines.
"GoDaddy’s Productivity suite of products help millions of small businesses run and grow their ventures. We are looking for an engineer that is passionate about software development to help accelerate our growth. If you’re into building world-class experiences on public cloud infrastructure using JavaScript and React, learning new things, and working with a fun team, we want to meet you!"
This line is the forth line down. If I delete it and everything after it, the scanner works fine. If I delete everything in the file and only have that line in the file as the first line it won't work either. Does anyone know why this is?

Why is this List<> throwing NullPointerException?

so i've been sitting above this code for a while , ready the NullPointerException threads, and still can't figure out what is going wrong in my code, so i turn to you.
public class Main {
public static void main(String[] args){
/* Making catalog, loading last state */
Collection catalog = new Collection();
try {
catalog.readFromFile();
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
catalog.addShip(new Ship("ABC123", "John", "Suzuki", 50));
}
}
And my Collection class looks like this:
public class Collection {
private List<Ship> shipList;
private String fileName = "catalog.txt";
private int income;
private int space;
public Collection() {
shipList = new ArrayList<Ship>();
income = 0;
space = 500;
File f = new File("catalog.txt");
if(!f.exists()) {
try {
f.createNewFile();
writeToFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void addShip(Ship SHIP){
space -= SHIP.LENGTH;
income += SHIP.COST;
shipList.add(SHIP);
}
public Ship getShip(int INDEX){
return shipList.get(INDEX);
}
public void writeToFile() throws IOException {
FileOutputStream f = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(f);
out.writeObject(shipList);
out.close();
}
#SuppressWarnings("unchecked")
public void readFromFile() throws IOException, ClassNotFoundException {
FileInputStream f = new FileInputStream(fileName);
ObjectInputStream in = new ObjectInputStream(f);
shipList = (ArrayList<Ship>)in.readObject();
in.close();
}
public int getIncome(){
return income;
}
public int getSpace(){
return space;
}
}
My problem is, when i call in main catalog.addship() i get nullptr error. After following the console errors, it says i get the nullptrexc when i call the addShip() on the catalog, following from there i get the error when i add() a Ship to the Collection's shipList. So what i concluded, it is because the shipList in the Collection is uninitialized. But in the constructor i write shipList = new ArrayList<Ship>(); so it is clearly initialized.
The exception stacktrace is the following:
Exception in thread "main" java.lang.NullPointerException
at collection.Collection.addShip(Collection.java:31)
at main.Main.main(Main.java:100)
In your main method, you initialize the ArrayList properly. But then, you make a
catalog.readFromFile()
call. In the readFromFile() method, you re-initialize the ArrayList
shipList = (ArrayList<Ship>)in.readObject();
the in.readObject() is returning null. That is why your shipList variable is null.
Hope this helps!

Declaring an array in java as an object?

I have recently been following some tutorials on how to program and whilst programming the public static void for an array, the tutorial said to declare the array as an object. Below is the code for the array and at the end of the code I have put a split between the two sections so it is visible to as where my question lies
import java.io.*;
import java.lang.*;
public class LoginList
{
int arraySize=500;
Login[] arrayLogin=new Login[arraySize];
int nextPosition=0;
int LoginLocation=-1;
public void addLogin(Login tempLoginParameters)
{
arrayLogin[nextPosition] = tempLoginParameters;
nextPosition++;
}
public void writeLogins()
{
try
{
BufferedWriter LoginWriter = new BufferedWriter(new FileWriter("LoginDetails.txt"));
for(int i=0;i<nextPosition;i++)
{
LoginWriter.write(arrayLogin[i].toString());
LoginWriter.newLine();
}
LoginWriter.close();
}
catch(Exception e)
{
System.out.println("Error with writer");
}
}
public void readLogins()
{
try
{
BufferedReader LoginReader = new BufferedReader(new FileReader("LoginDetails.txt"));
String ReadLine = LoginReader.readLine();
while(ReadLine!= null)
{
String[] arrayStringLogin = ReadLine.split(", ");
Login tempLogin = new Login();
tempLogin.UserName = arrayStringLogin[0];
tempLogin.Password = arrayStringLogin[1];
arrayLogin[nextPosition] = tempLogin;
nextPosition++;
ReadLine = LoginReader.readLine();
}
}
catch(Exception e)
{
System.out.println("Error with reader");
}
}
public void displayLoginDetails()
{
for(int i=0;i<nextPosition;i++)
{
System.out.println("Login "+nextPosition+": "+arrayLogin[i].toString());
}
}
public void searchLogins(String TempLog)
{
LoginLocation=-1;
for(int i=0;i<nextPosition;i++)
{
if(arrayLogin[i].UserName.equals(TempLog))
{
System.out.println("Match At Position:"+i);
LoginLocation=i;
}
else
{
System.out.println("No match for UserName");
}
}
}
public static void main(String[] args)
{
LoginList ll = new LoginList(); //Declares the array as an object
Why is it that you have to declare the array as an object? Look just above here.
Login tempLogin = new Login();
ll.readLogins();
ll.displayLoginDetails();
}
}
LoginList is not an array, it's a class that happens to have an array of Login objects as one of its instance members. The code in main creates an object of type LoginList and calls its methods; the LoginList object uses an array internally, but the main method doesn't have to know about it.

Reading a file after pressing a button

I have tried to create a program that lets you to choose a file,reads it and then prints the results out... This is what i have so far
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("Bebras braces matcher");
JButton selectf = new JButton("Open file");
selectf.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if(cmd.equals("Open file")) {
JFileChooser chooser =new JFileChooser();
FileFilter filefilter = new FileNameExtensionFilter("","txt");
chooser.setFileFilter(filefilter);
int returnVal = chooser.showOpenDialog(chooser);
if(returnVal==JFileChooser.APPROVE_OPTION) {
FileName=chooser.getSelectedFile().getName();
System.out.println(FileName);
}
}
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500,500);
frame.add(selectf);
frame.setVisible(true);
}
public static void countChar() throws FileNotFoundException {
Scanner scan = null;
try {
scan = new Scanner(new File(FileName));
}
catch (FileNotFoundException e) {
}
while (scan.hasNext()) {
String character = scan.next();
int index =0;
char close = '}';
char open = '{';
while(index<character.length()) {
if(character.charAt(index)==close){
CloseCount++;
}
else if(character.charAt(index)==open) {
OpenCount++;
}
index++;
}
}
System.out.println("Opened: "+OpenCount+"Closed: "+CloseCount);
}
private static String FileName;
private static int CloseCount = 0;
private static int OpenCount = 0;
private static final long serialVersionUID = 7526472295622776147L;
}
And it runs okay,just doesn't do what it need to... How do I make "countChar" run? Because it doesn't print what i should..
I forgot to mention, if I call it after i print out the files name, I get this errro: "Unhandled exception type FileNotFoundException", I actually know really less about those things..
You're almost there! You're just printing out the filename instead of calling that method.
See this?
if(returnVal==JFileChooser.APPROVE_OPTION) {
FileName=chooser.getSelectedFile().getName();
System.out.println(FileName);
}
Instead of (or before or after, if you prefer) System.out.println(FileName);, just put countChar();.
you just assign file name in FileName instead of file path.
so you use this
if(returnVal==JFileChooser.APPROVE_OPTION) {
FileName=chooser.getSelectedFile().getAbsolutePath();
countChar();
because if file is in same directory where you project is then work but when selected file reside in different places then need to use absolutepath of selected file.

Categories