I have OpenCSV reader in a Java project and its reading data from CSV files for me, but right now Im hardcoding the number of colums in the loop that reads it.
I can recall there was some method that could get the number of columns but I dont remember what it was called and how to use it.
Here is the code:
public ArrayList<ArrayList<String>> getCSVContent(String filepath) throws Exception {
CSVReader reader = new CSVReader(new FileReader(FILE_PATH));
ArrayList<ArrayList<String>> array = new ArrayList<ArrayList<String>>();
String[] nextLine;
while ((nextLine = reader.readNext()) != null) {
ArrayList<String> list = new ArrayList<String>();
for (int i = 0; i < 5; i++) { //5 is the number of columns in the file
list.add(nextLine[i]);
}
array.add(list);
}
reader.close();
return array;
}
Just count the items in the array with nextLine.length.
for (int i = 0; i < nextLine.length; i++) {
list.add(nextLine[i]);
}
Or use a for-each loop:
for (String col : nextLine) {
list.add(col);
}
Well a easy way is that you read the first line with a Scanner of BufferedReader and count the ";" or what you use to split the columns.
You are able to count it if you use
string.toCharArray();
and ++ a Integer if it is ';'.
A second way is the look at the methods of CSV Reader. I don't know them but you can type anywhere in eclipse(don't know how it works in netbeans) "reader." and press control + space. If you have luck there is one.
Try this one to get the column count: reader.getColumnCount()
Related
The numberOfFields() method is supposed to find out how many columns exist in a particular row of a csv file. I'm expecting 7 but my output comes out to be 0; which is what I've initialized cols as. So I used system.out.println() inside the while loop and I figured out that the while loop isn't being entered. My file has plenty of lines of text so I don't understand why readLine() returns null. Not sure where else I could be wrong.
public class CSVReader {
public BufferedReader bR1;
public CSVReader(String fileName) throws IOException {
bR1 = new BufferedReader(new FileReader(fileName));
}
public int numberOfFields(int row) throws IOException {
int rows = 1;
while (rows < row) {
bR1.readLine();
rows++;
}
int cols = 0;
String line;
while ((line=bR1.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line, ",");
while (st.hasMoreElements()) {
st.nextToken();
cols++;
}
}
return cols;
In my opinion, there may be two reason :
the parameter row you give exceed the line number of the file.
your fileName is wrong.
I suggest you add System.out.println(bR1.readLine) in the first while loop to see what happend.
An InputStream can only be read once.
If you call numberOfFields() more than once, all but the first call will fail, since bR1 is no longer positioned at the beginning of the file. It is actually positioned at the end of the file, since that where the first call left the reader.
Instead of opening the stream in the constructor, have each method open their own stream.
In the following, these issues have been fixed:
Using try-with-resources for correctly handling the closing of the stream.
Try-with-resources was added in Java 7, so unless you're running on ancient versions of Java, there is absolutely no good reason to use it.
Changed code to only count the columns of the request row, not the columns of all remaining rows.
Use of StringTokenizer has been replaced by regex. As the javadoc of StringTokenizer says:
StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead.
public class CSVReader {
public final String fileName;
public CSVReader(String fileName) {
this.fileName = fileName;
}
public int numberOfFields(int row) throws IOException {
try (BufferedReader bR1 = new BufferedReader(new FileReader(this.fileName))) {
// Skip row-1 rows
for (int rows = 1; rows < row; rows++) {
bR1.readLine();
}
// Count number of columns in next line, if available
String line = bR1.readLine();
return (line == null ? 0 : line.split(",", -1).length);
}
}
I got this code here:
try{
FileReader file = new FileReader("/Users/Tda/desktop/ReadFiles/tentares.txt");
BufferedReader br = new BufferedReader(file);
String line = null;
while((line = br.readLine()) != null){
String[] values = line.split(",");
grp1 = new int[values.length];
for(int i=0; i<grp1.length; i++){
try {
grp1[i]= Integer.parseInt(values[i]);
}catch (NumberFormatException e) {
continue;
}
}
System.out.println(Arrays.toString(grp1));
}
System.out.println("");
br.close();
}catch(IOException e){
System.out.println(e);
}
This is what the file im reading contains.
grp1:80,82,91,100,76,65,85,88,97,55,69,88,75,97,81
grp2:72,89,86,85,99,47,79,88,100,76,83,94,84,82,93
Right now im storing the values into one int array.
But if i wanted to store each line of values into two arrays?
Thought about using Arrays.CopyOfRange somehow, and copy the values from the int array
into two new arrays.
This answer won't correspond to your question, but will give a hint to my comment under your question post.
Try this at the beginning of your while loop:
Use String.IndexOf() to find the first occurence of the char : into each line. This will be the beginning index for the second part.
Call String.Substring() from your new beginning index to line.length. This will give you the line without the characters and your first numbers aren't lost.
Before the while
List<int[]> groups = new ArrayList<>();
Before the end of the loop:
groups.add(grp1);
Afterwards:
for (int[] grp : groups) {
...
}
A List is useful for a growing "array".
groups.size() grp1.length
groups.get(3) grp1[3]
groups.set(3, x) grp1[3 = x
I have a text file with 300 lines or so. And the format is like:
Name Amount Unit CountOfOrder
A 1 ml 5000
B 1 mgm 4500
C 4 gm 4200
// more data
I need to read the text file line by line because each line of data should be together for further processing.
Now I just use string array for each line and access the data by index.
for each line in file:
array[0] = {data from the 'Name' column}
array[1] = {data from the 'Amount' column}
array[2] = {data from the 'Unit' column}
array[3] = {data from the 'CountOfOrder' column}
....
someOtherMethods(array);
....
However, I realized that if the text file changes its format (e.g. switch two columns, or insert another column), it would break my program (accessing through index might be wrong or even cause exception).
So I would like to use the title as reference to access each column. Maybe HashMap is a good option, but since I have to keep each line of data together, if I build a HashMap for each line, that would be too expensive.
Does anyone have any thought on this? Please help!
you only need a single hash map to map your column names to the proper column index. you fill the arrays by indexing with integers as you did before, to retrieve a column by name you'd use array[hashmap.get("Amount")].
You can read the file using opencsv.
CSVReader reader = new CSVReader(new FileReader("yourfile.txt"), '\t');
List<String[]> lines = reader.readAll();
The fist line contains the headers.
you can read each line of the file and assuming that the first line of the file has the column header you can parse that line to get all the names of the columns.
String[] column_headers = firstline.split("\t");
This will give you the name of all the columns now you just read through splitting on tabs and they will all line up.
You could do something like this:
BufferedReader in = new BufferedReader(new InputStreamReader(
new FileInputStream(FILE)));
String line = null;
String[] headers = null;
String[] data = null;
Map<String, List<String>> contents = new HashMap<String, List<String>>();
if ((line = in.readLine()) != null) {
headers = line.split("\t");
}
for(String h : headers){
contents.put(h, new ArrayList<String>());
}
while ((line = in.readLine()) != null) {
data = line.split("\t");
if(data.length != headers.length){
throw new Exception();
}
for(int i = 0; i < data.length; i++){
contents.get(headers[i]).add(data[i]);
}
}
It would give you flexibility, and would only require making the map once. You can then get the data lists from the map, so it should be a convenient data structure for the rest of your program to use.
This will give you individual list of columns.
public static void main(String args[]) throws FileNotFoundException, IOException {
List<String> headerList = new ArrayList<String>();
List<String> column1 = new ArrayList<String>();
List<String> column2 = new ArrayList<String>();
List<String> column3 = new ArrayList<String>();
List<String> column4 = new ArrayList<String>();
int lineCount=0;
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
String tokens[];
while (line != null) {
tokens = line.split("\t");
if(lineCount != 0)
{
int count = 0;
column1.add(tokens[count]); ++count;
column2.add(tokens[count]); ++count;
column3.add(tokens[count]); ++count;
column4.add(tokens[count]); ++count;
continue;
}
if(lineCount==0){
for(int count=0; count<tokens.length; count++){
headerList.add(tokens[count]);
lineCount++;
}
}
}
} catch (IOException e) {
} finally {
br.close();
}
}
using standard java.util.Scanner
String aa = " asd 9 1 3 \n d -1 4 2";
Scanner ss = new Scanner(aa);
ss.useDelimiter("\n");
while ( ss.hasNext()){
String line = ss.next();
Scanner fs = new Scanner(line);
System.out.println( "1>"+ fs.next()+" " +fs.nextInt() +" " +fs.nextLong()+" " +fs.nextBigDecimal());
}
using a bunch of hashmap's is ok...i won't be afraid ;)
if you need to process a lot of data...then try to translate your problem into a dataprocessing transformation
for example:
read all of you data into a hashmap's, but store them in a database using some JPA implementation....then you can go round'a'round your data ;)\
I am trying to get the values from the second last row and third column in a semicolon separated file. I can't seat to get the values from the second last row and the third column.
I have searched for a method to achieve this but it has been fruitless. I would greatly appreciate if someone could point me in the right direction with an example.
This is the code I have so far:
private static void readmyfile() throws IOException {
String csvFilename = "C:/test.csv";
CSVReader reader = new CSVReader(new FileReader(csvFilename), ';', '\'', 1);
String[] nextLine;
int rowNumber=-1;
nextLine=reader.readNext();
while (nextLine!=null){
rowNumber++;
String speed = nextLine[rowNumber];
System.out.println(speed);
nextLine=reader.readNext();
}
}
My file is formatted like this:
Number; ID; NUM; Counter; Time
1;CCF;9999;1;18:07:05
1;CC8;8888;1;18:07:15
1;CC1;8888;1;18:07:15
1;DC7;1111;1;18:07:15
Date:;01/01/2000; Read:;5; on:;01.05; off:;02.04
Although you are reading the 2nd last line, this could possibly change to the 3rd or 4th last lines. Doing a custom solution here would definitely prove brittle. Therefore using a circular buffer such as Apache's CircularFifoBuffer will allow lines to be added without having to maintain a position count:
CSVReader reader = new CSVReader(new FileReader(csvFilename), ';', '\'', 1);
int rowCount = 2; // save last 2 lines
Buffer<String[]> savedBuffer = new CircularFifoBuffer<String[]>(rowCount);
String[] nextLine;
while ((nextLine = reader.readNext()) != null) {
savedBuffer.add(nextLine);
}
int columnIndex = 2; // zero based
System.out.println(savedBuffer.get()[columnIndex]);
Note: You will need the Generics version of Commons-Collections for this example.
I'm using BufferedReader to read a .csv file. I have no problem reading the file and extracting the data. However, the problem that I do have is that I have to hard-code my array declaration. For example:
String[][] numbers=new String[5258][16];
The .csv file I was using had 5258 rows and 16 columns. I'd like to be able to do something like this though:
String[][] numbers=new String[rowsInFile][16];
In other words, I want the variable 'rowsInFile' to be equivalent to the amount of rows in the file (I don't want to count the columns, because every .csv file I will be running through this program has 16 columns).
Here's the code I have so far:
int row = 0;
int col = 0;
String fileInput = JOptionPane.showInputDialog(null,
"Please enter the path of the CSV file to read:");
File file = new File(fileInput);
BufferedReader bufRdr;
bufRdr = new BufferedReader(new FileReader(file));
String line = null;
//get rows in the file
int rowsInFile = 0;
while(bufRdr.readLine() != null) {
rowsInFile++;
row++;
}
String[][] numbers=new String[rowsInFile][16];
//read each line of text file
row = 0;
while((line = bufRdr.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line,",");
col=0;
while (st.hasMoreTokens()) {
//get next token and store it in the array
numbers[row][col] = st.nextToken();
col++;
}
row++;
}
However, I'm getting a null pointer exception. Any ideas of what I should do?
P.S. Yes, this code is surrounded by a try/catch statement.
The problem is, once you go through the BufferedReader once, you can't go back through it again. In other words, you have to use a new BufferedReader.
bufRdr = new BufferedReader(new FileReader(file));
row = 0;
while((line = bufRdr.readLine()) != null) {
Alternatively, you could use a dynamic array structure like an ArrayList<String[]> or a LinkedList<String[]> to store the rows.
LinkedList<String[]> numbers = new LinkedList<String[]>();
while( (line = bufRdr.readLine()) != null ) {
numbers.add(line.split(","));
}
Then instead of doing numbers[i][j], you use numbers.get(i)[j].
Instead of an array use something dynamic like a List. For example:
List<String[]> data = new ArrayList<String[]>();
Also using String's split() method will simplify the loading of the row.
Your problem is that BufferedReaders work by reading until the end of a file, and then they get stuck there. Your code requires reading through the file twice, but because you already reached an EOF, the BufferedReader is stuck returning null. I tend to solve this by stuffing the lines into an ArrayList, and using the size() method to get the number of lines. The source code looks something like this:
int rowsInFile=0;
ArrayList<String> lines = new ArrayList<String>();
String tmp = "";
while(tmp=bugRdr.readLine())
{
lines.add(tmp);
}
rowsInFile = lines.size();
String[][] numbers = new String[rowsInFile][16];
int row = 0;
for(String line : lines)
{
StringTokenizer st = new StringTokenizer(line,",");
col=0;
while (st.hasMoreTokens()) {
//get next token and store it in the array
numbers[row][col] = st.nextToken();
col++;
}
row++;
}