【问题标题】:Encountered StringIndexOutOfBoundsException while parsing XML file in Android在 Android 中解析 XML 文件时遇到 StringIndexOutOfBoundsException
【发布时间】:2014-02-25 06:27:35
【问题描述】:

我正在尝试使用 DOM 解析器解析 XML 文件。 DocumentBuilder.parse() 函数抛出 StringIndexOutOfBoundsException。

    public class ParseCountryInfo {

public static ArrayList<CountryInfo> getCountryInfo(Context context) {
    ArrayList<CountryInfo> countryInfoList = new ArrayList<CountryInfo>();

    try {

        InputStream fXmlFile = context.getResources().openRawResource(R.raw.country_data);
        InputSource is = new InputSource(fXmlFile);
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.parse(is);

        doc.getDocumentElement().normalize();

        NodeList nList = doc.getElementsByTagName("country");

        for (int temp = 0; temp < nList.getLength(); temp++) {

            Node nNode = nList.item(temp);

            if (nNode.getNodeType() == Node.ELEMENT_NODE) {

                Element eElement = (Element) nNode;

                countryInfoList.add(new CountryInfo(eElement.getAttribute("name"),
                        eElement.getAttribute("capital"), eElement.getAttribute("population")));

            }
        }
        fXmlFile.close();

    } catch (Exception e) {
        e.printStackTrace();
    }

    return countryInfoList;
}

在以下行遇到错误:Document doc = dBuilder.parse(is) 我也试过:Document doc = dBuilder.parse(fXmlFile) 给出了同样的错误。

Detailed Log:

02-25 01:13:36.326: W/System.err(19634): java.lang.StringIndexOutOfBoundsException: length=34; index=34
02-25 01:13:36.334: W/System.err(19634):    at org.kxml2.io.KXmlParser.setInput(KXmlParser.java:1680)
02-25 01:13:36.334: W/System.err(19634):    at org.apache.harmony.xml.parsers.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:111)
02-25 01:13:36.350: W/System.err(19634):    at com.example.worldlymobile.ParseCountryInfo.getCountryInfo(ParseCountryInfo.java:28)
02-25 01:13:36.350: W/System.err(19634):    at com.example.worldlymobile.DbHelper.onCreate(DbHelper.java:43)
02-25 01:13:36.350: W/System.err(19634):    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)
02-25 01:13:36.350: W/System.err(19634):    at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:188)
02-25 01:13:36.350: W/System.err(19634):    at com.example.worldlymobile.CountryInfoActivity.initCountryInfoIfNeeded(CountryInfoActivity.java:48)
02-25 01:13:36.358: W/System.err(19634):    at com.example.worldlymobile.CountryInfoActivity.onResume(CountryInfoActivity.java:37)
02-25 01:13:36.358: W/System.err(19634):    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1187)
02-25 01:13:36.358: W/System.err(19634):    at android.app.Activity.performResume(Activity.java:5318)
02-25 01:13:36.365: W/System.err(19634):    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2595)
02-25 01:13:36.365: W/System.err(19634):    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2633)
02-25 01:13:36.373: W/System.err(19634):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2100)
02-25 01:13:36.373: W/System.err(19634):    at android.app.ActivityThread.access$600(ActivityThread.java:135)
02-25 01:13:36.373: W/System.err(19634):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201)
02-25 01:13:36.389: W/System.err(19634):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-25 01:13:36.389: W/System.err(19634):    at android.os.Looper.loop(Looper.java:137)
02-25 01:13:36.389: W/System.err(19634):    at android.app.ActivityThread.main(ActivityThread.java:4849)
02-25 01:13:36.389: W/System.err(19634):    at java.lang.reflect.Method.invokeNative(Native Method)
02-25 01:13:36.389: W/System.err(19634):    at java.lang.reflect.Method.invoke(Method.java:511)
02-25 01:13:36.397: W/System.err(19634):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
02-25 01:13:36.397: W/System.err(19634):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
02-25 01:13:36.397: W/System.err(19634):    at dalvik.system.NativeStart.main(Native Method)

我不确定 XML 文件本身是否不正确。文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <country>
        <name>Algeria</name>
        <capital>Algiers</capital>
        <population>36000000</population>
    </country>
    <country>
        <name>Angola</name>
        <capital>Luanda</capital>
        <population>19000000</population>
    </country>
    <country>
        <name>Benin</name>
        <capital>Porto-Novo</capital>
        <population>9800000</population>
    </country>
    <country>
        <name>Botswana</name>
        <capital>Gaborone</capital>
        <population>1800000</population>
    </country>
    <country>
        <name>Burkina Faso</name>
        <capital>Ouagadougou</capital>
        <population>16200000</population>
    </country>
    <country>
        <name>Burundi</name>
        <capital>Bujumbura</capital>
        <population>8500000</population>
    </country>
    <country>
        <name>Cameroon</name>
        <capital>Yaoundé</capital>
        <population>20000000</population>
    </country>
    <country>
        <name>Cape Verde</name>
        <capital>Praia</capital>
        <population>500000</population>
    </country>
    <country>
        <name>Central African Republic</name>
        <capital>Bangui</capital>
        <population>4800000</population>
    </country>
    <country>
        <name>Chad</name>
        <capital>N'Djamena</capital>
        <population>11500000</population>
    </country>
    <country>
        <name>Comoros</name>
        <capital>Moroni</capital>
        <population>727000</population>
    </country>
    <country>
        <name>Republic of Congo</name>
        <capital>Brazzaville</capital>
        <population>67800000</population>
    </country>
    <country>
        <name>Democratic Republic of the Congo</name>
        <capital>Kinshasa</capital>
        <population>3900000</population>
    </country>
    <country>
        <name>Cote d'Ivoire</name>
        <capital>Yamoussoukro</capital>
        <population>22000000</population>
    </country>
    <country>
        <name>Djibouti</name>
        <capital>Djibouti</capital>
        <population>900000</population>
    </country>
    <country>
        <name>Egypt</name>
        <capital>Cairo</capital>
        <population>80400000</population>
    </country>
    <country>
        <name>Equitorial Guinea</name>
        <capital>Malabo</capital>
        <population>700000</population>
    </country>
    <country>
        <name>Eritrea</name>
        <capital>Asmara</capital>
        <population>5200000</population>
    </country>
    <country>
        <name>Ethiopia</name>
        <capital>Addis Ababa</capital>
        <population>85000000</population>
    </country>
    <country>
        <name>Gabon</name>
        <capital>Libreville</capital>
        <population>1500000</population>
    </country>
    <country>
        <name>The Gambia</name>
        <capital>Banjul</capital>
        <population>1800000</population>
    </country>
    <country>
        <name>Ghana</name>
        <capital>Accra</capital>
        <population>24000000</population>
    </country>
    <country>
        <name>Guinea</name>
        <capital>Conakry</capital>
        <population>10800000</population>
    </country>
    <country>
        <name>Guinea-Bissau</name>
        <capital>Bissau</capital>
        <population>1600000</population>
    </country>
    <country>
        <name>Kenya</name>
        <capital>Nairobi</capital>
        <population>40000000</population>
    </country>
    <country>
        <name>Lesotho</name>
        <capital>Maseru</capital>
        <population>1900000</population>
    </country>
    <country>
        <name>Liberia</name>
        <capital>Monrovia</capital>
        <population>4100000</population>
    </country>
    <country>
        <name>Libya</name>
        <capital>Tripoli</capital>
        <population>6500000</population>
    </country>
    <country>
        <name>Madagascar</name>
        <capital>Antananarivo</capital>
        <population>20100000</population>
    </country>
    <country>
        <name>Malawi</name>
        <capital>Lilongwe</capital>
        <population>15400000</population>
    </country>
    <country>
        <name>Mali</name>
        <capital>Bamako</capital>
        <population>15200000</population>
    </country>
    <country>
        <name>Mauritania</name>
        <capital>Nouakchott</capital>
        <population>3400000</population>
    </country>
    <country>
        <name>Mauritius</name>
        <capital>Port Louis</capital>
        <population>1300000</population>
    </country>
    <country>
        <name>Morocco</name>
        <capital>Rabat</capital>
        <population>31900000</population>
    </country>
    <country>
        <name>Mozambique</name>
        <capital>Maputo</capital>
        <population>23400000</population>
    </country>
    <country>
        <name>Namibia</name>
        <capital>Windhoek</capital>
        <population>2200000</population>
    </country>
    <country>
        <name>Niger</name>
        <capital>Niamey</capital>
        <population>15900000</population>
    </country>
    <country>
        <name>Nigeria</name>
        <capital>Abuja</capital>
        <population>158300000</population>
    </country>
    <country>
        <name>Réunion</name>
        <capital>Saint-Denis</capital>
        <population>800000</population>
    </country>
    <country>
        <name>Rwanda</name>
        <capital>Kigali</capital>
        <population>10400000</population>
    </country>
    <country>
        <name>Saint Helena</name>
        <capital>Jamestown</capital>
        <population>6000</population>
    </country>
    <country>
        <name>São Tomé and Príncipe</name>
        <capital>São Tomé</capital>
        <population>200000</population>
    </country>
    <country>
        <name>Senegal</name>
        <capital>Dakar</capital>
        <population>12500000</population>
    </country>
    <country>
        <name>Seychelles</name>
        <capital>Victoria</capital>
        <population>100000</population>
    </country>
    <country>
        <name>Sierra Leone</name>
        <capital>Freetown</capital>
        <population>5800000</population>
    </country>
    <country>
        <name>Somalia</name>
        <capital>Mogadishu</capital>
        <population>9400000</population>
    </country>
    <country>
        <name>South Africa</name>
        <capital>Pretoria</capital>
        <population>49900000</population>
    </country>
    <country>
        <name>South Sudan</name>
        <capital>Juba</capital>
        <population>9000000</population>
    </country>
    <country>
        <name>Sudan</name>
        <capital>Khartoum</capital>
        <population>36000000</population>
    </country>
    <country>
        <name>Swaziland</name>
        <capital>Mbabane </capital>
        <population>1200000</population>
    </country>
    <country>
        <name>Tanzania </name>
        <capital>Dodoma</capital>
        <population>45000000</population>
    </country>
    <country>
        <name>Togo</name>
        <capital>Lomé</capital>
        <population>6800000</population>
    </country>
    <country>
        <name>Tunisia</name>
        <capital>Tunis</capital>
        <population>10500000</population>
    </country>
    <country>
        <name>Uganda</name>
        <capital>Kampala</capital>
        <population>33800000</population>
    </country>
    <country>
        <name>Western Sahara</name>
        <capital>El Aaiún</capital>
        <population>500000</population>
    </country>
    <country>
        <name>Zambia</name>
        <capital>Lusaka</capital>
        <population>13300000</population>
    </country>
    <country>
        <name>Zimbabwe</name>
        <capital>Harare</capital>
        <population>12600000</population>
    </country>
</data>

【问题讨论】:

  • 你能发布更详细的错误日志吗?

标签: android xml-parsing


【解决方案1】:

我刚刚尝试使用 XML 中的 5 个元素,上面的代码完美运行! 由于 DOM 解析器将整个 XML 加载到内存中,我相信这实际上是一个 OutOfMemory 错误。奇怪的是我得到了 StringIndexOutOfBounds 异常。无论如何,我使用了 SAX 解析器,一切正常。我在这里分享相同的代码。

SAX 处理程序:

public class SAXXMLHandler extends DefaultHandler {

    private final ArrayList<CountryInfo> countryInfoList;
    private String tempVal;
    private CountryInfo countryInfo;

    public SAXXMLHandler() {
        countryInfoList = new ArrayList<CountryInfo>();
    }

    public ArrayList<CountryInfo> getCountryInfoList() {
        return countryInfoList;
    }

    // Event Handlers
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        // reset
        tempVal = "";
        if (qName.equalsIgnoreCase("country")) {
            // create a new instance of employee
            countryInfo = new CountryInfo();
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        tempVal = new String(ch, start, length);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.equalsIgnoreCase("country")) {
            // add it to the list
            countryInfoList.add(countryInfo);
        } else if (qName.equalsIgnoreCase("name")) {
            countryInfo.setCountryName(tempVal);
        } else if (qName.equalsIgnoreCase("capital")) {
            countryInfo.setCountryCapital(tempVal);
        } else if (qName.equalsIgnoreCase("population")) {
            countryInfo.setCountryPopulation(tempVal);
            ;
        }
    }
}

解析:

   ArrayList<CountryInfo> countryInfoList = new ArrayList<CountryInfo>();
    try {
        // create a XMLReader from SAXParser
        XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
        // create a SAXXMLHandler
        SAXXMLHandler saxHandler = new SAXXMLHandler();
        // store handler in XMLReader
        xmlReader.setContentHandler(saxHandler);
        InputStream fXmlFile = context.getResources().openRawResource(R.raw.country_data);
        // the process starts
        xmlReader.parse(new InputSource(fXmlFile));
        // get the `Employee list`
        countryInfoList = saxHandler.getCountryInfoList();

    } catch (Exception ex) {
        Log.d("XML", "SAXXMLParser: parse() failed");
    }

希望这对遇到类似问题的人有所帮助。

【讨论】:

    【解决方案2】:

    改变这个条件...

    for (int temp = 0; temp < nList.getLength(); temp++) {
    

    到....

    for (int temp = 0; temp < nList.getLength()-1; temp++) {
    

    问题是……你试图访问一个不存在的字符串索引。

    String 的索引以0 开头...所以,它的最后一个索引必须比它的长度小1。这就是为什么当您尝试获取字符串的最后一个索引时,您将使用string.getLength()-1 获取它,如下所示...

    int last_index = string.getLength()-1;
    

    【讨论】:

    • 你确定吗?在该行之前遇到错误。具体来说:Document doc = dBuilder.parse(is)
    • 据我研究,这是导致StringIndexOutOfBoundsException...现在,试试...然后告诉我。
    • 我已经追踪到错误的来源。代码没有达到这一点。在以下位置遇到错误:Document doc = dBuilder.parse(is)@HamidShatu
    • 你能说ParseCountryInfo.java的哪一行是第28行吗?
    • 第 28 行:Document doc = dBuilder.parse(is);
    【解决方案3】:

    试试这个..

    Document doc = dBuilder.parse(fXmlFile);
    

    而不是这个..

    Document doc = dBuilder.parse(is);
    

    【讨论】:

    • @user2994485 Is 28 line in ParseCountryInfo is this Document doc = dBuilder.parse(is);
    • 我都试过了:Document doc = dBuilder.parse(fXmlFile);Document doc = dBuilder.parse(is);
    • @user2994485 ParseCountryInfo 中的第 28 行是什么
    • 第 28 行:Document doc = dBuilder.parse(is);
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    相关资源
    最近更新 更多