01 July 2012

การนำเข้าข้อมูลจาก .csv ลงในฐานข้อมูล

Updated on

        สำหรับการใช้ฐานข้อมูลเบื้องต้นให้อ่านจาก [Android Code] SQLite บน Android เบื้องต้น (แอบละเอียด)

        สำหรับใครที่ใช้ฐานข้อมูลเป็นภาษาไทย ให้เปลี่ยน Encoding จาก ANSI เป็น UTF-8 เพื่อแก้ปัญหาแสดงภาษาไทยเพี้ยนด้วย [Android Code] แก้ปัญหาภาษาไทยใน CSV แสดงผลเพี้ยน

        จากคราวก่อนที่เข้าของบล็อกพล่ามเรื่องฐานข้อมูลแล้ว ทีนี้การสร้างฐานข้อมูลขึ้นมาก็ต้องมีข้อมูลที่จะเอามาเก็บ ซึ่งก็แล้วแต่ว่าข้อมูลนั้นๆจะเอามาจากไหน จะให้ผู้ใช้แอพใส่ข้อมูลแล้วเก็บลงฐานข้อมูลก็ได้ หรือจะพิมใส่เตรียมไว้ก็ได้ (แบบตัวอย่างก่อนหน้า) หรือนำเข้าจากไฟล์ฐานข้อมูลต่างๆ

        ซึ่งเจ้าของบล็อกก็จะขอพูดถึงการนำเข้าข้อมูลจากไฟล์ CSV มาเก็บไว้ในฐานข้อมูลของแอพฯกัน ก่อนอื่นเลยเราก็ต้องมีไฟล์ CSV ที่จะเอามานำเข้าก่อน เจ้าของบล็อกก็เลยสร้างขึ้นมาเพื่อใช้เป็นตัวอย่าง โดยมีข้อมูลดังนี้


        ไฟล์จะชื่อว่า customerdata.csv จากนั้นก็ให้สร้างโปรเจคขึ้นมาใน Eclipse เลย แล้วเอาไฟล์ customdata.csv ใส่เข้าไปในโฟลเดอร์ assets



        ทีนี้ก็ลองอ่านค่าจากไฟล์นี้ก่อนละกัน ให้พิมคำสั่งตามนี้เลย โดยเจ้าของบล็อกจะให้แสดงข้อมูลผ่านหน้าต่าง LogCat

package app.akexorcist.databaseimportcsv;   
   
import java.io.BufferedReader;  
import java.io.IOException;   
import java.io.InputStreamReader;  
   
import android.os.Bundle;   
import android.util.Log;   
import android.app.Activity;   
   
public class Main extends Activity {   
    public void onCreate(Bundle savedInstanceState) {   
        super.onCreate(savedInstanceState);   
        setContentView(R.layout.main);   
   
        try {  
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(getAssets().open(
                    "customerdata.csv")));  
            String readLine = null;  
            try {  
                while ((readLine = br.readLine()) != null) { 
                    Log.i("Data Input", readLine);   
                }  
            } catch (IOException e) { }  
        } catch (IOException e) { }  
    }   
}  

        เริ่มจากที่คลาส BufferReader ก่อนเลยละกัน โดยคลาสที่ว่านี้เป็นคลาสสำหรับอ่านข้อมูลจากไฟล์ ซึ่งเจ้าของบล็อกกำหนดให้อ่านไฟล์ customdata.csv ที่อยู่ในส่วนของ Assets โดยใช้คำสั่ง

getAssets().open("customerdata.csv")

        มาเก็บไว้ใน InputStreamReader ก่อน แล้วเอามาเก็บใน BufferReader ต่อเลย แต่จะเห็นว่าเจ้าของบล็อกใช้คำสั่งแค่บรรทัดเดียวสร้าง InputStreamReader แล้วส่งค่าให้ BufferRead เลย ต่อมาก็ทำการสร้างตัวแปร String ขึ้นมาชื่อ readLine เอาไว้เก็บ String ของแต่ละแถว มาแสดงใน Log สำหรับการอ่าน String ในแต่ละแถว ก็จะใช้คำสั่ง

readLine =  br.readLine()

        เมื่อใช้คำสั่งนี้อีกครั้งจะเป็นการอ่านค่าในแถวต่อไปเรื่อยๆ โดยเช็คว่าค่าที่ได้เป็น null หรือป่าว ถ้าใช่ก็คืออ่านครบแล้ว จากนั้นก็จะแสดงข้อมูลผ่านหน้าต่าง LogCat ด้วยคำสั่ง

Log.i("Data Input", readLine);

        และเนื่องจากใช้ while วนรอบไปเรื่อยๆ ก็จะแสดงข้อมูล จากตัวแปร readLine ทุกๆครั้งที่มีการอ่านค่าบรรทัดใหม่จนครบ เมื่อลองทดสอบการทำงาน ก็จะเห็นว่า LogCat มีข้อความแสดงขึ้นมาเมื่อเปิดแอพ



        จะเห็นว่าข้อมูลที่ออกมาจะเป็นดังนี้

Name,Job,Age,Gender
Akito,Student,20,Male
Madeil,Student,19,Female
Henry,Engineer,32,Male
Densell,Magician,8,Male Elf

        ข้อมูลในแต่ละคอลัมน์จะถูกคั่นด้วยเครื่องหมายลูกน้ำ

        ทีนี้ก็จะเป็นการแบ่งข้อมูลไปเก็บไว้ในฐานข้อมูลกัน โดยจะใช้วิธีแบ่งข้อมูลแต่ละแถวให้เป็นแต่ละคอลัมน์ด้วยคำสั่ง

String[] str = readLine.split(",");

        ก็จะทำให้ข้อมูลแบ่งออกเป็นสี่คอลัมน์ด้วยกัน ซึ่งในแต่ละช่องก็จะมีข้อมูลดังนี้ (สมมติว่าแถวแรกสุด)

strRow[0] : Name
strRow[1] : Job
strRow[2] : Age
strRow[3] : Gender

        และเมื่อแบ่งข้อมูลครบทุกๆแถวแล้วก็จะได้ประมาณนี้



        ทีนี้ลองมาสร้างเป็นตัวอย่างจริงๆเลยละกัน ก่อนอื่นก็ต้องสร้างคลาส Database ขึ้นมาก่อน

Database.java
package app.akexorcist.databaseimportcsv;  
   
import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
  
import android.content.Context;  
import android.database.sqlite.SQLiteDatabase;  
import android.database.sqlite.SQLiteOpenHelper;  
  
class Database extends SQLiteOpenHelper {  
    private static final String DB_NAME = "My Business Data";  
    private static final int DB_VERSION = 1;  
     
    public static final String TABLE_NAME = "Customer";  
   
    public static final String COL_NAME = "name";  
    public static final String COL_JOB = "job";  
    public static final String COL_AGE = "age";  
    public static final String COL_GENDER = "gender";  
     
    Context context;  
     
    public Database(Context ctx) {  
        super(ctx, DB_NAME, null, DB_VERSION);  
        context = ctx;  
    }  
   
    public void onCreate(SQLiteDatabase db) {  
        db.execSQL("CREATE TABLE " + TABLE_NAME 
                + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, "   
                + COL_NAME + " TEXT, " + COL_JOB + " TEXT, " 
                + COL_AGE  + " INTEGER, " + COL_GENDER + " TEXT);");  
           
        try {  
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(context.getAssets().open(
                    "customerdata.csv")));  
            String readLine = null;  
            readLine = br.readLine();  

            try {  
                while ((readLine = br.readLine()) != null) {  
                    String[] str = readLine.split(",");  
                    db.execSQL("INSERT INTO " + TABLE_NAME 
                        + " (" + COL_NAME + ", " + COL_JOB 
                        + ", " + COL_AGE + ", " + COL_GENDER 
                        + ") VALUES ('" + str[0] 
                        + "', '" + str[1] + "', " + str[2] 
                        + ", '" + str[3] + "');");   
                }  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
       
    public void onUpgrade(SQLiteDatabase db, int oldVersion
            , int newVersion) {  
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);  
        onCreate(db);  
    }  
}

        คอลัมน์ของฐานข้อมูลเจ้าของบล็อกจะกำหนดชื่อเป็น name, job, age, gender ตามที่ต้องการไว้ แล้วใช้คำสั่ง

readLine = br.readLine();

        ครั้งหนึ่งก่อน เพื่อข้ามแถวแรกไปเพราะเป็นแค่ชื่อตาราง จากนั้นก็จะทำการทยอยแบ่งข้อมูลออกเป็นส่วนๆแล้วเก็บลงในฐานข้อมูล จนครบ

        ทีนี้มาที่หน้า Main.java ของเจ้าของบล็อก ก็จะกำหนดให้แสดงฐานข้อมูลที่มีอยู่ผ่าน List View

Main.java
package app.akexorcist.databaseimportcsv;  
   
import java.util.ArrayList;  
  
import android.os.Bundle;  
import android.view.Window;  
import android.widget.ArrayAdapter;  
import android.widget.ListView;  
import android.app.Activity;  
import android.database.Cursor;  
import android.database.sqlite.SQLiteDatabase;  
  
public class Main extends Activity {  
    SQLiteDatabase mDb;  
    Database mHelper;  
    Cursor mCursor;  
       
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        requestWindowFeature(Window.FEATURE_NO_TITLE);  
        setContentView(R.layout.main);  
       
        ListView listView1 = (ListView)findViewById(R.id.listView1);  
       
        mHelper = new Database(this);  
        mDb = mHelper.getWritableDatabase();  
        mHelper.onUpgrade(mDb, 1, 1);  
         
        mCursor = mDb.rawQuery("SELECT " + Database.COL_NAME + ", "   
            + Database.COL_JOB + ", " + Database.COL_AGE + ", "   
            + Database.COL_GENDER + " FROM " + Database.TABLE_NAME, null);  
         
        ArrayList<String> dirArray = new ArrayList<String>();  
        mCursor.moveToFirst();  

        while ( !mCursor.isAfterLast() ){  
            dirArray.add("Name : " + mCursor.getString
                    (mCursor.getColumnIndex(Database.COL_NAME)) + "\n" 
                    + "Job : " + mCursor.getString(mCursor.getColumnIndex
                    (Database.COL_JOB)) + "\n"  
                    + "Age : " + mCursor.getString(mCursor.getColumnIndex
                    (Database.COL_AGE)) + "\n" 
                    + "Gender : " + mCursor.getString(mCursor.getColumnIndex
                    (Database.COL_GENDER)));  
            mCursor.moveToNext();      
        }  
          
        ArrayAdapter<String> adapterDir = 
                new ArrayAdapter<String>(getApplicationContext()   
                , android.R.layout.simple_list_item_1, dirArray);  
        listView1.setAdapter(adapterDir);  
    }  
    
    public void onPause() {  
        super.onPause();  
        mHelper.close();  
        mDb.close();   
    }  
}  

        และสำหรับ main.xml เจ้าของบล็อกขอใช้เหมือนตัวอย่างที่แล้วละกัน

main.xml
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="vertical"  
    android:background="#666666" >  
    <TextView  
        android:id="@+id/textView1"  
        android:layout_width="fill_parent"  
        android:layout_height="wrap_content"  
        android:text="Customer"  
        android:textColor="#222222"  
        android:textSize="40dp"  
        android:gravity="center"  
        android:layout_marginTop="20dp" />  
    <ListView  
        android:id="@+id/listView1"  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_margin="30dp"  
        android:cacheColorHint="#00000000" />  
</LinearLayout> 

        ทีนี้ก็ลองทดสอบแอพฯดู ก็จะเห็นว่าไฟล์ CSV ได้ถูกเก็บลงบนฐานข้อมูลแล้วนำมาแสดงบน List View แล้ว




        สำหรับผู้ที่หลงเข้ามาอ่านที่จะเอาไปประยุกต์ใช้ ในตัวอย่างเจ้าของบล็อกใช้ฐานข้อมูลที่มี 4 คอลัมน์ ให้แก้ไขในส่วนของคอลัมน์ให้ตรงกับที่จะใช้ด้วย ทั้งชื่อคอลัมน์และจำนวนคอลัมน์ของข้อมูล

        สำหรับผู้ที่หลงเข้ามาอ่านที่อยากจะเอาไฟล์ตัวอย่างไปลองก็ดาวน์โหลดจากตรงนี้ได้เลย Database Import CSV [Google Drive]