I am trying to read multiple line from a file using java scanner. Each line has strings separated using comma, but there is no comma at the end of line. My text file contains value like below
98792203000000005091,89065012012341234100000000000167,084952103900000015
98792203000000005091,89065012012341234100000000000167,084952103900000015
The scanner is throwing a no element exception, it works fine if I add a comma t the end of line, but the original file will not have a comma. How do I make work
Scanner sc = new Scanner(outPutFile);
int outputDataStart = Integer.parseInt(outputDataStartLine);
skipLines(sc, outputDataStart);
sc.useDelimiter(",");
while(sc.hasNext())
{
OutputVariables outputVariables = new OutputVariables();
outputVariables.setIccid(sc.next());
outputVariables.setImsi(sc.next());
outputVariables.setKey(sc.next());
outputVariables.setPIN1(sc.next());
outputVariables.setPUK1(sc.next());
outputVariables.setPIN2(sc.next());
outputVariables.setPUK2(sc.next());
outputVariables.setPINAdm(sc.next());
outputVariables.setAccount(sc.next());
outputVariables.setKIC(sc.next());
outputVariables.setKID(sc.next());
outputVariables.setKIK(sc.next());
outputVariables.setOPCKey(sc.next());
OutputVariableList.add(outputVariables);
}
Insteard of using sc.useDelimiter(",") use sc.useDelimiter(",|\\n") it would break by both , and new line
You're asking the scanner to parse more values from a line of text than there are values. This is happening because you're calling next() without first checking hasNext(). Since you've told it to use the comma as the delimeter, it's hitting the end of the line continuing on to the next line until it finds the next comma.
Consider this CSV:
A,B,C,D
If you call next() after you parse the "D", the scanner will throw a NoSuchElementException.
It is not clear what you're attempting to do. If you're attempting to convert what is effectively a CSV into an object, then your best bet would be to use the Scanner to read each line, and then a String.split() call to split that line into parts.
If you're trying to parse multiple lines into an object, you'll of course need to figure out where your boundary is -- every fifteen comma separated values? every three lines? -- and apply that logic while collecting your segments.
As a simplified example, consider this collection of lines:
A,B,C,D
E,F,G,H
I,J,K
You would first use the Scanner to read line-by-line, and then use split each line apart and create the individual objects. Notice the last line is malformed -- you'll need to trap for that and catch it to avoid the NoSuchElementException.
Scanner sc = new Scanner(file);
while(sc.hasNext()) {
String line = sc.next();
String[] parts = line.split(",");
if(parts.length != 4) {
System.err.println("Invalid line: " + line);
continue; // skip this record, it is bad
}
// create your object here from parts
Pojo example = new Pojo(parts[0], parts[1], parts[2], parts[3]);
// etc
}
Alternatively if you're just trying to create a single massive object -- eg all lines belong to the same record -- you could tell it to consider a newline as a delimeter in addition to a comma. That way, after you hit the last comma in the first line, you would call next() and it would parse until the end of the line; and then when you called next() again, it would parse starting on the next line until it reached a comma or the end of the line, whichever came first.
I suggest you to use BufferedReader
it has a method named readLine()
first read a String then through the string.split(",") you can get the array of String
Related
I have some multiline text as a console input. Something like that:
first string with some text
second string with another text
third text with its own text
Number of lines may be different (one, two, three, four, etc., but not zero) every time, but this text is always putted in an instant with line separators (one pasting, not several inputs with pressing the enter key). This Java app has to immediately start to do something with those lines, but for some reason I can't understand, how to make this behavior. I mean, it has to save all these lines into String, or String[], or List<String>, or something else. If it's possible, I also would like to know, how to do this for "paste multiline text and Enter" input, but the main thing is for "paste multiline text (and no Enter)".
Of course, I tried to do that with Scanner, but I can't find working solution. It either gives me only the first line, or it doesn't understand, that the last line is the last one waiting for the next input.
There are two ways I can think of to make your scanner stop waiting for input and save your whole string as entered.
The first approach is to input your text into the console, hit Enter and then press CTRL+D, which will add an endline character. This endline character will make the scanner.hasNextLine() method return false, and therefore it will stop waiting for input. The code for this is pretty straightforward:
Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
while (scanner.hasNextLine()) {
sb.append(scanner.nextLine()).append("\n");
}
sb.deleteCharAt(sb.length() - 1); // delete the last \n character
String s = sb.toString();
Using this approach, even though your input is a whole multiline string, it will be read line by line using the scanner.nextLine() method. Each line will be appended to the StringBuilder, plus a newline character \n to keep the original input. As you can see, I then easily converted the sb into a String s.
StringBuilder is the recommended way of composing a string from multiple parts.
The second approach does not require CTRL+D and it is very similar to the first one. The addition is that every line of input is checked to see if it is empty, using the line.isEmpty() method. If it is empty, you'll simply break from the while loop without that line being appended to the sb:
Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.isEmpty()) {
break;
} // else
sb.append(line).append("\n");
}
sb.deleteCharAt(sb.length() - 1); // delete the last \n character
String s = sb.toString();
Now, this approach will obviously not work if your input contains empty lines in it (like breaks between paragraphs), because it will stop there and the rest of the string will be left out. However, instead of if (line.isEmpty()) you can decide on a stopping character and check if the line starts with it. If so, break:
if (line.startsWith("&")) {
break;
}
Again, this character won't be included in your sb.
Have a good one!
Okay so I'm having a slight problem with scanner advancing an extra line. I have a file that has many lines containing integers each separated by one space. Somewhere in the file there is a line with no integers and just the word "done".
When done is found we exit the loop and print out the largest prime integer that is less than each given integer in each line(if integer is already prime do nothing to it). We do this all the way up until the line with "done".
My problem: lets say the file contains 6 lines and on the 6th line is the word done. My output would skip lines 1, 3 and 5. It would only return the correct values for line 2 and 4.
Here's a snippet of code where I read the values in:
Scanner in = new Scanner(
new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
while(in.nextLine() != "done"){
String[] arr = in.nextLine().split(" ");
Now I sense the problem is that the nextLine call in my loop advances the line and then the nextline.split call also advances the line. Thus, all odd number lines will be lost. Would there be another way to check for "done" without advancing a line or is there a possible command I could call to somehow reset the scanner back to the start of the loop?
The problem is you have 2 calls to nextLine() try something like this
String line = in.nextLine();
while (!"done".equals(line)) {
String[] arr = line.split(" ");
// Process the line
if (!in.hasNextLine()) {
// Error reached end of file without finding done
}
line = in.nextLine();
}
Also note I fixed the check for "done" you should be using equals().
I think you are looking for this
while(in.hasNextLine()){
String str = in.nextLine();
if(str.trim().equals("done"){
break;
}else{
String[] arr = str.split("\\s+");
//then do whatever you want to do
}
}
This is my code:
Scanner scan = new Scanner(System.in);
String speed_string = scan.nextLine();
String[] string_array = speed_string.split("\\s");
I want my code to handle newlines, such as copy-pasting two or more paragraphs into a single nextLine. Is that possible? As it is currently, it will take in whatever the input until the newline.
It will stop at the newline, as per the API states:
Since this method continues to search through the input looking for a
line separator, it may buffer all of the input searching for the line
to skip if no line separators are present
So no, you cannot paste a big block and expect it to take it at once.
See nextLine method
You can't change the fact that nextLine() returns one line. that's its whole purpose. You can read two lines and combine those two strings, though. Of course that means some knowledge of the file format.
There is no possibility to do that using Scanner class because it can only read line confirmed by 'enter' or newline sign.
But you can also handle concatenating two lines using ArrayUtils.
Scanner scan = new Scanner(System.in);
String speed_string = scan.nextLine();
String speed_string1 = scan.nextLine();
String[] string_array = speed_string.split("\\s");
String[] string_array1 = speed_string.split("\\s");
String[] both = ArrayUtils.addAll(string_array , string_array1 );
I have an array with types and numbers and when printing this is the outcome:
car:1 car:2 car:3 boat:1 boat:2 boat:3 plane:1 plane:2 plane:3
I am looking for a way to determine when the type changes, and then make a new line. which means to print a "\n" after car:3 (and boat:3) so all the vehicles are on their own row.
I am printing all these items with a for-loop like this:
for(Types filename: TypeTable)
{
Scanner s;
s = new Scanner(filename.toString());
while (s.hasNext())
{
System.out.print(s.nextLine()+ " ");
}
and I guess I am in need for some local loop and to save the first type in some temp variable and in a loop print a newline when it changes, but I am kinda stuck.
edit2:
after taking a break and then coming back i managed to fix the problem, and even without having a blank line in beginning. the problem was that i had to define oldTransport in main-class :) ofc you couldnt have known how my structure was. thank you hovercraft of eel :)
Rather than printing the line via System.out.print(...) get the line and put it into a variable. Split it via the String#split(...) method, and compare the first part obtained (the String in the [0] spot of the array obtained from split) with the previous String's first part (that was also saved to a variable). If different, make a new line before printing the line out.
Also, if you are going to extract a nextLine() from the scanner, check for a hasNextLine(), not hasNext().
In pseudocode
String oldTransportation gets assigned ""
while the scanner has a next line
String variable line gets scanner's next line
String array called tokens gets this line split on ":"
String newTransportation gets the [0] item in the tokens array
Check if newTransportation equals(...) oldTransportation,
if different, call System.out.println().
print the line variable String
oldTransportation gets assigned newTransportation
end while scanner...
Lets keep track of the previous type.
String lastTypeName = "";
for(Types filename: TypeTable) {
if(!lastTypeName.equals(filename.toString()) {
lastTypeName = filename.toString();
System.out.println();
}
Scanner s = new Scanner(filename.toString());
while (s.hasNext()) {
System.out.print(s.nextLine()+ " ");
}
s.close();
}
A line break will get printed before the first line, but maybe that is not a problem.
I need to parse a log file which is in txt format.
I need to match the String and read above and below lines of the matched String.
I need to do something similar to grep -A 30 -B 50 'hello'.
If You have any other suggestions to do it you are welcome.
Read the file line by line, and match your string (either regexp or String.indexOf("")). Keep the previous n lines in memory so when you've matched your string you can print them. Use BuffereReader.readLine() to read the file line by line (note that using the BufferedReader is actually more complicated because you cannot jump back).
Or for more flexibility RandomAccessFile. With this method you can mark your position, print the next m lines and then jump back to continue your search from where you left it.
pseudocode:
initialize a Queue
for each line
if line matches regex
read/show lines from queue;
read/show next lines;
else {
if queue size > 30
queue.remove() // removes head of the queue
add this line to queue;
}
You can use BufferedReader to read a file line by line, Pattern to check the line against a regular expression, and Queue to store previous lines.
You may use following code(uses java 5 api java.util.Scanner):
Scanner scanner = new Scanner(new File("YourFilePath"));
String prev = null;
String current;
while (scanner.hasNextLine())
{
current = scanner.nextLine();
if (current.contains("YourRegEx"))
break;
else
prev = current;
}
String next = scanner.nextLine();
You may want to add additional checks for prev being not null and Calling scanner.hasNextLine() before String next = scanner.nextLine()