I have a text file that holds data like this:
Jones,Mary,903452
4342,2.5,A
3311,4,B+
I'm using Scanner to read the file. This is my code:
while(reader.hasNextLine())
{
reader.useDelimiter(",");
String lastN = reader.next();
String firstN = reader.next();
String id = reader.nextLine();
String course1 = reader.next();
double credits = reader.nextDouble();
String grade = reader.nextLine();
}
But when I print the line on the console, the , on the last part of the line doesn't get delimited and it prints like this:
Jones, Mary, ,903452
4342, 2.5, ,A
6.5, ,3.569
My toString method on my class:
public String toString() {
return lastName + ", " + firstName + ", " + idNo + "\n"
+ courseOne + ", " + credits + ", " + grade;
I'm searched around for a solution. I tried reader.useDelimiter("[,]") and reader.useDelimiter(",|,") but still gives me the same output. How can I fix this?
From the Scanner's documentation:
This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.
(Emphasis mine) This means that the whole rest of the line is returned, including delimiters. Setting id to reader.next() wouldn't work because it sucks up everything until the next delimiter. A better solution would be to make it accept line breaks as a delimiter, like so:
reader.useDelimiter("[,\n]");
Related
I am trying to get my output to display double quotations around the abbreviations and also the translated abbreviations. However I have not covered escape sequences in my current class so I was wondering if there was another way to accomplish this. The workbook will not accept when I try with escape sequence.
I have tried escape sequence and using two single quotes ('' '') but neither have worked. Perhaps I am missing something and am fairly new to the java language. Just trying to learn the most efficient way from a fundamental standpoint.
import java.util.Scanner;
public class TextMsgExpander {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
String txtMsg;
String BFF = "best friend forever";
String IDK = "I don't know";
String JK = "just kidding";
String TMI = "too much information";
String TTYL = "talk to you later";
System.out.println("Enter text: ");
txtMsg = scnr.nextLine();
System.out.println("You entered: " + txtMsg);
System.out.println();
if(txtMsg.contains("BFF")) {
txtMsg = txtMsg.replace("BFF", BFF);
System.out.println("Replaced BFF with " + BFF);
} // above line is where I tried escape sequence
if(txtMsg.contains("IDK")) {
txtMsg = txtMsg.replace("IDK", IDK);
System.out.println("Replaced IDK with " + IDK);
}
if(txtMsg.contains("JK")) {
txtMsg = txtMsg.replace("JK", JK);
System.out.println("Replaced JK with " + JK);
}
System.out.println();
System.out.println("Expanded: " + txtMsg);
return;
}
}
Your output
Enter text:
You entered: IDK how that happened. TTYL.
Replaced IDK with I don't know
Replaced TTYL with talk to you later
Expanded: I don't know how that happened. talk to you later.
Expected output
Enter text:
You entered: IDK how that happened. TTYL.
Replaced "IDK" with "I don't know".
Replaced "TTYL" with "talk to you later".
Expanded: I don't know how that happened. talk to you later.
Have you tried this:
\"example text\"
So you would have something like this:
System.out.println("Replaced \"BFF\" with " + "\"" + BFF + "\"");
or
System.out.println("Replaced \"BFF\" with \"" + BFF + "\"");
Normally it should work with escape characters.
Have u tried something like this:
System.out.println("\"These two semi colons are removed when i am printed\"");
I tested it and it worked for me.
If you cannot use \ escape sequences, for whatever reason, you can use the fact that an ' apostrophe doesn't need to be escaped in a "xx" string literal, and that a " double-quote doesn't need to be escaped in a 'x' character literal.
E.g. to print Replacing "foo" with 'bar' was easy, and foo and bar are from variables, you can do this:
String s = "Replacing " + '"' + foo + '"' + " with '" + bar + "' was easy"`;
I have a string that a user inputs their name in [Last, First Middle] format and I need to change it to [First Middle Last] format.
I've defined the last name as LFM.substring(0, commaSpace) . commaSpace being the name for the ", " in the input of the LFM (Last, First Middle) user input.
Then I needed to define firstMiddle . My question to you is, how could I define the end of the string LFM so I can have firstMiddle be LFM.substring(commaSpace, (end of string) ); ? That way I can just print firstMiddle + last .
ALL OF MY CURRENT CODE:
(IT'S REALLY MESSY, SORRY)
System.out.println();
System.out.println("This program will separate and convert a name in [Last, First, Middle] format to [First Middle Last].");
System.out.println();
System.out.print("Please enter a name in [Last, First Middle] format. ");
Scanner userInput = new Scanner(System.in);
String lineSeparator = System.getProperty("line.separator");
String LFM, first, middle, last, firstMiddle;
int commaSpace, end, lastLength;
userInput.useDelimiter(lineSeparator);
LFM = userInput.nextLine();
commaSpace = LFM.indexOf(",");
last = LFM.substring(0, commaSpace);
lastLength = last.length();
firstMiddle = LFM.substring(commaSpace, //?);
first = LFM.substring(commaSpace + firstMiddle.length());
System.out.println(firstMiddle + (" ") + last);
Use replaceAll or replaceFirst functions since it accepts regex as first argument.
string.replaceAll("^(\\w+),\\s*(\\w+)\\s+(\\w+)$", "$2 $3 $1");
DEMO
I'm trying to read separate names and instruments up until the total number of bandmembers(asked earlier in the program) is reached. The program reads the amount, and reads the first name. However after that it fails in that it only reads the first name, it does not print any name or instrument after.
The while loop below is the most likely source of the problem:
i = counter
while(i <= bandMembers)
{
System.out.println("What is band member " + i + "'s name?");
kb.nextLine();
String bName = kb.nextLine();
System.out.println("What instrument does " + bName + " play?");
kb.nextLine();
String bNamePlay = kb1.nextLine();
list = list + i + ":" + " " + bName + " - " + bNamePlay+ "\n";
i++;
}
This is what it prints if I entered the first name as bName1:
Band Members
--------------
1: bName1 -
2: -
3: -
Any help appreciated, thanks.
Use BufferedReader instead.This will fix your problem.:-
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
i=counter;
while(i<=bandMembers){
System.out.println("Enter band member "+i+" name:-");
String bName=br.readLine();
System.out.println("What instrument does "+bName+" play?");
String bNamePlay=br.readLine();
list = list + i + ":" + " " + bName + " - " + bNamePlay+ "\n";
i++;
}
You should be using
String bName = kb.next();
Under the assumption that you are using a Scanner.
When you call nextLine() it reads the remainder of the same line and does not wait for input.
I don't have enough rep to comment on the issue you're having:
I was using kb.next at first but it read each word separated by a space as the next name. For example I would input "Jimmy loose hands" and it would prompt for Jimmy's instrument correctly, but it would then ask for band member 2's name and "what instrument does loose play?" simultaneously. So it took the second word as the next name.
What you may want to do is remove the "kb.nextLine();" before "String bName = kb.nextLine();"
I don't have an IDE open to confirm it, but that may be the reason that it is taking the second word/string entered as the name.
I have one String text that i would like to split,result i want to get is that when i take text/split output each part like for example: Name: John, Last Name: Davidson, Date of Birth: 05051968, Place of Birth: London. But i am not getting correct result. my code is following:
public class Person{
public String name;
public String lastName;
public String dateOfBirth;
public String placeOfBirth;
poblic void printDetails(){
String text = "John.Davidson/0505168/London Micheal.Bartson/06061680/Paris";
String[] newText = text.split("[./ ]");
for(int i=0; i<newText.length; i++){
String name = newText[i].split("")[0];
String lastName = newText[i].split("")[0];
String dateOfBirth = newText[i].split("")[0];
String placeOfBirth = newText[i].split("")[0];
System.out.println("Name: " + name + ", last name: " + lastName + ", date of birth: " + dateOfBirth + ", place of birth: " + placeOfBirth);
}
Result i am getting is following:
Name: J, last Name: J, date of birth: J, place of birth: J
Name: D, last name: D, date of birth: D, place of birth: D .......
and it goes like that for every first character in text. Please can some one look and tell me where i am mistaking?
The results of the split come in groups of four, so you need to set the step of your loop at 4, and get the individual parts through offsets 0, 1, 2, and 3, like this:
for(int i=0; i<newText.length; i+=4){
String name = newText[i];
String lastName = newText[i+1];
String dateOfBirth = newText[i+2];
String placeOfBirth = newText[i+3];
System.out.println("Name: " + name + ", last name: " + lastName + ", date of birth: " + dateOfBirth + ", place of birth: " + placeOfBirth);
}
Demo.
You're splitting using the "" which means split every character. Then you take the first character. I don't know why you're doing it that way.
In summary, what happens in every loop is it takes the first character ([0]) of element i of the array, then sets every single value that wil lbe printed in the string to that character. Instead, try this
String[] newText = text.split("[./ ]");
for(int i = 0; i < newText.length - 4; i+=4){
System.out.println("Name: " + newText[i] + ", last name: " + newText[i+1] + ", date of birth: " + newText[i+2] + ", place of birth: " + newText[i+3]);
}
However, this is a terrible solution, it relies on fixed sized entries and should not be used in practice. What if someone enters the string in a different order, or with one too many inputs or one too few? Try using more flexible designs, such as the usage of a csv format parser, so you always split using commas, and the rows can be something like
entry-type, entry
entry-type, entry2
entry-type, entry3
Or something like that. Try it out. Always try to aim for flexible solutions that don't rely on exact input to work, otherwise you will have exceptions and runtime issues like there's no tomorrow.
PS the point of the split() method is to split the string between occurences of the specified input, i.e. [./], so don't use it if you want to just give a "", that's no different than making a charArray (except instead of char[] it is String[])
I am making an application where I will be fetching tweets and storing them in a database. I will have a column for the complete text of the tweet and another where only the words of the tweet will remain (I need the words to calculate which words were most used later).
How I currently do it is by using 6 different .replaceAll() functions which some of them might be triggered twice. For example I will have a for loop to remove every "hashtag" using replaceAll().
The problem is that I will be editing as many as thousands of tweets that I fetch every few minutes and I think that the way I am doing it will not be too efficient.
What my requirements are in this order (also written in comments down bellow):
Delete all usernames mentioned
Delete all RT (retweets flags)
Delete all hashtags mentioned
Replace all break lines with spaces
Replace all double spaces with single spaces
Delete all special characters except spaces
Here is a Short and Compilable Example:
public class StringTest {
public static void main(String args[]) {
String text = "RT #AshStewart09: Vote for Lady Gaga for \"Best Fans\""
+ " at iHeart Awards\n"
+ "\n"
+ "RT!!\n"
+ "\n"
+ "My vote for #FanArmy goes to #LittleMonsters #iHeartAwards"
+ " htt…";
String[] hashtags = {"#FanArmy", "#LittleMonsters", "#iHeartAwards"};
System.out.println("Before: " + text + "\n");
// Delete all usernames mentioned (may run multiple times)
text = text.replaceAll("#AshStewart09", "");
System.out.println("First Phase: " + text + "\n");
// Delete all RT (retweets flags)
text = text.replaceAll("RT", "");
System.out.println("Second Phase: " + text + "\n");
// Delete all hashtags mentioned
for (String hashtag : hashtags) {
text = text.replaceAll(hashtag, "");
}
System.out.println("Third Phase: " + text + "\n");
// Replace all break lines with spaces
text = text.replaceAll("\n", " ");
System.out.println("Fourth Phase: " + text + "\n");
// Replace all double spaces with single spaces
text = text.replaceAll(" +", " ");
System.out.println("Fifth Phase: " + text + "\n");
// Delete all special characters except spaces
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim();
System.out.println("Finaly: " + text);
}
}
Relying on replaceAll is probably the biggest performance killer as it compiles the regex again and again. The use of regexes for everything is probably the second most significant problem.
Assuming all usernames start with #, I'd replace
// Delete all usernames mentioned (may run multiple times)
text = text.replaceAll("#AshStewart09", "");
by a loop copying everything until it founds a #, then checking if the following chars match any of the listed usernames and possibly skipping them. For this lookup you could use a trie. A simpler method would be a replaceAll-like loop for the regex #\w+ together with a HashMap lookup.
// Delete all RT (retweets flags)
text = text.replaceAll("RT", "");
Here,
private static final Pattern RT_PATTERN = Pattern.compile("RT");
is a sure win. All the following parts could be handled similarly. Instead of
// Delete all special characters except spaces
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim();
you could use Guava's CharMatcher. The method removeFrom does exactly what you did, but collapseFrom or trimAndCollapseFrom might be better.
According to the now closed question, it all boils down to
tweet = tweet.replaceAll("#\\w+|#\\w+|\\bRT\\b", "")
.replaceAll("\n", " ")
.replaceAll("[^\\p{L}\\p{N} ]+", " ")
.replaceAll(" +", " ")
.trim();
The second line seems to be redundant as the third one does remove \n too. Changing the first line's replacement to " " doesn't change the outcome an allows to aggregate the replacements.
tweet = tweet.replaceAll("#\\w*|#\\w*|\\bRT\\b|[^##\\p{L}\\p{N} ]+", " ")
.replaceAll(" +", " ")
.trim();
I've changed the usernames and hashtags part to eating also lone # or #, so that it doesn't need to be consumed by the special chars part. This is necessary for corrent processing of strings like !#AshStewart09.
For maximum performance, you surely need a precompiled pattern. I'd also re-suggest to use Guava's CharMatcher for the second part. Guava is huge (2 MB I guess), but you surely find more useful things there. So in the end you can get
private static final Pattern PATTERN =
Pattern.compile("#\\w*|#\\w*|\\bRT\\b|[^##\\p{L}\\p{N} ]+");
private static final CharMatcher CHAR_MATCHER = CharMacher.is(" ");
tweet = PATTERN.matcher(tweet).replaceAll(" ");
tweet = CHAR_MATCHER.trimAndCollapseFrom(tweet, " ");
You can inline all of the things that are being replaced with nothing into one call to replace all and everything that is replaced with a space into one call like so (also using a regex to find the hashtags and usernames as this seems easier):
text = text.replaceAll("#\w+|#\w+|RT", "");
text = text.replaceAll("\n| +", " ");
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim();