I am using the Scanner method to read the csv file in Java. And wish to skip the empty row in the output.
What method should I use?
Scanner s=new Scanner(new File("file location"));
s.useDelimiter(",");
while(s.hasNext()){
System.out.print(s.next());
System.out.print("|");
System.out.print("\t");
}
s.close();
If a row is empty it will contain (col - 1) delimiters in that line of the file.
For example, with 5 columns, an empty row would be line 2, with (5-1)=4 delimiters:
line1: 5,4,3,2,1
line2: ,,,,
line3: 1,2,3,4,5
So scan in each line, split by delimiter, and ignore unless the length of the line is greater than number of columns - 1.
Scanner s=new Scanner(new File("file location"));
while(s.hasNextLine()){
String line = s.nextLine();
String[] cols = line.split(",");
// if every col is empty, the line will equal col-1 delimiters.
if(line.length() > cols.length - 1){
for(String str : cols){
System.out.print(str);
System.out.print("|");
System.out.print("\t");
}
}
}
s.close();
You could go through file lines by nextLine (and his has* part), check for emptiness and split the string by your delimiter.
If you try to print length for s.next() you can figure out what is causing this. It is caused of end of line characters \r and \n. So, removing them will give the desired result.
Scanner s=new Scanner(new File("1.csv"));
s.useDelimiter(",");
String contentRead="";
while(s.hasNext()){
contentRead = s.next().replaceAll("\\r","");
contentRead = contentRead.replaceAll("\\n","");
if(!contentRead.isEmpty()){
System.out.print(contentRead);
System.out.print("|");
System.out.print("\t");
}
}
s.close();
Use below code to solve your problem and skip empty line while reading CSV using Scanner
String line = "";
while (s.hasNext()) {
if (!(line = s.nextLine()).isEmpty()) {
System.out.print(line);
System.out.print("|");
System.out.print("\t");
}
}
There is no method available in Scanner class to achieve this.
here, rather than using "," as delimiter, use "\n" as delimiter.
This will help you get a particular line contents in each iteration.
Then you can verify if content of that particular line suit you and proceed as required.
s.useDelimiter("\n");
while(s.hasNext())
{
line = s.next();
System.out.println("\nNext Line :" +line);
//Here, tokenize the line and verify if any non-empty token exists
}
CSV can be tricky:
individual values may contain a newline separator (e.g. v1, "v2[\n]and a new line", v3): if you use a nextLine() equivalent you won't parse the data correctly.
individual values may contain the delimiter (e.g. v1,"v2[,] and more stuff", v3): in this case simply relying on a split() equivalent will produce multiple values instead of one.
Line breaks won't be handled properly in multiple platforms (e.g. v1 "v2[\r\n]and a new line", v3): if you parse this in Linux or MACOS the second column will be parsed to produce a blank line between v2 and and a new line (i.e. you'll get 3 lines instead 2).
Use a the CSV parser that comes with uniVocity-parsers to handle these sorts of situations reliably:
CsvParserSettings settings = new CsvParserSettings(); // many options here, check the tutorial.
settings.getFormat().setLineSeparator("\r\n");
CsvParser parser = new CsvParser(settings);
List<String[]> allRows = parser.parseAll(new FileReader(new File("path/to/file.csv")));
Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).
Related
How to append text to an existing file in Java?
I am using the method mentioned in the solution and i am taking user input.
But the text is appending with the last word. is there any way to add an new line there?
Scanner sc= new Scanner(System.in);
System.out.print("Enter a string: ");
String str= sc.nextLine();
try {
Files.write(Paths.get("C:\\Users\\souravpal\\Documents\\Bandicam\\buddy.txt"), str.getBytes(), StandardOpenOption.APPEND);
}catch (IOException e) {
//exception handling left as an exercise for the reader
}
You must use the new line character \n in your str variable if you want to move to the next line.
String str = "\n" + sc.nextLine();
You also should put it before the input becouse you will append it at the end of the file.
use the System.lineSeparator() constant that applies at runtime and compatible with all OS.
Files.write(Paths.get("C:\\Users\\souravpal\\Documents\\Bandicam\\buddy.txt"),
(System.lineSeparator() + str).getBytes(),StandardOpenOption.APPEND);
I want to create a program that reads from a text file with three different parts and then outputs the name. E.g. text file:
vanilla 12 24
chocolate 23 20
chocolate chip 12 12
However, there is a bit of an issue on the third line, as there is a space. So far, my code works for the first two lines, but then throws a InputMismatchException on the third one. How do I make it so it reads both words from one line and then outputs it? My relevant code:
while (in.hasNext())
{
iceCreamFlavor = in.next();
iceCreamRadius = in.nextDouble();
iceCreamHeight = in.nextDouble();
out.println("Ice Cream: " + iceCreamFlavor);
}
In your input file, the separator between fields is composed of multiples spaces, no ?
if yes, you could simply use split method of String object.
You read a line.
You split it to obtain a String array.
String[] splitString = myString.split(" ");
Ther first element «0» is the String, the two others can be parsed as double
This could looks like :
try (BufferedReader br = new BufferedReader(new FileReader("path/to/the/file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
String[] lineSplitted = line.split(" ");
String label = lineSplitted[0];
double d1 = Double.parseDouble(lineSplitted[1]);
double d2 = Double.parseDouble(lineSplitted[2]);
}
} catch (IOException e) {
e.printStackTrace();
}
You can use scanner.useDelimiter to change the delimiter or use a regular expression to parse the line.
//sets delimiter to 2 or more consecutive spaces
Scanner s = new Scanner(input).useDelimiter("(\\s){2-}");
Check the Scanner Javadoc for examples:
Here's the .txt file i'm trying to read from
20,Dan,09/05/1990,3,Here
5,Danezo,04/09/1990,99,There
And here's how I'm doing it.. Whenever the .txt file has only one line, it seems to be reading from file fine. Whenever more than one line is being read, I get this error
Exception in thread "main" java.lang.NumberFormatException: For input string: "Danezo"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at AttackMonitor.readFromFile(AttackMonitor.java:137)
at AttackMonitor.monitor(AttackMonitor.java:57)
at MonsterAttackDriver.main(MonsterAttackDriver.java:14)
Java Result: 1
Here's the readfromfile code.
private void readFromFile() throws FileNotFoundException, IOException
{
monsterAttacks.clear();
Scanner read = new Scanner(new File("Attacks.txt"));
read.useDelimiter(",");
String fullDateIn = "";
int attackIdIn = 0;
int attackVictimsIn = 0;
String monsterNameIn= "";
String attackLocationIn= "";
while (read.hasNext())
{
attackIdIn = Integer.parseInt(read.next());
monsterNameIn = read.next();
fullDateIn = read.next();
attackVictimsIn = Integer.parseInt(read.next());
attackLocationIn = read.next();
monsterAttacks.add(new MonsterAttack(fullDateIn, attackIdIn, attackVictimsIn, monsterNameIn, attackLocationIn));
}
read.close();
}
What is happening is that at the end of each line there is a newline character, which is currently not a delimiter. So your code is attempting to read it as the first integer of the next line, which it is not. This is causing the parse exception.
To remedy this, you can try adding newline to the list of delimiters for which to scan:
Scanner read = new Scanner(new File("Attacks.txt"));
read.useDelimiter("[,\r\n]+"); // use just \n on Linux
An alternative to this would be to just read in each entire line from the file and split on comma:
String[] parts = read.nextLine().split(",");
attackIdIn = Integer.parseInt(parts[0]);
monsterNameIn = parts[1];
fullDateIn = parts[2];
attackVictimsIn = Integer.parseInt(parts[3]);
attackLocationIn = parts[4];
You can use the Biegeleisen suggestion. Or else you can do as follows.
In your while loop you are using hasNext as condition. Instead of that you can use while (read.hasNextLine()) and get the nextLine inside the loop and then split it by your delimiter and do the processing. That would be a more appropriate approach.
e.g
while (read.hasNextLine()) {
String[] values = scanner.nextLine().split(".");
// do your rest of the logic
}
Put the while loop content in a try catch, and catch for NumberFormatException. So whenever it falls to catch code, you can understand you tried to convert a string to int.
Could help more if your business is explained.
attackLocationIn = read.next(); This value takes as "Here\n 5" because there is no comma between Here and 5 and it has new line character.
so 2nd iteration attackIdIn = Integer.parseInt(read.next()); here read.next() value is "Danezo" it is String and you are trying parse to Integer. That's why you are getting this exception.
What I suggest is use BufferReader to read line by line and split each line with comma. It will be fast also.
Or another solution Add comma at end of each line and use read.next().trim() in your code. That's it it will work with minimal changes to your current code.
I know that by default, the Scanner skips over whitespaces and newlines.
There is something wrong with my code because my Scanner does not ignore "\n".
For example: the input is "this is\na test." and the desired output should be ""this is a test."
this is what I did so far:
Scanner scan = new Scanner(System.in);
String token = scan.nextLine();
String[] output = token.split("\\s+");
for (int i = 0; i < output.length; i++) {
if (hashmap.containsKey(output[i])) {
output[i] = hashmap.get(output[i]);
}
System.out.print(output[i]);
if (i != output.length - 1) {
System.out.print(" ");
}
nextLine() ignores the specified delimiter (as optionally set by useDelimiter()), and reads to the end of the current line.
Since input is two lines:
this is
a test.
only the first line (this is) is returned.
You then split that on whitespace, so output will contain [this, is].
Since you never use the scanner again, the second line (a test.) will never be read.
In essence, your title is right on point: Java Scanner does not ignore new lines (\n)
It specifically processed the newline when you called nextLine().
You don't have to use a Scanner to do this
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String result = in.lines().collect(Collectors.joining(" "));
Or if you really want to use a Scanner this should also work
Scanner scanner = new Scanner(System.in);
Spliterator<String> si = Spliterators.spliteratorUnknownSize(scanner, Spliterator.ORDERED);
String result = StreamSupport.stream(si, false).collect(Collectors.joining(" "));
I have a scanner in my program that reads in parts of the file and formats them for HTML. When I am reading my file, I need to know how to make the scanner know that it is at the end of a line and start writing to the next line.
Here is the relevant part of my code, let me know if I left anything out :
//scanner object to read the input file
Scanner sc = new Scanner(file);
//filewriter object for writing to the output file
FileWriter fWrite = new FileWriter(outFile);
//Reads in the input file 1 word at a time and decides how to
////add it to the output file
while (sc.hasNext() == true)
{
String tempString = sc.next();
if (colorMap.containsKey(tempString) == true)
{
String word = tempString;
String color = colorMap.get(word);
String codeOut = colorize(word, color);
fWrite.write(codeOut + " ");
}
else
{
fWrite.write(tempString + " ");
}
}
//closes the files
reader.close();
fWrite.close();
sc.close();
I found out about sc.nextLine(), but I still don't know how to determine when I am at the end of a line.
If you want to use only Scanner, you need to create a temp string instantiate it to nextLine() of the grid of data (so it returns only the line it skipped) and a new Scanner object scanning the temp string. This way you're only using that line and hasNext() won't return a false positive (It isn't really a false positive because that's what it was meant to do, but in your situation it would technically be). You just keep nextLine()ing the first scanner and changing the temp string and the second scanner to scan each new line etc.
Lines are usually delimitted by \n or \r so if you need to check for it you can try doing it that way, though I'm not sure why you'd want to since you are already using nextLine() to read a whole line.
There is Scanner.hasNextLine() if you are worried about hasNext() not working for your specific case (not sure why it wouldn't though).
you can use the method hasNextLine to iterate the file line by line instead of word by word, then split the line by whitespaces and make your operations on the word
here is the same code using hasNextLine and split
//scanner object to read the input file
Scanner sc = new Scanner(file);
//filewriter object for writing to the output file
FileWriter fWrite = new FileWriter(outFile);
//get the line separator for the current platform
String newLine = System.getProperty("line.separator");
//Reads in the input file 1 word at a time and decides how to
////add it to the output file
while (sc.hasNextLine())
{
// split the line by whitespaces [ \t\n\x0B\f\r]
String[] words = sc.nextLine().split("\\s");
for(String word : words)
{
if (colorMap.containsKey(word))
{
String color = colorMap.get(word);
String codeOut = colorize(word, color);
fWrite.write(codeOut + " ");
}
else
{
fWrite.write(word + " ");
}
}
fWrite.write(newLine);
}
//closes the files
reader.close();
fWrite.close();
sc.close();
Wow I've been using java for 10 years and have never heard of scanner!
It appears to use white space delimiters by default so you can't tell when an end of line occurs.
Looks like you can change the delimiters of the scanner - see the example at Scanner Class:
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
System.out.println(s.nextInt());
System.out.println(s.nextInt());
System.out.println(s.next());
System.out.println(s.next());
s.close();