Adding a node to same xml file on sd card under it

2019-08-02 02:25发布

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条回答
萌系小妹纸
2楼-- · 2019-08-02 03:18

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();
        }
    }
}
查看更多
登录 后发表回答