I tried looking for answers online, but I don't know how to word it correctly to find what I'm looking for. I have a file that I need to split but some lines are missing the regex I am trying to use.
The file I need to split looks like this:
A,106,Chainsaw 12"
D,102
d,104
a,107,Chainsaw 10"
I need to split it in three different sections, Letter, ID, Tool but 102 and 104 are missing the comma and Tool section. I've tried:
String[] sec = line.split(",");
and
String[] sec = line.split(",| \n");
And several other regex combinations, but none of them work. I get an AOB error on the line such as (below) because its missing.
...[0];
...[1];
String tool = sec[2]; //here
Any help is appreciated
Use String[] sec = line.split(","); and then test the length of the sec array
If you have 2 then you can use sec[0] and sec[1] but if you have 3 you can also use sec[2] If you have 0 then you have a empty line
You were on the right path with
String[] sec = line.split(",");
This function will return an Array with (in your example) either 2 or 3 elements. Then you could simply check for the length of the array
String[] sec = line.split(",");
int length = sec.length;
Here you can see what type of entry you have. Either length will be 2, which mean that it is a letter-ID pair, or it is 3, which means it is a letter, Id and tool entry.
If you need to be able to distinguish between more categories, you will have to put in an extra check. For example: Lets say your entry can be missing out one of the other two elements (not only the tool) and you could encounter an entry like:
a,Chainsaw 10
In this case you will furthermore need to read out the type of the single elements. The first thing that comes to my mind is, that you could check the first element in your array and check its length (should always be 1, since it is just a letter) and parse the second one into Integer (I assume id is always a number)
You are splitting on , and you have cases where input string is not present in same pattern.
So for this knid of situation, after splitting the string, every-time you have to check for the array length.
If it's less than desired length, then you cannot access desired element, because it's not present in the array.
For example:
When you do String[] sec = line.split(","); for A,106,Chainsaw 12, you will have 3 length, and you can access elements like sec[0],sec[1],sec[2].
When you split A,106, then you will get 2 as length, and elements present in the array are going to be sec[0],sec[1].
Example code:
import java.util.*;
public class ArrayListDemo {
public static void main(String args[]) {
ArrayList<String> lines= new ArrayList<String>();
lines.add("A,106,Chainsaw 12");
lines.add("A,106");
lines.add("A");
for(String str:lines){
String[] parts = str.split(",");
if(parts.length<2){
for(int i = 0 ; i < parts.length ; i++)
System.out.println("Splitted Item at index " + "[" + i + "]" + "::" + parts[i]);
}else{
for(int i = 0 ; i < parts.length ; i++)
System.out.println("Splitted Item at index " + "[" + i + "]" + "::" + parts[i]);
}
}
}
}
Hope that helps..
Related
I'm trying to use a scanner to parse out some text but i keep getting an InputMismatchException. I'm using the scanner.next(Pattern pattern) method and i want to return the next n amount of characters (including whitespace).
For example when trying to parse out
"21 SPAN 1101"
I want to store the first 4 characters ("21 ") in a variable, then the next 6 characters (" ") in another variable, then the next 5 ("SPAN "), and finally the last 4 ("1101")
What I have so far is:
String input = "21 SPAN 1101";
Scanner parser = new Scanner(input);
avl = parser.next(".{4}");
cnt = parser.next(".{6}");
abbr = parser.next(".{5}");
num = parser.next(".{4}");
But this keeps throwing an InputMismatchException even though according to the java 8 documentation for the scanner.next(Pattern pattern) it doesn't throw that type of exception. Even if I explicitly declare the pattern and then pass that pattern into the method i get the same exception being thrown.
Am I approaching this problem with the wrong class/method altogether? As far as i can tell my syntax is correct but i still cant figure out why im getting this exception.
At documentation of next(String pattern) we can find that it (emphasis mine)
Returns the next token if it matches the pattern constructed from the specified string.
But Scanner is using as default delimiter one or more whitespaces so it doesn't consider spaces as part of token. So first token it returns is "21", not "21 " so condition "...if it matches the pattern constructed from the specified string" is not fulfilled for .{4} because of its length.
Simplest solution would be reading entire line with nextLine() and splitting it into separate parts via regex like (.{4})(.{6})(.{5})(.{4}) or series of substring methods.
You might want to consider creating a convenience method to cut your input String into variable number of pieces of variable length, as approach with Scanner.next() seems to fail due to not considering spaces as part of tokens (spaces are used as delimiter by default). That way you can store result pieces of input String in an array and assign specific elements of an array to other variables (I made some additional explanations in comments to proper lines):
public static void main(String[] args) throws IOException {
String input = "21 SPAN 1101";
String[] result = cutIntoPieces(input, 4, 6, 5, 4);
// You can assign elements of result to variables the following way:
String avl = result[0]; // "21 "
String cnt = result[1]; // " "
String abbr = result[2]; // "SPAN "
String num = result[3]; // "1101"
// Here is an example how you can print whole array to console:
System.out.println(Arrays.toString(result));
}
public static String[] cutIntoPieces(String input, int... howLongPiece) {
String[] pieces = new String[howLongPiece.length]; // Here you store pieces of input String
int startingIndex = 0;
for (int i = 0; i < howLongPiece.length; i++) { // for each "length" passed as an argument...
pieces[i] = input.substring(startingIndex, startingIndex + howLongPiece[i]); // store at the i-th index of pieces array a substring starting at startingIndex and ending "howLongPiece indexes later"
startingIndex += howLongPiece[i]; // update value of startingIndex for next iterations
}
return pieces; // return array containing all pieces
}
Output that you get:
[21 , , SPAN , 1101]
I have a function which takes a String containing a math expression such as 6+9*8 or 4+9 and it evaluates them from left to right (without normal order of operation rules).
I've been stuck with this problem for the past couple of hours and have finally found the culprit BUT I have no idea why it is doing what it does. When I split the string through regex (.split("\\d") and .split("\\D")), I make it go into 2 arrays, one is a int[] where it contains the numbers involved in the expression and a String[] where it contains the operations.
What I've realized is that when I do the following:
String question = "5+9*8";
String[] mathOperations = question.split("\\d");
for(int i = 0; i < mathOperations.length; i++) {
System.out.println("Math Operation at " + i + " is " + mathOperations[i]);
}
it does not put the first operation sign in index 0, rather it puts it in index 1. Why is this?
This is the system.out on the console:
Math Operation at 0 is
Math Operation at 1 is +
Math Operation at 2 is *
Because on position 0 of mathOperations there's an empty String. In other words
mathOperations = {"", "+", "*"};
According to split documentation
The array returned by this method contains each substring of this
string that is terminated by another substring that matches the given
expression or is terminated by the end of the string. ...
Why isn't there an empty string at the end of the array too?
Trailing empty strings are therefore not included in the resulting
array.
More detailed explanation - your regex matched the String like this:
"(5)+(9)*(8)" -> "" + (5) + "+" + (9) + "*" + (8) + ""
but the trailing empty string is discarded as specified by the documentation.
(hope this silly illustration helps)
Also a thing worth noting, the regex you used "\\d", would split following string "55+5" into
["", "", "+"]
That's because you match only a single character, you should probably use "\\d+"
You may find the following variation on your program helpful, as one split does the jobs of both of yours...
public class zw {
public static void main(String[] args) {
String question = "85+9*8-900+77";
String[] bits = question.split("\\b");
for (int i = 0; i < bits.length; ++i) System.out.println("[" + bits[i] + "]");
}
}
and its output:
[]
[85]
[+]
[9]
[*]
[8]
[-]
[900]
[+]
[77]
In this program, I used \b as a "zero-width boundary" to do the splitting. No characters were harmed during the split, they all went into the array.
More info here: https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html
and here: http://www.regular-expressions.info/wordboundaries.html
I am trying to get the "work" part of this string:
String test = "\prod\mp\incoming\users\work\test.java";
I have been trying to do it this way:
String result = test.substring(test.lastIndexOf("\\")+1 , test.length());
But this is returning "test.java"
try:
String test = "\\prod\\mp\\incoming\\users\\work\\test.java";
String[] s = test.split("\\");
result = s[s.length-2];
Here is the split method signature:
public String[] split(String regex);
It splits this string around matches of the given regular expression and returns an array of String containing the matches. In your case you need to get the second to last match which is the the match with index s.length-2 since the last element in the array s has the index s.length-1
Break your one-liners down into sensible parts. Instead of this...
String result = test.substring(test.lastIndexOf("\\") + 1 , test.length());
... try this...
int lastSlashIndex = test.lastIndexOf("\\");
int endIndex = test.length();
String result = test.substring(lastSlashIndex + 1, endIndex);
It then becomes painfully obvious that your substring goes from the last slash to the end of the string. So how do you fix it? First, you need to describe the problem properly. There are two possible things you are trying to do, and I have no idea which is correct:
You want to find the fifth item in the path.
You want to find the second to last item in the path.
I'll tackle the first, and if it turns out to be the second, you should be able to follow what I've done and do it yourself.
// Get the fifth item in the path
String[] items = test.split("\\");
String result = items[4];
Add some error checking to prevent an array index out of bounds exception.
String[] items = test.split("\\");
String result = "";
if (items.length > 4)
result = items[4];
I have a string
Product Description ID1 ID2 QTY Rate1 Rate2
I want do break it as
Product Description|ID1|ID2|QTY|Rate1|Rate2
The only common delimiter I could see is space. But product description can be any number of words. So I don't know how many spaces it will have. But the spaces in rest of the string is fixed.
Currently I split it into array, get its length and concat appropriately. Is there a more direct way?
It is not entirely clear what you mean by "more directly", but I'm assuming that you want to avoid the concatenation step.
One way would be as follows:
make an initial pass using Matcher.find(int) to find the position of the "N - 5th" separator. (This requires an int[] with 5 elements that you use as a sort of queue for the offsets determined using find.)
use String.substring to extract the strings before and after that separator
use String.split to split the 2nd substring to separate the last 5 fields.
If you kept the offsets and match lengths (from step #1) you could replace the split call in step #3 with a loop and substring calls.
(The reason you can't in general split "backwards" is that regexes cannot be matched backwards. Or more precisely, if you did that you might end up splitting differently to when you did it "forwards". This makes it non-trivial to avoid doing 2 passes. Obviously in your specific case, the separator regex would be "one-or-more-whitespace" which would work in both directions ... if there was a capability to do that in the Matcher API.).
Split it into an array as normal
You will end up with an array with n + 5 components where n is the number of words in the product description.
Then you know:
Rate2 = arr[len-1]
Rate1 = arr[len-2]
QTY = arr[len-3]
ID2 = arr[len-4]
ID3 = arr[len-5]
Then combine elements arr[0] to arr[len-6] adding a space in between them. This gives you your product description.
Alternatively you could use Collections.reverse() on the output array but both methods get the same result
Using a StringBuilder, this is probably as compact as you can get. The good thing is you don't have to juggle a lot of indices around. In fact, you don't have to juggle any.
String foo = "Product Description Test Potato ID1 ID2 QTY Rate1 Rate2 ";
foo = foo.trim(); // get rid of any extra spaces, in case we have any, as a safety check
//the code that does your work
StringBuilder bar = new StringBuilder(foo);
// we have to add the pipe 5 times
for (int i = 5; i > 0; i--) {
bar.setCharAt(bar.lastIndexOf(" "), '|');
}
foo = bar.toString();
// Product Description ID1 ID2 QTY Rate1 Rate2
// Product Description|ID1|ID2|QTY|Rate1|Rate2
String actWord = "Product it a middle data Description ID1 ID2 QTY Rate1 Rate2";
String outputWord = null;
String[] arr = actWord.split(" ");
StringBuffer buf = new StringBuffer();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i] + "=" + (i < arr.length - 5));
if (i < arr.length - 5) {
buf.append(arr[i] + " ");
} else
buf.append("|" + arr[i]);
}
System.out.println("output - " + buf.toString().trim());
I hope this solves your req.
Reverse, the string.
Parse/Split based on space.
Re-reverse all the words as you pull them out of the collection of parsed/split words.
Not super elegant, but it should work.
I need to print from an array so that it has columns but even after looking around online I cannot figure this out. I have the following code:
public void printDirectory() {
System.out.println("Surname " + "Initial " + "Extension");
for (int i = 0; i < directory.length; i++) {
System.out.println(directory[i]);
}
}
public static void main(String[] args) {
ArrayDirectory r = new ArrayDirectory();
r.inputEntries();
r.printDirectory();
}
The program inputs data from a text file where there are Surnames, initials and a telephone extension. For example, I have "Smith J 0583" (There will be a number of these in the array all of different lengths) when I print them out I get very badly formatted output. I am aware that it is possible to format in Java but i am not sure how to use it since the string is all in one place.
Thank you for your help.
You can use System.out.format to do this.
Using Java formatting, you can specify the lengths of Strings. So, you can make each column a set length in characters to make it format well. The only caveat is that you need to know the maximum length surname can be. In this example, i'll just guess 12.
String formatString = "%12s %7s %9s\n";
System.out.format(formatString, "Surname", "Initial", "Extension");
System.out.format(formatString, (Object[]) directory[i].split(" "));
What the formatString does is it specifies 3 strings, one that is 12 characters in length, then 7 characters in length, then 9 characters in length, all separated by spaces. Then, it ends with a new line. When you input three strings using this, they'll always be the same lengths, as long as none go over the length, which makes for nice formatting.