I am creating a database in Android, all was going nice, but when I was testing the queries retrieving the correct data I've got an error.
E/AndroidRuntime(14126): java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
I know that means that there is no data matching the query, but the fact is that I inserted the data by query and it actually has a match. And the same query works with all the codes that doesn't have accents.
These are the queries for inserting the rows.
INSERT INTO "codigo" VALUES('A','PEATÓN');
INSERT INTO "codigo" VALUES('B','PEATÓN');
INSERT INTO "codigo" VALUES('C','PEATÓN');
So I did a query that gets the values of the field that I was replacing, like this:
String selectCode = "select distinct c.tipo from codigo c";
Cursor cursor = database.rawQuery(selectCodigo, new String[] {});
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
String codigo= cursor.getString(0);
codigos.add(codigo);
System.out.println(codigo);
cursor.moveToNext();
}
cursor.close();
return codigos;
And the result was this:
10-14 16:40:32.140: I/System.out(13716): PEAT�N
I have the text file in the /raw folder and I edited from the Eclipse so I make sure it wasn't the table export I did, but I have the same results.
This is the code that reads the file:
public int insertFromFile(SQLiteDatabase db,Context context, int resourceId) throws IOException {
// Reseting Counter
int result = 0;
// Open the resource
InputStream insertsStream = context.getResources().openRawResource(resourceId);
BufferedReader insertReader = new BufferedReader(new InputStreamReader(insertsStream));
// Iterate through lines (assuming each insert has its own line and theres no other stuff)
while (insertReader.ready()) {
String insertStmt = insertReader.readLine();
db.execSQL(insertStmt);
result++;
}
insertReader.close();
// returning number of inserted rows
return result;
}
How could I get that accent working?
I am using a lot of them, so, replacing the word is not a way out.
Please help, is the only thing I need to finish this project.
UPDATE:
Had the same problems two more times later. The first I fixed it by working with a .sql file coded in cp1525 and opened it in Eclipse with the default editor and find/replaced the wrong characters.
The last time I've got this error I made it the right way, and found that if you are working with SQLiteManager it imports files encoded in UTF-8 but it export files in ANSI, so I opened the file with Notepad++, change the enconding of the .sql file from ANSI to UTF-8 and it works fine, all the characters were shown fine.
The InputStreamReader constructor documentation says:
Constructs a new InputStreamReader on the InputStream in. This constructor sets the character converter to the encoding specified in the "file.encoding" property and falls back to ISO 8859_1 (ISO-Latin-1) if the property doesn't exist.
If the file is encoded in UTF-8, you have to tell the reader this.
in your SQLQueryString just add before
PRAGMA encoding = "UTF-8";
example
"PRAGMA encoding = \"UTF-8\"; INSERT INTO MYTABLE (mytablefield) VALUES ('value'); "
Related
I am going to create an android dictionary application which goal is to translate my mother language (Zazaki) to Turkish.
I have 2 documents which have a format like below:
Zazaki to Turkish word docs
ban: ev ====> home
Turkish to Zazaki
ev: ban, çe ===> home
In my mind, first taking word before colon as key, after colon as value.
Then putting it into a database.
My question is:
"Do I have to do this operation for every time?
How can I make this database available for every download by not importing the word list documents into my database"?
First, if you have excel, it's quite easy to make a word document into a database , by splitting by ' ' and deleting the resulting columns you don't need. You can then export it, e.g. into a .csv file.
For your request, I would use the following pseudo-code as a guide for my code:
int currIndex = 0;
string key, value;
while(!EndOfFile){
currIndex = find('=');
key = getWordBeforeCurrentIndex();
currIndex = find('>');
value = getWordAfterCurrentIndex();
myDictionary.Add(key, value);
}
Make that into real code and voila - you got yourself an app parsing a document into a dictionary.
If you know that your document has an exact format like:
ev ====> home
word2 ===> translation2
word3 ===> translation3
You can of course leverage this and go
Dictionary myDict = new HashTable<string, string>();
InputStream wordDictionary = getResources().openRawResource(R.raw.wordDictionary);
DataInputStream myDIS = new DataInputStream(wordDictionary);
ArrayList<string> lines = new ArrayList<Lines>();
string currLine;
//Read document into arraylist:
while((myLine=myDIS.readline())!=null) list.add(myLine);
//Take each line, add left word as key, add right word as value:
foreach(line : lines){
myDict.add(line.substring(0, line.indexOf(" ")), line.substring(line.indexOf(" ", line.indexOf(" ")+1));
}
I have a csv file with only one column of values. I would like to take the values from each row and display them in separate TextViews using OpenCSV. My code goes something like this:
try {
CSVReader reader = new CSVReader(new FileReader(csvInPath));
String [] row;
while ((row = reader.readNext()) != null) {
tvN[1].setText(row[1].toString());
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
It gives me an ArrayIndexOutOfBoundsException error in LogCat and the app force closes.
Can someone tell me what I'm doing wrong and how to do this right? Thanks.
As greenapps pointed out, I was referencing to row[1], which does not exist, as I only have 1 column of values. Turns out OpenCSV reads csv files column by column, and since I had only 1 column, I had to either use row[0], or make my csv have multiple columns. ie:
My csv file:
Name1
Name 2
Name 3
What I should use:
1. Name 2. Name2 3. Name3
It would also be better to rename row[] to column[] to avoid any confusion.
When the user downloads my app for the first time, the app downloads a CSV file which contains about 100,000 rows of data.
Then, I would like to populate my SQLite database with it.
Here is my code:
InputStream inputStream = activity.openFileInput(file);
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line = null;
dbHelper.beginTransaction();
while((line = bufferedReader.readLine()) != null) {
String[] values = line.replaceAll("'", "''").split(",");
dbHelper.insert(values);
}
dbHelper.setTransactionSuccessful();
dbHelper.endTransaction();
dbHelper.close();
In my DBHelper class, here is the method insert:
public void insert(String[] data) {
ContentValues values = new ContentValues();
values.put(DBHelper.SHAPE_ID, data[0]);
values.put(DBHelper.SHAPE_PT_LAT, data[1]);
values.put(DBHelper.SHAPE_PT_LON, data[2]);
values.put(DBHelper.SHAPE_PT_SEQUENCE, data[3]);
myDB.insert(DBHelper.TABLE_SHAPES, null, values);
}
I tried this code, it worked BUT it took 7 minutes to do it...
Am I doing something wrong ? Is there a better way (read faster) to populate a SQLite database?
You should download the SQLite database file itself.
If there is other data in the database that you want to keep, you could either
copy that other data into the downloaded database (since it is not as much data, this should be fast); or
keep the downloaded database and the other database separated (and ATTACH one to the other if you need to do joins between them).
Use a prepared statement, that should give a performance boost.
Something like:
SQLiteStatement statement = db.compileStatement("INSERT INTO " + TABLE_SHAPES + " VALUES(?, ?));
and change your insert() method to do something like:
statement.bindString(1, data[0]);
statement.bindString(2, data[1]);
statement.executeInsert();
According to this, SQLite3 has facilities to import a CSV file built-in:
.separator ','
.import '/path/to/csv/data' [table]
I'd imagine this can be done on Android using the DatabaseUtils.InsertHelper:
DatabaseUtils.InsertHelper helper = new DatabaseUtils.InsertHelper(dbFilePath, dbTablename);
helper.prepareForInsert();
// use the bind* methods to bind your columns of CSV data to the helper in a loop
helper.execute();
I also see the the class is now marked as deprecated (API level 17) in lieu of SQLiteStatement, which may or may not be relevant to your application. If you have further questions, please leave a comment.
Hey Guys ive got a problem with my database.
iam displaying my database in a textview looking like:
hh:mm dd:MM:yyyy text
12:14 12.12.2014 awdawdawd
13:12 13:12:2015 awdaw awdw
onclick iam getting the text by:
StringBuilder ortsplit = new StringBuilder();
String item = ((TextView) view).getText().toString();
String[] itemsplit = item.split("\\s+");
String uhrsplit = itemsplit[0].toString();
String datumsplit = itemsplit[1].toString();
ortsplit.setLength(0);
for (int i = 2; i < itemsplit.length; i++) {
ortsplit.append(" " + itemsplit[i].toString());
}
String sortsplit = String.valueOf(ortsplit);
then iam opening my database:
datasource.open();
datasource.findedel(uhrsplit,datumsplit,sortsplit);
datasource.close();
my datasource.findedel:
public void findedel(String pZeit, String pDatum, String pOrt) {
database.delete("TABELLE", "UHRZEIT="+Zeit +"AND DATUM="+Datum+"AND ORT="+Ort,null);
}
ive got no "id" displayed in the rows, earlier it looked like:
1 hh:mm dd:MM:yyyy text
2 12:14 12.12.2014 awdawdawd
3 13:12 13:12:2015 awdaw awdw
and ive just took the "id" and searched my entries for that id = id and deleted the row, but since i deleted the first row i want to search the row by the content.
any1 got a solution for my problem?
You have multiple errors and also you are prone to SQL injection.
You must use prepared statements or you must add quotes to your strings and escaping the quotes the string has, for example, in your code:
database.delete("TABELLE", "UHRZEIT="+Zeit +"AND DATUM="+Datum+"AND ORT="+Ort,null);
this: DATUM="+Datum+"AND is bad coded, there is not space between Datum and AND so, if datum is equal to test, then you string will be like this: DATUM=testAND. That will return syntax errors in mysql, and also string must be quoted like this: DATUM='test' AND.
The main problem of quoting this way is that if Datum has quotes by itself, you will have errors too. For example, if Datum equals to te'st then your string is going to be like this: DATUM='te'st' AND. As you see, you will have 3 quotes and then will return syntax error.
You must read and understand this before going further, because you will end up with a really messy code plenty of errors and vulnerabilities: http://wangling.me/2009/08/whats-good-about-selectionargs-in-sqlite-queries.html
Good luck ;)
And also, in Java all variable names must start in lowercase (Instead of String Datum use String datum)
I have a database thats in the form of a text file, my job is to parse the txt file and display the data in a listview. I have no idea where to start.
Heres an example entry.
"|9251115|,|0|,|DETAILS|,||,||,|Heading Price Text Text |,||,||
Where each || represents a field. There are also html tags between heading price and the text (p,b)
My first idea would be to parse it similarly to an xml document, i.e have it create a new line where it starts with a "|", fill it with everything in between and end the line when it reaches the next "|". But I still have no concrete idea on how to do this.
EDIT:
Taking it one step at a time for now. Using stringtokenizer to read it line by line and remove "," for a start. Ran into a problem, the textview to display the results is displaying false for some reason instead of the scanned text. here's my code if anyone needs a good headscratcher.
Context myContext;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView t = (TextView) findViewById(R.id.text);
st = new ArrayList<property>();
try
{
InputStream is;
is = myContext.getAssets().open("rooms.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
String read = br.readLine();
while( read != null)
{
StringTokenizer st = new StringTokenizer(read,",");
{
while(st.hasMoreTokens())
{
String a = st.nextToken();
String b = st.nextToken();
String c = st.nextToken();
String d = st.nextToken();
String e = st.nextToken();
String f = st.nextToken();
String g = st.nextToken();
String h = st.nextToken();
t.setText(a+" "+b+" "+c+" "+d+" "+e+" "+f+" "+g+" "+h);
}
}
}
}
catch(Exception e)
{
e.printStackTrace();
}
While you can definitely implement your own parser using pure Java code, you should consider using a SQLite database (1) to store your data, which will allow you to insert, delete, modify and query much more easily.
If you database comes in that format from an external source, I'd write a one-time parser that parses the data and inserts it into the SQLite database for future use.
Remember that the CPU on Android devices is slower than your average PC CPU, so if you are parsing large amounts of data in this format all the time, your app might become very slow. Hence my suggestion of converting it to a database.
Another option you have in this case is using XML like you said, because there are ready-to-use parsers out there. But the advice about performance remains: you should really avoid reparsing the data all the time and, instead, store it in a ready-to-use format.
(1): http://developer.android.com/reference/android/database/sqlite/package-summary.html
Here is how I would do,
Have an object with getter/setter
Have a list intialized
1) You need to use StreamReaders/Bufferedreader to read the file
2) If each is not empty
2a) Use StringTokenizer to parse the string with "," as delimiter
2b) Set tokenized values to object
2c) Add object to list
3) return the list created in above step.
Note: If large data you need to be careful while reading entire file, you may get OutofMemoryError.
Bruno Oliveira gave very good advice.
You can parse your file by reading it line by line and then use string.split method, as result you will have all your data in an array where you can easily read and put into a list view or move it to a sqlite database.