I have a string which has delimiter in it. I want to know the best way to replace the delimiter with a new line. I have had various issues with using the String Tokenizer the main problem being NoSuchElementException. Basically my approach thus far is to retrieve data from a database Once this has been achieved I store each of the records in a string String question = c.getString(1);
Here is the string tokenizer StringTokenizer st = new StringTokenizer(question,"<ENTER>"); I loop through the tokens using a while loop
while (st.hasMoreTokens()) {
System.err.println(st.nextToken());
// quest.setText(String.valueOf(st.nextToken("<ENTER>")));
}
Working example in code
String in = "What is the output of: <ENTER><ENTER>echo 6 % 4;";
in=in.substring(in.indexOf("<ENTER>")+7,in.lastIndexOf("<ENTER>"));
String[] mSplitted= in.replaceAll("<ENTER><ENTER>", "<ENTER>").split("<ENTER>");
for(int i=0;i<mSplitted.length;i++)
{
System.out.println("values: "+mSplitted[i]);
quest.setText(String.valueOf(mSplitted[i]));
}
xml code
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/quest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="false"
android:text="TextView" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="0.08"
android:text="#string/hello" />
<Button
android:id="#+id/Next"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
output
can't you use split() of String.
String in = "<ENTER>title=Java-Samples<ENTER>" +
"<ENTER>author=Emiley J<ENTER>" +
"<ENTER>publisher=java-samples.com<ENTER>" +
"<ENTER>copyright=2007<ENTER>";
in=in.substring(in.indexOf("<ENTER>")+7,in.lastIndexOf("<ENTER>"));
String[] mSplitted= in.replaceAll("<ENTER><ENTER>", "<ENTER>").split("<ENTER>");
String mFinal="";
for(int i=0;i<mSplitted.length;i++)
{
System.out.println("values: "+mSplitted[i]);
mFinal= mFinal+ mSplitted[i];
}
quest.setText(mFinal);
The reason behind NoSuchElementException is that you are checking whether your Tokenizer has more tokens, but if it does, then you are reading two tokens at the same time.
Documentation says hasMoreTokens tests if there are more tokens available from this tokenizer's string.
If this method returns true, then a subsequent call to nextToken() with no argument will successfully return a token.
That means hasMoreTokens is only sure about the next token but not the token next to that!
Your condition should be..
while(st.hasMoreTokens()) {
String key = st.nextToken();
String val="";
if(st.hasMoreTokens())
val = st.nextToken();
System.out.println(key + "\n" + val);
}
As your condition will work for only even number of elements.
Related
Goal:
Compare the strings
Problem:
It doesn't work when I use the syntax code equals, equalsIgnoreCase and compareTo.
What is the part that am I missing?
Info:
*Im new in android
Thank you!
New picture:
private String _EASY = "Easy", _MEDIUM = "Medium", _HARD = "Hard";
public void calculateMath(View view)
{
TextView status = (TextView)findViewById(R.id.txtvw_status);
String a1 = status.getText().toString();
String a2 = _EASY;
if (status.getText().toString().equals(_EASY));
{
int ffsdf = 23;
}
if (a1.equals(a2));
{
int ffsdf = 23;
}
if (a1.equalsIgnoreCase(a2))
{
int ffsdf = 23;
}
if (a1.compareTo(a2) == 0)
{
int ffsdf = 23;
}
}
layout/activity_play.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/txtvw_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="50sp"
android:text="Easy"
android:textSize="30sp" />
<Button
android:id="#+id/btn_calculate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:onClick="calculateMath"
android:text="Calculate" />
</LinearLayout>
The problem with your code is the declaration of ffsdf. You have to declare it outside of if statement.
This will work
private String _EASY = "Easy", _MEDIUM = "Medium", _HARD = "Hard";
public void calculateMath(View view)
{
TextView status = (TextView)findViewById(R.id.txtvw_status);
String a1 = status.getText().toString();
String a2 = _EASY;
int ffsdf;
if (a1.compareTo(a2) == 0)
{
ffsdf = 23;
}
}
As to why this is happening, refer to this question Why can't variables be declared in an if statement?
I've had similar issues when trying to compare strings in the past. Try Objects.equals(a1,a2), .equals() tests for value equality (whether they are logically "equal").
Objects.equals() just checks for nulls before calling .equals() so you don't have to do it.
You almost always want to use Objects.equals() when it comes to Strings in my opinion.
You can find more information about the Objects class here: Objects class
CompareTo:
Compares this object with the specified object for order. Returns a
negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object.
Best suited for numerical values in its default form, you would have to override it in order to compare Strings.Information about overriding can be found here
(more information about the compareTo method can be found here)
I would like to get name from values resource file.
for example
values.xml
<string name="ind_ginger">Ginger</string>
<string name="ind_garlic">Garlic</string>
I am using them for the check boxes like
<CheckBox
android:id="#+id/c01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="21dp"
android:text="#string/ind_garlic"
android:layout_alignTop="#+id/c02"
android:layout_alignRight="#+id/saveChanges"
android:layout_alignEnd="#+id/saveChanges" />
<CheckBox
android:id="#+id/c02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="81dp"
android:layout_marginStart="81dp"
android:checked="false"
android:text="#string/ind_ginger"
android:visibility="visible"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="40dp" />
In application I need access String Name ( Please note value)
for (CheckBox item : checkBoxList){
if(item.isChecked())
{
//String text=item.getText().toString();String viewID = getResources().getResourceName(item.getId()); // gets me the name
String name = getResources().getResourceEntryName(item.getId());
String tName =
//item.getText().toString();
// String id = item.getTag().toString();
Toast.makeText(getApplicationContext(), tName,Toast.LENGTH_SHORT).show();
Log.d(viewID, TAG);
}
}
Is parsing the XML only way?
Try
String ginger = getResources().getString(R.string.ind_ginger)
Easiest way to get the "KEY" name is as following:
Log.e("KEY_NAME", getResources().getResourceEntryName(R.string.app_name));
Here you will get "app_name" as result.
This can be also help in support multi-language support feature.
You can use this to fetch all the String Keys in string.xml
Field[] fields = R.string.class.getFields();
String[] allStringNames = new String[fields.length];
for (int i =0; i < fields.length; i++) {
allStringNames[i] = fields[i].getName();
Log.e("String Key Name",""+allStringNames[i]);
}
Hope this will help
Just Store you string items in (And its better if you store your string file in in strings.xml and not value.xml )
strings.xml
<string name="ind_ginger">Ginger</string>
<string name="ind_garlic">Garlic</string>
Firstly if you need ind_ginger you need to change your code from this
<string name="ind_ginger">Ginger</string>
to
<string name="ind_ginger">ind_ginger</string>
and
String ginger = getResources().getString(R.string.ind_ginger)
to get the ind_ginger.
But what I can see from your code is you are using .getResourceEntryName(item.getId()) for that you need to create a String arraylist which would have all the itemId from strings.xml and then you can use them with item.get(position).
Here position is the position of the item in your array list.
Declaration :
DecimalFormat mAmtFormat = new DecimalFormat("##,##,##,##0.00");
edtAmounts = (EditText) findViewById(R.id.txtAmounts);
From xml File Edit text as
<EditText
android:id="#+id/txtAmounts"
android:layout_height="50dip"
android:layout_marginLeft="10dip"
android:background="#FFFFFF"
android:gravity="center_vertical"
android:inputType="numberDecimal"
android:singleLine="true"
android:textSize="18dip"
android:textStyle="bold"
android:width="170dip" />
From Back End mCurtotamt is 565656565(double)
Fetching Data From Sqlite DataBase:
edtAmounts.setText(String.valueOf(mAmtFormat.format(mDoubleformat
.parse(mCurtotamt).doubleValue())))
but the value set into the edit text as 56,56,57,000.00
what is happening over here.
When you get the value from the back end, do not get it as a String like this:
String mCurtotamt = cursor.getString(cursor.getColumnIndex("column_name"));
Instead, get it as a double directly, like this:
double mCurtotamt = cursor.getDouble(cursor.getColumnIndex("column_name"));
Then you don't need to parse it when you set the edit text, but can format it directly:
edtAmounts.setText(String.valueOf(mAmtFormat.format(mCurtoamt)));
The problem is being introduced when converting it to a String when you call cursor.getString().
Use this one for indian format like this "##,##,##0.00" :
static public String formatCurrency(Double doubleVal) {
return new DecimalFormat("##,##,##0.00").format(doubleVal);
}
This function return the value in correct given format. If you pass 5555555.00 value then function return 55,55,555.00 as a string.
I'm able to break a line using following code:
String str1 = "TEST1"; // length = 5
String str2 = "TEST2"; // length = 5
TextView textView = (TextView)findViewById( R.id.text_view );
textView.setText(str1 + '\n' + str2);
But the final text length is equal to 11.
Question:
Is there any special character or method that will allow me to reach the same result inside my TextView without increasing text length?
What I'm trying to achieve:
I have a data format, which is stored in JSON. It looks like
[{type: line, params: {line params}}, {type: text, params: {text params}, ...]
There is always line at the start
Each paragraph begins with line ( so it acts like a line separator which is stored at the beginning of line, not at the end )
Size of each line equals to 1, i.e. each line counts as a single character
Each paragraph ends with text's last character ( not '\n' )
There are some line params ( like BulletList, Numeric list, Paragraph )
I need a strict mapping between my TextView and source data, i.e. for each cursor position in my TextView I need to count how many characters preceed it in source data.
Take two TextViews and add one below another .Then you won't find any length problem.
like : <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView1" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:text="TextView2" />
</RelativeLayout>
String str1 = "TEST1";
String str2 = "TEST2";
TextView text=(TextView)vi.findViewById(R.id.text);
text.setText(str1);
text.append(Html.fromHtml(< br>));
text.append(str2);
Hope it works :)
For your question my answer will be no. But you could make your own TextView and change how it calculates the length of the text by for example ignoring "/n" when counting the length.
Well there is tricky way
String str1 = "TEST1"; // length = 5
String str2 = "TEST2"; // length = 5
textView = (TextView)findViewById( R.id.textView1 );
textView.setWidth(120);
textView.setTextSize(20);
textView.setText(str1 + str2);
//textView.getText().toString().length() length = 10
in XMl
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="TextView" />
I have an app that works on the emulator but will intermittently crash when testing on a real device. I am running a modified version of Code Overtones Android Crash report. (http://jyro.blogspot.com/2009/09/crash-report-for-android-app.html) The emailed cause states:
The content of the adapter has changed but ListView did not receive a
notification. Make sure the content of your adapter is not modified
from a background thread, but only from the UI thread. [in
ListView(2131296303, class android.widget.ListView) with Adapter(class
android.widget.SimpleAdapter)]
The code does not modify the adapter outside of the UI main thread. All access to the adapter is through the onPostExecute of an AsyncTask. The code is:
#Override
protected void onPostExecute(String result) {
MyLog.d(TAG, "onPostExecute");
foodDescArrayList.clear();
int entries = holdFoodDescArrayList.size();
HashMap<String, String> listEntry;
for (int i = 0; i < entries; i++) {
listEntry = new HashMap<String, String>();
listEntry = holdFoodDescArrayList.get(i);
foodDescArrayList.add(listEntry);
}
holdFoodDescArrayList.clear();
hideProgress();
foodDescAdapter.notifyDataSetChanged();
String ents = " entries";
if (rowsReturned == 1) {
ents = " entry";
}
foodDescHeader.setText("Page " + Integer.toString(currentPage + 1)
+ " of " + Integer.toString(pageCount) + " (" + Integer.toString(rowsReturned) + ents + ")");
loadActive = false;
}
The holdFoodDescArrayList is a stand alone list filled in the background task from an SQLite database. the foodDescArrayList is the array associated with the ListView adapter. (I've found that there is a performance boost when queuing this way. Maybe because the adapter is out of the loop during database access. Less overhead?)
The crash always occurs on first entry (onCreate) after a home key exit and then reentry to the top level activity that calls the list activity. The time between crashes is from 30 minutes to 2 hours during continuous testing. The code that is crashing has been traversed hundreds of times and is linear with no exits.
The only possible hole I can find in reviewing the code is the clear() preceding the array load. Does the clear function act as one change and the group of adds as a second change? Is there a timing consideration? There are from 1 to 24 entries in the list, so the load should take milliseconds and not seconds...
I'm looking for ideas and clues. Please scan the code and see if you see a glaring error or side effect in the code. It is the only place the ListView's associated array data is altered in the app. The background code only alters the hold array.
Please don't enter a full code rewrite in an answer. I'm continuing to try and find the why and which. I don't want to waste more than a few minutes of your time. I will look at this post often for the next few days and answer any questions I find. Thanks for any help...
----------- Update to add code requested ----------
The code in onCreate is:
setContentView(R.layout.fooddeslist);
foodDescHeader = (TextView) findViewById(R.id.foodDescHeading);
foodDescListView = (ListView) findViewById(R.id.foodDescList);
foodDescArrayList = new ArrayList<HashMap<String, String>>();
holdFoodDescArrayList = new ArrayList<HashMap<String, String>>();
foodDescAdapter = new SimpleAdapter(this, foodDescArrayList,
R.layout.longdescitem, new String[] { GC.FOODDESCLIST_LINE1,
GC.FOODDESCLIST_LINE2 },
new int[] { R.id.longdescListItemLine1,
R.id.longdescListItemLine2 });
foodDescListView.setAdapter(foodDescAdapter);
registerForContextMenu(foodDescListView);
The array entries are:
listEntry = new HashMap<String, String>();
The hold array is a duplicate of the adapter's array. The hold array is loaded in the doInBackground function in the AsyncTask. I'd show the background code, but it's about 500 lines of code. The end result is that the hold array is loaded with the 2 lines to display and ancillary data that is unique to each entry. Row ids for various bits of data in other tables that is used when an entry is selected. The duplicate tables allow me to take eons (to gigahertz processors) loading the array. The transfer in the UI running post execute just takes a couple of milliseconds.
longdescitem.xml is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView android:id="#+id/longdescListItemLine1"
android:textStyle="italic"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#ff9900"
/>
<TextView android:id="#+id/longdescListItemLine2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#b89300"
/>
</LinearLayout>
R.layout.fooddesclist is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/foodDescHeading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginLeft="2dip"
android:text="Page 1 of 10 (nnn entries)"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#b89300" />
<ImageButton
android:id="#+id/foodDescForward"
android:layout_width="50px"
android:layout_height="50px"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="12dip"
android:layout_marginTop="5dip"
android:background="#drawable/forward"
android:clickable="true"
android:onClick="foodDescForwardClicked" />
<ImageButton
android:id="#+id/foodDescBack"
android:layout_width="50px"
android:layout_height="50px"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="12dip"
android:layout_marginTop="5dip"
android:background="#drawable/back"
android:clickable="true"
android:onClick="foodDescBackClicked" />
<View
android:id="#+id/foodDescSpacer1"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_alignParentLeft="true"
android:layout_below="#id/foodDescForward"
android:layout_marginBottom="2dip"
android:layout_marginTop="2dip"
android:background="#drawable/divider" />
<ListView
android:id="#+id/foodDescList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#id/foodDescSpacer1"
android:layout_marginLeft="2dip"
android:layout_marginRight="2dip"
android:cacheColorHint="#00000000"
android:divider="#b89300"
android:dividerHeight="1.0px" />
</RelativeLayout>
-------- Another Update --------------
I've added some code to the opPostExecute function.
protected void onPostExecute(String result) {
MyLog.d(TAG, "onPostExecute");
foodDescArrayList.clear();
foodDescAdapter.notifyDataSetChanged();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
MyLog.d(TAG, "Sleep failed: " + e.getMessage());
}
int entries = holdFoodDescArrayList.size();
HashMap<String, String> listEntry;
for (int i = 0; i < entries; i++) {
listEntry = new HashMap<String, String>();
listEntry = holdFoodDescArrayList.get(i);
foodDescArrayList.add(listEntry);
}
holdFoodDescArrayList.clear();
hideProgress();
foodDescAdapter.notifyDataSetChanged();
String ents = " entries";
if (rowsReturned == 1) {
ents = " entry";
}
foodDescHeader.setText("Page " + Integer.toString(currentPage + 1)
+ " of " + Integer.toString(pageCount) + " (" + Integer.toString(rowsReturned) + ents + ")");
loadActive = false;
}
After two hours of steady testing on the Atrix, it hasn't crashed yet. Before the code, I would get a crash at least once and sometimes twice in 2 hours. I added the notifydatasetchanged after the clear and followed it with a 300 msec sleep. I think the operating system was stepping on its toes because the original notify got lost. Although the database queries can take up to 8 seconds, most of the time it's instant answer. The progress dialog never had a chance to fully set up. The screen would flicker and then the listview would show. The progress display was never identifiable. (The progress dialog is turned on in the preExecute function.) The entire AsyncTask was completing in less than 300 milliseconds. Maybe this is a fix and maybe not.
I'm answering this myself to close the post as answered.