问题
Hello friends I have this code in which I am writing an xml file to my sd card:
public class SingleItemView extends Activity {
File newxmlfile = new File(Environment.getExternalStorageDirectory() + "/testfinal.xml");
TextView txtmdname,txtutcost,txtdesc,txtmodno;
// Declare Variables
String mdname;
String utcost;
String desc;
String modno;
String flag;
String toolscat;
String tan;
int number;
String numberOfItems;
ProgressDialog mProgressDialog;
Bitmap bmImg = null;
ImageView addToCartButton;
final Context context = this;
FileOutputStream fileos = null;
//String newxmlfile;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
// Get the view from singleitemview.xml
setContentView(R.layout.singleitemview);
// Execute loadSingleView AsyncTask
toolscat=getIntent().getExtras().getString("toolscat");
tan=getIntent().getExtras().getString("tan");
new loadSingleView().execute();
if (newxmlfile.exists()){
try{
fileos = new FileOutputStream(newxmlfile, true);
}catch(FileNotFoundException e){
Log.e("FileNotFoundException", "can't create FileOutputStream");
}
} else {
try{
newxmlfile.createNewFile();
}catch(IOException e){
Log.e("IOException", "exception in createNewFile() method");
}
try{
fileos = new FileOutputStream(newxmlfile);
}catch(FileNotFoundException e){
Log.e("FileNotFoundException", "can't create FileOutputStream");
}
}
//xml
addToCartButton=(ImageView)findViewById(R.id.imageView1);
addToCartButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// get prompts.xml view
LayoutInflater li = LayoutInflater.from(context);
View promptsView = li.inflate(R.layout.promptdialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set prompts.xml to alertdialog builder
alertDialogBuilder.setView(promptsView);
final EditText userInput = (EditText) promptsView
.findViewById(R.id.editTextDialogUserInput);
// set dialog message
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@SuppressWarnings("null")
public void onClick(DialogInterface dialog,int id) {
numberOfItems=userInput.getText().toString();
number=Integer.parseInt(numberOfItems);
String utCostString=txtutcost.getText().toString();
float cost=Float.parseFloat(utCostString);
float totalCost=Float.parseFloat(utCostString)*number;
String tc = Float.toString(totalCost);
String codeText=txtmodno.getText().toString();
//Loop for writing xml
XmlSerializer serializer = Xml.newSerializer();
try {
serializer.setOutput(fileos, "UTF-8");
if(newxmlfile.length()==0) {
serializer.startDocument(null, Boolean.valueOf(true));
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, "root");
serializer.startTag(null, "code");
serializer.text(codeText);
serializer.endTag(null, "code");
serializer.startTag(null, "price");
serializer.text(utCostString);
serializer.endTag(null, "price");
serializer.startTag(null, "quantity");
serializer.text(numberOfItems);
serializer.endTag(null, "quantity");
serializer.startTag(null, "totalcost");
serializer.text(tc);
serializer.endTag(null, "totalcost");
serializer.endTag(null, "root");
} else {
serializer.startTag(null, "root");
serializer.startTag(null, "code");
serializer.text(codeText);
serializer.endTag(null, "code");
serializer.startTag(null, "price");
serializer.text(utCostString);
serializer.endTag(null, "price");
serializer.startTag(null, "quantity");
serializer.text(numberOfItems);
serializer.endTag(null, "quantity");
serializer.startTag(null, "totalcost");
serializer.text(tc);
serializer.endTag(null, "totalcost");
serializer.endTag(null, "root");
}
serializer.endDocument();
serializer.flush();
fileos.close();
Context context = getApplicationContext();
CharSequence text = "Save!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} catch (Exception e) {
Log.e("Exception","error occurred while creating xml file");
}
//end of xml lopp
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
public class loadSingleView extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// Create a progressdialog
mProgressDialog = new ProgressDialog(SingleItemView.this);
// Set progressdialog title
mProgressDialog.setTitle("Progress");
// Set progressdialog message
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
@Override
protected String doInBackground(String... args) {
try {
// Retrieve data from ListViewAdapter on click event
Intent i = getIntent();
// Get the result of rank
mdname = i.getStringExtra("mdname");
// Get the result of country
utcost = i.getStringExtra("utcost");
// Get the result of population
desc = i.getStringExtra("desc");
modno = i.getStringExtra("modno");
// Get the result of flag
flag = i.getStringExtra("flag");
// Download the Image from the result URL given by flag
URL url = new URL(flag);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bmImg = BitmapFactory.decodeStream(is);
} catch (IOException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String args) {
// Locate the TextViews in singleitemview.xml
txtmdname = (TextView) findViewById(R.id.mdname);
txtutcost = (TextView) findViewById(R.id.utcost);
txtdesc = (TextView) findViewById(R.id.desc);
txtmodno = (TextView) findViewById(R.id.modno);
// Locate the ImageView in singleitemview.xml
ImageView imgflag = (ImageView) findViewById(R.id.flag);
// Set results to the TextViews
txtmdname.setText(mdname);
txtutcost.setText(utcost);
txtdesc.setText(desc);
txtmodno.setText(modno);
// txtpopulation.setText(population);
// Set results to the ImageView
imgflag.setImageBitmap(bmImg);
// Close the progressdialog
mProgressDialog.dismiss();
}
}
}
This code is giving me an output like this on my xml file:
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<root>
<code>ACT445</code>
<price>110.00</price>
<quantity>4</quantity>
<totalcost>440.0</totalcost>
</root><root><code>ACT430</code><price>110.00</price><quantity>5</quantity><totalcost>550.0</totalcost></root>
where as I want the output xml file to be like this:
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<root>
<code>ACT445</code>
<price>110.00</price>
<quantity>4</quantity>
<totalcost>440.0</totalcost>
<code>ACT430</code>
<price>110.00</price>
<quantity>5</quantity>
<totalcost>550.0</totalcost>
</root>
Please suggest changes I need to make to get the output the way I want above. Any help will be appreciated. Thanks in advance.
*****************UPDATE*****************
After making changes the way Sandster mentioned. Now it can easily enter two entries to the xml without a problem. But when I try to write the third entry it gets written with some extra character like this:
<?xml version='1.0' standalone='yes' ?>
<root>
<item>
<code>ACT358</code>
<price>110.00</price>
<quantity>3</quantity>
<totalcost>330.0</totalcost>
</item>
<item>
<code>ACT443</code>
<price>110.00</price>
<quantity>5</quantity>
<totalcost>550.0</totalcost>
</item>
<
<item>
<code>ACT388</code>
<price>110.00</price>
<quantity>4</quantity>
<totalcost>440.0</totalcost>
</item>
</root>
As you see after the second time there is an extra <
thats get written. I cant seem to find out as to why.
My new code is as follows:
public class SingleItemView extends Activity {
File newxmlfile = new File(Environment.getExternalStorageDirectory() + "/testfinal.xml");
TextView txtmdname,txtutcost,txtdesc,txtmodno;
// Declare Variables
String mdname;
String utcost;
String desc;
String modno;
String flag;
String toolscat;
String tan;
int number;
String numberOfItems;
ProgressDialog mProgressDialog;
Bitmap bmImg = null;
ImageView addToCartButton;
final Context context = this;
FileOutputStream fileos = null;
//String newxmlfile;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
// Get the view from singleitemview.xml
setContentView(R.layout.singleitemview);
// Execute loadSingleView AsyncTask
toolscat=getIntent().getExtras().getString("toolscat");
tan=getIntent().getExtras().getString("tan");
new loadSingleView().execute();
if (!newxmlfile.exists()){
try{
newxmlfile.createNewFile();
}catch(IOException e){
Log.e("IOException", "exception in createNewFile() method");
}
}
//xml
addToCartButton=(ImageView)findViewById(R.id.imageView1);
addToCartButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// get prompts.xml view
LayoutInflater li = LayoutInflater.from(context);
View promptsView = li.inflate(R.layout.promptdialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// set prompts.xml to alertdialog builder
alertDialogBuilder.setView(promptsView);
final EditText userInput = (EditText) promptsView
.findViewById(R.id.editTextDialogUserInput);
// set dialog message
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@SuppressWarnings("null")
public void onClick(DialogInterface dialog,int id) {
numberOfItems=userInput.getText().toString();
number=Integer.parseInt(numberOfItems);
String utCostString=txtutcost.getText().toString();
float cost=Float.parseFloat(utCostString);
float totalCost=Float.parseFloat(utCostString)*number;
String tc = Float.toString(totalCost);
String codeText=txtmodno.getText().toString();
//Loop for writing xml
try {
updateFile(codeText, utCostString, tc);
Context context = getApplicationContext();
CharSequence text = "Save!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} catch (Exception e) {
Log.e("Exception", "error occurred while creating xml file");
}
//end of xml lopp
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
//start of update function
public class loadSingleView extends AsyncTask<String, String, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// Create a progressdialog
mProgressDialog = new ProgressDialog(SingleItemView.this);
// Set progressdialog title
mProgressDialog.setTitle("Progress");
// Set progressdialog message
mProgressDialog.setMessage("Loading...");
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
@Override
protected String doInBackground(String... args) {
try {
// Retrieve data from ListViewAdapter on click event
Intent i = getIntent();
// Get the result of rank
mdname = i.getStringExtra("mdname");
// Get the result of country
utcost = i.getStringExtra("utcost");
// Get the result of population
desc = i.getStringExtra("desc");
modno = i.getStringExtra("modno");
// Get the result of flag
flag = i.getStringExtra("flag");
// Download the Image from the result URL given by flag
URL url = new URL(flag);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bmImg = BitmapFactory.decodeStream(is);
} catch (IOException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String args) {
// Locate the TextViews in singleitemview.xml
txtmdname = (TextView) findViewById(R.id.mdname);
txtutcost = (TextView) findViewById(R.id.utcost);
txtdesc = (TextView) findViewById(R.id.desc);
txtmodno = (TextView) findViewById(R.id.modno);
// Locate the ImageView in singleitemview.xml
ImageView imgflag = (ImageView) findViewById(R.id.flag);
// Set results to the TextViews
txtmdname.setText(mdname);
txtutcost.setText(utcost);
txtdesc.setText(desc);
txtmodno.setText(modno);
// txtpopulation.setText(population);
// Set results to the ImageView
imgflag.setImageBitmap(bmImg);
// Close the progressdialog
mProgressDialog.dismiss();
}
}
private void updateFile(final String codeText, final String utCostString, final String tc)
{
RandomAccessFile randomAccessFile = null;
String lastLine = null;
boolean fileExists = true;
if (newxmlfile.length() == 0) {
fileExists = false;
try {
randomAccessFile = new RandomAccessFile(newxmlfile, "rw");
} catch(FileNotFoundException e) {
Log.e("FileNotFoundException", "can't create FileOutputStream");
}
} else {
try {
randomAccessFile = new RandomAccessFile(newxmlfile, "rw");
randomAccessFile.seek(0);
final Scanner scanner = new Scanner(newxmlfile);
int lastLineOffset = 0;
int lastLineLength = 0;
while (scanner.hasNextLine()) {
// +1 is for end line symbol
lastLine = scanner.nextLine();
lastLineLength = lastLine.length() + 2;
lastLineOffset += lastLineLength;
}
// don't need last </root> line offset
lastLineOffset -= lastLineLength;
// got to string before last
randomAccessFile.seek(lastLineOffset);
} catch(FileNotFoundException e) {
Log.e("FileNotFoundException", "can't create FileOutputStream");
} catch (IOException e) {
Log.e("IOException", "Failed to find last line");
}
}
// Now random access file is positioned properly, we can append new xml data
//we create a XmlSerializer in order to write xml data
XmlSerializer serializer = Xml.newSerializer();
if (randomAccessFile == null) {
return;
}
try {
final StringWriter writer = new StringWriter();
serializer.setOutput(writer);
if (!fileExists) {
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, "root");
} else {
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
}
serializer.startTag(null, "item");
serializer.startTag(null, "code");
serializer.text(codeText);
serializer.endTag(null, "code");
serializer.startTag(null, "price");
serializer.text(utCostString);
serializer.endTag(null, "price");
serializer.startTag(null, "quantity");
serializer.text(numberOfItems);
serializer.endTag(null, "quantity");
serializer.startTag(null, "totalcost");
serializer.text(tc);
serializer.endTag(null, "totalcost");
serializer.endTag(null, "item");
if (!fileExists) {
serializer.endTag(null, "root");
}
serializer.flush();
if (lastLine != null) {
serializer.endDocument();
writer.append("\n");
writer.append(lastLine);
}
// Add \n just for better output in console
randomAccessFile.writeBytes(writer.toString() + "\n");
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks in advance.
回答1:
The issue with your code is that You're not appending new data properly.
As described in this answer in case if file exists You need to find last line of it (in this case it's </root>
) and provide new data before it, so it will appear in the same xml document, but not new one.
The code is below (I've moved file modification part to separate function and removed all stuff which is not related to your problem):
public class MyActivity extends Activity {
private static final String TAG = "MyActivity";
File newxmlfile = new File(Environment.getExternalStorageDirectory() + "/testfinal.xml");
int number;
String numberOfItems;
ImageView addToCartButton;
final Context context = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Log.e(TAG, "File is " + Environment.getExternalStorageDirectory() + "/testfinal.xml");
if (!newxmlfile.exists()){
try{
newxmlfile.createNewFile();
}catch(IOException e){
Log.e("IOException", "exception in createNewFile() method");
}
}
//xml
addToCartButton = (ImageView)findViewById(R.id.imageView1);
addToCartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// get prompts.xml view
LayoutInflater li = LayoutInflater.from(context);
View promptsView = li.inflate(R.layout.promptdialog, null);
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
if (promptsView == null) {
return;
}
// set prompts.xml to alertdialog builder
alertDialogBuilder.setView(promptsView);
final EditText userInput = (EditText) promptsView.findViewById(R.id.editTextDialogUserInput);
// set dialog message
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
if (userInput == null || userInput.getText() == null) {
return;
}
numberOfItems = userInput.getText().toString();
number = Integer.parseInt(numberOfItems);
String utCostString = "200";//txtutcost.getText().toString();
float cost = Float.parseFloat(utCostString);
float totalCost = Float.parseFloat(utCostString) * number;
String tc = Float.toString(totalCost);
String codeText = "codeText";//txtmodno.getText().toString();
//Loop for writing xml
try {
updateFile(codeText, utCostString, tc);
Context context = getApplicationContext();
CharSequence text = "Save!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} catch (Exception e) {
Log.e("Exception", "error occurred while creating xml file");
}
//end of xml lopp
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
// create alert dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// show it
alertDialog.show();
}
});
}
/**
* Appends new data to the file
*
* @param codeText
* @param utCostString
* @param tc
*/
private void updateFile(final String codeText, final String utCostString, final String tc) throws IOException {
RandomAccessFile randomAccessFile = null;
String closingLine = null;
boolean fileExists = true;
if (newxmlfile.length() == 0) {
fileExists = false;
try {
randomAccessFile = new RandomAccessFile(newxmlfile, "rw");
} catch(FileNotFoundException e) {
Log.e("FileNotFoundException", "can't create FileOutputStream");
}
} else {
try {
randomAccessFile = new RandomAccessFile(newxmlfile, "rw");
randomAccessFile.seek(0);
String lastLine;
long lastLineOffset = 0;
int lastLineLength = 0;
lastLine = randomAccessFile.readLine();
while (lastLine != null) {
// +1 is for end line symbol
lastLineLength = lastLine.length();
lastLineOffset = randomAccessFile.getFilePointer();
closingLine = lastLine;
lastLine = randomAccessFile.readLine();
}
lastLineOffset -= lastLineLength;
// got to string before last
randomAccessFile.seek(lastLineOffset);
} catch(FileNotFoundException e) {
Log.e("FileNotFoundException", "can't create FileOutputStream");
} catch (IOException e) {
Log.e("IOException", "Failed to find last line");
}
}
// Now random access file is positioned properly, we can append new xml data
//we create a XmlSerializer in order to write xml data
XmlSerializer serializer = Xml.newSerializer();
if (randomAccessFile == null) {
return;
}
try {
final StringWriter writer = new StringWriter();
serializer.setOutput(writer);
if (!fileExists) {
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, "root");
} else {
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
}
serializer.startTag(null, "code");
serializer.text(codeText);
serializer.endTag(null, "code");
serializer.startTag(null, "price");
serializer.text(utCostString);
serializer.endTag(null, "price");
serializer.startTag(null, "quantity");
serializer.text(numberOfItems);
serializer.endTag(null, "quantity");
serializer.startTag(null, "totalcost");
serializer.text(tc);
serializer.endTag(null, "totalcost");
if (!fileExists) {
serializer.endTag(null, "root");
}
serializer.flush();
if (closingLine != null) {
serializer.endDocument();
writer.append("\n");
writer.append(closingLine);
}
// Add \n just for better output in console
randomAccessFile.writeBytes(writer.toString());
randomAccessFile.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
randomAccessFile.close();
}
}
}
来源:https://stackoverflow.com/questions/21318966/adding-a-node-to-same-xml-file-on-sd-card-under-its-root-tag-in-android