如何在 Android Studio 中将 CSV 文件解析为数组

Posted

技术标签:

【中文标题】如何在 Android Studio 中将 CSV 文件解析为数组【英文标题】:How to parse CSV file into an array in Android Studio 【发布时间】:2016-11-19 19:39:36 【问题描述】:

我想知道如何解析 CSV 文件并将内容存储到数组中。我的 csv 文件看起来像这样:

1,bulbasaur,1,7,69,64,1,1
2,ivysaur,2,10,130,142,2,1

我只想要名字,所以第二个字段。我想将 csv 中的所有这些项目存储到字符串的数组或数组列表中。

任何想法如何做到这一点?

任何帮助将不胜感激!

【问题讨论】:

【参考方案1】:

将 CSV 文件放在 Android 中的什么位置 在“res”文件夹中创建一个名为“raw”的文件夹,并将 CSV 文件放入其中。

如何读取 CSV 文件, 自从它的android以来没有什么特别的。我们将使用我们的标准 Java 代码。最好使用我们自己的代码而不是使用 API。下面的类是一个读取 CSV 文件的实用程序,它可以在 Android 应用程序中使用。 我们将在哪个数组中存储 csv 文件的项目 在这些示例中,它是 scorelist arraylist 。

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

那么如何从“raw”文件夹中加载 CSV 文件并使用上述工具读取呢?

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

MainActivity.java

public class MainActivity extends Activity 
    private ListView listView;
    private ItemArrayAdapter itemArrayAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listView = (ListView) findViewById(R.id.listView);
        itemArrayAdapter = new ItemArrayAdapter(getApplicationContext(), R.layout.item_layout);

        Parcelable state = listView.onSaveInstanceState();
        listView.setAdapter(itemArrayAdapter);
        listView.onRestoreInstanceState(state);

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

        for(String[] scoreData:scoreList ) 
            itemArrayAdapter.add(scoreData);
        
    

ItemArrayAdapter.java

public class ItemArrayAdapter extends ArrayAdapter 
    private List scoreList = new ArrayList();

    static class ItemViewHolder 
        TextView name;
        TextView score;
    

    public ItemArrayAdapter(Context context, int textViewResourceId) 
        super(context, textViewResourceId);
    

    @Override
    public void add(String[] object) 
        scoreList.add(object);
        super.add(object);
    

    @Override
    public int getCount() 
        return this.scoreList.size();
    

    @Override
    public String[] getItem(int index) 
        return this.scoreList.get(index);
    

    @Override
    public View getView(int position, View convertView, ViewGroup parent) 
        View row = convertView;
        ItemViewHolder viewHolder;
        if (row == null) 
            LayoutInflater inflater = (LayoutInflater) this.getContext().
                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = inflater.inflate(R.layout.item_layout, parent, false);
            viewHolder = new ItemViewHolder();
            viewHolder.name = (TextView) row.findViewById(R.id.name);
            viewHolder.score = (TextView) row.findViewById(R.id.score);
            row.setTag(viewHolder);
         else 
            viewHolder = (ItemViewHolder)row.getTag();
        
        String[] stat = getItem(position);
        viewHolder.name.setText(stat[0]);
        viewHolder.score.setText(stat[1]);
        return row;
    

activity_mail.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    tools:context="com.javapapers.android.csvfileread.app.MainActivity">
    <ListView
        android:layout_
        android:layout_
        android:id="@+id/listView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="10dp" />
</RelativeLayout>

item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_>
    <TextView
        android:layout_
        android:layout_
        android:id="@+id/name"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="20dp" />
    <TextView
        android:layout_
        android:layout_
        android:id="@+id/score"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="20dp" />
</RelativeLayout>

完整的源代码可以参考这些链接javapapers.com/wp-content/uploads/2014/07/CSVFileRead.zip

我认为这会有所帮助

【讨论】:

如果 ',' 嵌套在嵌套引号中,这会避免拆分字符串吗? 公共类 CSVFile 放在哪里?在 mainactivity.java 中? 我的 csv 文件非常大,在“scoreData”中只有 10-12 个第一行项目。 csv 文件没有新的行或内容,只是 ',' 分隔项目【参考方案2】:

更好的 CSV 解析器处理引用字段

    import android.content.Context;
    import android.widget.Toast;
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;

    public class CSVReader 
        private class StringDArray 
            private String[] data=new String[0];
            private int used=0;
            public void add(String str) 
                if (used >= data.length)
                    int new_size= used+1;
                    String[] new_data=new String[new_size];
                    java.lang.System.arraycopy( data,0,new_data,0,used);
                    data=new_data;
                
                data[used++] = str;
            
            public int length()
                return  used;
            
            public String[] get_araay()
                return data;
            
        
        private  Context context;
        public CSVReader(Context context)
            this.context=context;
        
        public List read(File file)
            List resultList = new ArrayList();
            try
                InputStream inputStream= new FileInputStream(file);
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                String csvLine;
                final char Separator = ',';
                final char Delimiter = '"';
                final char LF = '\n';
                final char CR = '\r';
                boolean quote_open = false;
                while ((csvLine = reader.readLine()) != null) 
                    //String[] row = csvLine.split(",");// simple way
                    StringDArray a=new StringDArray();
                    String token="";
                        csvLine+=Separator;
                    for(char c:csvLine.toCharArray())
                        switch (c)
                            case LF: case CR:// not required as we are already read line
                                quote_open=false;
                                a.add(token);
                                token="";
                            break;
                            case Delimiter:
                                quote_open=!quote_open;
                            break;
                            case Separator:
                                if(quote_open==false)
                                    a.add(token);
                                    token="";
                                else
                                    token+=c;
                                
                            break;
                            default:
                                token+=c;
                            break;
                        
                    
                    if(a.length()>0 ) 
                        if(resultList.size()>0)
                            String[] header_row =(String[]) resultList.get(0);
                            if(a.length()>=header_row.length) 
                                String[] row = a.get_araay();
                                resultList.add(row);
                            
                        else
                            String[] row = a.get_araay();
                            resultList.add(row);//header row
                        
                    
                
                inputStream.close();
            catch (Exception e)
                Toast.makeText(context,"Error : " + e.getMessage(), Toast.LENGTH_LONG).show();
            
            return resultList;
        
    

用法

    File file=new File(path);
    CSVReader csvReader=new CSVReader(activity.this);
    List csv=csvReader.read(file);
    if(csv.size()>0)
        String[] header_row =(String[]) csv.get(0);
        if(header_row.length>1)
            String col1=header_row[0];
            String col2=header_row[1];
        
    

    Toast.makeText(activity.this,csv.size() + " rows", Toast.LENGTH_LONG).show();

使用的样本数据 身份证、姓名 1、测试项目1 "2","测试项目 2" "3","测试,第 3 项" 4、测试项目4

【讨论】:

【参考方案3】:

免责声明:我从未使用过 Android,但我知道 Java,所以希望一切都一样。

话虽如此,你可以试试这样的。

Scanner scanner = new Scanner(new File("file.csv"));
ArrayList<String> pokemon = new ArrayList<>();
while(scanner.hasNextLine()) 
    pokemon.add(scanner.nextLine().split(",")[1]);

scanner.close();

【讨论】:

【参考方案4】:

Android 默认不创建 raw 文件夹。在项目的 res/raw 下创建 raw 文件夹。在其中复制您的 CSV 文件。将 CSV 文件的名称保持小写,并在询问时转换为文本格式。我的 CSV 文件名为 welldata.scv WellData - 它是带有 getter 和 setter 的模型类。 wellDataList 是存储数据的ArrayList。

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) 
       //set splitter
        String[] tokens = line.split(",");

        //read the data
        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();

【讨论】:

【参考方案5】:

我扩展了 Sharma 的答案,使核心类在 CSV 文件的各种条件下更加灵活。我更喜欢构建器设计模式来配置如何读取 CSV 文件。

public class CSVFile 
    private static final Charset UTF8 = Charset.forName("UTF-8");
    private final static String DEFAULT_DELIMITER = ",";

    private InputStream inputStream;
    private Charset charset;
    private String delimiter;
    private boolean ignoreHead;

    public CSVFile(InputStream inputStream) 
        this.inputStream = inputStream;
        this.charset = UTF8;
        this.delimiter = DEFAULT_DELIMITER;
        this.ignoreHead = false;
    

    public CSVFile setCharset(Charset charset) 
        this.charset = charset;
        return this;
    

    public CSVFile setDelimiter(String delimiter) 
        this.delimiter = delimiter;
        return this;
    

    public CSVFile ignoreHead() 
        ignoreHead = true;
        return this;
    

    public List<String[]> read() 
        boolean firstRow = true;
        List<String[]> resultList = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset));
        try 
            String csvLine;
            while ((csvLine = reader.readLine()) != null) 
                if (firstRow) 
                    firstRow = false;

                    if (ignoreHead) 
                        continue;
                    
                

                String[] row = csvLine.split(delimiter);
                resultList.add(row);
            
         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;
    

【讨论】:

以上是关于如何在 Android Studio 中将 CSV 文件解析为数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android Studio 中将 ListView 更改为 RecyclerView?

如何在 Android Studio Java 中将数组上传到 Firestore 数据

如何在Android Studio中将Pdf文件转换为文本

如何在 Android Studio 项目中将库添加到 Gradle 构建?

如何在 android studio 中将 .aar 文件添加到 gradle.kts?

如何在 Android Studio 中将一个 VideoView 放在另一个 VideoView 下方?