2010-05-22 76 views
28

Có thể lấy tệp csv được lưu trữ trong thư mục res/raw resource và sử dụng nó để điền bảng trong cơ sở dữ liệu sqlite3 không? Tôi nghĩ rằng, nếu có một cách để thực hiện nhập khẩu số lượng lớn cho toàn bộ tệp vào bảng thì nó sẽ sạch hơn và nhanh hơn lặp lại trên mỗi dòng trong tệp và thực hiện các câu lệnh chèn riêng lẻ ...Điền vào cơ sở dữ liệu Android Từ tệp CSV?

tôi đã phát hiện ra rằng có một lệnh nhập khẩu sqlite cho phép này: How to import load a .sql or .csv file into SQLite?

... nhưng tôi đang gặp rắc rối áp dụng các báo cáo trong ứng dụng Android của tôi. Ý nghĩ đầu tiên của tôi là thử một số thứ như sau ... nhưng không may mắn:

db.execSQL("CREATE TABLE " + TABLE_NAME + "(id INTEGER PRIMARY KEY, name TEXT)"); 
db.execSQL(".mode csv"); 
db.execSQL(".import res/raw/MyFile.csv " + TABLE_NAME); 

Điều này có thể?

Tôi có nên thử cách tiếp cận khác để điền cơ sở dữ liệu của mình không?

CẬP NHẬT: Tôi đánh dấu phản ứng của Josef là câu trả lời (chèn hàng loạt bằng giao dịch) vì nó hoạt động tốt và trả lời trực tiếp câu hỏi của tôi dựa trên tiêu đề của tôi (cảm ơn Josef). Tuy nhiên, tôi vẫn đang tìm cách chèn hàng loạt trong ứng dụng Android từ tệp csv vào bảng sqlite3 bằng cách sử dụng câu lệnh nhập. Nếu bạn biết làm thế nào để làm điều này xin vui lòng trả lời.

Cảm ơn câu trả lời của bạn!

Trả lời

30

Nếu bạn muốn gói dữ liệu tĩnh với ứng dụng của mình, tôi khuyên bạn nên chuẩn bị cơ sở dữ liệu vào thời gian phát triển (sử dụng bất kỳ lệnh UI hoặc csv-import nào bạn thích) và vận chuyển tệp sqlite bên trong thư mục nội dung. Sau đó bạn có thể chỉ cần sao chép toàn bộ tệp sqlite vào thiết bị khi ứng dụng của bạn lần đầu tiên chạy. Theseposts đưa bạn qua ý tưởng này rất có thể là cách nhanh nhất để thiết lập cơ sở dữ liệu (tốc độ sao chép tệp).

Nếu vì một số lý do bạn cần chèn nhiều dữ liệu vào thời gian chạy, tôi khuyên bạn nên xem xét cách bulk insert using transactions để tăng tốc.

+0

Cảm ơn bạn đã trả lời Josef, tôi đã cố gắng gửi tệp sqlite3 .db trong thư mục nội dung của tệp .apk (như bản phác thảo bài đăng reigndesign). Vấn đề tôi gặp phải với giải pháp thiết kế lại là onUpgrade() không được gọi khi phiên bản cơ sở dữ liệu của tôi # thay đổi.Trong thực tế, cách duy nhất tôi có thể làm cho nó thay thế cơ sở dữ liệu hiện có bằng một phiên bản mới hơn là làm việc xung quanh onUpgrade() và thêm một câu lệnh xóa cơ sở dữ liệu ngay trước khi createDataBase() gọi cơ bản tạo lại cơ sở dữ liệu mỗi khi Activity chạy ... = ( – MoMo

+0

Đối với việc sử dụng các giao dịch có thể là giải pháp khả thi.Tôi có thể nhận được onUpgrad() để gọi tính nhất quán khi triển khai giải pháp này (http: // www .screaming-penguin.com/node/7742) nhưng một câu lệnh nhập sql đơn giản vẫn lý tưởng xem xét việc nâng cấp và tinh chỉnh cần thiết để có giải pháp reigndesign để làm việc (tức là cột '_id' và bảng 'android_metadata'). tinh chỉnh không khó thực hiện Tôi sợ nó thêm phụ thuộc không cần thiết vào nền tảng Android mong đợi cơ sở dữ liệu của họ được tạo ra như thế nào.Nếu có thay đổi để giải pháp của chúng tôi ... – MoMo

+3

Vận chuyển với một tệp sqlite3 được dựng sẵn e là KHÔNG thực hành tốt. Các nhà sản xuất có thể thực hiện/sử dụng bất kỳ công nghệ nào họ muốn theo mui xe nhưng phải tuân thủ các giao diện sqlite3 - vì vậy, sqlite3 dựng sẵn của bạn có thể không hoạt động trên một số thiết bị. Vì vậy, thực hành tốt nhất/an toàn nhất là luôn để thiết bị của bạn tạo cơ sở dữ liệu, sau đó nhập số lượng lớn vào cơ sở dữ liệu đó. – straya

14

Tôi đã dành rất nhiều thời gian tìm kiếm một giải pháp đơn giản và đã tự mình tạo ra một chút mã. Đối với những người tương lai tìm kiếm này giống như tôi là bạn có thể sử dụng này:

BufferedReader in = new BufferedReader(your csv file source here); 
String reader = ""; 
while ((reader = in.readLine()) != null){ 
    String[] RowData = reader.split(","); 
    date = RowData[0]; 
    value = RowData[1]; 
    ContentValues values = new ContentValues(); 
    values.put(CsvProvider.DATE, date); 
    values.put(CsvProvider.VALUE, value); 
    getContentResolver().insert(CsvProvider.CONTENT_URI, values); 
} 
in.close(); 

tập tin CSV My không có tiêu đề và chỉ có 2 cột nhưng hơn hai cột không phải là một vấn đề. Chỉ cần nhớ để xác định những gì được chia tách các cột của bạn và cho mỗi cột thêm một RowData[#] (bạn phải bắt đầu với 0). Bạn muốn chắc chắn rằng bất cứ điều gì bạn sẽ làm với mỗi dòng được thực hiện trước khi bạn gọi in.close(). Tôi đang sử dụng một nhà cung cấp nội dung nhưng bạn thực sự có thể làm bất cứ điều gì bạn muốn với dữ liệu như thêm nó vào một String[] hoặc bất cứ điều gì khác.

Trong khi tôi đang sử dụng luồng đầu vào, bạn có thể trỏ BufferedReader đến bất cứ nơi nào bạn muốn. Miễn là BufferedReader có thể đọc nó thì nó sẽ hoạt động.

+0

không hoạt động với "|" Dấu phân cách ...? – kthorat

+1

mà seperator là một nỗi đau. Tôi không biết tại sao mọi người sử dụng nó để bắt đầu. Tôi đang cố gắng loại bỏ nó khỏi một tập tin và nó chỉ ở lại. Có cách nào để sử dụng dấu phẩy hoặc ký tự khác hoặc là từ một số máy chủ web ở đâu đó? – Opy

+0

Nope .. nó phải là "|", vì có 700-800k hồ sơ và Im sử dụng "," như dữ liệu ..: (.. anyways tôi đã nhận nó làm việc ... Tôi đã sử dụng StringTokenizer cho tách .. vẫn im thậm chí không gần để giải quyết vấn đề .. Tôi đã chia tập tin thành 1mb mỗi .. Im sử dụng AsyncTask và có thể chèn 5k hồ sơ .. bộ đệm là phá vỡ sau đó ... đó là kỳ lạ nó thực sự dài chỉ để sao chép và tạo db. ..Tôi chưa bắt đầu làm việc trên ứng dụng ... :( – kthorat

Các vấn đề liên quan