Java 在 Android 应用程序中读取 CSV 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43055661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:38:58  来源:igfitidea点击:

Reading CSV File In Android App

javaandroidcsv

提问by TheBlindDeveloper

I'm working on a proof-of-concept app so that I can implement the feature in a larger app I'm making. I'm a bit new to Java and Android Dev but hopefully this shouldn't be too simple or complex of a question.

我正在开发一个概念验证应用程序,以便我可以在我正在制作的更大的应用程序中实现该功能。我对 Java 和 Android Dev 有点陌生,但希望这不应该是一个太简单或太复杂的问题。

Basically, I'm trying to read in a list of strings from a CSV file and make it usable in displaying the list on the app's Main Activity.

基本上,我试图从 CSV 文件中读取字符串列表,并使其可用于在应用程序的主活动中显示列表。

I'm using an external class for reading in CSV's. Here's the class code:

我正在使用外部类来读取 CSV 文件。这是类代码:

CSVFile.java

CSV文件.java

package com.yourtechwhiz.listdisplay;

import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class CSVFile {
    InputStream inputStream;

    public CSVFile(InputStream inputStream){
        this.inputStream = inputStream;
    }

    public List read(){
        List resultList = new ArrayList();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        try {
            String csvLine;
            while ((csvLine = reader.readLine()) != null) {
                String[] row = csvLine.split(",");
                resultList.add(row);
                Log.d("VariableTag", row[0].toString());
            }
        }
        catch (IOException ex) {
            throw new RuntimeException("Error in reading CSV file: "+ex);
        }
        finally {
            try {
                inputStream.close();
            }
            catch (IOException e) {
                throw new RuntimeException("Error while closing input stream: "+e);
            }
        }
        return resultList;
    }
}

Here's my main activity code:

这是我的主要活动代码:

MainActivity.java

主活动.java

package com.yourtechwhiz.listdisplay;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    // Array of strings that's used to display on screen
    String[] mobileArray = {"Android","IPhone","WindowsMobile","Blackberry",
            "WebOS","Ubuntu","Windows7","Max OS X"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        prepArray();

        //Display List on Activity
        ArrayAdapter adapter = new ArrayAdapter<String>(this,
                R.layout.activity_listview, mobileArray);
        ListView listView = (ListView) findViewById(R.id.mobile_list);
        listView.setAdapter(adapter);

    }

    //Get list of strings from CSV ready to use
    private void prepArray() {

        InputStream inputStream = getResources().openRawResource(R.raw.strings);
        CSVFile csvFile = new CSVFile(inputStream);
        List myList = csvFile.read();

        //This is where it has an error
        //Set first array in myList to this new array myArray
        String[] myArray = myList.get(0);

    }

}

I'm not actually to the point of setting the mobileArray array yet. Right now I'm just trying to "extract" the information out of the List object myList...

我实际上还没有到设置 mobileArray 数组的地步。现在我只是想从 List 对象 myList 中“提取”信息......

Can someone explain to me how this is done? Maybe I'm just not understanding the List type completely. It seems like when resultList is returned in the CSVFile read method, it's returned as an List object consisting of String array objects. But I can't seem to get it to work like that.

有人可以向我解释这是如何完成的吗?也许我只是没有完全理解 List 类型。似乎当在 CSVFile 读取方法中返回 resultList 时,它作为由 String 数组对象组成的 List 对象返回。但我似乎无法让它像那样工作。

Any help is appreciated!

任何帮助表示赞赏!

FINAL EDIT (working code)

最终编辑(工作代码)

private void prepArray() {

        try{
            CSVReader reader = new CSVReader(new InputStreamReader(getResources().openRawResource(R.raw.strings)));//Specify asset file name
            String [] nextLine;
            while ((nextLine = reader.readNext()) != null) {
                // nextLine[] is an array of values from the line
                System.out.println(nextLine[0] + nextLine[1] + "etc...");
                Log.d("VariableTag", nextLine[0]);
            }
        }catch(Exception e){
            e.printStackTrace();
            Toast.makeText(this, "The specified file was not found", Toast.LENGTH_SHORT).show();
        }

    }

EDIT

编辑

Now my prepArray function looks like the following:

现在我的 prepArray 函数如下所示:

    private void prepArray() {

        try{
            String csvfileString = this.getApplicationInfo().dataDir + File.separatorChar + "strings.csv"
            File csvfile = new File(csvfileString);
            CSVReader reader = new CSVReader(new FileReader("csvfile.getAbsolutePath()"));
            String [] nextLine;
            while ((nextLine = reader.readNext()) != null) {
                // nextLine[] is an array of values from the line
                System.out.println(nextLine[0] + nextLine[1] + "etc...");
            }
        }catch(FileNotFoundException e){
            e.printStackTrace();
            Toast.makeText(this, "The specified file was not found", Toast.LENGTH_SHORT).show();
        }

    }

Still produces the FileNotFoundException.

仍然会产生 FileNotFoundException。

EDIT 2/3

编辑 2/3

Here's the log that's produced when I run the app on an actual phone with the strings.csv in a subfolder of strings (src\main\assets\strings\strings.csv) with the change you requested to the code:

这是我在实际手机上使用字符串子文件夹 (src\main\assets\strings\strings.csv) 中的 strings.csv 运行应用程序时生成的日志,其中包含您对代码请求的更改:

03/27 17:44:01: Launching app
        $ adb push C:\Users\Roy\AndroidStudioProjects\ListDisplay\app\build\outputs\apk\app-debug.apk /data/local/tmp/com.yourtechwhiz.listdisplay
        $ adb shell pm install -r "/data/local/tmp/com.yourtechwhiz.listdisplay"
        pkg: /data/local/tmp/com.yourtechwhiz.listdisplay
        Success


        $ adb shell am start -n "com.yourtechwhiz.listdisplay/com.yourtechwhiz.listdisplay.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -D
        Connecting to com.yourtechwhiz.listdisplay
        D/HyLog: I : /data/font/config/sfconfig.dat, No such file or directory (2)
        D/HyLog: I : /data/font/config/dfactpre.dat, No such file or directory (2)
        D/HyLog: I : /data/font/config/sfconfig.dat, No such file or directory (2)
        W/ActivityThread: Application com.yourtechwhiz.listdisplay is waiting for the debugger on port 8100...
        I/System.out: Sending WAIT chunk
        I/dalvikvm: Debugger is active
        I/System.out: Debugger has connected
        I/System.out: waiting for debugger to settle...
        Connected to the target VM, address: 'localhost:8609', transport: 'socket'
        I/System.out: waiting for debugger to settle...
        I/System.out: waiting for debugger to settle...
        I/System.out: waiting for debugger to settle...
        I/System.out: waiting for debugger to settle...
        I/System.out: waiting for debugger to settle...
        I/System.out: waiting for debugger to settle...
        I/System.out: waiting for debugger to settle...
        I/System.out: debugger has settled (1498)
        I/dalvikvm: Could not find method android.view.Window$Callback.onProvideKeyboardShortcuts, referenced from method android.support.v7.view.WindowCallbackWrapper.onProvideKeyboardShortcuts
        W/dalvikvm: VFY: unable to resolve interface method 16152: Landroid/view/Window$Callback;.onProvideKeyboardShortcuts (Ljava/util/List;Landroid/view/Menu;I)V
        D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
        W/dalvikvm: VFY: unable to find class referenced in signature (Landroid/view/SearchEvent;)
        I/dalvikvm: Could not find method android.view.Window$Callback.onSearchRequested, referenced from method android.support.v7.view.WindowCallbackWrapper.onSearchRequested
        W/dalvikvm: VFY: unable to resolve interface method 16154: Landroid/view/Window$Callback;.onSearchRequested (Landroid/view/SearchEvent;)Z
        D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
        I/dalvikvm: Could not find method android.view.Window$Callback.onWindowStartingActionMode, referenced from method android.support.v7.view.WindowCallbackWrapper.onWindowStartingActionMode
        W/dalvikvm: VFY: unable to resolve interface method 16158: Landroid/view/Window$Callback;.onWindowStartingActionMode (Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
        D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
        I/dalvikvm: Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.widget.TintTypedArray.getChangingConfigurations
        W/dalvikvm: VFY: unable to resolve virtual method 455: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
        D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
        I/dalvikvm: Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.widget.TintTypedArray.getType
        W/dalvikvm: VFY: unable to resolve virtual method 477: Landroid/content/res/TypedArray;.getType (I)I
        D/dalvikvm: VFY: replacing opcode 0x6e at 0x0008
        I/dalvikvm: Could not find method android.widget.FrameLayout.startActionModeForChild, referenced from method android.support.v7.widget.ActionBarContainer.startActionModeForChild
        W/dalvikvm: VFY: unable to resolve virtual method 16589: Landroid/widget/FrameLayout;.startActionModeForChild (Landroid/view/View;Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
        D/dalvikvm: VFY: replacing opcode 0x6f at 0x0002
        I/dalvikvm: Could not find method android.content.Context.getColorStateList, referenced from method android.support.v7.content.res.AppCompatResources.getColorStateList
        W/dalvikvm: VFY: unable to resolve virtual method 269: Landroid/content/Context;.getColorStateList (I)Landroid/content/res/ColorStateList;
        D/dalvikvm: VFY: replacing opcode 0x6e at 0x0006
        I/dalvikvm: Could not find method android.content.res.Resources.getDrawable, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawable
        W/dalvikvm: VFY: unable to resolve virtual method 418: Landroid/content/res/Resources;.getDrawable (ILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
        D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
        I/dalvikvm: Could not find method android.content.res.Resources.getDrawableForDensity, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawableForDensity
        W/dalvikvm: VFY: unable to resolve virtual method 420: Landroid/content/res/Resources;.getDrawableForDensity (IILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
        D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
        E/dalvikvm: Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering
        W/dalvikvm: VFY: unable to resolve instanceof 140 (Landroid/graphics/drawable/RippleDrawable;) in Landroid/support/v7/widget/AppCompatImageHelper;
        D/dalvikvm: VFY: replacing opcode 0x20 at 0x000c
        W/System.err: java.io.FileNotFoundException: /csvfile.getAbsolutePath(): open failed: ENOENT (No such file or directory)
        W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:462)
        W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:78)
        W/System.err:     at java.io.FileInputStream.<init>(FileInputStream.java:105)
        W/System.err:     at java.io.FileReader.<init>(FileReader.java:66)
        W/System.err:     at com.yourtechwhiz.listdisplay.MainActivity.prepArray(MainActivity.java:43)
        W/System.err:     at com.yourtechwhiz.listdisplay.MainActivity.onCreate(MainActivity.java:26)
        W/System.err:     at android.app.Activity.performCreate(Activity.java:5287)
        W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
        W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2145)
        W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2231)
        W/System.err:     at android.app.ActivityThread.access0(ActivityThread.java:139)
        W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1401)
        W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
        W/System.err:     at android.os.Looper.loop(Looper.java:137)
        W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5082)
        W/System.err:     at java.lang.reflect.Method.invokeNative(Native Method)
        W/System.err:     at java.lang.reflect.Method.invoke(Method.java:515)
        W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
        W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:598)
        W/System.err:     at dalvik.system.NativeStart.main(Native Method)
        W/System.err: Caused by: libcore.io.ErrnoException: open failed: ENOENT (No such file or directory)
        W/System.err:     at libcore.io.Posix.open(Native Method)
        W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:110)
        W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:446)
        W/System.err:   ... 19 more
        I/Adreno-EGL: <qeglDrvAPI_eglInitialize:385>: EGL 1.4 QUALCOMM build:  ()
        OpenGL ES Shader Compiler Version: E031.24.00.01
        Build Date: 12/27/13 Fri
        Local Branch: qualcomm_only
        Remote Branch:
        Local Patches:
        Reconstruct Branch:
        D/OpenGLRenderer: Enabling debug mode 0
        D/OpenGLRenderer: GL error from OpenGLRenderer: 0x502
        E/OpenGLRenderer:   GL_INVALID_OPERATION

采纳答案by buradd

Try OpenCSV- it will make your life easier.

试试OpenCSV- 它会让你的生活更轻松。

First, add this package to your gradledependencies as follows

首先,将此包添加到您的gradle依赖项中,如下所示

implementation 'com.opencsv:opencsv:4.6'

Then you can either do

然后你可以做

import com.opencsv.CSVReader;
import java.io.IOException;
import java.io.FileReader;


...

try {
    CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
    String[] nextLine;
    while ((nextLine = reader.readNext()) != null) {
        // nextLine[] is an array of values from the line
        System.out.println(nextLine[0] + nextLine[1] + "etc...");
    }
} catch (IOException e) {

}

or

或者

CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
List myEntries = reader.readAll();


Edit after comment

评论后编辑

try {
    File csvfile = new File(Environment.getExternalStorageDirectory() + "/csvfile.csv");
    CSVReader reader = new CSVReader(new FileReader(csvfile.getAbsolutePath()));
    String[] nextLine;
    while ((nextLine = reader.readNext()) != null) {
        // nextLine[] is an array of values from the line
        System.out.println(nextLine[0] + nextLine[1] + "etc...");
    }
} catch (Exception e) {
    e.printStackTrace();
    Toast.makeText(this, "The specified file was not found", Toast.LENGTH_SHORT).show();
}

If you want to package the .csvfile with the application and have it install on the internal storage when the app installs, create an assetsfolder in your project src/mainfolder (e.g., c:\myapp\app\src\main\assets\), and put the .csvfile in there, then reference it like this in your activity:

如果您想将.csv文件与应用程序打包并在应用程序安装时将其安装在内部存储上,请assets在您的项目src/main文件夹中创建一个文件夹(例如,c:\myapp\app\src\main\assets\),并将.csv文件放在那里,然后在您的活动中像这样引用它:

String csvfileString = this.getApplicationInfo().dataDir + File.separatorChar + "csvfile.csv"
File csvfile = new File(csvfileString);

回答by Rohan

The following snippet reads a CSV file from the rawresources folder (which will be packed into your .apkfile upon compilation).

以下代码段从raw资源文件夹中读取一个 CSV 文件(.apk编译时将打包到您的文件中)。

Android by default does not create the rawfolder. Create a raw folder under res/rawin your project and copy your CSV File into it. Keep the name of the CSV file lower case and convert it into text format when asked. My CSV file name is welldata.csv.

Android 默认不创建raw文件夹。res/raw在您的项目下创建一个原始文件夹并将您的 CSV 文件复制到其中。保持 CSV 文件的名称小写,并在询问时将其转换为文本格式。我的 CSV 文件名是welldata.csv.

In the snippet, WellDatais the model class (with constructor, getter and setter) and wellDataListis the ArrayListto store the data.

在代码片段中,WellData是模型类(带有构造函数、getter 和 setter)并且wellDataListArrayList存储数据的 。

private void readData() {
    InputStream is = getResources().openRawResource(R.raw.welldata);
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(is, Charset.forName("UTF-8")));
    String line = "";

    try {
        while ((line = reader.readLine()) != null) {
           // Split the line into different tokens (using the comma as a separator).
            String[] tokens = line.split(",");

            // Read the data and store it in the WellData POJO.
            WellData wellData = new WellData();
            wellData.setOwner(tokens[0]);
            wellData.setApi(tokens[1]);
            wellData.setLongitude(tokens[2]);
            wellData.setLatitude(tokens[3]);
            wellData.setProperty(tokens[4]);
            wellData.setWellName(tokens[5]);
            wellDataList.add(wellData);

            Log.d("MainActivity" ,"Just Created " + wellData);
        }
    } catch (IOException e1) {
        Log.e("MainActivity", "Error" + line, e1);
        e1.printStackTrace();
    }
}

回答by Sanzhar Askaruly

Here is a simple way, which worked for me.

这是一个简单的方法,对我有用。

MainActivity.java

主活动.java

// Do not forget to call readWeatherData() in onCreate or wherever you need to :)

// Defining ordered collection as WeatherSample class
private List<WeatherSample> weatherSamples = new ArrayList<>();

private void readWeatherData() {
    // Read the raw csv file
    InputStream is = getResources().openRawResource(R.raw.data);

    // Reads text from character-input stream, buffering characters for efficient reading
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(is, Charset.forName("UTF-8"))
    );

    // Initialization
    String line = "";

    // Initialization
    try {
        // Step over headers
        reader.readLine();

        // If buffer is not empty
        while ((line = reader.readLine()) != null) {
            Log.d("MyActivity","Line: " + line);
            // use comma as separator columns of CSV
            String[] tokens = line.split(",");
            // Read the data
            WeatherSample sample = new WeatherSample();

            // Setters
            sample.setMonth(tokens[0]);
            sample.setRainfall(Double.parseDouble(tokens[1]));
            sample.setSumHours(Integer.parseInt(tokens[2]));

            // Adding object to a class
            weatherSamples.add(sample);

            // Log the object
            Log.d("My Activity", "Just created: " + sample);
        }

    } catch (IOException e) {
        // Logs error with priority level
        Log.wtf("MyActivity", "Error reading data file on line" + line, e);

        // Prints throwable details
        e.printStackTrace();
    }
}

WeatherSample.java

天气样本.java

public class WeatherSample {
private String month;
private double rainfall;
private int sumHours;

public String getMonth() {
    return month;
}

public void setMonth(String month) {
    this.month = month;
}

public double getRainfall() {
    return rainfall;
}

public void setRainfall(double rainfall) {
    this.rainfall = rainfall;
}

public int getSumHours() {
    return sumHours;
}

public void setSumHours(int sumHours) {
    this.sumHours = sumHours;
}

@Override
public String toString() {
    return "WeatherSample{" +
            "month='" + month + '\'' +
            ", rainfall=" + rainfall +
            ", sumHours=" + sumHours +
            '}';
}

}

}

As for your source CSV file, first create directory:
app -> res (Right click) -> New -> Android resource directory -> Resource type (raw) -> OK

至于你的源 CSV 文件,首先创建目录:
app -> res(右键单击)-> New -> Android 资源目录 -> Resource type (raw) -> OK

Then copy and paste your .csv file into that newly appeared directory:
raw (Right click) -> Show in Explorer

然后将您的 .csv 文件复制并粘贴到新出现的目录中:
raw(右键单击)-> 在资源管理器中显示

Here is the source file I used for the project:
data.csv

这是我用于项目的源文件:
data.csv

If you still have some error, here is a link to the full project:
Source Code

如果你仍然有一些错误,这里是完整项目的链接:
源代码

Hope it helps, have fun :)

希望它有帮助,玩得开心:)

回答by Mark Bowman

New coder for Android Studio. I've been researching how to read CSV files and this works best for my needs. (s0, s1, etc. Strings were defined at the beginning of my program).

Android Studio 的新编码器。我一直在研究如何读取 CSV 文件,这最适合我的需求。(s0、s1 等。字符串是在我的程序开始时定义的)。

    File fileDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
    File fileToGet = new File(fileDirectory,"aFileName.csv");
        try {
            BufferedReader br = new BufferedReader(new FileReader(fileToGet));
            String line;
            while ((line = br.readLine()) !=null) {
                String[] tokens = line.split(",");
                s0=tokens[0].toString(); s1=tokens[1].toString(); s2=tokens[2].toString();
                s3=tokens[3].toString(); s4=tokens[4].toString(); s5=tokens[5].toString();
                                                  }
            }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

回答by wazawoo

This worked for me in Kotlin. You will need to place the myfile.csv file in the res/raw folder, creating it if it isn't there.

这在 Kotlin 中对我有用。您需要将 myfile.csv 文件放在 res/raw 文件夹中,如果不存在则创建它。

val inputStream: InputStream = resources.openRawResource(R.raw.myfile)
val reader = BufferedReader(InputStreamReader(inputStream, Charset.forName("UTF-8")))
reader.readLines().forEach {

    //get a string array of all items in this line
    val items = it.split(",")

    //do what you want with each item
}