Parse CSV file in java, and delaing with empty values - java

I am parsing a CSV file into my program, spliting the values at the , element, and it's working fine, except for when I have lines that have missing values.
The parser is working like this:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CsvReader
{
private static final String DELIMITER = ",";
private final BufferedReader br;
private final String path;
public CsvReader(final String path) throws IOException
{
this.path = path;
this.br = new BufferedReader(new FileReader(path));
}
public String[] nextLine() throws IOException
{
final String line = br.readLine();
return (line == null) ? new String[0] : line.split(DELIMITER);
}
}
The lines of data look like this (one line as an example):
J1024205,5028197000004,1,,00,20150603,,Accessories,Factory Test Article (m),ENG,010,110,5,T1,99,99,,,99,99,99,ZZ,ZZ,,5028197242053,30,35028197242054,6,,,OPZ848,3013607800239,OPZ848,,,,50,,
Most of the lines in the file complete with this: 50,85028197242127,8640
But on some lines, the data is missing, so it ends like this: 50,,
When the file is being processed, these lines are causing a java.lang.ArrayIndexOutOfBoundsException.
How can I best deal with this, if I know that the numbers of objects in the file will remain constant?
I've been told that I need to replace empty values with a null value.

From the Javadoc of String.split(regex)
This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array.
So, in your case, when the string ends with ,,, empty strings wont be part of the resultant array.
To Fix: Use this variant of split
line.split(DELIMITER, -1);
This will include all trailing empty strings. So you won't get an exception.

This code results in array elements that are null if the column was empty.
// ... rest of OP's code
public String[] nextLine() throws IOException
{
final String line = br.readLine();
if(line == null)
{
return null;
}
String columns[] = line.split(DELIMITER, -1);
for(int i = 0; i < columns.length; i++)
{
if(columns[i].isEmpty())
{
columns[i] = null;
}
}
return columns;
}

You can this way also. Just call split method on the String returned with comma
public String replaceNullSplitLine(String line){
if(line.endsWith(",")){
line = line+"***";
}
line = line.replaceAll(",,", ",***,");
return line;
}

Check the length of the array before trying to use the last (and in that case non-existed) values
myArray.length

Related

How can I fix the startsWith() error of java

I cannot figure out the startsWith(str) in the while loop below have the error
The method startsWith(String) is undefined for the type InfoProcessor.
I want to get the String that follows the line that starts with the given String (str).
It is great pleasure to have your help.
import java.util.*;
public class InfoProcessor {
private ArrayList<String> lines = new ArrayList<String>();
public InfoProcessor(ArrayList<String> lines) {
this.lines = lines;
}
String getNextStringStartsWith(String str) {
for (int i = 0 ; i < lines.size(); i++){
Scanner scanner = new Scanner(lines.get(i));
while (startsWith(str)){
String hobby = scanner.nextLine();
String[] tokens = hobby.split("\\s+");
return tokens[1];
}
}
return null;
}
You are trying to invoke a String method but you are not invoking it on a String. Therefore, the compiler interprets your attempt as invoking the method on this class. This class does not implement that method so the method is undefined. In your case, you want to invoke that method on an individual line to see if it contains the prefix.
public String findWordAfterPrefix(String prefix) {
for (String line : lines) { // iterate over the lines
if (line.startsWith(prefix)) { // does the line start with the prefix?
/// find the next word and return it - that is a separate issue! ;)
}
}
return null; // return null if we never found the prefix
}
p.s. You may find some other String method useful as you pull out the next word (e.g. trim(), substring(int).
The error means exactly what it says: there is no startsWith() method in your InfoProcessor class.
You may have intended str.startsWith(...) instead of startsWith(str).

How to retrieve array values and assign to String variable in java

I am trying to store the contents from a file into an array String retval[] , copy that array to String[] fed() and pass the array into main. So far, the array stores and copies but the array method returns null in main String []feed; feed=uio.fed();.
UserIO.java
package fileio;
import classes.*;
import java.util.*;
import java.lang.*;
import java.io.*;
public class UserIO
{
public String search (String line0)
{
String line;
try
{
FileInputStream ufin = new FileInputStream("E:\\3rd sem\\OOP\\Projects\\New folder (2)\\BOOK LIBRARY\\fileio\\user.txt");
Scanner sc = new Scanner(ufin);
while (sc.hasNextLine())
{
line=sc.nextLine();
if(line.contains(line0))
{
String retval[]= line.split(" ");
feed= new String[retval.length];
for (String s: retval)
{
System.out.println("\t\t\tFrom retval:"+s);
}
for (int n=0;n<retval.length;n++)
{
feed[n]=retval[n];
System.out.println("\tFrom feed:"+feed[n]);
}
}
}
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
return line0;
}
public static String [] feed;
public static String[] fed()
{
String [] fd;
fd= new String[feed.length];
for (int n=0;n<feed.length;n++)
{
fd[n]=feed[n];
System.out.println("From fd:"+fd[n]);
}
return fd;
}
}
Down below is the main method
Execute.java
import java.lang.*;
import java.util.*;
import classes.*;
import fileio.*;
public class Execute
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
String adminusername = "a";
String adminpassword = "p";
String readerusername = "r";
String readerpassword = "p";
String nreaderusername;
String nreaderpassword;
Library b = new Library();
UserFileReadWriteDemo ufrwd = new UserFileReadWriteDemo();
UserIO uio = new UserIO();
System.out.println("enter id ");
String id = sc.next();
uio.search(id);
try
{
String []feed;
feed=uio.fed();
//uio.fed()=feed.clone;
for(int s=0;s<feed.length;s+=5)
{
String nid00= null;
feed[0+s]= nid00;
String name00=null;
feed[1+s]= name00;
String age00= null;
feed[2+s]= age00;
String uname00= null;
feed[3+s]= uname00;
String upassword00= null;
feed[4+s]= upassword00;
Reader c00 = new Reader(nid00, name00, age00,uname00,upassword00);
b.insertReader(c00);
System.out.println(" In main"+feed[s]);
}
}
catch (NullPointerException n)
{
n.printStackTrace();
}
}
Your code is a little bit difficult to read and also has a lot of unnecessary repetitions, for example method fed has no role, why not call search and make search return an array with the found elements? You are making search return the line you are searching for which you already know when you gave search that argument in the first place, it is just returning a useless value.
Also it is difficult to understand what search actually does, from what i see it finds the last occurrence of line0 in the file, because it continues to iterate over lines and every time it finds line0 it will create new feed array in UserIO and eliminate all the previous array it found, and will return when all file has been read. If this is your intention then this is not the right way to do it as it is inefficient, because you keep creating arrays that will be discarded. If your intention is the last occurrence of line0 then you can just assign a found line to a String variable and when the iteration finishes just split and return that array as it will be the last occurrence of line0 in the file.
As i see it the only way that fed will return null is if there is no line with line0 in the file because search initializes the array if it finds line0 at least once in the file, this way feed will be an uninitialized array which will be a null pointer.
These lines has no meaning:
String nid00= null;
feed[0+s]= nid00;
String name00=null;
feed[1+s]= name00;
String age00= null;
feed[2+s]= age00;
String uname00= null;
feed[3+s]= uname00;
String upassword00= null;
feed[4+s]= upassword00;
I think you meant nid00 = feed[0+s] and so on, because the way you wrote the assignment to nid00 and the other variables will be always null which will be useless.
Also when you copy arrays try to use Arrays.copyOf methods or System.arraycopy they save you writing several lines and also they are more efficient, read about them in the documentation.
And the last thing, it is not useful to catch nullpointer exception if you wrote your code, in general you must know what your methods do and if there is a nullpointer exception in something you wrote then there is something wrong in your code, if for example a method you wrote returns null then you must know about the possibility of a null return and handle that possible return, this way it will be easier for you to read your code and use it and also for others who use your code.
The nullpointer you are getting is because you trying to get the length of an uninitialized feed inside fed method, you must be very careful.

List of class objects

I'm stuck.. I trying to parse a text from file in words, but save it in List of objects. Whether it is possible to do so?
public class Text {
public static List<Words> words = new ArrayList<Words>();
}
public class Words {
private String path;
private String[] inside;
private BufferedReader in;
public Words(String path, String[] inside) {
this.inside = inside;
this.path = path;
}
public String[] splittinIntoWords() throws IOException {
in = new BufferedReader(new FileReader(path));
String s;
while ((s = in.readLine()) != null) {
inside = s.split(" ");
//System.out.println(Arrays.toString(inside));
}
return inside;
}
}
and main class
public class Main {
public static void main(String[] args) throws IOException {
String file_name = "book.doc";
String[] inside = null;
Words w = new Words(file_name, inside);
w.splittinIntoWords();
Text.words.add(w); //after add in list i have a reference.
System.out.println(Text.words.toString());
}
}
i do smthg wrong. I understand how to do this with List of Strings
tell me please, it is possible, to add text splitting into words in List of Words
You’re overwriting the array of words Words.inside with each line you read. You need to add the output of split() to a List every time round the while loop, not just at the end.
I would expect your code to display the words in the last line of your file, but possibly it has a blank last line, in which case you will see nothing.
Also, I assume your "book.doc" is not really a .doc format file—word processor files need special parsing; what you have written will only work on plain text files.
there is several things wrong with your code.
Text.words shouldn't be static. Every instance of text consists of a different collection of words.
When you make a "Collection of Words", then it should be Collection< Word>. Because every item inside the collection is just a single item.
but then again, Collection< Word> is just the same as Collection< String>. So use that.
"path", "in" should not be member variables of "Words". Just use them locally in your method. Especially since you never closed "in".
you're overwriting whatever is in "inside" for each line in your file that you loop over. When you have your "Collection< String> words", then just do words.addAll(inside); in
your loop.
Yes, I know this is not an answer, but I'm trying to point you in the right direction. This might help you more in the long run.

Importing data from text

I have a bunch of text files with entries that look like this:
20662 = {
name="Durgulel"
dynasty=100603
martial=7
diplomacy=4
intrigue=5
stewardship=4
learning=6
religion="orthodox"
culture="alan"
trait="chaste"
trait="arbitrary"
trait="scholarly_theologian"
father=41592
992.1.1={
birth="992.1.1"
}
1068.1.1={
death="1068.1.1"
}
}
Is there a standard way for reading values from something like this into variables?
You could use a StreamTokenizer; should look roughly like this (untested):
static Map<String,Object> parse(
StreamTokenizer tokenizer, int endToken) throws IOException {
Map<String,Object> result = new TreeMap<String,Object>();
while (tokenizer.nextToken() != endToken) {
String key = tokenizer.sval;
if (tokenizer.nextToken() != '=') {
throw new RuntimeException("'=' expected");
}
if (tokenizer.nextToken() == '{') {
result.put(key, parse(tokenizer, '}'));
} else {
tokenizer.nextToken();
result.put(key, tokenizer.sval);
}
}
return result;
}
static void main(String[] args) throws IOException {
Reader reader = new FileReader(args[0]);
Map<String,Object> parsed = parse(
new StreamTokenizer(reader), StreamTokenizer.TT_EOF);
System.out.println(parsed);
}
p.s. This will need some additional handling for 922.1.1 and similar keys. If the format is really just line based, it might be more straight forward to use BufferedReader.readLine(), trim() and check for { / } / =
p.p.s If by variables you mean instance member variables, you could use the Java reflection API to set them accordingly (instead of reading to a map as in the example). You'd hand in the object to fill and then look up and set the members via object.getClass().getField(key).set(object, value)
Yes, there are a few ways to read files into a program. I'd recommend reading about BufferedReader, FileReader, and Scanner. Some documentation on the following:
FileReader
BufferedReader
Scanner
I usually pair BufferedReader and FileReader because the BuffereReader method nextLine() is conveniant for string variables. It's implemented as follows:
FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr);
String x = br.readLine();
I'd also recommend some sort of regex expression for reading in your lines because of how the document is formatted. An example of an way of reading in seperate words into indices of a String[] with readLIne() and a simple regex expression is: String wH[] = br.readLine().split("\\W+"); This might be useful for splitting each line based on its contents, but since your lines don't appear to be separated by spaces, it always viable to just examine the raw string based in by readLine() in some sort of for-loop.
Once you've targeted the exact values you want, you can assign them to variables. For example, lets say you have a condition that detects the phrase "name" in a line, you could then assign the value that comes after the = and between the quotes to your desired variable. Then Rinse and Repeat.
Hope this helps.

printing arrays

Okay, I'm trying to get file scanner to return the array itemList.
However, I don't understand why everytime I get to return itemList and try with a println form.
It returns:
[Ljava.lang.String;#3d3b5a3a
[Ljava.lang.String;#10cb42cf
[Ljava.lang.String;#482d59a3
[Ljava.lang.String;#18f42160
When the file I'm reading it contains stuff like
apples 10
fish 20
import java.io.*;
import java.util.*;
class loadInventory{ /*This class is used for loading the inventory */
private String[] itemList; /*The lines of the inventory are stored in this array */
private int numItems; /* The number of items is stored in this variable */
public loadInventory(String fileName){ /*We can do everything in the constructor. It gets the fileName from the superMarket
object */
itemList = new String[100]; /*We assume there are not more than 100 items in the inventory */
numItems=0; /*initialize numItems to 0*/
/*Read the file using the try-catch block below. We are not specifically catching any exception.
We will not cover reading or writing of files and exceptions in this unit. So you
don't need to understand this piece of code. */
try{
BufferedReader reader = new BufferedReader(new FileReader(fileName)); /*standard code for reading a file */
String line = reader.readLine(); /*read the next line from the file and store in line */
while (line != null){ /*as long as there are lines */
itemList[numItems]= line; /*store the line in the current location of the array */
numItems++; /*increment the number of items */
line = reader.readLine(); /*read the next line */
}
reader.close(); /*close the reader */
} catch (IOException e){ /*we don't catch any exception */
}
System.out.println(itemList);
}
public String[] getItemList() {
return itemList;
}
}
Print the array of instances like this:
System.out.println(Arrays.toString(itemList));
An array itself uses the default toString() from Object, so it does not print its contents. You will need to use java.util.Arrays.toString(Object[]) to print out the content of the array (or loop over it yourself).
int length = itemList.length;
int count =0;
while(count<length)
{
System.out.println(itemList[count]);
count++;
}
thats a simplest way to iterate the list.
Because you are trying to print the whole array object while doing:
System.out.println(itemList);
Instead you need to print the single String elements stored inside the array:
System.out.println(Arrays.toString(itemList));
Don't print the String[] value directly. use like this,
for (int i = 0; i < itemList.length; i++) {
System.out.println("Value::> " +itemList[i]);
}
Pay attention on this code
while (line != null)
{
itemList[numItems]= line;
numItems++;
line = (String)reader.readLine();
}
Try this.

Categories