I have a scanner with many lines of text(representing number) and I want to convert all the text in the scanner to a List.
Example:
Scanner myScanner = new Scanner(new File("input.txt"));
input.txt:
000110100110
010101110111
111100101011
101101001101
011011111110
011100011001
110010011100
000001011100
101110100110
010001011100
011111001010
100111100101
111111000010
My first thought was to convert it to a String by changing the delimiter to something I know is not in the file:
myScanner.useDelimiter("impossible String");
String content = myScanner.next();
and then use
List<String> fullInput = Arrays.asList(content.split("\n"));
However, it gives me problems later on with parsing the numbers on the scanner. I've tried debugging it but I can't seem to understand the problem. For example, I made it print the String to the console before parsing it. It would print a proper number(asString) and then give me NumberFormatException when it is supposed to parse.
Here's the runnable code:
public static void main(String[] args) throws FileNotFoundException {
Scanner myScanner = new Scanner(new File("input.txt"));
myScanner.useDelimiter("impossible String");
String content = myScanner.next();
List<String> fullInput = Arrays.asList(content.split("\n"));
System.out.println(fullInput.get(1));
System.out.println(Long.parseLong(fullInput.get(1)));
}
This is what I ended up using after the first didn't work:
Scanner myScanner = new Scanner(new File("input.txt"));
List<String> fullInput = new ArrayList<>();
while (sc.hasNextLine())
fullInput.add(myScanner.nextLine());
Do you know what's wrong with the first method or is there a better way to do this?
Because you are parsing a string that represents a number that's beyond the size of an integer.
int values can be between -2,147,483,648 to 2,147,483,647.
fullInput.get(1) gives you 010101110111 which is greater than 2,147,483,647.
You can use long.
long val = Long.parseLong(fullInput.get(1));
If the string represents binary numbers and you want to convert them to int, then you need to provide the base when parsing the string.
int val = Integer.parseInt(fullInput.get(1), 2);
For what you are trying to do here, Scanner is the wrong solution.
If your goal is to simply read the all lines of the file as String[] you can use the Files.readAllLines(Path, Charset) method (javadoc) to do this. You could then wrap that as a List using Arrays.asList(...).
What you are actually doing could work under some circumstances. But one possible problem is that String.split("\n") only works on systems where the line terminator is a single NL character. On Windows, the line terminator is a CR NL sequence. And in that case, String.split("\n") will leave a CR at the end of all but the last string / line. That would be sufficient to cause Long.parseLong(...) to throw a NumberFormatException. (The parseXxx methods do not tolerate extraneous characters such as whitespace in the argument.)
A possible solution to the extraneous whitespace problem is to trim the string; e.g.
System.out.println(Long.parseLong(fullInput.get(1).trim()));
The trim() method (javadoc) returns a string with any leading and/or trailing whitespace removed.
But there is another way to deal with this. If you don't care whether each number in the input file is on a separate line, you could do something like this:
Scanner myScanner = new Scanner(new File("input.txt"));
List<Long> numbers = new ArrayList<>();
while (myScanner.hasNextLong()) {
numbers.append(myScanner.nextLong());
}
Finally, #ChengThao makes a valid point. It looks like these are binary numbers. If they are in fact binary, then it makes more sense to parse them using Long.parseLong(string, radix) with a radix value of 2. However if you parse them as decimal using parseLong (as you are currently doing) the values in your question will fit into a long type.
Related
New to programming, so my apologies if this is dumb question.
When utilizing the Scanner class, I fail to see if there is an option for obtaining a single character as input. For example,
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String a = input.nextLine();
}
}
The above code allows me to pull the next line into a string, which can then be validated by using a while or if statement using a.length() != 1 and then stored into a character if needed.
But is there a way to pull a single character instead of utilizing a string and then validating? If not, can someone explain why this is not allowed? I think it may be due to classes or objects vs primitive types, but am unsure.
You can use System.in.read() instead of Scanner
char input = (char) System.in.read();
You can also use Scanner, doing something like:
Scanner scanner = new Scanner(System.in);
char input = scanner.next().charAt(0);
For using Stringinstead of char, you can also to convert to String:
Scanner scanner = new Scanner(System.in);
String input = String.valueOf(input.next().charAt(0));
This is less fancy than other ways, but for a newbie, it'll be easier to understand. On the other hand, I think the problem proposed doesn't need amazing performance.
Set the delimiter so every character is a token:
Scanner input = new Scanner(System.in).useDelimiter("(?<=.)");
String c = input.next(); // one char
The regex (?<=.) is a look behind, which has zero width, that matches after every character.
I am writing a program which will allow users to reserve a room in a hotel (University Project). I have got this problem where when I try and read data from the file and store it in an array I receive a NumberFormatException.
I have been stuck on this problem for a while now and cannot figure out where I am going wrong. I've read up on it and apparently its when I try and convert a String to a numeric but I cannot figure out how to fix it.
Any suggestions, please?
This is my code for my reader.
FileReader file = new FileReader("rooms.txt");
Scanner reader = new Scanner(file);
int index = 0;
while(reader.hasNext()) {
int RoomNum = Integer.parseInt(reader.nextLine());
String Type = reader.nextLine();
double Price = Double.parseDouble(reader.nextLine());
boolean Balcony = Boolean.parseBoolean(reader.nextLine());
boolean Lounge = Boolean.parseBoolean(reader.nextLine());
String Reserved = reader.nextLine();
rooms[index] = new Room(RoomNum, Type, Price, Balcony, Lounge, Reserved);
index++;
}
reader.close();
This is the error message
This is the data in my file which I am trying to read:
Change your while loop like this
while (reader.hasNextLine())
{
// then split reader.nextLine() data using .split() function
// and store it in string array
// after that you can extract data from the array and do whatever you want
}
You're trying to parse the whole line to Integer. You can read the whole line as a String, call
.split(" ")
on it. This will split the whole line into multiple values and put them into an array. Then you can grab each item from the array and parse separately as you intended.
Please avoid posting screenshots next time, use proper formatting and text so someone can easily copy your code or test data to IDE and reproduce the scenario.
Use next() instead of nextLine().
With Scanner one must use hasNextLine, nextLine, hasNext, next, hasNextInt, nextInt etcetera. I would do it as follows:
Using Path and Files - the newer more general classes i.o. File.
Files can read lines, here I use Files.lines which gives a Stream of lines, a bit like a loop.
Try-with-resources: try (AutoCloseable in = ...) { ... } ensures that in.close() is always called implicitly, even on exception or return.
The line is without line ending.
The line is split into words separated by one or more spaces.
Only lines with at least 6 words are handled.
Create a Room from the words.
Collect an array of Room-s.
So:
Path file = Paths.get("rooms.txt");
try (Stream<String> in = Files.lines(file)) {
rooms = in // Stream<String>
.map(line -> line.split(" +")) // Stream<String[]>
.filter(words -> words.length >= 6)
.map(words -> {
int roomNum = Integer.parseInt(words[0]);
String type = words[1];
double price = Double.parseDouble(words[2]);
boolean balcony = Boolean.parseBoolean(words[3]);
boolean lounge = Boolean.parseBoolean(words[4]);
String reserved = words[5];
return new Room(roomNum, type, price, balcony, lounge, reserved);
}) // Stream<Room>
.toArray(Room[]::new); // Room[]
}
For local variables use camelCase with a small letter in front.
The code uses the default character encoding of the system to convert the bytes in the file to java Unicode String. If you want all Unicode symbols,
you might store your list as Unicode UTF-8, and read them as follows:
try (Stream<String> in = Files.lines(file, StandardCharsets.UTF_8)) {
An other issue is the imprecise floating point double. You might use BigDecimal instead; it holds a precision:
BigDecimal price = new BigDecimal(words[2]);
It is however much more verbose, so you need to look at a couple of examples.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
The string is, for example "r1" and I need the 1 in an int form
Scanner sc = new Scanner("r1");
int result = sc.nextInt(); // should be 1
compiles correctly but has a runtime error, should I be using the delimiter? Im unsure what the delimiter does.
Well, there's a few options. Since you literally want to skip the "r" then read the number, you could use Scanner#skip. For example, to skip all non-digits then read the number:
Scanner sc = new Scanner("r1");
sc.skip("[^0-9]*");
int n = sc.nextInt();
That will also work if there are no leading non-digits.
Another option is to use non-digits as delimiters, as you mentioned. For example:
Scanner sc = new Scanner("x1 r2kk3 4 x56y 7g");
sc.useDelimiter("[^0-9]+"); // note we use + not *
while (sc.hasNextInt())
System.out.println(sc.nextInt());
Outputs the six numbers: 1, 2, 3, 4, 56, 7.
And yet another option, depending on the nature of your input, is to pre-process the string by replacing all non-digits with whitespace ahead of time, then using a scanner in its default configuration, e.g.:
String input = "r1";
input = input.replaceAll("[^0-9]+", " ");
And, of course, you could always just pre-process the string to remove the first character if you know it's in that form, then use the scanner (or just Integer#parseInt):
String input = "r1";
input = input.substring(1);
What you do depends on what's most appropriate for your input. Replace "non-digit" with whatever it is exactly that you want to skip.
By the way I believe a light scolding is in order for this:
Im unsure what the delimiter does.
The documentation for Scanner explains this quite clearly in the intro text, and even shows an example.
Additionally, the definition of the word "delimiter" itself is readily available.
There are some fundamental mistakes here.
First, you say:
One = sc.nextInt("r1");
compiles correctly ...
No it doesn't. If sc is really a java.util.Scanner, then there is no Scanner.nextInt(String) method, so that cannot compile.
The second problem is that the hasNextXXX and nextXXX methods do not parse their arguments. They parse the characters in the scanner's input source.
The third problem is that Scanner doesn't provide a single method that does what you are (apparently) trying to do.
If you have a String s that contains the value "r1", then you don't need a Scanner at all. What you need to do us something like this:
String s = ...
int i = Integer.parseInt(s.substring(1));
or maybe something this:
Matcher m = Pattern.compile("r(\\d+)").matcher(s);
if (m.matches()) {
int i = Integer.parseInt(m.group(1));
}
... which checks that the field is in the expected format before extracting the number.
On the other hand if you are really trying to read the string from a scanner them, you could do something like this:
String s = sc.next();
and then extract the number as above.
If the formatting is the same for all your input where the last char is the value you could use this:
String s = sc.nextLine()
Int i = Integer.parseInt(s.charAt(s.length() -1));
Else you could for instance make the string a char Array, iterate trough it and check whether each char is a number.
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 some text files with time information, like:
46321882696937;46322241663603;358966666
46325844895266;46326074026933;229131667
46417974251902;46418206896898;232644996
46422760835237;46423223321897;462486660
For now, I need the third column of the file, to calculate the average.
How can I do this? I need to get every text lines, and then get the last column?
You can read the file line by line using a BufferedReader or a Scanner, or even some other techinique. Using a Scanner is pretty straightforward, like this:
public void read(File file) throws IOException{
Scanner scanner = new Scanner(file);
while(scanner.hasNext()){
System.out.println(scanner.nextLine());
}
}
For splitting a String with a defined separator, you can use the split method, that recevies a Regular Expression as argument, and splits a String by all the character sequences that match that expression. In your case it's pretty simple, just the ;
String[] matches = myString.split(";");
And if you want to get the last item of an array you can just use it's length as parameter. remembering that the last item of an array is always in the index length - 1
String lastItem = matches[matches.length - 1];
And if you join all that together you can get something like this:
public void read(File file) throws IOException{
Scanner scanner = new Scanner(file);
while(scanner.hasNext()){
String[] tokens = scanner.nextLine().split(";");
String last = tokens[tokens.length - 1];
System.out.println(last);
}
}
Yes you have to read each line of the file and split it by ";" separator and read third element.