OpenCSV Get Value from last row and specific column - java

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.

Related

readLine() returns null even though file has content

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);
}
}

Reading text file into an array in Java

I'm pretty new to Java (currently enrolled in my first programming class), so the answer to my question could be right in front of me.
My goal is to read in a text file that reads as follows:
4563123,112211324135412
2312311,222121324135211
2312345,112211324135421
5527687,212111313124412
7867567,111111111111111
where the first set of numbers is an ID, and the second set is a set of answers to a test (of which I have the key). Once I've read in the answers I need to store them in an array (and I assume just an array, as my class has not covered ArrayLists yet). All of this data would need to be stored in one array, since I need to return it at the end of the method.
Here is the code that I have so far:
public static String[] readFile(String filename)throws IOException{
Scanner inFile = new Scanner(filename);
String line;
String[] results = new String[101];
int i = 0;
while (inFile.hasNextLine()){
line = inFile.nextLine();
String[] incoming = line.split(",");
String wid = incoming[0];
String answer = incoming[1];
results[i] = wid;
results[i + 1] = answer;
i += 2;
}
inFile.close();
return results;
}
It's safe to ignore the String filename, it was passed in from the main.
Every time I run this method, I keep running into an ArrayOutOfBoundsException, mainly when I try to assign incoming[1] to answer.
I've been staring at this code longer than what is probably good for me, but it seems that I just can't wrap my head around it. Any help would be appreciated, whether that be telling me what is wrong or what I can do to improve.
Since you are using Java 7, use the new Files API and a try-with-resources statement; also, avoid copying empty lines:
final Path file = Paths.get(filename);
String line;
String[] incoming;
String[] results = new String[101];
int nrElements = 0;
try (
final BufferedReader reader = Files.newBufferedReader(path,
StandardCharsets.UTF_8);
) {
while ((line = reader.readLine()) != null) {
incoming = line.split(",");
if (incoming.length != 2)
continue;
results[nrElements++] = incoming[0];
results[nrElements++] = incoming[1];
}
}
return Arrays.copyOfRange(results, 0, nrElements);
Either you are having an empty line in your file. Or a garbage line that doesn't have any comma in it. So before accessing the slitted array, just give a check.
if(incoming != null && incoming.length >= 2){
String wid = incoming[0];
String answer = incoming[1];
// ... other dependent codes go here!
}
It will help you to avoid the Exception.

How to read and store data from a text file in which the first line are titles, and the other lines are related data

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 ;)\

OpenCSV reader for Java - how to get the number of columns?

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()

Using BufferedReader to count rows in a multi-dimensional array

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++;
}

Categories

Resources