在android的root标签下的sd卡上添加一个节点到同一个xml文件

时间:2014-01-23 20:46:32

标签: android xml xml-serialization fileoutputstream appendchild

朋友们,我有这个代码,我正在写一个xml文件到我的SD卡:

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();
        }
    }
}

这段代码在我的xml文件中给出了这样的输出:

<?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>

我希望输出xml文件是这样的:

<?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>

请提出我需要做的更改,以便按上述方式获取输出。任何帮助将不胜感激。提前致谢。

** * ** * ** * 的** * ** * ** 更新 * ** * ** * ** * ** * ****

按照桑德斯特提到的方式进行更改。现在它可以轻松地向xml输入两个条目而不会出现问题。但是当我尝试编写第三个条目时,它会被写成一些额外的字符:

<?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>

正如您在第二次看到之后会有额外的<写入。我似乎无法找出原因。

我的新代码如下:

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();
        }
    }
}

提前致谢。

1 个答案:

答案 0 :(得分:0)

您的代码存在的问题是您没有正确添加新数据。

this answer中所述,如果文件存在你需要找到它的最后一行(在这种情况下它是</root>)并在它之前提供新数据,因此它将出现在同一个xml中文件,但不是新文件。

代码如下(我已将文件修改部分移至单独的功能并删除了与您的问题无关的所有内容):

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();
        }
    }
}