How nextLine() method works - java

Consider the code :
import java.util.*;
public class TestClass
{
public static void main(String[] args)
{
Scanner input= new Scanner ("34\n567");
while(input.hasNext())
{
System.out.println(input.nextLine());
}
input.close();
}
}
the output I get:
34
567
When I try to read the string by nextLine(), it should not read it like this as it has to terminate only at line separator and \n is not line separator in Java.
So how does this happen?

Try this one
String s = "a\r\nb";
for (String str : s.split(System.getProperty("line.separator"))) {
System.out.println(str);
}
System.out.println("Length:"+s.split(System.getProperty("line.separator")).length);
\r\n represents new line.
output
a
b
Length:2

nextLine() is base in the regulare expression "\r\n|[\n\r\u2028\u2029\u0085]". This accepts any line break of the supported plattforms of java and is not limited to plattform this instance of the jvm is actually running on. In fact most methods in java for detecting a line break work this way. Thus it's not really correct that there's a definition how the line break should look like.

Related

Java Split("\\|") not working for strings with space

for the below input im expecting all the strings delimited with "|" to be available in an array. but only first string is available and the next string is partially available.the rest is not at all available. please help me in understanding it. i explored all the help docs and previous stackoverflow stuff but not able to solve it. i tried with split(String regex,int limit)as well but no use. I dont want to replace the whitespace as i need to retain that.
input "1|New York|1345|134|45634"
Expected output is: 1,New York,1345,134,45634
Actual output is:1,New
public class test1 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String strinp=scanner.next();
//System.out.println(strinp.replaceAll(" ", ""));
String[] strArr=strinp.split("\\|");
//System.out.println(Arrays.deepToString(strArr));
for (String s:strArr) {
System.out.println(s);
}
}
}
scanner.next() splits on spaces itself. So your first scanner.next() call reads 1|New which you then split.
Use scanner.nextLine() to read the whole line, it will be split successfully.
Change:
String strinp = scanner.next();
To:
String strinp = scanner.nextLine();
Or you can declare scanner as:
Scanner scanner = new Scanner(System.in).useDelimiter("\\n");

Runtime Error Using Scanner class [duplicate]

I got an run time exception in my program while I am reading a file through a Scanner.
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at Day1.ReadFile.read(ReadFile.java:49)
at Day1.ParseTree.main(ParseTree.java:17)
My code is:
while((str=sc.nextLine())!=null){
i=0;
if(str.equals("Locations"))
{
size=4;
t=3;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Professions"))
{
size=3;
t=2;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Individuals"))
{
size=4;
t=4;
str=sc.nextLine();
str=sc.nextLine();
}
int j=0;
String loc[]=new String[size];
while(j<size){
beg=0;
end=str.indexOf(',');
if(end!=-1){
tmp=str.substring(beg, end);
beg=end+2;
}
if(end==-1)
{
tmp=str.substring(beg);
}
if(beg<str.length())
str=str.substring(beg);
loc[i]=tmp;
i++;
if(i==size ){
if(t==3)
{
location.add(loc);
}
if(t==2)
{
profession.add(loc);
}
if(t==4)
{
individual.add(loc);
}
i=0;
}
j++;
System.out.print("\n");
}
with Scanner you need to check if there is a next line with hasNextLine()
so the loop becomes
while(sc.hasNextLine()){
str=sc.nextLine();
//...
}
it's readers that return null on EOF
ofcourse in this piece of code this is dependent on whether the input is properly formatted
I also encounter with that problem.
In my case the problem was that i closed the scanner inside one of the funcs..
public class Main
{
public static void main(String[] args)
{
Scanner menu = new Scanner(System.in);
boolean exit = new Boolean(false);
while(!exit){
String choose = menu.nextLine();
Part1 t=new Part1()
t.start();
System.out.println("Noooooo Come back!!!"+choose);
}
menu.close();
}
}
public class Part1 extends Thread
{
public void run()
{
Scanner s = new Scanner(System.in);
String st = s.nextLine();
System.out.print("bllaaaaaaa\n"+st);
s.close();
}
}
The code above made the same exaption, the solution was to close the scanner only once at the main.
You're calling nextLine() and it's throwing an exception when there's no line, exactly as the javadoc describes. It will never return null
https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html
For whatever reason, the Scanner class also issues this same exception if it encounters special characters it cannot read. Beyond using the hasNextLine() method before each call to nextLine(), make sure the correct encoding is passed to the Scanner constructor, e.g.:
Scanner scanner = new Scanner(new FileInputStream(filePath), "UTF-8");
Your real problem is that you are calling "sc.nextLine()" MORE TIMES than the number of lines.
For example, if you have only TEN input lines, then you can ONLY call "sc.nextLine()" TEN times.
Every time you call "sc.nextLine()", one input line will be consumed. If you call "sc.nextLine()" MORE TIMES than the number of lines, you will have an exception called
"java.util.NoSuchElementException: No line found".
If you have to call "sc.nextLine()" n times, then you have to have at least n lines.
Try to change your code to match the number of times you call "sc.nextLine()" with the number of lines, and I guarantee that your problem will be solved.
Need to use top comment but also pay attention to nextLine(). To eliminate this error only call
sc.nextLine()
Once from inside your while loop
while (sc.hasNextLine()) {sc.nextLine()...}
You are using while to look ahead only 1 line. Then using sc.nextLine() to read 2 lines ahead of the single line you asked the while loop to look ahead.
Also change the multiple IF statements to IF, ELSE to avoid reading more than one line also.
I ran into this problem, my structure was:
1 - System
2 - Registration <-> 3 - validate
I was closing Scanner on each of the 3 steps. I started to close the Scanner only in system and it solved.

Regular expression["0-9"] issue in java

I have a text file as follows:
Title
XYZ
Id name
1 abc
2 pqr
3 xyz
I need to read the content starting with the integer value and I used the regular expression as in the following code.
public static void main(String[] args) throws FileNotFoundException {
FileInputStream file= new FileInputStream("C:\\Users\\ap\\Downloads\\sample1.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("[0-9]")) {
System.out.println("Line: "+line);
}
}
}
The above code can't detect the lines starting with integers. However, it works fine if single integer values are passed to startsWith() function.
Please suggest, where I went wrong.
String#startsWith(String) method doesn't take regex. It takes a string literal.
To check the first character is digit or not, you can get the character at index 0 using String#charAt(int index) method. And then test that character is digit or not using Character#isDigit(char) method:
if (Character.isDigit(line.charAt(0)) {
System.out.println(line);
}
For regex you can use the "matches" method, like this:
line.matches("^[0-9].*")

Java: Overwrite one character while copying a textfile

My current program reads a file and copies it to another directory, but I want it to change one single character to x, which is given by two ints for the number of the line and the number of the character in the line.
For example if int line = 5 and int char = 4, the fourth character in line five is changed to an x, the rest remains.
How can I add this to my program?
import java.io.*;
import java.util.Scanner;
public class copytest {
public static void main(String[] args) throws Exception {
readFile();
}
public static void readFile() throws Exception {
// Location of file to read
File file = new File("Old.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
//System.out.println(line);
writeFile(line);
}
scanner.close();
System.out.println("File Copied");
}
public static void writeFile(String copyText) throws Exception {
String newLine = System.getProperty("line.separator");
// Location of file to output
Writer output = null;
File file = new File("New.txt");
output = new BufferedWriter(new FileWriter(file, true));
output.write(copyText);
output.write(newLine);
output.close();
}
}
Change your loop to:
int i=0;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (i == lineNumber) {
if (line.length() >= charNumber) {
line = line.substring(0,charNumber) + wantedChar +
line.substring(charNumber);
}
}
writeFile(line);
i++;
}
Note that it will replace the char only if the line long enogth.
Ran Eldan has answered your Question, but I want to point out a couple of other major problems with your code:
You are violating Java's identifier style rules. Java class names should be "camel case" and the first character should be an uppercase letter; i.e.
public class copytest {
should be
public class CopyTest {
This is not just a random nit-pick. If you ignore these style rules, you are liable to get yourself into problem when one of your class names collides with a member or package name defined by your ... or someone else's code. The errors can be very hard to spot.
And of course, if you flout the style rules, you will get continual flak from other programmers when they need to read your code.
Your writeFile method is horribly inefficient. Each time you call it, you open the file, write a line and close it again. This results in at least 3 system calls for each line written. Syscall overheads are significant.
And in addition to being inefficient, you have the problem of dealing with existing output files when the program is run multiple times.
What you should do is open the file once at the start of the run, and use the same BufferedWriter throughout.

java regex line

In java i would like to read a file line by line and print the line to the output.
I want to solve this with regular expressions.
while (...)
{
private static java.util.regex.Pattern line = java.util.regex.Pattern.compile(".*\\n");
System.out.print(scanner.next(line));
}
The regex in the code is not correct, as i get InputMismatchException.
I am working on this regex for 2 hours. Please help with it.
With regex powertoy i see that ".*\n" is correct. But my program runs incorrectly.
The whole source is:
/**
* Extracts the points in the standard input in off file format to the standard output in ascii points format.
*/
import java.util.regex.Pattern;
import java.util.Scanner;
class off_to_ascii_points
{
private static Scanner scanner = new Scanner(System.in);
private static Pattern fat_word_pattern = Pattern.compile("\\s*\\S*\\s*");
private static Pattern line = Pattern.compile(".*\\n", Pattern.MULTILINE);
public static void main(String[] args)
{
try
{
scanner.useLocale(java.util.Locale.US);
/* skip to the number of points */
scanner.skip(fat_word_pattern);
int n_points = scanner.nextInt();
/* skip the rest of the 2. line */
scanner.skip(fat_word_pattern); scanner.skip(fat_word_pattern);
for (int i = 0; i < n_points; ++i)
{
System.out.print(scanner.next(line));
/*
Here my mistake is.
next() reads only until the delimiter,
which is by default any white-space-sequence.
That is next() does not read till the end of the line
what i wanted.
Changing "next(line)" to "nextLine()" solves the problem.
Also, setting the delimiter to line_separator
right before the loop solves the problem too.
*/
}
}
catch(java.lang.Exception e)
{
System.err.println("exception");
e.printStackTrace();
}
}
}
The beginning of an example input is:
OFF
4999996 10000000 0
-28.6663 -11.3788 -58.8252
-28.5917 -11.329 -58.8287
-28.5103 -11.4786 -58.8651
-28.8888 -11.7784 -58.9071
-29.6105 -11.2297 -58.6101
-29.1189 -11.429 -58.7828
-29.4967 -11.7289 -58.787
-29.1581 -11.8285 -58.8766
-30.0735 -11.6798 -58.5941
-29.9395 -11.2302 -58.4986
-29.7318 -11.5794 -58.6753
-29.0862 -11.1293 -58.7048
-30.2359 -11.6801 -58.5331
-30.2021 -11.3805 -58.4527
-30.3594 -11.3808 -58.3798
I first skip to the number 4999996 which is the number of lines containing point coordinates. These lines are that i am trying to write to the output.
I suggest using
private static Pattern line = Pattern.compile(".*");
scanner.useDelimiter("[\\r\\n]+"); // Insert right before the for-loop
System.out.println(scanner.next(line)); //Replace print with println
Why your code doesn't work as expected:
This has to do with the Scanner class you use and how that class works.
The javadoc states:
A Scanner breaks its input into tokens
using a delimiter pattern, which by
default matches whitespace.
That means when you call one of the Scanner's.next* methods the scanner reads the specified input until the next delimiter is encountered.
So your first call to scanner.next(line) starts reading the following line
-28.6663 -11.3788 -58.8252
And stops at the space after -28.6663. Then it checks if the token (-28.6663) matches your provided pattern (.*\n) which obviously doesn't match (-28.6663). That's why.
If you only want to print the file to standard out, why do you want to use regexps? If you know that you always want to skip the first two lines, there are simpler ways to accomplish it.
import java.util.Scanner;
import java.io.File;
public class TestClass {
public static void main(String[] args) throws Exception {
Scanner in=new Scanner(new File("test.txt"));
in.useDelimiter("\n"); // Or whatever line delimiter is appropriate
in.next(); in.next(); // Skip first two lines
while(in.hasNext())
System.out.println(in.next());
}
}
You have to switch the Pattern into multiline mode.
line = Pattern.compile("^.*$", Pattern.MULTILINE);
System.out.println(scanner.next(line));
By default the scanner uses the white space as its delimiter. You must change the delimiter to the new line before you read the line after the first skips. The code you need to change is to insert the following line before the for loop:
scanner.useDelimiter(Pattern.compile(System.getProperty("line.separator")));
and update the Pattern variable line as following:
private static Pattern line = Pattern.compile(".*", Pattern.MULTILINE);
Thank everybody for the help.
Now i understand my mistake:
The API documentation states, that every nextT() method of the Scanner class first skips the delimiter pattern, then it tries to read a T value. However it forgets to say that each next...() method reads only till the first occurrence of the delimiter!

Categories