Android CSV parser problem - android

I am having an issue while parsing a CSV file. It is only 2 rows of data with a comma separating them. Row one is a date and row 2 is a value. The date field will always have dates in it but sometimes the value is blank (or null?). When it gets to the null value I get a StringIndexOutOfBoundsException and the app crashes. I am logging each loop and can see the data but as soon as I get to a null value it stops looping and gives the error. If there are no null values then it works perfect. Here is my code:
BufferedReader buf = new BufferedReader(new StringReader(file));
String line = null;
while ((line = buf.readLine()) != null) {
try {
String date = null, value = null;
String[] RowData = line.split(",");
date = RowData[0];
value = RowData[1]; (this is the row it crashes on)
This is what the CSV looks like:
2011-08-28 09:16,8.23
2011-08-28 09:15,8.24
2011-08-28 09:14,8.26
2011-08-28 09:13,8.34
2011-08-28 09:12,
2011-08-28 09:11,10.72
2011-08-28 09:10,
2011-08-28 09:09,
the value at 09:13 is the last thing in logcat before I get the error.
This fixed it:
if(RowData.length == 2) {
date = RowData[0];
value = RowData[1];
} else {
date = RowData[0];
value = "0";
}
I wrote a 0 in the value field so later processes will not choke on the null value. Thanks for all your help guys!

You want to do this or something like it:
String date = null, value = null;
String[] RowData = line.split(",");
date = RowData[0];
if(RowData.length ==2)value = RowData[1]; (this is the row it crashes on)
Or some variation of it e.g. if(RowData.length < 2) dont attempt to read the value. Its a pretty standard thing - if you ask an array for an index of a value it doesn't have Java will crash.

Why write your own CSV parsing when you could use a library that has already been written which will do it for you? Perhaps OpenCSV would help you achieve your CSV parsing goal.

Check the length of RowData before you try to access it. It looks like split() is returning an array with a single object but you're trying to access the second object, which is indeed out of bounds.

public class CityParser {
DocumentBuilderFactory factory;
DocumentBuilder builder;
Document doc;
Element ele;
int mediaThumbnailCount;`enter code here`
boolean urlflag;
CityListBean objBean = null;
Vector<CityListBean> vecCityList;
public CityParser() {
}
public Vector<CityListBean> getCityData() {
vecCityList = new Vector<CityListBean>();
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpGet httpGet = new HttpGet(
"http://heresmyparty.com/cms/index.php?option=com_chronocontact&chronoformname=add_event_form_download");
HttpResponse response = httpClient.execute(httpGet, localContext);
// String result = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
CSVReader csvreader = new CSVReader(reader);
String[] nextLine;
while ((nextLine = csvreader.readNext()) != null) {
CityListBean objcitylist = new CityListBean();
// nextLine[] is an array of values from the line
objcitylist.setText_title(nextLine[5]);
objcitylist.setText_host(nextLine[6]);
objcitylist.setText_price(nextLine[7]);
objcitylist.setDate(nextLine[8]);
objcitylist.setText_venue(nextLine[11]);
objcitylist.setAddress(nextLine[12]);
objcitylist.setLatitude(nextLine[13]);
objcitylist.setLongitude(nextLine[14]);
objcitylist.setFile(nextLine[15]);
objcitylist.setText_description(nextLine[16]);
objcitylist.setCity(nextLine[17]);
vecCityList.addElement(objcitylist);
}
/*for (int i = 0; i < vecCityList.size(); i++) { CityListBean
objcity = (CityListBean) vecCityList.get(i);
System.out.println("Cf_id : " + objcity.getCityName());
System.out.println("-----------------------------------"); }*/
} catch (Exception ex) {
ex.printStackTrace();
}
return vecCityList;
}
}
==========================================================================================
public class CSVReader {
private BufferedReader br;
private boolean hasNext = true;
private char separator;
private char quotechar;
private int skipLines;
private boolean linesSkiped;
public static final char DEFAULT_SEPARATOR = ',';
public static final char DEFAULT_QUOTE_CHARACTER = '"';
public static final int DEFAULT_SKIP_LINES = 0;
public CSVReader(Reader reader) {
this(reader, DEFAULT_SEPARATOR, DEFAULT_QUOTE_CHARACTER,
DEFAULT_SKIP_LINES);
}
public CSVReader(Reader reader, char separator, char quotechar, int line) {
this.br = new BufferedReader(reader);
this.separator = separator;
this.quotechar = quotechar;
this.skipLines = line;
}
public String[] readNext() throws IOException {
String nextLine = getNextLine();
return hasNext ? parseLine(nextLine) : null;
}
private String getNextLine() throws IOException {
if (!this.linesSkiped) {
for (int i = 0; i < skipLines; i++) {
br.readLine();
}
this.linesSkiped = true;
}
String nextLine = br.readLine();
if (nextLine == null) {
hasNext = false;
}
return hasNext ? nextLine : null;
}
private String[] parseLine(String nextLine) throws IOException {
if (nextLine == null) {
return null;
}
List<String> tokensOnThisLine = new ArrayList<String>();
StringBuffer sb = new StringBuffer();
boolean inQuotes = false;
do {
if (inQuotes) {
// continuing a quoted section, reappend newline
sb.append("\n");
nextLine = getNextLine();
if (nextLine == null)
break;
}
for (int i = 0; i < nextLine.length(); i++) {
char c = nextLine.charAt(i);
if (c == quotechar) {
// this gets complex... the quote may end a quoted block, or escape another quote.
// do a 1-char lookahead:
if( inQuotes // we are in quotes, therefore there can be escaped quotes in here.
&& nextLine.length() > (i+1) // there is indeed another character to check.
&& nextLine.charAt(i+1) == quotechar ){ // ..and that char. is a quote also.
// we have two quote chars in a row == one quote char, so consume them both and
// put one on the token. we do *not* exit the quoted text.
sb.append(nextLine.charAt(i+1));
i++;
}else{
inQuotes = !inQuotes;
// the tricky case of an embedded quote in the middle: a,bc"d"ef,g
if(i>2 //not on the begining of the line
&& nextLine.charAt(i-1) != this.separator //not at the begining of an escape sequence
&& nextLine.length()>(i+1) &&
nextLine.charAt(i+1) != this.separator //not at the end of an escape sequence
){
sb.append(c);
}
}
} else if (c == separator && !inQuotes) {
tokensOnThisLine.add(sb.toString());
sb = new StringBuffer(); // start work on next token
} else {
sb.append(c);
}
}
} while (inQuotes);
tokensOnThisLine.add(sb.toString());
return (String[]) tokensOnThisLine.toArray(new String[0]);
}
public void close() throws IOException{
br.close();
}
}

Have you tried to check first
if (RowData[1]!=null) or possibly if (RowData[1]!="")
I don't see why that would cause your app to crash though,
it should just set value to null or ""

Related

How to Read from text file and Store into an Array in android

Hie Friends
I am developing an android application in that text file should be generated with some numbers. and after this one by one application should call to that numbers.
For eg:
9876452125,
9876452135,
9876452115,
Mostly that text file have 8 numbers which is Separated by "," and New Line "\n"
Now I want to read From that file line by line.
My Code for read file and store to array is:
public void read(String fname)
{
BufferedReader br = null;
try
{
StringBuffer output = new StringBuffer();
String fpath = "/sdcard/" + fname + ".txt";
br = new BufferedReader(new FileReader(fpath));
String line = null;
int index = 0;
String[][] num = new String[15][10];
List<String[]> collection = new ArrayList<String[]>();
while ((line = br.readLine()) != null)
{
if (index < num.length)
{
output.append(line);
// output.append("\n");
num[index] = line.split(",");
if (num.length > 0)
{
collection.add(num[index]);
}
}
Toast.makeText(getApplicationContext(), "" + collection, 5000)
.show();
index++;
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
Now My problem is when I printing collection to Toast it display some random strings. I don't know why??
Does any one have proper idea or sample code for how to read from file line by line and store to Array.
Thanks allot.
If I was you I'd use a scanner. You haven't given information on how you plan to store them: for example, why you use String[][] num = new String[15][10];, but I'll give you an example of if you wanted to store each number in it's own element, and you can adjust if necessary (I am assuming there is only one newline at the end of every line in your file).
public void read(String fname) {
String fpath = "/sdcard/" + fname + ".txt";
File file = new File(fpath);
Scanner scanner = new Scanner(new FileInputStream(file));
List<String[]> collection = new ArrayList<String[]>();
while (scanner.hasNextLine()){
String line = scanner.nextLine();
String.replaceAll("\n", ""); // strip the newline
String[] myList = myString.split(",");
for (i=0; i < myList.length; i++) {
collection.add(myList[i]);
}
}
scanner.close();
}
This doesn't have any android elements in it, but like I said you can adjust as necessary to do what you specifically need it to do.
ArrayList<ArrayList<String>> myArray = new ArrayList<ArrayList<String>>();
ArrayList<String> stringArray = new ArrayList<String>();
String random = "9876452125, 9876452135, 9876452115,";
String[] splitArray = random.split(",");
for (int i = 0; i < splitArray.length; i++) {
stringArray.add(splitArray[i]);
}
myArray.add(stringArray);
// printing all values
for (int i = 0; i < myArray.size(); i++) {
for (int j = 0; j < myArray.get(i).size(); j++) {
System.out.println("values of index " + i + " are :"
+ myArray.get(i).get(j));
}
}

Parsing XML error, arrayindexoutofbounds exception.

I'm trying to parse some XML to a string and I'm getting an outofbounds exception. I'm fairly new to android as well as trying to get text from a website, namely the CTA Bus Tracker API . One block of the XML looks like this:
<route>
<rt>1</rt>
<rtnm>Bronzeville/Union Station</rtnm>
</route>
This is my method:
class loadRoutes extends AsyncTask<String, String, String[]> {
#Override
protected String[] doInBackground(String... strings) {
try {
URL routesURL = new URL(strings[0]);
BufferedReader in = new BufferedReader(new InputStreamReader(routesURL.openStream()));
String [] result = new String[2];
String line;
while((line = in.readLine()) != null) {
if(line.contains("<rt>")) {
int firstPos = line.indexOf("<rt>");
String tempNum = line.substring(firstPos);
tempNum = tempNum.replace("<rt>", "");
int lastPos = tempNum.indexOf("</rt>");
result[0] = tempNum.substring(0, lastPos);
in.readLine();
firstPos = line.indexOf("<rtnm>");
String tempName = line.substring(firstPos);
tempName = tempName.replace("<rtnm>", "");
lastPos = tempName.indexOf("</rtnm>");
result[1] = tempName.substring(0, lastPos);
}
}
in.close();
return result;
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
The first readline() gets to the line with an rt and grabs that line, then in the if statement, readline() should get the next line, which should contain rtnm. I keep getting indexoutofbounds on the line firstPos = line.indexOf("rtnm").
The while loop is already reading in the next line, so you don't need to in.readLine(); in the if statement. Try running it like this:
while((line = in.readLine()) != null) {
if(line.contains("<rt>")) {
int firstPos = line.indexOf("<rt>");
String tempNum = line.substring(firstPos);
tempNum = tempNum.replace("<rt>", "");
int lastPos = tempNum.indexOf("</rt>");
result[0] = tempNum.substring(0, lastPos);
} else if (line.contains("<rtnm>") {
firstPos = line.indexOf("<rtnm>");
String tempName = line.substring(firstPos);
tempName = tempName.replace("<rtnm>", "");
lastPos = tempName.indexOf("</rtnm>");
result[1] = tempName.substring(0, lastPos);
}
}
Also, it might be easier to write your own XML parser in a different class. This XML parser android documentation has an example of exactly what you are trying to do.

checking for a set of string in a text file android

I am trying to check if all of the strings in tr are present in file output. If not then I should return true so that I can notify the user, but something is wrong: I am getting the notification again and again even if all strings are present in the file .
public boolean checkinfile(File output, String[] tr) throws IOException {
Boolean flag = false;
BufferedReader br = new BufferedReader(new FileReader(output));
String read = br.readLine();
int x = 0;
for (x = 0; x < tr.length; x++) {
if ((read.contains(tr[x]))) {
}
else {
flag = true;
return flag;
}
}
return flag;
}
try this code : your code read only the first line of file , in my suggestion , when it reads the file , if a string not present in the file ,break the loop of reading and return true:
public boolean checkinfile(File output, String[] tr) throws IOException {
Boolean flag = false;
BufferedReader br = new BufferedReader(new FileReader(output));
for (int x = 0; x < tr.length; x++) {
String read = br.readLine();
if (!(read.contains(tr[x]))) {
flag=true;
break;
}
}
return flag;
}
You're only reading the first line of the file. You need to loop reading all the lines.

I'm not understanding the following code

I have to understand this code to create my own app(almost based on this function):
public static String[][] ReadFilePerLine(Context context, String nom) {
int i = 0;
try {
FileInputStream fIn = context.openFileInput(nom);
InputStreamReader ipsr = new InputStreamReader(fIn);
BufferedReader b = new BufferedReader(ipsr);
i = getLineNumber(context, nom);
String[][] s = new String[2][i/2];
i = 0;
String ligne;
int j = 0;
while ((ligne = b.readLine()) != null) {
if (i % 2 == 0)
s[0][j] = ligne;
else {
s[1][j] = ligne;
j++;
}
i++;
}
fIn.close();
ipsr.close();
return s;
}
catch (Exception e)
{}
I'm not understanding why the using of a 2D array? and with two rows ?(String[][] s = new String[2][i/2];)
here is the data that it will be stored in the file:
data = date + " : " + y + "L/100KM"+ " " + value1 + "L "+ value2 + "KM\n";
Necessary functions:
public void updatelv(Activity activity) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String fileName = getResources().getString(R.string.fileName);
fileDir = "" + preferences.getString("login", "") + "."+ preferences.getString("marque", "") + ".";
s = myIO.ReadFilePerLine(getApplicationContext(), fileDir+fileName);
ListView L = (ListView) findViewById(R.id.lv);
L.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, s[0]));
for (int i = 0; i< s[0].length; i++) {
Log.d("Saves",s[0][i]);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.histo);
context = getApplicationContext();
activity = this;
final SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(context);
String fileName = getResources().getString(R.string.fileName);
fileDir = "" + preferences.getString("login", "") + "."+ preferences.getString("marque", "") + ".";
s = myIO.ReadFilePerLine(getApplicationContext(), fileDir + fileName);
updatelv(this);
ListView L = (ListView) findViewById(R.id.lv);
L.setTextFilterEnabled(true);
L.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// When clicked, show a toast with the TextView text
String tmp = s[1][position];
if (tmp == null)
tmp = "Aucun fichier trouvé!";
Toast.makeText(getApplicationContext(), tmp, Toast.LENGTH_SHORT)
.show();
}
});
ReadFilePerLine function:
public static String[][] ReadFilePerLine(Context context, String nom) {
int i = 0;
try {
FileInputStream fIn = context.openFileInput(nom);
InputStreamReader ipsr = new InputStreamReader(fIn);
BufferedReader b = new BufferedReader(ipsr);
i = getLineNumber(context, nom);
String[][] s = new String[2][i/2];
i = 0;
String ligne;
int j = 0;
while ((ligne = b.readLine()) != null) {
if (i % 2 == 0)
s[0][j] = ligne;
else {
s[1][j] = ligne;
j++;
}
i++;
}
fIn.close();
ipsr.close();
return s;
}
catch (Exception e)
{
}
Thank you for you help.
The code is clearly reading from a file whose format consists of pairs of lines; it puts the first line of each pair in s[0][...] and the second line of each pair in s[1][...]. If your format doesn't have that peculiarity -- which it doesn't sound as if it does -- then you don't need to do that. Just make an ordinary 1-dimensional array of Strings.
It appears that what they are doing is breaking the file down into two lists (or String arrays, in this case), one which contains all the even-numbered lines, and one which contains all the odd-numbered lines. I'll comment up the code for you:
public static String[][] ReadFilePerLine(Context context, String nom) {
int i = 0;
try {
//open the specified input file and create a reader
FileInputStream fIn = context.openFileInput(nom);
InputStreamReader ipsr = new InputStreamReader(fIn);
BufferedReader b = new BufferedReader(ipsr);
//get the total number of lines in the file, and allocate
//a buffer large enough to hold them all
i = getLineNumber(context, nom);
String[][] s = new String[2][i/2];
i = 0; //set the current line to 0
String ligne;
int j = 0; //set the section index to 0
//now read through the lines in the file, and place every
//even-numbered line in the first section ('s[0]'), and every
//odd-numbered line in the second section ('s[1]')
while ((ligne = b.readLine()) != null) {
if (i % 2 == 0)
//even-numbered line, it goes into the first section
s[0][j] = ligne;
else {
//odd-numbered line, it goes into the second section
s[1][j] = ligne;
j++; //increment the section index
}
i++; //increment the line count
}
//done, cleanup and return
fIn.close();
ipsr.close();
return s;
}
catch (Exception e) {
//should at least log an error here...
}
}
As to why they chose to use a String[][], I cannot say. Probably for convenience, since they want a single object that they can return from this function that contains both lists. Personally I would use a Map that has two List instances in it, but the String[][] works just as well and is probably marginally more efficient.
Judging from your example data it does not appear that you need to use this format. But if you want to use it, you need to structure your data so that the key is on one line, and its associated value is on the next, like:
date
2011-03-19
userName
someGuy
it seems to read from a file, split it into the two dimensional array (based on row count).
Why it does it? I have no idea why you'd want that. Check out the function that it returns s to and find out!

Fail to split downloaded txt file

I have a String that I try to split. The following code works
lsSagor = "some text\n Some more text\n More text~Text again\n Text\n text~Some text ..."
final String[] laList = lsSagor.split("~");
String[] laSaga = laList[0].split("\n");
Gives:
laSaga[0] => some text
laSaga[1] => some more text
laSaga[2] => More text
But if I download the textfile, it fails to split and gives:
laSaga[0] => "some text\n Some more text\n More text"
So it seems the first split works, but not the second.
Here is the code I use to download the file
String lsSagor = getFileFromUrl(BASEURL+"/sagor.txt");
public static String getFileFromUrl(String url)
{
InputStream content = null;
try
{
HttpGet httpGet = new HttpGet(url);
HttpClient httpclient = new DefaultHttpClient();
// Execute HTTP Get Request
HttpResponse response = httpclient.execute(httpGet);
content = response.getEntity().getContent();
}
catch (Exception e)
{
//handle the exception !
}
BufferedReader rd = new BufferedReader(new InputStreamReader(content), 4096);
String line;
StringBuilder sb = new StringBuilder();
try {
while ((line = rd.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
rd.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return sb.toString();
}
From the documentation
I don't think you will find your string contains any newline character to split on, you would need to do
while ((line = rd.readLine()) != null) {
sb.append(line);
sb.append("\n");
}
to get that and I'm sure there is an easier way to just read it newlines and all in the first place.
Hi I think the problem is in String.split() function
Old method but work :)
public static String[] splitString(String str, char separator)
{
String[] retVal = null;
int length = str.length();
int size = 1;
int jIndx = 0;
int expressionLength = 0;
while ((jIndx = str.indexOf(separator, jIndx + 1)) != -1)
{
size++;
}
retVal = new String[size];
jIndx = 0;
char[] charArray = str.toCharArray() ;
for (int index = 0; index < length; index++)
{
if (charArray[index] == separator)
{
retVal[jIndx] = str.substring(index - expressionLength, index);
jIndx++;
expressionLength = 0;
}
else
expressionLength++;
if (index + 1 == length)
{
retVal[jIndx] = str.substring(index + 1 - expressionLength, index + 1);
}
}
return retVal;
}
This is the (not so beautiful) solution
lsSagor = "some text# Some more text# More text~Text again\n Text# text~Some text ..."
String lsSagor = getFileFromUrl(BASEURL+"/sagor.txt");
final String[] laList = lsSagor.split("~");
giAntalSagor = laList.length;
String[] laSaga = laList[0].split("#");
final String[] guiLaList = new String[giAntalSagor];
for (int i = 0; i < giAntalSagor; i++)
{
guiLaList[i] = laList[i].replaceAll("#", "\n");
}
guiLaList is used for layout with "\n" and the other list laList to get the information I wanted.

Categories

Resources