Manipulating Strings in a File Scanner ~ Java - java

I was given a file that has list of names phone numbers, calls in and out ect... Like this
Adams#Marilyn#8233331109#0#0#01012014#C
Anderson#John#5025559980#20#15#12152013#M
Baker-Brown#Angelica#9021329944#0#3#02112014#C
The # are delimiters between data items and each line has the call status as the last item.
I need to know how I can display each persons information on the screen in a format such as:
Name Phone Calls Out Calls In Last Call
Marilyn Adams (823) 333-1109 0 0 01-01-2104
John Anderson (502) 555-9980 20 15 12-15-2013
Angelica Baker-Brown (859) 254-1109 11 5 02-11-2014
I have to use substring method to extract the phone number and add parentheses/dashes ect...
So Far my code looks like this
Also I am in a beginners Java coding class....
import java.util.Scanner;
import java.io.*;
public class phonedata2_1 {
public static void main(String[] args) throws IOException {
String Phonefile, FirstName, LastName;
Scanner PhoneScan, fileScan;
System.out.println(" Name Phone Calls Out Calls In Last Call Status");
fileScan = new Scanner(new File("phonedata.txt"));
while (fileScan.hasNext()) {
Phonefile = fileScan.nextLine();
PhoneScan = new Scanner(Phonefile);
PhoneScan.useDelimiter("#");
System.out.println(PhoneScan.next() + " "
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next() + "\t"
+ PhoneScan.next());
}
System.out.println("\nTotal outgoing calls for the period: " + "\nTotal incoming calls for the period: \n");
}
}

Finds every "data-segment" by using regex, then splits it with # as delimiter and prints it:
File blub = new File("blub.txt");
Scanner scanner = null;
try
{
scanner = new Scanner(blub);
}
catch (FileNotFoundException e){}
while(scanner.hasNext("((\\S*)#){6}(\\w)"))
{
String buffer = scanner.next("((\\S*)#){6}(\\w)");
for(String value : buffer.split("#"))
System.out.print(value + " ");
System.out.println();
}
Output:
Adams Marilyn 8233331109 0 0 01012014 C
Anderson John 5025559980 20 15 12152013 M
Baker-Brown Angelica 9021329944 0 3 02112014 C
Note:
You can use any whitespace character to separate each data-segment in the input file, so even spaces are okay or tabs(or crazy mix with empty lines and so on).
For farther use of data:
you could add your data in an arraylist since buffer.split("#") gives you an array of the data-segment, so you can output it easier with your desired changes to each value.(or in a different order)

You can use the .split(String regex) to split the line you are reading by throwing in the # as a delimeter. This will yield an array which you can traverse and print the contents accordingly. Also, it would seem that besides the initial line, all call data starts with a , so you could use split twice to parse your text file:
EDIT: Seeing your comment, I also realized that afterwards, however, since the .split() method takes a regex as parameter, it means that this problem can be walked around without much hassle. My example is as follows:
String str = "Adams#Marilyn#8233331109#0#0#01012014#C Anderson#John#5025559980#20#15#12152013#M Baker-Brown#Angelica#9021329944#0#3#02112014#C";
String[] lines = str.split(" ");
System.out.println("Name\tPhone\tCalls\tOut\tCalls In\tLast Call");
for(String line : lines)
{
String[] lineInfo = line.split("#");
for(String info : lineInfo)
{
System.out.print(info + "\t");
}
System.out.println();
}
I had to add some extra tabs manually, but this is the output:
Name Phone Calls Out Calls In Last Call
Adams Marilyn 8233331109 0 0 01012014 C
Anderson John 5025559980 20 15 12152013 M
Baker-Brown Angelica 9021329944 0 3 02112014 C

Something like this should work. You still need to do all the manipulation of the phone number yourself, but all the data will be in the call info so you should be able to work from that!
while (fileScan.hasNext())
{
//Get a single record
Phonefile = fileScan.nextLine();
//Seperate the elements of the record
String[] callInfo = Phonefile.split("#");
for(String infoPart: callInfo)
{
System.out.print(infoPart+ "\t");
}
System.out.println()
}

Related

What is wrong in my file reading with Scanner class?

Every time I run it, gives this message (( InputMismatchException )) where is the problem from ?
File f = new File("nameList.txt");
try {
PrintWriter out;
out = new PrintWriter(f);
for (int i = 0; i < 4; i++) {
out.printf("Name : %s Age : %d ", "Rezaee-Hadi", 19);
out.println("");
}
out.close();
} catch (IOException ex) {
System.out.println("Exception thrown : " + ex);
}
try {
Scanner in = new Scanner(f);
String name = in.nextLine();
int age = in.nextInt();
for (int i = 0; i < 4; i++) {
System.out.println(name);
System.out.println(age);
}
in.close();
} catch (FileNotFoundException ex) {
System.out.println("Exception thrown : " + ex);
}
You are creating your data file in the following data format:
Name : Rezaee-Hadi Age : 19
Now, it really doesn't matter (to some extent) how you format your data file as long as you realize that you may need to parse that data later on. You really don't need to maintain a header with your data on each file line. We already know that the first piece of data on any file line is to be a Name and the second piece of data on any file line is to be the Age of the person the Name relates to. So, the following is sufficient:
Rezaee-Hadi, 19
If you want, you can place a header as the very first line of the data file so that it can easily be determined what each piece of data on each line relates to, for example:
Name, Age
Rezaee-Hadi, 19
Fred Flintstone, 32
Tom Jones, 66
John Smith, 54
This is actually a typical format for CSV data files.
Keeping with the file data format you are already using:
There is nothing wrong with using the Scanner#nextLine() method. It's a good way to go but you should be iterating through the file line by line using a while loop because you may not always know exactly how many actual data lines are contained within the file, for example:
Scanner in = new Scanner(f);
String dataLine;
while (in.hasNextLine()) {
dataLine = in.nextLine().trim();
// Skip Blank Lines
if (dataLine.equals("")) {
continue;
}
System.out.println(dataLine);
}
This will print all the data lines contained within your file. But this is not what you really want is it. You want to separate the name and age from each line which means then that you need to parse the data from each line. One way (in your case) would be something like this:
String dataLine;
Scanner in = new Scanner(f);
while (in.hasNextLine()) {
dataLine = in.nextLine().trim();
// Skip Blank Lines
if (dataLine.equals("")) {
continue;
}
String[] dataParts = dataLine.replace("Name : " , "").split(" Age : ");
System.out.println("The Person's Name: " + dataParts[0] + System.lineSeparator()
+ "The Person's Age: " + dataParts[1] + System.lineSeparator());
}
In the above code we iterate through the entire data file one line at a time using a while loop. As each line is read into the dataLine string variable it is also trimmed of any leading or trailing whitespaces. Normally we don't want these. We then check to make sure the line is not blank. We don't normally want these either and here we skip past those blank lines by issuing a continue to the while loop so as to immediately initiate another iteration. If the file line line actually contains data then it is held within the dataLine variable.
Now we want to parse that data so as to retrieve the Name and the Age and place them into a String Array. We do this by using the String#split() method but first we get rid of the "Name : " portion of the line using the String#replace() method since we don't want to deal with this text while we parse the line. In the String#split() method we supply a string delimiter to split by and that delimiter is " Age : ".
String[] dataParts = dataLine.replace("Name : " , "").split(" Age : ");
Now when each line is parsed, the Name and Age will be contained within the dataParts[] string array as elements located at index 0 and index 1. We now use these array elements to display the results to console window.
At this point the Age is a string located in the dataParts[] array at index 1 but you may want to convert this age to a Integer (int) type value. To do this you can utilize the Integer.parseInt() or Integer.valueOf() methods but before you do that you should validate the fact the the string you are about to pass to either of these methods is indeed a string numerical integer value. To do this you would utilize the String#matches() method along with a simple little Regular Expression (RegEx):
int age = 0;
if (dataParts[1].matches("\\d+")) {
age = Integer.parseInt(dataParts[1]);
// OR age = Integer.valueOf(dataParts[1]);
System.out.println("Age = " + age);
}
else {
System.out.println("Age is not a numerical value!");
}
The regular expression "\\d+" placed within the String#matches() method basically means, "Is the supplied string a string representation of a integer numerical value?". If the method finds that it is not then boolean false is returned. If it finds that the value supplied is a string integer numerical value then boolean true is returned. Doing things this way will prevent any NumberFormatException's from occurring.
Replace this:
int age=0;
while (in.hasNext()) {
// if the next is a Int,
// print found and the Int
if (in.hasNextInt()) {
age = in.nextInt();
System.out.println("Found Int value :"
+ age);
}
}
in place of this:
int age = in.nextInt();
Then you will not get "InputMismatchException" anymore..

cannot split a specific kind of strings using Java

I am working in Java. I have list of parameters stored in a string which is coming form excel. I want to split it only at starting hyphen of every new line. This string is stored in every excel cell and I am trying to extract it using Apache poi. The format is as below:
String text =
"- I am string one\n" +
"-I am string two\n" +
"- I am string-three\n" +
"with new line\n" +
"-I am string-four\n" +
"- I am string five";
What I want
array or arraylist which looks like this
[I am string one,
I am string two,
I am string-three with new line,
I am string-four,
I am string five]
What I Tried
I tried to use split function like this:
String[] newline_split = text.split("-");
but the output I get is not what I want
My O/P
[, I am string one,
I am string two,
I am string, // wrong
three // wrong
with new line, // wrong
I am string, // wrong!
four, // wrong!
I am string five]
I might have to tweak split function a bit but not able to understand how, because there are so many hyphens and new lines in the string.
P.S.
If i try splitting only at new line then the line - I am string-three \n with new line breaks into two parts which again is not correct.
EDIT:
Please know that this data inside string is incorrectly formatted just like what is shown above. It is coming from an excel file which I have received. I am trying to use apache poi to extract all the content out of each excel cell in a form of a string.
I intentionally tried to keep the format like what client gave me. For those who are confused about description inside A, I have changed it because I cannot post the contents on here as it is against privacy of my workplace.
You can
remove line separators (replace it with space) if they don't have - after it (in next line): .replaceAll("\\R(?!-)", " ") should do the trick
\R (written as "\\R" in string literal) since Java 8 can be used to represent line separators
(?!...) is negative-look-ahead mechanism - ensures that there is no - after place in which it was used (will not include it in match so we will not remove potential - which ware matched by it)
then remove - placed at start of each line (lets also include followed whitespaces to trim start of the string). In other words replace - placed
after line separators: can be represented by "\\R"
after start of string: can be represented by ^
This should do the trick: .replaceAll("(?<=\\R|^)-\\s*","")
split on remaining line separtors: .split("\\R")
Demo:
String text =
"- I am string one\n" +
"-I am string two\n" +
"- I am string-three\n" +
"with new line\n" +
"-I am string-four\n" +
"- I am string five";
String[] split = text.replaceAll("\\R(?!-)", " ")
.replaceAll("(?<=\\R|^)-\\s*","")
.split("\\R");
for (String s: split){
System.out.println("'"+s+"'");
}
Output (surrounded with ' to show start and end of results):
'I am string one'
'I am string two'
'I am string-three with new line'
'I am string-four'
'I am string five'
This is how I would do:
import java.util.*;
public class MyClass {
public static void main(String args[]) {
String A = "- I am string one \n" +
" -I am string two\n" +
" - I am string-three \n" +
" with new line\n" +
" -I am string-four\n" +
"- I am string five";
String[] s2 = A.split("\r?\n");
List<String> lines = new ArrayList<String>();
String line = "";
for (int i = 0; i < s2.length; i++) {
String ss = s2[i].trim();
if (i == 0) { // first line MUST start with "-"
line = ss.substring(1).trim();
} else if (ss.startsWith("-")) {
lines.add(line);
ss = ss.substring(1).trim();
line = ss;
} else {
line = line + " " + ss;
}
}
lines.add(line);
System.out.println(lines.toString());
}
}
I hope it helps.
A little explanation:
I will process line by line, trimming each one.
If it starts with '-' it means the end of the previous line, so I include it in the list. If not, I concatenate with the previous line.
looks as if you are splitting the FIRST - of each line, so you need to remove every instance of a "newline -"
str.replace("\n-", '\n')
then Remove the initial "-"
str = str.substring(1);

Error in reading a file in java

I've been trying to practice I/O file programming and I'm still at the basics. Writing into a file using the java was simple enough but reading to a file is beginning to give me a headache. Here's a simple program I tried to run(btw, I based the program from a book by Liang) .
import java.util.Scanner;
import java.io.File;
public class Reading {
private static Scanner n;
public static void main(String[] args) throws Exception
{
File files = new File("samples.txt");
n = new Scanner(files);
while(n.hasNext())
{
String firstName = n.next();
String mi = n.next();
String lastName = n.next();
int score = n.nextInt();
System.out.println(
firstName + " " + mi + " " + lastName + " " + score);
}
n.close();
}
}
Here's the error:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at java.util.Scanner.nextInt(Unknown Source)
at OOPFinals.Reading.main(Reading.java:17)
How do I make this program work?
Help!
The NoSuchElementException is thrown by Scanner.next() and means there are no more tokens to be found in the file.
The problem here is that your while() loop only guarantees that there is at least ONE token left to read from the file, however on each iteration of the loop you are reading in FIVE tokens.
What is happening in your code, you are trying to read from the Scanner although there's nothing left there to read.
What you should do - You need to check n.hasNext() before each call to n.next() or n.nextInt(), or just read the entire line (which seems exactly what you want):
while (n.hasNextLine()) {
String line = n.nextLine();
System.out.println(line);
}
Your code is working given that the right input file "samples.txt" is provided. For example, given the following input:
Richard Phillips Feynman 100
Paul Adrien Dirac 90
Everything works fine, however if you use the following:
Richard Feynman 100
Paul Adrien Dirac 90
then you obtain the NoSuchElementException. In the last example, I removed the middle name that your program is expecting. As such, we can conclude that you are expecting to read information in a file with no information left to read. I recommend something like the following:
import java.util.Scanner;
import java.util.StringTokenizer;
import java.io.File;
public class Reading {
private static Scanner n;
public static void main(String[] args) throws Exception
{
File files = new File("samples.txt");
n = new Scanner(files);
String data;
while(n.hasNextLine() && !(data = n.nextLine()).equals(""))
{
StringTokenizer st = new StringTokenizer(data);
if(st.countTokens() >= 4) {
String firstName = (String) st.nextElement();
String mi = (String) st.nextElement();
String lastName = (String) st.nextElement();
int score = Integer.parseInt( (String) st.nextElement());
System.out.println(
firstName + " " + mi + " " + lastName + " " + score);
} else {
System.err.println("This line is malformed!");
}
}
n.close();
}
}
In this program, you can have a sample file that has empty lines and it expects to read 4 tokens per line or else it prints an error message informing you that a line has malformed input.
Sometimes when you're reading a file you'll run into various characters. Some are letters, some are numbers, and some are integers. You need to check whether it's a letter, number, or an integer because the following line assumes you are passing an integer:
int score = n.nextInt();
It can be resolved by checking for integers:
int score = 0;
if(n.hasNextInt()) { score = n.nextInt(); }
When you're reading from the program, make sure to take Cathial's answer into consideration. By using hasNext(), you're only checking if there is one string, also known as a token. You should check if there are n strings available where n is the number of .next() functions in your loop.

Replacing a particular word in a scanned in string and concatenating using substring() in Java

I'm brand new to all of this so I am trying to write a simple bit of code that allows the user to type in text (saved as a string) and then have the code search for the position of a word, replace it and join the string back together. I.e.:
'I like foo for lunch'
foo is found at position 7
The new input is: I like Foo for lunch
Here is what I have thus far:
import java.util.Scanner;
public class FooExample
{
public static void main(String[] args)
{
/** Create a scanner to read the input from the keyboard */
Scanner sc = new Scanner (System.in);
System.out.println("Enter a line of text with foo: ");
String input = sc.nextLine();
System.out.println();
System.out.println("The string read is: " + input);
/** Use indexOf() to position of 'foo' */
int position = input.indexOf("foo");
System.out.println("Found \'foo\' at pos: " + position);
/** Replace 'foo' with 'Foo' and print the string */
input = input.substring(0, position) + "Foo";
System.out.println("The new sentence is: " + input);
The problem is occurring at the end -- where I am stumped on how to tack the rest of the sentence on to the concatenation:
input = input.substring(0, position) + "Foo";
I can get the word to be replaced but I am scratching my head over how to get the rest of the string attached on.
input = input.substring(0,position) + "Foo" + input.substring(position+3 , input.length());
or simply you can use replace method.
input = input.replace("foo", "Foo");
Slight update to what Achintya posted, to take into account you don't want to include "foo" again:
input = input.substring(0, position) + "Foo" + input.substring(position + 3 , input.length());
This may be overkill, but if you are looking for words in sentences, you could easily use StringTokenizer
StringTokenizer st = new StringTokenizer(input);
String output="";
String temp = "";
while (st.hasMoreElements()) {
temp = st.nextElement();
if(temp.equals("foo"))
output+=" "+"Foo";
else
output +=" "+temp;
}

Having trouble reading files in java

I have some trouble reading file in Java.
What a file looks like:
Answer 1:
1. This is an apple
2. Something
Answer 2:
1. This is a cool website
2. I love banana
3. This is a table
4. Programming is fun
Answer 3.
1. Hello World
....
What I want to do is separate them into two items:
One is the Answer number; The other one is list of answers.
So assuming I have a object class called Answer:
String of answer number
List of answers.
This is what I have done so far to debug my code before I put it into object class. But I'm not able to get the correct result
public void reader(String file) throws FileNotFoundException, IOException {
FileReader fR = new FileReader(file);
BufferedReader bR = new BufferedReader(fR);
String line = null;
int count = 0 ;
String blockNum = "";
String printState = "" ;
while ((line = bR.readLine()) != null) {
if(line.contains("Answer")){
//System.out.println("Contain Answer statement: " + line);
count++;
blockNum = line;
printState = "";
}
else{
//System.out.println("No Answer Statement: " + line);
printState += line + " / " ;
}
System.out.println( count + " " + blockNum + " " + printState );
}
// Close the input stream
bR.close();
fR.close();
}
I'm pretty sure I did something stupid while I'm coding. I'm not too sure how to read it so that it will have separate it.
Right now the output looks like this:
1 Answer 1:
1 Answer 1: 1. This is an apple /
1 Answer 1: 1. This is an apple / 2. Something /
2 Answer 2:
2 Answer 2: 1. This is a cool website /
2 Answer 2: 1. This is a cool website / 2. I love banana /
2 Answer 2: 1. This is a cool website / 2. I love banana / 3. This is a table /
2 Answer 2: 1. This is a cool website / 2. I love banana / 3. This is a table / 4. Programming is fun /
3 Answer 3.
3 Answer 3. 1. Hello World /
But I want the output to be something like this:
1 Answer 1: 1. This is an apple / 2. Something /
2 Answer 2: 1. This is a cool website / 2. I love banana / 3. This is a table / 4. Programming is fun /
3 Answer 3. 1. Hello World /
You are printing a line of output for each line of input you read. Try moving the println inside the part of the loop that checks for answer to make sure you print each answer/answer value set only once. E.g.:
if(line.contains("Answer")) {
if (printState != "") {
System.out.println(count + " " + blockNum + " " + printState);
}
...
}
EDIT: You will also need to print when you exit the while loop to make sure you print the last answer/answer value set.
One solution use a flag for printTime as a boolean.
boolean printTime = false;
...
if(line.contains("Answer")) {
if (printTime!= false) {
System.out.println( count + " " + blockNum + " " + printState );
printTime=false;
}
...
}else{
//System.out.println("No Answer Statement: " + line);
printState += line + " / " ;
printTime=true; // you have one answer
}
...
add a little extra print at the end of the while for last answer
that way you can have several printState for one answer in one line.
But correct "java" way of handle this is to create your objects:
List<Answer> listOfAnswer = new LinkedList<Answer>();
Answer answer;
...
if(line.contains("Answer")){
//System.out.println("Contain Answer statement: " + line);
count++;
answer = new Answer(line);
listOfAnswer.add(answer)
}
else{
answer.add(new Answer(line));
}
}
...
and only after print them out :)
System.out.println(listOfAnswer.toString());
Simpler solution is to use a
Map<Integer, LinkedList<String>> answers = new LinkedHashMap<Integer, LinkedList<String>();
The main output issue is that you are printing inside the line-iterating loop (while).
To solve it, you can follow what #Albion answered and change where the print is done inside the while, but as the EDIT on his answer states, there is a flaw and you will have to print an extra time after the loop, in order to get the correct result.
There is an alternative tough, that is to not print it inside the loop at all, which i consider to be the correct approach in your case. To do it, you need little more than using StringBuilder instead of String!
I have also spotted some needless variables, and there is also a flaw in using the if(line.contains("Answer")) method, that is that if "Answer" string appears inside one of the options texts, it will get a true and mess your results, for example:
Answer 1:
1. This is an apple
2. Capitalizing Is The Answer!
3. Something
Will output:
1 Answer 1: 1. This is an apple /
2 2. Capitalizing Is The Answer! 3. Something
In most cases, the best approach to finding a dynamic pattern (as yours is, for it changes the number and, in the last Answer, the ':' with a '.' too) is to use a (pattern) Matcher! I used this: if(line.matches("Answer \\d[\\:\\.]")), and if you are not yet used to it, see the Pattern Docs, as String.matches() is something you will probably use a lot when processing text.
Explaining every single change is a little troublesome, and the code is simple enough for you master after you analyse it, so i'll simply post what my approach would be:
public static void StackAnswer(String file) throws FileNotFoundException, IOException{
BufferedReader br = new BufferedReader(new FileReader(file));
StringBuilder output = new StringBuilder();
int count = 0;
while(br.ready()){
String line = br.readLine().trim();
if(line.matches("Answer \\d[\\:\\.]")){
count++;
output.append(System.lineSeparator()).append(count).append(' ').append(line);
} else {
output.append(" / ").append(line);
}
}
System.out.println(output.toString().trim());
br.close();
}
Good luck!
See working example:
public void reader(String file) throws FileNotFoundException,
IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = "";
while (reader.ready()) {
line = reader.readLine();
if (!line.contains("Answer")) {
System.out.print(line + " / ");
} else {
System.out.println();
System.out.print(line + " ");
}
}
}

Categories