how to print an extra element in 1d array without bound exception? - java

at the beginning I read the file and used split() method and stored each value in 1d array. i must store index 0 and 1 in a string value ans index 2,3 and 4 must be stored in 1d array because "supervisor" object arguments contains two string values(name and id) and 1d array (interests) the problem is at row 0 there is an extra interest (3 interests) and at row 1 and 2 there are two interests.
what i thought about is to store the interests in an arraylist (because the size is not static )and convert it back to 1d array but it did not work
tries to store the interests in 2d array and convert t back to 1d array but it did not work , while splitting the file i splitted (, and #) but i noticed at the end of every interest there is a #
so i kept the # and thought if i can do an if condition while reading the file. is there any simple idea to avoid the error?
the file supervisor.txt contains:
00023, Dr. Haneen, artificial intelligent, data mining, pattern recognition#
00013, Dr. Manar, database, network#
00011, Dr. Hajar, software engineering, games#
Code
public static void main(String[] args)throws Exception {
File supervisorFile=new File("supervisor.txt");
if (!supervisorFile.exists()) {
System.out.println("Sorry the file is not found!"); //checks if the file exists if no it terminates the program
System.exit(0);
}
supervisor sup=null;
String[]supArray=null;
Scanner supRead=new Scanner(supervisorFile);//read supervisor file
while (supRead.hasNext()) {
supArray=supRead.nextLine().split(",");
sup=addSupervisor(supArray);
//System.out.println(sup.toString());
}
}
public static supervisor addSupervisor(String[]arr){
String id=arr[0];
String name=arr[1];
String[] interest=new String[3];
for (int i = 0; i < interest.length; i++) { //here i tried to store all the interests
interest[i]=arr[2]+arr[3]+arr[4];
}//it prints artificial intelligent data mining pattern recognition# and then an indexOutOfBoundsException
return new supervisor(id,name,interest);
}

The solution is to use split with a limit parameter.
class Supervisor{
final String id;
final String name;
String[] fields;
Supervisor(String id, String name, String[] fields) {
this.id = id;
this.name = name;
this.fields = fields;
}
}
Path path = Paths.get("supervisor.txt");
List<Supervisor> supervisors = Files.lines(path, Charset.defaultCharset())
.filter(l -> l.endsWith("#"))
.map(l -> l.substring(0, l.length() - 1)) // Remove #
.map(l -> l.split(",\\s*", 3)) // "00013", "Dr. Manar", "database, network"
.filter(w -> w.length == 3)
.map(w -> new Supervisor(w[0], w[1], w[2].split(",\s*")))
.collect(Collectors.toList());

Use split & ArraysList
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import lombok.AllArgsConstructor;
#AllArgsConstructor
class Supervisor {
String id;
String name;
List<String> interest;
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.NO_CLASS_NAME_STYLE);
}
}
public class AMain {
public static void main(String[] args) {
String id, name, line;
String[] arr;
List<String> list = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader("file/supervisor.txt"))) {
while ((line = br.readLine()) != null) {
arr = line.trim().split(",");
list.addAll(Arrays.asList(arr));
if (list.size() > 2) {
id = list.get(0); // get id
list.remove(0); // remove id
name = list.get(0); // get name
list.remove(0); // remove name
System.out.println(new Supervisor(id, name, list));
}
list.clear(); // clear all
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Output
[id=00023,name= Dr. Haneen,interest=[ artificial intelligent, data mining, pattern recognition#]]
[id=00013,name= Dr. Manar,interest=[ database, network#]]
[id=00011,name= Dr. Hajar,interest=[ software engineering, games#]]

Your second and third line only has 4 Strings split up by a comma. That makes it 4 Strings in the Array. In your addSupervisor methode you are trying to access arr[4], the 5th String, which is out of bound.

You get an error because you are trying to use arr[4], but wioth the lines 2 and 3 the size of the array will be 4, so the maximum index you can use is 3.
I don't know for sue what Supervisor is, but would this work:
public static supervisoraddSupervisor(String[]arr){
String id=arr[0];
String name=arr[1];
String[] interest=new String[arr.length - 2];
for (int i = 0; i < interest.length; i++) {
interest[i]=arr[i + 2];
}
return new supervisor(id,name,interest);
}
Try it online!

First you should get the line and then work with it like you do. The problem is in the loop for where you suppose all the "supervisor" have 3 interests. Also you are storing all the interest in the first pos of the array:
for (int i = 0; i < interest.length; i++) { //here i tried to store all the interests
interest[i]=arr[2]+arr[3]+arr[4];
}
So I think you should use a function like this:
private static String[] extractInterest(String[] line) {
String[] res = new String[line.length - 2]; //There are two index that haven't got interest
for(int i = 0; i<res.length; ++i) {
res[i] = line[i+2].replaceFirst(" ", "").replace("#","");
}
return res;
}
And this is the "main":
public static void main(String[] args) {
File file = new File("Data.txt");
try (Scanner sc = new Scanner(file)) { //Will close the sc automatically
String[] line;
while(sc.hasNext()) {
line = sc.nextLine().split(",");
int id = Integer.parseInt(line[0]);
String name = line[1].replaceFirst(" ",""); //For delete first " "
String[] interest = extractInterest(line);
Supervisor s = new Supervisor(id,name,interest);
System.out.println(s.toString());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
A final advice, Java classes names must begin with uppercase by agreement. So you should change the name of your class "supervisor" to "Supervisor"

Related

search for multiple strings from a text file in java

I'm trying to search of multiple words given from a user ( i used array to store them in ) from one txt file , and then if that word presented once in the file it will be displayed and if it's not it won't.
also for the words itself , if it's duplicated it will search it once.
the problem now when i search for only one it worked , but with multiple words it keeps repeated that the word isn't present even if it's there.
i would like to know where should i put the for loop and what's the possible changes.
package search;
import java.io.*;
import java.util.Scanner;
public class Read {
public static void main(String[] args) throws IOException
{
Scanner sc = new Scanner(System.in);
String[] words=null;
FileReader fr = new FileReader("java.txt");
BufferedReader br = new BufferedReader(fr);
String s;
System.out.println("Enter the number of words:");
Integer n = sc.nextInt();
String wordsArray[] = new String[n];
System.out.println("Enter words:");
for(int i=0; i<n; i++)
{
wordsArray[i]=sc.next();
}
for (int i = 0; i <n; i++) {
int count=0; //Intialize the word to zero
while((s=br.readLine())!=null) //Reading Content from the file
{
{
words=s.split(" "); //Split the word using space
for (String word : words)
{
if (word.equals(wordsArray[i])) //Search for the given word
{
count++; //If Present increase the count by one
}
}
if(count == 1)
{
System.out.println(wordsArray[i] + " is unique in file ");
}
else if (count == 0)
{
System.out.println("The given word is not present in the file");
}
else
{
System.out.println("The given word is present in the file more than 1 time");
}
}
}
}
fr.close();
}
}
The code which you wrote is error prone and remember always there should be proper break condition when you use while loop.
Try the following code:
public class Read {
public static void main(String[] args)
{
// Declaring the String
String paragraph = "These words can be searched";
// Declaring a HashMap of <String, Integer>
Map<String, Integer> hashMap = new HashMap<>();
// Splitting the words of string
// and storing them in the array.
String[] words = new String[]{"These", "can", "searched"};
for (String word : words) {
// Asking whether the HashMap contains the
// key or not. Will return null if not.
Integer integer = hashMap.get(word);
if (integer == null)
// Storing the word as key and its
// occurrence as value in the HashMap.
hashMap.put(word, 1);
else {
// Incrementing the value if the word
// is already present in the HashMap.
hashMap.put(word, integer + 1);
}
}
System.out.println(hashMap);
}
}
I've tried by hard coding the values, you can take words and paragraph from the file and console.
The 'proper' class to use for extracting words from text is java.text.BreakIterator
You can try the following (reading line-wise in case of large files)
import java.text.BreakIterator;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import java.nio.file.Files;
import java.nio.file.Paths;
public class WordFinder {
public static void main(String[] args) {
try {
if (args.length < 2) {
WordFinder.usage();
System.exit(1);
}
ArrayList<String> argv = new ArrayList<>(Arrays.asList(args));
String path = argv.remove(0);
List<String> found = WordFinder.findWords(Files.lines(Paths.get(path)), argv);
System.out.printf("Found the following word(s) in file at %s%n", path);
System.out.println(found);
} catch (Throwable t) {
t.printStackTrace();
}
}
public static List<String> findWords(Stream<String> lines, ArrayList<String> searchWords) {
List<String> result = new ArrayList<>();
BreakIterator boundary = BreakIterator.getWordInstance();
lines.forEach(line -> {
boundary.setText(line);
int start = boundary.first();
for (int end = boundary.next(); end != BreakIterator.DONE; start = end, end = boundary.next()) {
String candidate = line.substring(start, end);
if (searchWords.contains(candidate)) {
result.add(candidate);
searchWords.remove(candidate);
}
}
});
return result;
}
private static void usage() {
System.err.println("Usage: java WordFinder <Path to input file> <Word 1> [<Word 2> <Word 3>...]");
}
}
Sample run:
goose#t410:/tmp$ echo 'the quick brown fox jumps over the lazy dog' >quick.txt
goose#t410:/tmp$ java WordFinder quick.txt dog goose the did quick over
Found the following word(s) in file at quick.txt
[the, quick, over, dog]
goose#t410:/tmp$

String Array Returns Null Values

In the following code I read text file with a list of movies and create a String array of the list of movies using a helper method. Within the method I am able to read and print each line of the file. However, when I attempt to iterate over the returned array in the main method I get only "null". Why is this happening. In my research so far, I have not been able to find a similar problem posted by someone else. Please help. Thanks.
import java.util.Random;
import java.util.Scanner;
import java.io.File;
public class GuessTheMovie {
public static void main(String[] args) throws Exception {
try {
// Create File and Scanner objects
File file = new File("movies.txt");
Scanner scanner = new Scanner(file);
// Create String array to store all movie titles
List<String> movies = createMoviesArray(scanner);
for (String movie : movies) {
System.out.println(movie);
}
/*
String[] movies = createMoviesArray(scanner);
for (int i = 0; i < movies.length; i++) {
System.out.println(movies[i]);
} */
} catch (Exception e) {
System.out.println("Could not find file.");
}
}
////////////////////////// HELPER METHODS ////////////////////////////////////
/*
// Create String array to store all movie titles
private static String[] createMoviesArray(Scanner scanner) {
int count = 0;
String[] movies; // = new String[500];
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(count + " : " + line);
count += 1;
}
movies = new String[count];
return movies;
}*/
private static List<String> createMoviesArray(Scanner scanner) {
List<String> movies = new ArrayList<>();
// get line count for the size of the array
while (scanner.hasNextLine()) {
movies.add(scanner.nextLine());
}
return movies;
}
That is quite normal, since you don't put any values in your array.
private static String[] createMoviesArray(Scanner scanner) {
int count = 0;
String[] movies; // = new String[500];
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(count + " : " + line);
count += 1;
}
movies = new String[count]; // all you do here, is create an array with 'count' spaces, all default values (being null)
return movies;
}
If you want to work like this, you have two options (that immediately jump to mind):
Use an array, and create a new one for after every read. This is very resource consuming, meaning: DON'T DO THIS
Since you don't know the number of elements before all are read: use a List.
private static List<String> createMoviesArray(Scanner scanner) {
List<String> movies = new ArrayList<>();
while (scanner.hasNextLine()) {
movies.add(scanner.nextLine());
}
return movies;
}
Just before return in the createMoviesArray() method you create a new array. You never add anything to that array and thus it is empty after returning from that method. You should make a new array before iterating over the file.
If you don't know the size of the file and how many lines it has you probably should use some Collection with dynamic size, like ArrayList.
With your line movies = new String[count]; you are creating a new array of Strings. At this point in time the array will contain only NULL values which. Nowhere in your code you are actually writing something into the array. Thats why your main method correctly prints null.
This is because you are not adding the data to the movies array, you are only initializing it.
If you were to print the movies object at the end of your helper method you would see that it also is null.
I suggest using an ArrayList as you don't know how large the array needs to be, it would then go something like this:
import java.util.Random;
import java.util.Scanner;
import java.io.File;
public class GuessTheMovie {
public static void main(String[] args) throws Exception {
try {
// Create File and Scanner objects
File file = new File("movies.txt");
Scanner scanner = new Scanner(file);
// Create String array to store all movie titles
ArrayList<String> movies = createMoviesArray(scanner); // change this to ArrayList
for (movie : movies) { // I used a foreach loop
System.out.println(movie);
}
} catch (Exception e) {
System.out.println("Could not find file.");
}
}
////////////////////////// HELPER METHODS ////////////////////////////////////
// Create String array to store all movie titles
private static String[] createMoviesArray(Scanner scanner) {
int count = 0;
ArrayList<String> movies = new ArrayList<String>(); // change to Array List
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(count + " : " + line);
count += 1;
movies.add(line); // Add to end of ArrayList
}
return movies;
}
You can do the same thing in this way also:-
package com.adddemo;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class GuessTheMovie {
public static void main(String[] args) throws Exception {
try {
// Create File and Scanner objects
File file = new File("C:\\Users\\lenovo\\Desktop\\movies.txt");
Scanner scanner = new Scanner(file);
// Create String array to store all movie titles
List movies = createMoviesArray(scanner);
for (int i = 0; i < movies.size(); i++) {
System.out.println(i+" : "+movies.get(i));
}
} catch (Exception e) {
System.out.println("Could not find file.");
}
}
////////////////////////// HELPER METHODS ////////////////////////////////////
// Create String array to store all movie titles
private static List createMoviesArray(Scanner scanner) {
int count = 0;
List movies = new ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(count + " : " + line);
count += 1;
movies.add(line);
}
return movies;
}
}

Splitting an arraylist and textfile

What I'm trying to do is add numbers from a .txt file and split it by ; into my ArrayList listR2. As of now it semi works, however the result is that only the last 2 persons score is added, the first persons score is just getting null.
Is it some problem with my split?
Any ideas how i get the program to write all the scores?
It is skipping lines (from your file) in your code because you have used
for (int i = 3; i < itemStudent.length; i++) {
String test = studin.readLine(); //<--- this is the error
listR2.add(test);
}
Instead use
String test = itemStudent[i]; // to add the scores into the listR2
First, your code:
BufferedReader studin = new BufferedReader(new FileReader(studentFile));
grader.Student student;
student = new Student();
String line, eNamn, fNamn, eMail;
ArrayList<String> listR = new ArrayList<String>();
ArrayList<String> listR2 = new ArrayList<String>();
//loop for the file and setters for first, lastname and email
while ((line = studin.readLine()) != null) {
if (line.contains(";")) {
//# you don't need regex to split on a single specific character
String[] itemStudent = line.split("[;]");
eNamn = itemStudent[0];
fNamn = itemStudent[1];
eMail = itemStudent[2];
//#why are you using the Student object if you never use it in any way ?
//#also you are always updating the same "Student". if you expect to add it to say an ArrayList,
//#you need to declare a new student at the beginning of the loop (not outside of it)
student.setFirstName(fNamn);
student.setLastName(eNamn);
student.setEmail(eMail);
//Loop for the sum of the tests
Integer sum = 0; //# why Interger, the "int" primitive is more than sufficient
for (int index = 3; index < itemStudent.length; index++) {
try {
sum += Integer.parseInt(itemStudent[index]);
listR.add(itemStudent[index]);
} catch (Exception ex) {} //very bad practice, nerver silently drop exceptions.
}
//# that part is just wrong in many ways, I guess it's some left over debug/testing code
//# this also makes you skip lines as you will read as many lines as you have elements (minus 3) in itemStudent
/*
for (int i = 3; i < itemStudent.length; i++) {
String test = studin.readLine();
listR2.add(test);
}
*/
System.out.println(eNamn + " " + fNamn + " " + eMail + " SUMMA:" + sum + " " );
//# you'll get a nice pointer address, but not it's values, you need to itterate the list to view it's content
System.out.println(listR2);
}
}
The //# mark my comments
and here a quick example displaying the object approach:
(may contains misspells/missing imports but otherwise should be fine the compiler should will you). to run it:
java Main "your_file"
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
class Student{
String fname;
String lname;
String mail;
int sum;
Student(String fn,String ln,String ml){
fname=fn;
lname=ln;
mail=ml;
sum=0;
}
void addScore(int n){
sum += n;
}
public String toString() {
return "Student: "+fname+" "+lname+", "+mail+" sum: "+sum;
}
}
try {
BufferedReader br = new BufferedReader(new FileReader(args[0]));
ArrayList<Student> stdnts = new ArrayList<Student>();
String line = br.readLine();
while (line != null) {
if (line.contains(";")) {
String[] stdnt_arr = line.split(";");
Student stdnt = new Student(stdnt_arr[0],stdnt_arr[1],stdnt_arr[2]);
for (int i = 3;i<stdnt_arr.length;i++){
try {
stdnt.addScore(Integer.parseInt(stdnt_arr[i]));
} catch (NumberFormatException e) {
//not a number
e.printStackTrace();
}
}
stdnts.add(stdnt);
System.out.println(stdnt.toString());
}
line = br.readLine();
}
} catch(IOException e){
//things went wrong reading the file
e.printStackTrace();
}
}
}

Reading a sequence until the empty line

I am writing a Java program. I need help with the input of the program, that is a sequence of lines containing two tokens separated by one or more spaces.
import java.util.Scanner;
class ArrayCustomer {
public static void main(String[] args) {
Customer[] array = new Customer[5];
Scanner aScanner = new Scanner(System.in);
int index = readInput(aScanner, array);
}
}
It is better to use value.trim().length()
The trim() method will remove extra spaces if any.
Also String is assigned to Customer you will need to create a object out of the String of type Customer before assigning it.
Try this code... You can put the file you want to read from where "stuff.txt" currently is. This code uses the split() method from the String class to tokenize each line of text until the end of the file. In the code the split() method splits each line based on a space. This method takes a regex such as the empty space in this code to determine how to tokenize.
import java.io.*;
import java.util.ArrayList;
public class ReadFile {
static ArrayList<String> AL = new ArrayList<String>();
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new FileReader("stuff.txt"));
String datLine;
while((datLine = br.readLine()) != null) {
AL.add(datLine); // add line of text to ArrayList
System.out.println(datLine); //print line
}
System.out.println("tokenizing...");
//loop through String array
for(String x: AL) {
//split each line into 2 segments based on the space between them
String[] tokens = x.split(" ");
//loop through the tokens array
for(int j=0; j<tokens.length; j++) {
//only print if j is a multiple of two and j+1 is not greater or equal to the length of the tokens array to preven ArrayIndexOutOfBoundsException
if ( j % 2 ==0 && (j+1) < tokens.length) {
System.out.println(tokens[j] + " " + tokens[j+1]);
}
}
}
} catch(IOException ioe) {
System.out.println("this was thrown: " + ioe);
}
}
}

Using a method to call individual strings from an array (looping)

This is the question from my assignment that I am unsure of:
The class is to contain a public method nextWord(). When a new line is read, use the String method .split("\s+") to create an array of the words that are on the line. Each call to the nextWord() method is to return the next word in the array. When all of the words in the array have been processed, read the next line in the file. The nextWord()method returns the value null when the end of the file is reached.
I have read the file, and stored each individual string in an array called tokenz.
I'm not sure how I can have a method called "nextWord" which returns each individual word from tokenz one at a time. Maybe I don't understand the question?
The last part of the question is:
In your main class, write a method named processWords() which instantiates the MyReader class (using the String "A2Q2in.txt"). Then write a loop that obtains one word at a time from the MyReader class using the nextWord() method and prints each word on a new line.
I've thought of ways to do this but I'm not sure how to return each word from the nextWord method i'm supposed to write. I can't increase a count because after the String is returned, anything after the return statement cannot be reached because the method is done processing.
Any help would be appreciated, maybe I'm going about this the wrong way?
Can't use array lists or anything like that.
Here is my code.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class A2Q2
{
public static void main (String [] args)
{
processWords();
}
public static void processWords()
{
MyReader reader = new MyReader("A2Q2.txt");
String[] words = new String[174];
words[0] = reader.nextWord();
System.out.println(words[0]);
}
}
class MyReader
{
static String name;
static BufferedReader fileIn;
static String inputLine;
static int tokensLength = 0;
static String[] tokens;
static int counter = 0;
// constructor.
public MyReader(String name)
{
this.name = name;
}
public static String[] readFile()
{
String[] tokenz = new String[174];
int tokensLength = 0;
try
{
fileIn = new BufferedReader (new FileReader(name));
inputLine = fileIn.readLine();
while(inputLine !=null)
{
tokens = inputLine.split("\\s+");
for (int i = 0 ; i < tokens.length; i++)
{
int j = i + tokensLength;
tokenz[j] = tokens[i];
}
tokensLength = tokensLength + tokens.length;
inputLine = fileIn.readLine();
}
fileIn.close();
}
catch (IOException ioe)
{
System.out.println(ioe.getMessage());
ioe.printStackTrace();
}
//FULL ARRAY OF STRINGS IN TOKENZ
return tokenz;
}
public static String nextWord()
{
String[] tokenzz = readFile();
//????
return tokenzz[0];
}
}
Here's a conceptual model for you.
Keep track of your MyReader's state to know which value to return next.
the following example uses tokenIndex to decide where to read at next.
class MyReader
{
String[] tokens;
int tokenIndex = 0;
public String nextWord()
{
if(tokens == null || tokens.length <= tokenIndex)
{
// feel free to replace this line with whatever logic you want to
// use to fill in a new line.
tokens = readNextLine();
tokenIndex = 0;
}
String retVal = tokens[tokenIndex];
tokenIndex++;
return retval;
}
}
Mind you, this isn't a complete solution(it doesn't check for the end of file for instance), only a demonstration of the concept. You might have to elaborate a bit.
Use a loop and process each element in the array, printing them one at a time?

Categories