I am using a string buffer to read to store values being read from an SQLite database. Inside the loop, the buffer always starts reading from the first database reference.
Eg: The database has the values apple,orange,banana.
Everytime I call the funtion,the string buffer stores the items from the beginning:
first function call: apple
second function call: apple apple orange
third function call: apple apple orange apple orange banana
On the third call i need it just to be: apple orange banana
How can I do this?
public void db{
Cursor res= databaseHelper.getAllData();
if(res!=null){
res.moveToFirst();
try{
while(res.moveToNext())
{
if(res.getString(0)!=null){
stringBuffer.append(res.getString(0)+"\n");
Log.i("TAG",stringBuffer.toString());
stringBuffer1.append(res.getString(1)+"\n");
stringBuffer2.append(res.getString(2)+"\n");
stringBuffer.setLength(0);
stringBuffer1.setLength(0);
stringBuffer2.setLength(0);
}catch(Exception e){}}}
If you need just print "apple orange banana", then use as follow
public void db(){
Cursor res = databaseHelper.getAllData();
if (res != null) {
while (res.moveToNext()) {
String value = res.getString(0) + " ";
stringBuffer.append(value);
Log.d(TAG, stringBuffer.toString())
...
}
res.close()
}
}
Just put StringBuffer stringBuffer = new StringBuffer(""); after public void db{ or clear the stringBuffer by stringBuffer.delete(0, stringBuffer.length()); before you start the loop.
I don't know where you declared stringBuffer but it keeps the previous values. Also you may lose the 1st item in db because you do moveFirst and immediately moveNext, so drop moveFirst
int i =0;
if (cursor.moveToFirst()){
do{
stringBuffer.append.(cursor.getString (i));
i++;
}
while(cursor.moveToNext());
}
cursor.close();
}
Try this instead of that, may this helps you.
Related
I've been searching online and trying, but I didn't find the solution.
I have the following ArrayList:
{ Cate1, Cate3, Cate6, Cate2, ...., thru Cate10 }
I gave tried the following solutions:
public ArrayList<String> GetAllCategories_ByAscOrder() {
db = getWritableDatabase();
ArrayList<String> Category_ArrayList = new ArrayList<String>();
Cursor cursor = db.query(Category_TABLE, null, null, null, null, null, Category_List + " ASC");
if(cursor != null)
{
while(cursor.moveToNext())
{
String CATEGORY = cursor.getString(cursor.getColumnIndex(Category_List));
Category_ArrayList.add(CATEGORY);
}
}
cursor.close();
return Category_ArrayList;
}
And these:
Collections.sort(CATEGORY_LIST, new Comparator<String>(){
public int compare(String obj1, String obj2)
{
return obj1.compareToIgnoreCase(obj2);
}
});
}
//OR THIS:
Collections.sort(CATEGORY_LIST, new Comparator<String>(){
public int compare(String obj1, String obj2)
{
return obj1.compareTo(obj2);
}
});
}
//OR THIS:
Collections.sort(CATEGORY_LIST, String.CASE_INSENSITIVE_ORDER);
But ALL of them gave me the same sorting results:
Cate1, Cart10, Cate2, Cate3,, etc.... Cate9
I want the sorted list to be like this:
Cate1 thru Cate10
Can someone please guide me on how I can achieve this?
Thank you very much
Edit:
I forgot to mention that I let the users freely name their Category Names.
do like this :
Collections.sort(list , new Comparator<String>(){
public int compare( String a, String b ){
// if contains number
if( a.substring(4).matches("\\d+") && b.substring(4).matches("\\d+")) {
return new Integer( a.substring(4) ) - new Integer( b.substring(4) );
}
// else, compare normally.
return a.compareTo( b );
}
});
Its sorted by lexicographical order.
If you want it sorted like that, you should switch to using two digits,
eg. Cate01, Cate02, ...
Note that this happens in Windows/Linux filesystems too (if you have numbered files in a folder).
Technically, the results you got are correct - Cart10 alphabetically comes before Cart2 (since 1 comes before 2).
Try adding leading 0s to your numbers before sorting: Cart01, Cart02, etc - though you'll need to pad with leading zeros to make sure you cover the largest you expect your list to get (if it'll be over 100 elements, you'll need more zeros).
Alternatively, why not just store it as ArrayList<Integer> and prepend with "Cart" when you go to output the results? How you ultimately solve this depends on what you want to use the values for...
my app retrieves VCards as Strings and puts all together to a big string via StringBuilder
public String getVcardStrings() throws Exception {
Cursor cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
StringBuilder builder = new StringBuilder();
if (cursor.moveToFirst()) ;
do {
String s = getVCardStringFromContact(cursor);
L.d("VCARD", s);
builder.append(s);
} while (cursor.moveToNext());
cursor.close();
L.d("VCARD", "Output: \n" + builder.toString());
return builder.toString();
}
The output of each getVCardAsString() call is correct. It contains all data. but calling builder.toString() onlly returns the vcard data of 1,5 Contacts, which is about 4kb of text data and the rest is simply missing!
There is no exception and I´ve read that StringBuilders capacity theoretically reaches up to 4GB. Now my question is, what is happening here?
I'm pretty sure this is a false positive:
In other words the data is there but is being truncated by logcat.
This observation would seem to be validated by this define:
#define LOGGER_ENTRY_MAX_LEN (4*1024)
Which is bang-on 4KB and relates directly to what you are experiencing.
Write your output to a file to check if its actually there.
I am testing the capabilities of the device -- to show the customer the size of data that can be stored inside the device, how fast it can be retrieved, how fast the search works, etc.
I am using my content provider to access the product database table with few columns. I have already moved the code to the content provider to avoid the extra communication when inserting the test records. The following code is called via menu from an activity to fill the table with the test content
Uri uri = Uri.parse(DemoContentProvider.PRODUCTS_CONTENT_URI + "/insertdemo");
getContentResolver().insert(uri, null);
The URI is recognized in the .insert method of the content provider and the following private method (of the same content provider) is called to fill the table (notice the 100 thousands of items):
private void insertDemoProducts() {
for (int i = 1; i <= 100000; ++i) {
String id = Integer.toString(i);
insertProduct(id, "Test product " + id, "100", "75.50", "70.27");
}
}
The inner insertProduct() looks like that:
private void insertProduct(String code, String name, String stock,
String price, String listprice) {
SQLiteDatabase sqlDB = database.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(ProductTable.COLUMN_CODE, code);
values.put(ProductTable.COLUMN_NAME, name);
values.put(ProductTable.COLUMN_STOCK, stock);
values.put(ProductTable.COLUMN_PRICE, price);
values.put(ProductTable.COLUMN_LISTPRICE, listprice);
sqlDB.insert(ProductTable.TABLE_PRODUCT, null, values);
}
It works, but it takes "forever". How can I make it faster? What is the fastest method you know to fill the table?
Just some numbers to consider: 1000 items takes about 20 seconds to be created.
You need to use transactions when writing to a sqlite-database, otherwise it will persist the data for every insert i.e save it to sd which will take "forever".
for instance, make insertProduct take a list of products and save them in one transaction:
private void insertProducts(List<Product> products) {
try {
db.beginTransaction();
for(Product product : products) {
insertProduct(...);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
This is how you can implement it in your existing code:
private void insertDemoProducts() {
SQLiteDatabase sqlDB = database.getWritableDatabase();
try {
sqlDB.beginTransaction();
for (int i = 1; i <= 100000; ++i) {
String id = Integer.toString(i);
insertProduct(id, "Test product " + id, "100", "75.50", "70.27");
}
sqlDB.setTransactionSuccessful();
} finally {
sqlDB.endTransaction();
}
}
Anyway, I am not completely satisfied with the accepted question because I do not understand the reason why adding the transaction makes it faster.
Looking at the Android sources, I have found that the sqlDB.insert(...) calls insertWithOnConflict(...) and that one construct the string for the SQL command using the StringBuilder class (with questionmarks as placeholders for the inserted values). Only then the string is passed to the SQLiteStatement constructor together with array of the inserted values. This means that string with the SQL command is being built again and again.
Further, a string representation of an SQL command template can be precompiled thus avoiding also the repeated compilation of the command. Then .bindXxx and .execute methods can be used for inserting the wanted records into the table. When put together, I did use the followig code (iside the outer transaction as Dean suggested):
StringBuilder sql = new StringBuilder();
sql.append("INSERT INTO ");
sql.append(ProductTable.TABLENAME);
sql.append("(");
sql.append(ProductTable.COLUMN_CODE);
sql.append(",");
sql.append(ProductTable.COLUMN_NAME);
sql.append(",");
sql.append(ProductTable.COLUMN_STOCK);
sql.append(",");
sql.append(ProductTable.COLUMN_PRICE);
sql.append(",");
sql.append(ProductTable.COLUMN_LISTPRICE);
sql.append(") VALUES (?, ?, 100, 75.50, 70.27)");
SQLiteStatement insert = sqldb.compileStatement(sql.toString());
for (int i = 1; i <= 300000; ++i) {
insert.bindLong(1, i);
insert.bindString(2, "Test product " + i);
insert.execute();
}
When compared with adding the transaction only, the result is about 3-times faster. The 300 thousands records were inserted in about 3 minutes and 15 seconds on Nexus 7.
I need to process a SQLite dataset in an Android system.
In my dataBaseHelper file (DataBaseAccessor) I have the following code (which when attached to a listview shows the relevant data).
public static ArrayList<QuestionListQuestion> getQuestionListQuestions(long id){
String qry = "select QuestionListQuestionID, QuestionListQuestionQuestionListID, QuestionListQuestionQuestionID, QuestionListQuestionSortOrder, QuestionListQuestionSupplementalQuestionIDYes, QuestionListQuestionSupplementalQuestionIDNo, QuestionListQuestionSupplementalQuestionIDText, QuestionListQuestionSurveyGroupID from QuestionListQuestion where QuestionListQuestionQuestionListID=" + id;
ArrayList<QuestionListQuestion> list = new ArrayList<QuestionListQuestion>();
try{
Cursor cursor = wdb.rawQuery(qry, null);
while (cursor.moveToNext()) {
QuestionListQuestion questionlistquestion = new QuestionListQuestion();
questionlistquestion.QuestionListQuestionID = cursor.getLong(0);
questionlistquestion.QuestionListQuestionQuestionListID = cursor.getLong(1);
questionlistquestion.QuestionListQuestionQuestionID = cursor.getLong(2);
questionlistquestion.QuestionListQuestionSortOrder = cursor.getLong(3);
questionlistquestion.QuestionListQuestionSupplementalQuestionIDYes = cursor.getString(4); questionlistquestion.QuestionListQuestionSupplementalQuestionIDNo = cursor.getString(5);
questionlistquestion.QuestionListQuestionSupplementalQuestionIDText = cursor.getString(6);
questionlistquestion.QuestionListQuestionSurveyGroupID = cursor.getLong(7);
list.add(questionlistquestion);
}
cursor.close();
}
catch (Exception e) {
e.printStackTrace();
}
return list;
}
I now need to extend the system so that I can process the data and create new records in another table based on the original list returned.
I tried the following attached to a button (selecting the relevant list ID from a spinner):-
QuestionListID = (String) SiteGenerateQuestions.this.spnQuestL.getSelectedItem().toString();
long SpinnerSelectedBT;
SpinnerSelectedBT = GenerateQuestions.this.spnQuestL.getSelectedItemId();
list = DatabaseAccessor.getQuestionListQuestions(SpinnerSelectedBT);
for (int i=0; i < list.size(); i++){
Toast.makeText(SiteGenerateQuestions.this," list.get(" + i + ") = " + list.get(i) + " " , Toast.LENGTH_SHORT).show();
}
The Toast displays the following:-
list.get(0) = com.tw.question.entity.QuestionListQuestion#407a6F70
list.get(1) = com.tw.question.entity.QuestionListQuestion#407bc170
etc...
How can I get access to the actual data instead of ... .entity.QuestionListQuestion#407bc170 or am I completely off-track?
Many Thanks
I agree with #wsanville the get() method will return the object in that location of the list. When you print out an object (in a toast, log, System.out.println etc) it will use the toString() value in the printout. The default toString() is the package name followed by # which is followed by a hex representation of that object. Your class will need to override the toString() method so when you use get() it will print out whatever you put in your toString() method.
The output you're seeing is because you haven't implemented the toString() method of your QuestionListQuestion class. Other than that, it seems like you do have the data you're looking for. Just try outputting the ID of your object, rather than concatenating the object itself (which will call toString() under the hood).
Also, since it looks like you're doing a database operation when a button gets clicked, make sure to do your database operations outside the UI thread. Check out the docs for a high level overview. You might want to use an AsyncTask for your database operation in question.
This is my first time using a database and I'm not really sure how this works. I made the database and made a query that returns a cursor and... now what? What is a cursor, really? Can I just use that to navigate through my data or do I have to put it in an ArrayList or ListActivity or what?
You need to iterate the cursor to get your results.
Use cursor.moveToFirst() and/or cursor.moveToNext() (with a while loop). Then you can use the getX() method, like cursor.getInt() or cursor.getString().
For example, ir your are expecting one result from your query:
if (cursor.moveToFirst()) {
String name = cursor.getString(cursor.getColumnIndex('NAME'));
int age = cursor.getInt(cursor.getColumnIndex('AGE'));
} else {
// oops nothing found!
}
First call cursor.moveToFirst(). Each time you call cursor.moveToNext() it will move to the next row. Make sure when you are done with your cursor you call cursor.deactivate() or you will get errors in your log cat.
Iterate over the returned Cursor instance
public List<Object[]> cursorToTableRows(Cursor cursor) {
List<Object[]> result = new ArrayList<Object[]>(cursor.getCount());
cursor.move(0);
cursor.moveToNext();
while (cursor.isAfterLast() == false) {
Object[] tableRow = new Object[cursor.getColumnCount()];
for(int i=0; i<cursor.getColumnNames().length; i++) {
int columnIndex = cursor.getColumnIndex(cursor.getColumnName(i));
String columnValue = cursor.getString(columnIndex);
tableRow[i] = columnValue;
}
result.add(tableRow);
cursor.moveToNext();
}
cursor.close();
return result;
}
Then create the desired objects.
public List<Vehicle> getVehicles() {
List<Vehicle> vehicles = new ArrayList<Vehicle>();
Cursor cursor = null;
List<Object[]> objects = cursorToTableRows(cursor);
for(Object[] row : objects) {
int i=0;
Vehicle vehicle = new Vehicle(row[i++].toString(), row[i++].toString()));
vehicles.add(vehicle)
}
return vehicles;
}
from Developer.android: This interface provides random read-write access to the result set returned by a database query.
In other words: query returns you a set of data represented by a cursor. First you need to make sure you got a valid cursor (not null) and then try to move it to desired position in the data set (use moveToXXX methods). In order to obtain data pointed by cursor use getXXX methods. When done using it make sure to call close to release resources.
According to this link it looks like you can iterate through the query return using something like:
cursor.next();
And grab the data at the location you are looking for using:
cursor.getString(0)
After you successfully have your Cursor setup, you would typically want to display that to a view in some form.
Have a look at the following answer for a detailed, but simple example of using a Cursor Adapter to pair up your newly-minted Cursor with your desired XML View:
https://stackoverflow.com/a/20532937/293280