TomCat - Constructor threw exception when trying to read from File - java

I have some methods below and basically my issue is when I try to read from a .txt file. The application works fine in memory. When I add the decode() to the overloaded constructor I get the following error in Tomcat Server logs:
Constructor threw exception; nested exception is java.lang.NumberFormatException: For input string: ""
When I look more at this it points to this line in the decode method
currentDVD.setDvdId(Integer.parseInt((currentTokens[0]))); but I can't seem to figure out what the issue is. At one point I was able to read from the file and then I was trying to get the encode method to work and something happened at some point. Any help would be appreciated.
public class DvdLibraryInFileImpl implements DvdLibraryDao {
private Map<Integer, DVD> dvdMap = new HashMap<>();
public static final String DVD_FILE = "dvd.txt";
public static final String DELIMITER = "::";
private static int dvdIdCounter = 0;
public DvdLibraryInFileImpl() throws FileNotFoundException {
decode();
}
#Override
public DVD addDVD(DVD dvd) {
dvd.setDvdId(dvdIdCounter);
dvdIdCounter++;
dvdMap.put(dvd.getDvdId(), dvd);
return dvd;
}
#Override
public DVD getDVDById(int dvdId) {
return dvdMap.get(dvdId);
}
#Override
public List<DVD> getAllDVDSByName(String searchByName) {
throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public List<DVD> getAllDVDS() {
List<DVD> allDVDS = new ArrayList<>(dvdMap.values());
return allDVDS;
}
#Override
public void updateDVD(DVD dvd) {
dvdMap.put(dvd.getDvdId(), dvd);
}
#Override
public void removeDVD(int dvdId) {
dvdMap.remove(dvdId);
}
#Override
public void decode() throws FileNotFoundException {
Scanner sc = new Scanner(new BufferedReader(new FileReader(DVD_FILE)));
String[] currentTokens;
while (sc.hasNextLine()) {
String currentLine = sc.nextLine();
currentTokens = currentLine.split(DELIMITER);
DVD currentDVD = new DVD();
currentDVD.setDvdId(Integer.parseInt((currentTokens[0])));
currentDVD.setTitle(currentTokens[1]);
currentDVD.setReleaseDate(currentTokens[2]);
currentDVD.setMpaaRating(currentTokens[3]);
currentDVD.setDirectorsName(currentTokens[4]);
currentDVD.setStudio(currentTokens[5]);
currentDVD.setUserRating(currentTokens[6]);
dvdMap.put(Integer.parseInt((currentTokens[0])), currentDVD);
}
}
#Override
public void encode() throws IOException {
PrintWriter out = new PrintWriter(new FileWriter(DVD_FILE));
Set<Integer> keySet = dvdMap.keySet();
for (Integer i : keySet) {
out.print((dvdMap.get(i)).getDvdId());
out.print(DELIMITER);
out.print((dvdMap.get(i)).getTitle());
out.print(DELIMITER);
out.print((dvdMap.get(i)).getReleaseDate());
out.print(DELIMITER);
out.print((dvdMap.get(i)).getMpaaRating());
out.print(DELIMITER);
out.print((dvdMap.get(i)).getDirectorsName());
out.print(DELIMITER);
out.print((dvdMap.get(i)).getStudio());
out.print(DELIMITER);
out.print((dvdMap.get(i)).getUserRating());
out.println("");
}
out.flush();
out.close();
}
}

The problem is because currentLine does NOT have the proper input data received (from user entry).
You should ensure that currentTokens is having proper DvdId set (should be numeric value), otherwise Integer.parseInt((currentTokens[0])) line will throw NumberFormatException for non-numeric or empty ("") data.
You need to ensure that the input data entered is correct with numeric dvdid.
For example, enter below data:
1234::DVDTITLE::29-OCT-2016::RATING1::DIRECTOR::STUDIO::RATING2
I strongly recommend you to add the input validations to handle the scenarios like entering the non-numeric values or rating higher that max value or director name containg numeric values, etc....

Related

Saving multiple input data in one .txt file. Is it possible to overwrite and get data from specific line?

Code first:
import java.io.*;
import java.util.Scanner;
public class Test {
public String date;
public String fridge1;
public String fridge2;
public String info;
static final int lineNumber = 0;
public Test(String date, String fridge1, String fridge2, String info) {
this.date = date;
this.fridge1 = fridge1;
this.fridge2 = fridge2;
this.info = info;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getFridge1() {
return fridge1;
}
public void setFridge1(String fridge1) {
this.fridge1 = fridge1;
}
public String getFridge2() {
return fridge2;
}
public void setFridge2(String fridge2) {
this.fridge2 = fridge2;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
#Override
public String toString() {
return
date + "\n" +
fridge1 + "\n" +
fridge2 + "\n" +
info + "\n";
}
public void saveData() {
File file = new File("text.txt");
boolean checker = true;
try (Scanner scanner = new Scanner(file)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.contains(date)) {
checker = false;
break;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (checker) {
try (FileOutputStream fos = new FileOutputStream("text.txt", true)) {
fos.write(toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
}
} else {
...
}
}
}
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
// Test test = new Test("19/02/1992", "10", "9", "ok");
// test.saveData();
Test test2 = new Test("19/02/1900", "8", "4", "not ok");
test2.saveData();
}
}
I want to do program in Java to get some inputs and date, mostly Strings. I just create a methods to write all data in one .txt file, one data - 1 line. If there is already existing date program is not writing new data. Finally, I would like to overwrite data. If I put the same date in, I would like to overwrite existing date to new one. So in my mind if I have in .txt file this data:
line1 17/05/16 line2 blabla line3 blabla line4 blabla
and I will put in Main this:
Test test2 = new Test("17/05/16", "8", "4", "not ok");
test2.saveData();
it should find where is 17/05/16 and then replace lines 2-4 like this.
line1 17/05/16
line2 8
line3 4
line4 not ok
It is possible? Then how to find out all data in reverse way? In mean when I would like to check my data from specific date ex. 17/05/16?
As you can see I just stuck in moment when I have to search where is my data. I can't find good methods.
When your program does start, your first step must always be reading whole text file into memory, line by line. Visit this page how you can achive it. Use your timestamp as key for the HashMap.
One advantage of HashMap is, you can easily check of occurences or add some data at the end. And if you want just update an existing entry, use the same key and the content will be overwritten.
After this, the next page demonstrate how to write the content back to your text file.
Please note: As I wrote in comment section the use of Spring Boot is a better option for your task.

Text not found in .txt , but it's already there

I am going through Mooc.fi Java course and I can't figure how not to write String into file if the file already contains it. I tried only with one String and tried without " " (empty space), and without another string, but still it adds the string even when the file already contains it.
And translate() method doesn't find/return whole line in which it found the given word.
public class main {
public static void main(String[] args) throws Exception {
MindfulDictionary dict = new MindfulDictionary();
dict.add("apina", "monkey");
dict.add("banaani", "banana");
dict.add("apina", "apfe");
System.out.println( dict.translate("apina") );
System.out.println( dict.translate("monkey") );
System.out.println( dict.translate("programming") );
System.out.println( dict.translate("banana") );
}
}
public class MindfulDictionary {
File file;
FileWriter writer;
Scanner imeskanera;
public MindfulDictionary() throws Exception {
this.file = new File("C:\\Users\\USER\\Desktop\\test.txt");
this.imeskanera = new Scanner(this.file, "UTF-8");
}
public void add(String word, String translation) throws Exception {
boolean found = false;
while(this.imeskanera.hasNextLine()) {
String lineFromFile = this.imeskanera.nextLine();
if(word.contains(lineFromFile)) {
found = true;
break;
}
}
if(!found) {
this.writer = new FileWriter(this.file,true);
this.writer.write(word +" " + translation +"\n");
this.writer.close();
}
}
public String translate(String word) throws Exception {
String line = null;
while(this.imeskanera.hasNextLine()) {
String data = this.imeskanera.nextLine();
if(data.contains(word)) {
line = data;
break;
}
}
return line;
}
}
The problem is that your Scanner object has already been consumed by the add() method. You need to reopen the input stream in order to read the contents of the file. If you add
this.imeskanera = new Scanner(this.file, "UTF-8");
At the beginning of the translate() method, it should word. Which basically tell you that there is no need for Scanner to be a global field. Use it locally in each method. This is how I have explain the concept of file streams in the past:
Think about file streams (for reading and writing) logically. You
cannot allow for such a stream to be "circular". Otherwise, when you
try to get the "next line", there will always be a next line and you
will never be able to stop reading (or writing). The stream is
consumed when it reach the end, and once that is done, to go back to
the beginning of the stream, you will need to open a new one; not
reuse the old one.
I thought I needed to add this explanation even after the answer was accepted because I know new developer struggle with this concept and it because of that, it is necessary to explain it in detail.
With that said, your MindfulDictionary class should look like this:
public class MindfulDictionary {
File file;
FileWriter writer;
// Scanner imeskanera;
public MindfulDictionary() throws Exception {
this.file = new File("test.txt"); // I changed the path to the file to make it work for me. You can change it back if you want to.
file.createNewFile();
}
public void add(String word, String translation) throws Exception {
Scanner imeskanera = new Scanner(this.file, "UTF-8");
boolean found = false;
while (imeskanera.hasNextLine()) {
String lineFromFile = imeskanera.nextLine();
if (word.contains(lineFromFile)) {
found = true;
break;
}
}
if (!found) {
this.writer = new FileWriter(this.file, true);
this.writer.write(word + " " + translation + "\n");
this.writer.close();
}
imeskanera.close();
}
public String translate(String word) throws Exception {
Scanner imeskanera = new Scanner(this.file, "UTF-8");
String line = null;
while (imeskanera.hasNextLine()) {
String data = imeskanera.nextLine();
if (data.contains(word)) {
line = data;
break;
}
}
imeskanera.close();
return line;
}
}
I ran your code with my modifications and now the output is
apina monkey
apina monkey
null
banaani banana
In addition to the Scanner issue mentioned by the answer of #hfontanez, following changes.
if (word.contains(lineFromFile))
This checks if the first word contains the line, this is not true. The file contains the first word and translation. so this can be changed to
if (lineFromFile.contains(word))
as #ghostCat mentioned searching the key(word) can be refactored. Code with these changes.
public class MindfulDictionary {
File file;
FileWriter writer;
// Scanner imeskanera;
public MindfulDictionary() throws Exception {
this.file = new File("test.txt");
file.createNewFile();
}
public void add(String word, String translation) throws Exception {
if (get(word) == null) {
this.writer = new FileWriter(this.file, true);
this.writer.write(word + " " + translation + "\n");
System.out.println("Out>>:"+word + " " + translation + "\n");
this.writer.close();
}
}
private String get(String word) throws Exception {
Scanner imeskanera = new Scanner(this.file, "UTF-8");
boolean found = false;
String retStr= null;
while (imeskanera.hasNextLine()) {
String lineFromFile = imeskanera.nextLine();
if (lineFromFile.contains(word)) {
found = true;
retStr=lineFromFile;
break;
}
}
imeskanera.close();
return(retStr);
}
public String translate(String word) throws Exception {
return get(word);
}
public static void main(String[] args) throws Exception {
MindfulDictionary dict = new MindfulDictionary();
dict.add("apina", "monkey");
dict.add("apina", "monkey");
dict.add("banaani", "banana");
dict.add("apina", "apfe");
System.out.println( dict.translate("apina") );
System.out.println( dict.translate("monkey") );
System.out.println( dict.translate("programming") );
System.out.println( dict.translate("banana") );
}
}

trying to make a function in a object class that divides text file to parts (Java)

I am trying to divide a text file to 150 parts, so I made a function in the object class itself.
This is the full object class :
public TehilimEpisode(int EpisodeID, String[] ab)
{
this.EpisodeID=EpisodeID;
this.Perek=ab;
}
public static void setperek(TehilimEpisode[] pirkoni) throws IOException
{
BufferedReader inputReader = new BufferedReader(new FileReader("C:\\\\*.txt"));
String nextLine; String[] ab;
while ((nextLine = inputReader.readLine()) != null)
{
for(int i=1; i<=150;i++)
{
ab = nextLine.split("$");
pirkoni[i] = new TehilimEpisode(i, ab);
}
}
for(int i=1; i<=150; i++)
pirkoni.toString();
}
#Override
public String toString() {
return String.format(EpisodeID + " & " + Arrays.toString(Perek));
}
#Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
#Override
public boolean equals(Object obj) {
// TODO Auto-generated method stub
return super.equals(obj);
}
#Override
protected void finalize() throws Throwable {
// TODO Auto-generated method stub
super.finalize();
}
#Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}
}
The function name is setperek. when I am trying to run the function from the main class, it is writing this error :
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at TehilimEpisode.setperek(TehilimEpisode.java:25)
at main.main(main.java:48)
You have to read the whole txt in single string then split it by "$".Here is the example in which I use delimiter \\z that read the whole file in single string and then I split the string by "$".In below example we read the whole book in single line then split it into episode by "$" as you added in your book at the end of episode.
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class FileReadingWithScanner {
public static void main(String[] args) throws IOException {
File file = new File("D:\\book.txt");
String book = "";
Scanner sc = new Scanner(file);
/* Using this delimiter you will be able to read whole file in single line. */
sc.useDelimiter("\\Z");
book = sc.next();
String[] episodeArr = book.split("$");
//Do whatever you want.
}
}
Update
String.split() takes in regex as argument and $ is a metacharacter in Java regex API. Therefore, you need to escape it:
Use this book.split("\\$");
The problem is caused here: ab = scanner.nextLine().split("$"); pirkoni[i] = new TehilimEpisode(i, ab);. Imagine there's no next line. It will try to create the TehilimEpisode object with ab = null. To fix this you should check if there's a next line: for(int i=1; i<=150 && scanner.hasNextLine() ;i++). Select as answer if It worked! :D
Change your for loop to below, here i change scanner.nextLine() method to nextLine String.
while ((nextLine = inputReader.readLine()) != null)
{
for(int i=1; i<=150;i++)
{
ab = nextLine.split("$");
pirkoni[i] = new TehilimEpisode(i, ab);
}
}
There is no need for scanner class in your code, you already have BufferedReader to read the file. Having both is redundant.
toString() method override
Add something like below method to your class.
#Override
public String toString() {
return String.format(EpisodeID + " & " + Arrays.toString(Perek));
}

writeFile() method not working

I am trying to write to a text file. I am able to write to the console however, i am not able to write to my text file. One thing i have noticed is that String data doesn't contain any data if i were to just print to the console which is probably why nothing appears in my textfile. Does anyone know why that is though and how i can come about it?
writeFile() method code:
public static void writeFile(String filename, String content) throws IOException
{
try
{
Files.write(Paths.get(filename), content.getBytes()); // write file
}
catch (IOException e)
{
System.out.println("Error writing file: " + e);
}
}
Test code:
public class QuickTest {
public static void main(String... p) throws IOException {
List<SensorInfo> readings = new ArrayList<>();
SensorInfo info = null;
String data = createStringFromInfo(readings);
writeFile("datastore.txt", data);
String filedata = readFile("client-temp.txt");
List<SensorInfo> temps = createInfoFromData(filedata);
System.out.println(header());
for (SensorInfo reading : temps) {
System.out.print(reading.display());
}
}
}
CreateFromInfo Method:
public static String createStringFromInfo(List<SensorInfo> infoList)
{
String data = "";
for (SensorInfo info : infoList)
{
data += info.asData();
}
return data;
}
createInfoFromData
public static List<SensorInfo> createInfoFromData(String data)
{
List<SensorInfo> infoList = new ArrayList<>();
String[] lines = data.split("\n");
for (String line : lines)
{
SensorInfo info = new SensorInfo(line);
infoList.add(info);
}
return infoList;
}
That implementation of createStringFromInfo() confirms my guess: it will return an empty string when its argument is an empty list, as is the case in your program. I agree with you that that is why you get an empty file.
You fix it by filling the readings list with SensorInfo objects describing the information you want written to the file (before you invoke createStringFromInfo()). If the data for those SensorInfo objects should come from reading file "client-temp.txt" then you should read it in first, then pass that List to createStringFromInfo() to get the data to write.

AsyncTask Returns Error

I have been trying to parse XML files using Asynctask, following [1] and [2] tutorials. I have implemented a class in my Activity as follows:
private class GetRoutes extends AsyncTask<String, Void, String[]> {
#Override
protected String[] doInBackground(String... urls) {
String[] read;
try{
RouteReader route = new RouteReader();
read = route.getRoutes();
} catch(IOException iox){
read = new String[1];
read[0] = getResources().getString(R.string.loading_error);
} catch(ArrayIndexOutOfBoundsException aiob){
read = new String[1];
read[0] = getResources().getString(R.string.loading_error);
} catch(NullPointerException npe){
read = new String[1];
read[0] = getResources().getString(R.string.loading_error);
}
return read;
}
#Override
protected void onPostExecute(String[] result) {
values = result;
}
}
This is then called in my onCreate method as new GetRoutes().execute("test");.
However, when I try to run this, my app crashes as a result of a NullPointerException (logcat is available here).
Could you please guide me on how I can fix this?
For further reference, my RouteReader class is as follows:
public class RouteReader extends Reader{
public final static String routeURL =
"http://webservices.nextbus.com/service/publicXMLFeed?command=routeList&a=ttc";
private Map<String, String> routes;
public RouteReader()
throws IOException, ArrayIndexOutOfBoundsException{
super(new URL(routeURL));
routes = xmlToMap();
}
public String[] getRoutes(){
return (String[]) routes.keySet().toArray();
}
public String getRouteNum(String route){
return routes.get(route);
}
private Map<String, String> xmlToMap()
throws IOException, ArrayIndexOutOfBoundsException{
Map<String, String> data = new HashMap<String, String>();
String input;
do{
input = getReader().readLine();
if (input.startsWith("<route")){
String[] read = input.split("\"");
data.put(read[3], read[1]);
}
}while (!input.equals("</body>"));
return data;
}
}
from your log:
Caused by: java.lang.NumberFormatException: Invalid int: "1S"
this is probably caused in this line:
data.put(read[3], Integer.parseInt(read[1]));
We'll your log shows a NumberFormatException at RouteReader lines 35. That's not a NullPointerException - it's a failure to parse a string as an integer, because the string is "1S". You should work out what you want to do with invalid data, and handle it appropriately.
Additionally, you're comparing strings with == instead of equals, which is almost never what you want to do. Personally I wouldn't try to use string operations to parse the XML in the first place: use an XML parser... That's what it's there for. Your current approach is very brittle in the face of seemingly-harmless changes in the XML format.

Categories