InputStreamReader, Buffered Reader, Java issue with reading standard input - java

I have a standard input that contains lines of text. Each line contains 2 numbers that are separated by a comma. I need to separate the two numbers so that I can use them in another function. I don't know what would be a good way to read each line, separate the numbers and then use them to call function until there are no more lines to be read. I read the documentation regarding InputStreamReader and BufferedReader, however, since I'm relatively new to java they didn't make much sense.
public static void main(String[] args) throws IOException {
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(reader);
try {
double num1 = Double.parseDouble(in.readLine());
double num2 = Double.parseDouble(in.readLine());
Main.function(num1,num2);
}

When you call in.readLine() then you get a string, probably something like "42.1,100.2". The next step would be splitting the string and after that you can convert the split string(s) to numbers.
String line = in.readLine(); // read one line
String[] parts = line.split(","); // split the line around the comma(s)
double num1 = Double.parseDouble(parts[0]); // convert the first part to double
double num2 = Double.parseDouble(parts[1]); // convert the second part to double
Main.function(num1, num2);
Note that this only reads from one line in the file (many lines -> looping) and that this only works correctly when the input is well formatted. You probably want to lookup the trim() method on String.

Double is not recognize the commas instead you will have to take the input string and replace all commas with empty strings. e.g. you have this input
String input = "123,321.3" ;
input = input.replaceAll("," , "");
in result you will have this
input -> "123321.3"
Then you can parse the string to double.
Hope it will help.
Regards , Erik.

Related

Java reading csv and understanding types

I need to read from a csv file. The file has some different types like int, float, String, char. How can I know what the type is?
I did write some code for it but my problem is with floating point numbers. In my computer java say that "7.9" is not a floating point number, but "7,9" is.
But on some computers "7.9" is a float. How can I solve this?
public static void Read(String filename) throws FileNotFoundException{
File file = new File(filename);
Scanner scanner1 = new Scanner(file);
String line ;
Scanner scanner;
int a;
float f;
String temp ;
while(scanner1.hasNextLine()){
line = scanner1.nextLine();
scanner = new Scanner(line);
scanner.useDelimiter(",|\\n");
while (scanner.hasNext()){
if (scanner.hasNextInt()){
a = scanner.nextInt();
System.err.printf("Int :%d",a);
}
else if(scanner.hasNextFloat()){
f = scanner.nextFloat();
System.err.printf("flt :%f",f);
}
else {
temp = scanner.next();
if(temp.length() == 1)
System.err.printf("char:%s",temp);
else
System.err.printf("string:%s",temp);
}
}
System.err.printf("\n");
scanner.close();
}
}
The more I read this more I realize I was wrong.
If your CSV data is like
1,2,3,4
Then it could be (1,2 and 3,4) eg (1.2, 3.4) or it could be the integers 1 through 4
If its properly quoted
"1,2","3,4"
Then your parser wont work because its not using quotes as the delimiters.
So its hard to say what is causeing your issue with out seeing the data.
You could add handeling of the quotes in your scanner but there are more cases inolved if your vlaues contain quotes themselves
Ideally use a proper CSV parse like http://opencsv.sourceforge.net/
Otherwise you need to walk through your data nad make sure your parse is covering all the cases you have today, and might have tomorrow.
A hack work around would be to modify your strings using replaceAll(".",","); but there are many pitfulls when doing that again, your scanner may confuse the elements as new entries in your CSV.
Specifically to change from representing decimals from 1,2 to 1.2 you can modify the Local for the number types you want with
scanner1.useLocale(Locale.US);
From what I can tell there is no way to have more than one locale for the scanner. One approach is to use two scanners, with two different Locales at the same time to parse the float differently.
You can change the scanner's locale using #useLocale(java.util.Locale)
Set the locale to one which uses . as the decimal point. I.e)
scanner.useDelimiter(",|\\n");
scanner.useLocale( Locale.US ); // Use '.' as decimal point

How do I separate a string like this line by line?

I have a string that I want to read line by line:
"8688642986379252 Michael_Thompson 816 2500.0
8904000405634912 Barbara_Martin
8610835007621519 Charles_Jackson 1019 52800.0"
It goes on on and on in that format.
I tried separating it using for loops, charAt() and reducing the size of the string using substring() but I failed miserably.
I'm sure it's something simple but I just can't get it. Any ideas?
I would suggest using str.split("\n"). It will produce an array of strings, one index for each line. This is assuming you can read the whole thing into a string. If the input is large, this won't work.
Use Scanner to read line by line using nextLine. Then, split every String by blank space" ":
Scanner scanner = new Scanner(stringWithBreaklines);
while (scanner.hasNext()) {
String line = scanner.nextLine();
String[] content = line.split(" ");
//do what you want/need with content
}
If the String is inside a file, then read the file directly using Scanner:
Scanner scanner = new Scanner(new File("file.txt"));
//same code as above...
Use the java.util.Scanner class to read tokens one by one.
http://docs.oracle.com/javase/tutorial/essential/io/scanning.html

User enters numbers separated by spaces, tabs, or new lines

I am in an beginner java programming class and am stuck on something I know should be simple, but it's killing me. The user is prompted to enter any number of x,y values and can be entered separated by a space, a tab, or a new line. So it can be entered like this:
1.0 1.0 2.0 2.0 3.0 3.0 etc...
or
1.0 (tab) 1.0 (tab) 2.0 (tab) 2.0 (tab) etc...
or
1.0 1.0
2.0 2.0
3.0 3.0
etc...
Well that's fine and great but I don't know how to separate these numbers. I'm thinking of having an x var and a y var and would like to separate them into this, but how do I do this? My first thought was maybe an array but we haven't even covered those yet. I feel like this is ridiculously easy and I'm just missing it
If you take the input as a String you could do something like
String[] input = inputString.split(" ");
Then convert each element to your desired type.
You're going to want to use a regular expression for this - find all white space in the string, then split on that.
String[] vals = t1.split("[\\s]+");
\s is the whitespace character regex search pattern.
You can split a string up by space using the following:
String[] parts = userinput.split(" ");
You can split a string up by tab using the following:
String[] parts = userinput.split("\t");
You can split a string up by line return using the following:
String[] parts = userinput.split("\n");
note: you may beed to add a '/r' to the above \n
So, find your delimiter, split your string by that using one of the above (or more if needed)
then you should have all your data in a String array
I can offer you to use scanner. You can set your delimeters that can be entered.
Scanner s = new Scanner("This is a , test word \n ");
s.useDelimiter(",|\\n");
while(s.hasNext()){
System.out.println(s.next());
}
Here you go. [ \t] is a regular expression meaning either a space or a tab.
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
while (line != null && !line.isEmpty())
{
String[] arr = line.split("[ \t]");
for (int i = 0; i < arr.length; i += 2)
{
doSomething(Double.parseDouble(arr[i]), Double.parseDouble(arr[i+1]));
}
line = br.readLine();
}
}
static void doSomething(double x, double y)
{
System.out.println("x is "+x+", y is "+y);
}
You may want to also include some error checking.
you can use BufferedReader + Scanner to read data that are separated by spaces or newlines:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
Scanner input = new Scanner(br);
& read the numbers one by one using Scanner , which will wait until it meets a number then read it no matter what is separating them a space or a new line
int numbersCount = 5; //numbersCount is the count of the numbers you are wanting to read from the input , so if you are waiting 5 numbers then it will be 5.
int[] numbers = new int[numbersCount];
for (int i=0;i<numbersCount;i++)
{
numbers[i] = input.nextInt();
}
so the array numbers will contain all the numbers you want isA
hope this helps

How do I change the delimiter from a text file?

Let's say I got a textfile.txt that I want to read from. This is the text in the file:
23:years:old
15:years:young
Using the useDelimiter method, how can I tell my program that : and newlines are delimiters? Putting the text in one line and using useDelimter(":"); works. The problem is when I got several lines of text.
Scanner input = new Scanner(new File("textfile.txt));
input.useDelimiter(:);
while(data.hasNextLine()) {
int age = input.nextInt();
String something = input.next();
String somethingelse = input.next();
}
Using this code I will get an inputMisMatch error.
Try
scanner.useDelimiter("[:]+");
The complete code is
Scanner scanner = new Scanner(new File("C:/temp/text.txt"));
scanner.useDelimiter("[:]+");
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
The output is
23
years
old
15
years
young
Use this code
Scanner input;
String tokenizer[];
try {
input = new Scanner(new File("D:\\textfile.txt"));
input.useDelimiter("\\n");
while(input.hasNextLine()) {
tokenizer = input.next().split(":");
System.out.println(tokenizer[0]+" |"+tokenizer[1]+" | "+tokenizer[2]);
}
}catch(Exception e){}
It will give you output like
23 |years | old
15 |years | young
You have two ways to do this:
Concatenate the string to make it one line.
delimit "newline" first, then delimit ":" each return string token.
If all you want is to get everything split up all at once then I guess you can use
useDelimiter(":\\n")
That should split on both : and newspace but it is not the most efficient way of processing data, especially if each line of text is set out in the same format and represents a complete entry. If that is the case then my suggestion would be to only split on a new line to begin with, like this;
s.useDelimiter("\\n");
while(s.hasNext()){
String[] result = s.next.split(":");
//do whatever you need to with the data and store it somewhere
}
This will allow you to process the data line by line and will also split it at the required places. However if you do plan on going through line by line I recommend you look at BufferedReader as it has a readLine() function that makes things a lot easier.
As long as all the lines have all three fields you can just use input.useDelimiter(":\n");
you probably wants to create a delimiter pattern which includes both ':' and newline
I didn't test it, but [\s|:]+ is a regular expression that matches one or more whitespace characters, and also ':'.
Try put:
input.useDelimiter("[\\s|:]+");

Scanner input from InputStream

I'm doing test driven development which requires me to write a test function for a class that takes input from the user. Since the console input function stops for input during tests, I wrote the tests using an InputStream which uses a string.
String str="3\n2\n1\n4\n";
InputStream is = new ByteArrayInputStream(str.getBytes());
assertTrue(app.RunApp(is));
This leads to the calling of the function getChoice(InputStream i) which involves console input from a Scanner.
public int getChoice(InputStream i) throws IOException {
Scanner s=new Scanner(i);
s.useDelimiter("\n");
String y= s.next();
int x=Integer.parseInt(y);
return x;
}
I want the above code to take the numbers in the string one by one. But, what is happening is that it takes the first number properly and then, the position of the stream goes directly to the end of the stream which causes a NoSuchElementException. Please Help!
Use...
String y = s.nextLine(); // That will take the entire line instead of only 1st word

Categories