我在解析内部存储中的 xml 文件时遇到问题。我有一个看起来像这样的 xml 文件:
<?xml version="1.0" encoding="utf-8"?>
<entries>
<entry>
<name>Name 1</name>
<submenu>Submenu 1</submenu>
<color>Color 1</color>
</entry>
<entry>
<name>Name 2</name>
<submenu>Submenu 2</submenu>
<color>Color 2</color>
</entry>
<entry>
<name>Name 3</name>
<submenu>Submenu 3</submenu>
<color>Color 3</color>
</entry>
</entries>
我的资产文件夹中有一个名为 test.xml 的 xml 文件副本,我的网络服务器上有一个名为 test.xml 的副本。当我尝试解析资产文件夹中的文件时,一切正常。当我从互联网下载文件并尝试从内部存储解析它时,它不起作用。这是我的活动代码,其中包含所有功能:
package com.example.testdl;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
ProgressDialog mProgressDialog;
Button button;
int x = 0;
String URL = "http://www.classicknightstudio.com/marthasvillans/test.xml";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle("Test1");
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.myButton);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
if (x == 0) {
// Execute DownloadFile AsyncTask
new DownloadFile().execute(URL);
x = x + 1;
} else {
logNames();
}
}
});
}
// DownloadFile AsyncTask
private class DownloadFile extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setTitle("Downloads");
mProgressDialog.setMessage("Downloading, Please Wait!");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.show();
}
@Override
protected String doInBackground(String... sUrl) {
try {
URL url = new URL(sUrl[0]);
URLConnection connection = url.openConnection();
connection.connect();
// Detect the file length
int fileLength = connection.getContentLength();
// Download the file
InputStream input = new BufferedInputStream(url.openStream());
FileOutputStream output = openFileOutput("test.xml",
Context.MODE_PRIVATE);
output.write("test.xml".getBytes());
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// Publish the progress
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
// Close connection
output.flush();
output.close();
input.close();
} catch (Exception e) {
// Error Log
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
mProgressDialog.setProgress(progress[0]);
}
}
private class XmlParser {
private final String ns = null;
public List parse(InputStream in) throws XmlPullParserException,
IOException {
try {
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,
false);
parser.setInput(in, null);
parser.nextTag();
return readFeed(parser);
} finally {
in.close();
}
}
private List<Entry> readFeed(XmlPullParser parser)
throws XmlPullParserException, IOException {
List<Entry> entries = new ArrayList<Entry>();
parser.require(XmlPullParser.START_TAG, ns, "entries");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("entry")) {
entries.add(readEntry(parser));
} else {
skip(parser);
}
}
return entries;
}
private Entry readEntry(XmlPullParser parser)
throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, "entry");
String titleName = null;
String submenu = null;
String color = null;
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("name")) {
titleName = readTitleName(parser);
} else if (name.equals("submenu")) {
submenu = readSubmenu(parser);
} else if (name.equals("color")) {
color = readColor(parser);
} else {
skip(parser);
}
}
return new Entry(titleName, submenu, color);
}
private String readTitleName(XmlPullParser parser) throws IOException,
XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "name");
String titleName = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "name");
return titleName;
}
private String readSubmenu(XmlPullParser parser) throws IOException,
XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "submenu");
String submenu = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "submenu");
return submenu;
}
private String readColor(XmlPullParser parser) throws IOException,
XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "color");
String color = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "color");
return color;
}
private String readText(XmlPullParser parser) throws IOException,
XmlPullParserException {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
return result;
}
private void skip(XmlPullParser parser) throws XmlPullParserException,
IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
}
public static class Entry {
public final String titleName;
public final String submenu;
public final String color;
public Entry(String titleName, String submenu, String color) {
this.titleName = titleName;
this.submenu = submenu;
this.color = color;
}
public String getTitleName() {
return titleName;
}
public String getSubmenu() {
return submenu;
}
public String getColor() {
return color;
}
}
protected void logNames() {
File file = getBaseContext().getFileStreamPath("test.xml");
if (file.exists()) {
Log.d("TEST1", "file exists");
try {
// InputStream in = getApplicationContext().getAssets().open("test.xml");
FileInputStream in = openFileInput("test.xml");
XmlParser myParse = new XmlParser();
try {
@SuppressWarnings("unchecked")
ArrayList<Entry> TheParse = (ArrayList<Entry>) myParse
.parse(in);
for (int i = 0; i < TheParse.size(); i = i + 1) {
Log.d("TEST1", "" + TheParse.get(i).getTitleName());
}
} catch (XmlPullParserException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
活动设置为当您第一次按下按钮时,它会从网络下载文件。然后,当您第二次按下该按钮时,它会在 logcat 中记录每个条目的名称。
在 logNames 方法中,我发布的代码使用 FileInputStream in = openFileInput("test.xml");
上面注释掉的是一个从 assets 文件夹中获取文件的流。我知道要从资产文件夹中读取文件,我不需要所有下载的东西。所以,如果我注释掉:
FileInputStream in = openFileInput("test.xml");
在 logNames 方法中并取消注释:
InputStream in = getApplicationContext().getAssets().open("test.xml");
然后一切正常,名称显示在日志猫中。但是,如果我使用如图所示的代码(尝试从网络下载 xml,将其保存到外部存储,然后解析它),我会收到以下错误:
08-12 04:38:56.899: W/System.err(17622): org.xmlpull.v1.XmlPullParserException: Unexpected token (position:TEXT test.xml@1:9 in java.io.InputStreamReader@4278f850)
08-12 04:38:56.909: W/System.err(17622): at org.kxml2.io.KXmlParser.next(KXmlParser.java:426)
08-12 04:38:56.909: W/System.err(17622): at org.kxml2.io.KXmlParser.next(KXmlParser.java:310)
08-12 04:38:56.909: W/System.err(17622): at org.kxml2.io.KXmlParser.nextTag(KXmlParser.java:2029)
08-12 04:38:56.909: W/System.err(17622): at com.example.testdl.MainActivity$XmlParser.parse(MainActivity.java:143)
08-12 04:38:56.909: W/System.err(17622): at com.example.testdl.MainActivity.logNames(MainActivity.java:292)
08-12 04:38:56.909: W/System.err(17622): at com.example.testdl.MainActivity$1.onClick(MainActivity.java:59)
08-12 04:38:56.909: W/System.err(17622): at android.view.View.performClick(View.java:4203)
08-12 04:38:56.909: W/System.err(17622): at android.view.View$PerformClick.run(View.java:17189)
08-12 04:38:56.909: W/System.err(17622): at android.os.Handler.handleCallback(Handler.java:615)
08-12 04:38:56.909: W/System.err(17622): at android.os.Handler.dispatchMessage(Handler.java:92)
08-12 04:38:56.909: W/System.err(17622): at android.os.Looper.loop(Looper.java:137)
08-12 04:38:56.909: W/System.err(17622): at android.app.ActivityThread.main(ActivityThread.java:4950)
08-12 04:38:56.909: W/System.err(17622): at java.lang.reflect.Method.invokeNative(Native Method)
08-12 04:38:56.909: W/System.err(17622): at java.lang.reflect.Method.invoke(Method.java:511)
08-12 04:38:56.909: W/System.err(17622): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
08-12 04:38:56.909: W/System.err(17622): at c com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
08-12 04:38:56.919: W/System.err(17622): at dalvik.system.NativeStart.main(Native Method)
08-12 04:38:58.210: D/TEST1(17622): file exists
08-12 04:38:58.210: W/System.err(17622): org.xmlpull.v1.XmlPullParserException: Unexpected token (position:TEXT test.xml@1:9 in java.io.InputStreamReader@4279b7c8)
08-12 04:38:58.210: W/System.err(17622): at org.kxml2.io.KXmlParser.next(KXmlParser.java:426)
08-12 04:38:58.210: W/System.err(17622): at org.kxml2.io.KXmlParser.next(KXmlParser.java:310)
08-12 04:38:58.210: W/System.err(17622): at org.kxml2.io.KXmlParser.nextTag(KXmlParser.java:2029)
08-12 04:38:58.210: W/System.err(17622): at com.example.testdl.MainActivity$XmlParser.parse(MainActivity.java:143)
08-12 04:38:58.220: W/System.err(17622): at com.example.testdl.MainActivity.logNames(MainActivity.java:292)
08-12 04:38:58.220: W/System.err(17622): at com.example.testdl.MainActivity$1.onClick(MainActivity.java:59)
08-12 04:38:58.220: W/System.err(17622): at android.view.View.performClick(View.java:4203)
08-12 04:38:58.220: W/System.err(17622): at and android.view.View$PerformClick.run(View.java:17189)
08-12 04:38:58.220: W/System.err(17622): at android.os.Handler.handleCallback(Handler.java:615)
08-12 04:38:58.220: W/System.err(17622): at android.os.Handler.dispatchMessage(Handler.java:92)
08-12 04:38:58.220: W/System.err(17622): at android.os.Looper.loop(Looper.java:137)
08-12 04:38:58.220: W/System.err(17622): at android.app.ActivityThread.main(ActivityThread.java:4950)
08-12 04:38:58.220: W/System.err(17622): at java.lang.reflect.Method.invokeNative(Native Method)
08-12 04:38:58.220: W/System.err(17622): at java.lang.reflect.Method.invoke(Method.java:511)
08-12 04:38:58.220: W/System.err(17622): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
08-12 04:38:58.220: W/System.err(17622): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
08-12 04:38:58.220: W/System.err(17622): at dalvik.system.NativeStart.main(Native Method)
该文件是否存在于 logNames 方法中的检查通过了,看起来该文件确实保存到了内部存储中。任何帮助表示赞赏。