web-dev-qa-db-fra.com

Lecture de fichier CSV dans une application Android

Je travaille sur une application de validation de principe afin de pouvoir implémenter cette fonctionnalité dans une application plus grande que je suis en train de créer. Je suis un peu nouveau sur Java et Android Dev, mais j'espère que cela ne devrait pas être une question trop simple ou complexe.

En gros, j'essaie de lire une liste de chaînes à partir d'un fichier CSV et de le rendre utilisable pour afficher la liste sur l'activité principale de l'application.

J'utilise une classe externe pour lire en CSV. Voici le code de la classe:

CSVFile.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;
    }
}

Voici mon code d'activité principale:

MainActivity.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);

    }

}

Je ne suis pas encore sur le point de définir le tableau mobileArray. En ce moment, j'essaye juste d'extraire les informations de l'objet List myList ...

Quelqu'un peut-il m'expliquer comment cela est fait? Peut-être que je ne comprends pas tout à fait le type de liste. Il semble que lorsque resultList est renvoyé dans la méthode de lecture CSVFile, il est renvoyé sous forme d'objet List composé d'objets de tableau String. Mais je n'arrive pas à le faire fonctionner comme ça.

Toute aide est appréciée!

FINAL EDIT (code de travail)

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

    }

MODIFIER

Maintenant, ma fonction prepArray ressemble à ceci:

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

    }

Produit toujours l’exception FileNotFoundException.

EDIT 2/3

Voici le journal généré lorsque je lance l'application sur un téléphone réel avec strings.csv dans un sous-dossier de chaînes (src\main\assets\strings\strings.csv) avec la modification que vous avez demandée au code:

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.access$700(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
8
TheBlindDeveloper

Essayez OpenCSV - cela vous facilitera la vie.

Tout d’abord, ajoutez ce paquet à vos dépendances gradle comme suit

compile 'com.opencsv:opencsv:3.9'

Ensuite, vous pouvez soit faire

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) {

}

ou

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

Editer après le commentaire

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

Si vous souhaitez conditionner le fichier .csv avec l'application et l'installer sur le stockage interne lors de l'installation de l'application, créez un dossier assets dans votre dossier project src/main (par exemple, c:\myapp\app\src\main\assets\) et insérez-y le fichier .csv, puis faites référence comme ça dans ton activité:

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

L'extrait suivant lit un fichier CSV à partir du dossier raw resources (qui sera compressé dans votre fichier .apk lors de la compilation). 

Android par défaut ne crée pas le dossier raw. Créez un dossier brut sous res/raw dans votre projet et copiez-y votre fichier CSV. Conservez le nom du fichier CSV en minuscule et convertissez-le au format texte à la demande. Mon nom de fichier CSV est welldata.csv.

Dans l'extrait, WellData est la classe de modèle (avec constructeur, getter et setter) et wellDataList est la ArrayList pour stocker les données.

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

Nouveau codeur pour Android Studio. J'ai recherché comment lire les fichiers CSV et cela répond le mieux à mes besoins. (s0, s1, etc. Les chaînes ont été définies au début de mon programme).

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

Voici un moyen simple, qui a fonctionné pour moi.

MainActivity.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

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 +
            '}';
}

}

En ce qui concerne votre fichier CSV source, commencez par créer un répertoire:
app -> res (clic droit) -> Nouveau -> Répertoire des ressources Android -> Type de ressource (raw) -> OK 

Ensuite, copiez et collez votre fichier .csv dans ce nouveau répertoire:
raw (clic droit) -> Afficher dans l'explorateur

Voici le fichier source que j'ai utilisé pour le projet:
data.csv

Si vous avez encore des erreurs, voici un lien vers le projet complet:
Code source

J'espère que ça aide, amusez-vous :)

0
Sanzhar Askaruly