【问题标题】:Android : Apache POI duplicate entry: org/apache/xmlbeans/xml/stream/Location.class errorAndroid:Apache POI 重复条目:org/apache/xmlbeans/xml/stream/Location.class 错误
【发布时间】:2021-06-26 13:31:34
【问题描述】:

您好,我在运行我的 android 项目时遇到以下错误:

Error:Execution failed for task ':app:transformClassesWithJarMergingForDebug'.
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: org/apache/xmlbeans/xml/stream/Location.class

我在网上搜索过这个问题,不同类型的解决方案提供的解决方案很少,如下所示:

1] Enable multidex, (by doing `multiDexEnabled true`),
2] Remove support library v4 as v7 comes with it, (I am using only v7),
3] Increase jvm heap size through gradle or through gradle.properties,
2] Do not use multiple playstore library versions (Which I am not using already)

当我在 gradle 中添加对 Apache POI 的依赖时,以上所有内容都开始了:

dependencies {
    ....
    compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.14'
}

以上都不适用于我的情况。为什么会发生这种情况以及什么是可靠的解决方案。

【问题讨论】:

    标签: java android android-gradle-plugin apache-poi android-multidex


    【解决方案1】:

    有一些可用的项目试图解决在 Android 上使用 POI 时出现的一些问题。

    请查看示例项目https://github.com/centic9/poi-on-android/,它允许在 Android 上为 POI 构建单个 jar 文件。它删除了重复项,还修复了一些其他与被禁止的包名称和其他问题有关的问题。

    该领域的另一个项目是https://github.com/andruhon/android5xlsx,但它目前仅支持旧版本的 POI。

    【讨论】:

    【解决方案2】:

    poi 库与 multidex apk 构建存在依赖冲突。 要解决这些冲突:

    1. 删除对依赖项或 jar 的 gradle 引用 [如下所示]。
    2. this jar without clashing dependancies 添加到/lib
    3. 将以下行添加到模块 gradle:

      //    implementation 'org.apache.poi:poi-ooxml:3.17'
      

      实现文件('libs/poishadow-all.jar')

    4. 您也可以右键单击 jar 并选择添加为库,它会自动执行此操作

    jar 是从 This Github repository 构建的

    【讨论】:

    • 我正在使用这个库,但是有一个错误 "Caused by: org.apache.poi.javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.EventFactory not found" 。这个有什么解决办法..
    【解决方案3】:

    解决此问题的另一种方法是排除您在实现中视为错误的组,然后再次尝试运行。

    像这样:

    implementation ('org.apache.poi:poi-ooxml:3.17')
    {
        exclude group: 'org.apache.xmlbeans', module: 'xmlbeans'
        //https://stackoverflow.com/a/56029604/7710739
    }
    

    注意:检查您的构建错误并将您获得的类替换为 Duplicate。

    【讨论】:

    • 如果排除xmlbeans,也可以排除poi-ooxml。要处理 .xlsx/.pptx 等 OOXML 文件,您需要两者。
    • @kiwiwings 我猜这个类已经在某个库中了,所以我猜排除它不会是一个问题,它工作正常
    • 你不觉得,依赖一些旧的 xmlbeans 版本(jetified-xmlbeans-2.6.0)正在等待事故发生吗?秘密地,我也是“在我的机器上工作”的粉丝......但是 xmlbeans 2.6.0 附加了一个CVE,您可能不希望您的用户受到影响......
    • @kiwiwings 谢谢,我会研究如何让它更安全
    【解决方案4】:

    在你的 Gradle 中使用 support:multidex 编译并添加 dexOptions

    android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"
    
    
    
    defaultConfig {
       ..............
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    
    
    }
    dexOptions {
        //incremental = true;
        preDexLibraries = false
        javaMaxHeapSize "4g"
    }
    
    packagingOptions {
        exclude 'META-INF/NOTICE.txt' // will not include NOTICE file
        exclude 'META-INF/LICENSE.txt' // will not include LICENSE file
    }
    
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
     }
    
     dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    //Your Dependencies
    compile 'com.android.support:multidex:1.0.1'
     }
    

    在你的 AndroidManifest.xml 添加这行 android:name

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:name="android.support.multidex.MultiDexApplication"
        >
    

    如果您使用播放服务库而不是替换为

     compile 'com.google.android.gms:play-services:+'
    

    代替

       compile 'com.google.android.gms:play-services-maps:8.4.0' //or other
    

    【讨论】:

      【解决方案5】:

      在做了一些其他阅读后,我发现在 android 中使用 poi 库存在问题,请参见下面的链接:

      https://bz.apache.org/bugzilla/show_bug.cgi?id=59268#c0

      https://github.com/andruhon/android5xlsx 的项目减少了 poi.jar 和 poi-ooxml.jar 的库版本,将它们导入您的 libs 文件夹并在您的 gradle 中包含以下代码:

      compile fileTree(include: ['*.jar'], dir: 'libs')
      

      这个工作的原因是创建这个项目的人已经从基本 poi.jar 中排除了 xmlbeans.jar,而 Android 构建存在问题。归功于 andruhon 这个家伙。

      此解决方法对我有用,因此发布为答案

      【讨论】:

        【解决方案6】:

        为了帮助其他人,这里是使用 POI v 3.17(Android API 15 及更高版本)读取 XLS 文件的完整工作解决方案(XLSX 也是,但有些行需要更改)。

        首先在这里下载 0.5 版本的 POI jar 文件形式:Releases 并将其粘贴到 Android Studio 的 /lib 文件夹中。

        您的布局带有一个简单的 TextView 和一个简单的 Button:

        <?xml version="1.0" encoding="utf-8"?>
        <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#FFEB3B"
            tools:context=".MainActivity">
        
            <TextView
                android:id="@+id/textView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_marginLeft="24dp"
                android:layout_marginTop="24dp"
                android:layout_marginRight="24dp"
                android:layout_marginBottom="24dp"
                android:background="#FFFFFF"
                android:inputType="textMultiLine"
                android:padding="24dp"
                android:singleLine="false"
                android:text="Hello World!"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent" />
        
            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="8dp"
                android:text="Button"
                app:layout_constraintBottom_toBottomOf="@+id/textView"
                app:layout_constraintEnd_toEndOf="@+id/textView"
                app:layout_constraintStart_toStartOf="@+id/textView" />
        
        </android.support.constraint.ConstraintLayout>
        

        然后将这一行放在模块gradle中:

        implementation files('libs/poishadow-all.jar')
        

        现在(试用该应用程序)创建一个示例 excel 文件,3 列,3 行,任何您想要的数据。您可以创建更多列和工作表。但如果您是第一次尝试此代码,请仅使用三列。现在将文件名与“myexcelsheet.xls”相同 转到 android 项目目录并打开您的 android 项目。进入文件夹 app -> src -> main。在那里,您将看到两个文件夹名称为 java 和 res。现在在此处创建一个新文件夹,命名为 assets,并将 myexcelsheet.xls 文件放入其中。

        最后是 Main Activity 代码:

        package com.example.readexcelfiles;
        
        import android.content.res.AssetManager;
        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;
        import android.util.Log;
        import android.view.View;
        import android.widget.Button;
        import android.widget.TextView;
        
        import org.apache.poi.hssf.usermodel.HSSFCell;
        import org.apache.poi.hssf.usermodel.HSSFRow;
        import org.apache.poi.hssf.usermodel.HSSFSheet;
        import org.apache.poi.hssf.usermodel.HSSFWorkbook;
        import org.apache.poi.poifs.filesystem.POIFSFileSystem;
        import org.apache.poi.ss.usermodel.Cell;
        import org.apache.poi.ss.usermodel.Row;
        
        import java.io.InputStream;
        import java.util.Iterator;
        
        public class MainActivity extends AppCompatActivity {
        
            TextView txtView;
            Button btnRead;
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        
                txtView = findViewById(R.id.textView);
                btnRead = findViewById(R.id.button);
        
        
        
                btnRead.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        readExcelFileFromAssets();
                    }
                });
        
            }
        
        
            public void readExcelFileFromAssets() {
                try {
                    InputStream myInput;
                    // initialize asset manager
                    AssetManager assetManager = getAssets();
                    //  open excel sheet
                    myInput = assetManager.open("myexcelsheet.xls");
                    // Create a POI File System object
                    POIFSFileSystem myFileSystem = new POIFSFileSystem(myInput);
                    // Create a workbook using the File System
                    HSSFWorkbook myWorkBook = new HSSFWorkbook(myFileSystem);
                    // Get the first sheet from workbook
                    HSSFSheet mySheet = myWorkBook.getSheetAt(0);
                    // We now need something to iterate through the cells.
                    Iterator<Row> rowIter = mySheet.rowIterator();
                    int rowno =0;
                    txtView.append("\n");
                    while (rowIter.hasNext()) {
                        Log.e("aaa", " row no "+ rowno );
                        HSSFRow myRow = (HSSFRow) rowIter.next();
                        if(rowno !=0) {
                            Iterator<Cell> cellIter = myRow.cellIterator();
                            int colNum =0;
                            String sno="", date="", det="";
                            while (cellIter.hasNext()) {
                                HSSFCell myCell = (HSSFCell) cellIter.next();
                                if (colNum==0){
                                    sno = myCell.toString();
                                }else if (colNum==1){
                                    date = myCell.toString();
                                }else if (colNum==2){
                                    det = myCell.toString();
                                }
                                colNum++;
                                Log.e("aaa", " Index :" + myCell.getColumnIndex() + " -- " + myCell.toString());
                            }
                            txtView.append( sno + " -- "+ date+ "  -- "+ det+"\n");
                        }
                        rowno++;
                    }
                } catch (Exception e) {
                    Log.e("aaa", "error "+ e.toString());
                }
            }
        
        
        
        
        
        }
        

        要阅读 XLSX 文件,请阅读 Kamal Bunkar 先生的评论:

        首先了解符号。 XSSF(XML 电子表格格式)——用于读取和写入 Open Office XML (XLSX) 格式文件。 HSSF(可怕的电子表格格式)– 用于读取和写入 Microsoft Excel (XLS) 格式文件。 HWPF (Horrible Word Processor Format) – 读写 Microsoft Word 97 (DOC) 格式文件。

        在我的教程中我正在使用

        // Get the first sheet from workbook
        HSSFSheet mySheet = myWorkBook.getSheetAt(0);
        

        现在要使用 xlsx,您应该使用此代码

        File myFile = new File(“C://temp/Employee.xlsx”);
        FileInputStream fis = new FileInputStream(myFile);
        // Finds the workbook instance for XLSX file
        XSSFWorkbook myWorkBook = new XSSFWorkbook (fis);
        // Return first sheet from the XLSX workbook
        XSSFSheet mySheet = myWorkBook.getSheetAt(0);
        // Get iterator to all the rows in current sheet
        Iterator rowIterator = mySheet.iterator();
        // Traversing over each row of XLSX file
        while (rowIterator.hasNext())
        {
        Row row = rowIterator.next();
        // For each row, iterate through each columns
        Iterator cellIterator = row.cellIterator();
        while (cellIterator.hasNext()) {
        Cell cell = cellIterator.next();
        switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: System.out.print(cell.getStringCellValue() + “\t”);
        break; case Cell.CELL_TYPE_NUMERIC:System.out.print(cell.getNumericCellValue() + “\t”);
        break; case Cell.CELL_TYPE_BOOLEAN: System.out.print(cell.getBooleanCellValue() + “\t”);
        break; default : }
        }
        System.out.println(“”);
        }
        

        显然要适应Android文件位置...

        希望能帮到你……

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-24
          • 1970-01-01
          • 1970-01-01
          • 2015-12-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多