– Bài tập này Tôi sẽ hướng dẫn các bạn cách xử lý tập tin trong Android, bao gồm:

+ Internal Storage

+ External Storage

+ Saving Cache Files

– Các bạn chú ý là Android sử dụng cấu trúc tập tin giống như trong ứng dụng Java thuần túy.

– Tập tin trong Android có thể được lưu trữ trong Main Memory (thường là lưu trữ tập tin có dung lượng nhỏ) hoặc SD Card (thường là lưu trữ tập tin có dung lượng lớn).

– Các tập tin được lưu trữ cùng với các tài nguyên khác trong bộ nhớ trong (chẳng hạn như Icons, hình ảnh, nhạc,…) thì người ta gọi chung là Resource Files.

– Trên mạng có đầy rẫy website hướng dẫn về thao tác với tập tin trong Android, nhưng ở đây Tôi muốn trình bày theo cách của Tôi.

1) Internal Storage

– Ở đây có 2 trường hợp:

– Thứ nhất: đọc Resource File (Read only)

– Thứ nhì : đọc và ghi tập tin (Read & Write).

* Đọc Resource File:

– Bạn xem giao diện bên dưới: Tôi tạo 1 tập tin và nhập đại vào một số dữ liệu rồi kéo thả tập tin đó vào thư mục drawable. Nếu như ứng dụng của bạn không có thư mục này thì bạn tự tạo nó nhớ là viết y xì “drawable“, tên file cũng đừng để khoảng trắng, đừng để chữ số đằng trước.

28_file_0– Khi nhấn chọn “Read Data“, chương trình sẽ đọc nội dung từ myfile.txt và hiển thị lên EditText.

– Ở đây Tôi muốn hỏi các bạn là : “Tại sao các resource được đóng gói trong APK lại là Read Only?“. Tôi nghĩ câu trả lời đơn giản nhất đó là sử dụng tối ưu bộ nhớ. Vì điện thoại không giống như máy tính, bộ nhớ trong của nó không có bao la bát ngát như PC, mỗi phần mềm (.APK) được cài đặt vào thì nó sẽ không muốn “Co Giãn” dung lượng vì nó cần quản lý phần mềm để tối ưu nhất (sử dụng bộ nhớ ít nhất).

– Bạn xem cấu trúc XML của giao diện (activity_main.xml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >
<Button
 android:id="@+id/btnreaddata"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Read Data" />
<EditText
 android:id="@+id/editdata"
 android:layout_width="match_parent"
 android:layout_height="0dip"
 android:layout_weight="2"
 android:ems="10"
 android:gravity="top|left"
 android:inputType="textMultiLine" >
<requestFocus />
 </EditText>

– Đây là source code để đọc Resource File:

– Bạn chỉ cần copy đoạn code này vào sự kiện của nút đọc là xong:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void readData()
 {
 String data;
 InputStream in= getResources().openRawResource(R.drawable.myfile);
 InputStreamReader inreader=new InputStreamReader(in);
 BufferedReader bufreader=new BufferedReader(inreader);
 StringBuilder builder=new StringBuilder();
 if(in!=null)
 {
 try
{
 while((data=bufreader.readLine())!=null)
 {
 builder.append(data);
 builder.append("\n");
 }
 in.close();
 editdata.setText(builder.toString());
}
 catch(IOException ex){
 Log.e("ERROR", ex.getMessage());
 }
}
}

– Ở đây Tôi không cung cấp source nguồn, vì nó chỉ có 1 hàm xí xi đó. Các bạn chỉ cần thiết kế giao diện cho giống như XML Layout rồi copy code vào sự kiện của nút nhấn là xong.

– Cách đọc tập tin trong Android y chang như trong Java thuần túy, ở đây bạn chỉ để ý dòng lệnh số 4:

InputStream in= getResources().openRawResource(R.drawable.myfile);

Dòng lệnh này để đọc Resource File và trả về InputStream. Khi có InputStream rồi thì mọi xử lý sẽ giống như Java.

* Đọc và ghi tập tin:

– Trường hợp này bạn kéo thả tập tin vào cấu trúc thư mục như hình bên dưới (dùng DDMS):

– Nhìn vào những vệt Tôi tô màu vàng, các bạn kéo thả vào đúng vị trí ứng dụng của bạn.

28_file_1

– XML Resource cho bài tập này:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >
<Button
 android:id="@+id/btnreaddata"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Read Data" />
<EditText
 android:id="@+id/editdata"
 android:layout_width="match_parent"
 android:layout_height="0dip"
 android:layout_weight="2"
 android:ems="10"
 android:gravity="top|left"
 android:inputType="textMultiLine" >
<requestFocus />
 </EditText>
<Button
 android:id="@+id/btnwritedata"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Write Data" />
</LinearLayout>

– XML resource trên sẽ tạo giao diện như hình bên dưới:

28_file_2

– Source Activity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package tranduythanh.com;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity implements OnClickListener{
Button btnread,btnwrite;
 EditText editdata;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 btnread=(Button) findViewById(R.id.btnreaddata);
 btnwrite=(Button) findViewById(R.id.btnwritedata);
 editdata=(EditText) findViewById(R.id.editdata);
 btnread.setOnClickListener(this);
 btnwrite.setOnClickListener(this);
 }
 public void onClick(View v) {
 if(v.getId()==R.id.btnreaddata)
 {
 readData();
 }
 else if(v.getId()==R.id.btnwritedata)
 {
 writeData();
 }
 }
 /**
 * Hàm đọc tập tin trong Android
 * Dùng openFileInput trong Android để đọc
 * ra FileInputStream
 */
 public void readData()
 {
 try {
 FileInputStream in= openFileInput("myfile.txt");
 BufferedReader reader=new
 BufferedReader(new InputStreamReader(in));
 String data="";
 StringBuilder builder=new StringBuilder();
 while((data=reader.readLine())!=null)
 {
 builder.append(data);
 builder.append("\n");
 }
 in.close();
 editdata.setText(builder.toString());
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 /**
 * Hàm ghi tập tin trong Android
 * dùng openFileOutput để ghi
 * openFileOutput tạo ra FileOutputStream
 */
 public void writeData()
 {
 try {
 FileOutputStream out=
 openFileOutput("myfile.txt",0);
 OutputStreamWriter writer=
 new OutputStreamWriter(out);
 writer.write(editdata.getText().toString());
 writer.close();
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 /*
 * hàm này là đọc Resource File, Tôi gom chung vào đây
 */
 public void readData2()
 {
 String data;
 InputStream in= getResources()
 .openRawResource(R.drawable.myfile);
 InputStreamReader inreader=new InputStreamReader(in);
 BufferedReader bufreader=new BufferedReader(inreader);
 StringBuilder builder=new StringBuilder();
 if(in!=null)
 {
 try{
 while((data=bufreader.readLine())!=null)
 {
 builder.append(data);
 builder.append("\n");
 }
 in.close();
 editdata.setText(builder.toString());
 }
 catch(IOException ex){
 Log.e("ERROR", ex.getMessage());
 }
 }
 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }
}

– Bạn nhìn vào dòng lệnh 52: FileInputStream in= openFileInput(“myfile.txt”);

Lệnh ở dòng này mở tập tin lên để đọc, nó trả về FileInputStream nên mọi thứ sẽ giống như Java thuần túy.

– Tiếp tục nhìn vào dòng lệnh 78: FileOutputStream out=openFileOutput(“myfile.txt”,0);

Lệnh ở dòng này mở tập tin lên để ghi. đối số thứ 2 Tôi để là số 0 (MODE_PRIVATE) là mặc định. Bạn có thể dùng MODE_APPENDMODE_WORLD_READABLE,MODE_WORLD_WRITEABLE. Ý nghĩa của mỗi mode bạn có thể lên mạng tìm. Hoặc chỉ cần di chuyển chuột vào hàm trên là eclipse tự giải thích cho các bạn (nếu eclipse bạn đã cài Javadoc).

– Bạn tải source code mẫu phần này ở đây:

http://www.mediafire.com/download/toi0ht8ht0t5gd3/LearnFileInternalStorage.rar

2. External Storage:

– Phần này Tôi muốn hướng dẫn các bạn cách tương tác với tập tin được lữu trữ trên SD Card.

– Để thao tác được trên SD Card, bạn phải cấp quyền cho ứng dụng (uses – permission)

– Để vừa ghi vừa đọc trên SD Card thì ta phải sử dụng 2 permission bên dưới trongAndroidManifest:

<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />
<uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” />

– Để lấy được đường dẫn của SD Card ta dùng lệnh:

String sdcard=Environment.getExternalStorageDirectory().getAbsolutePath();

– Sau đó mọi thứ tương tác với tập tin thì y xì như Java thuần túy, ở đây Tôi dùng Scanner để đọc và OutputStreamWriter để ghi.

– Vì vậy giao diện Tôi làm y chang như Internal Storage:

– Bạn tạo Project và kéo thả tập tin vào SD card (dĩ nhiên khi tạo AVD thì bạn phải checked vào using SD card thì mới có). Bạn xem hình để biết cách kéo thả vào SD Card:

28_file_3

– Ở hình trên bạn vào DDMS, tới thư mục mnt/ chọn sdcard. Phải chọn cho đúng vì nó có nhiều thư mục cùng tên sdcard, nhưng bạn chọn sdcard ở trong thư mục mnt thôi. Sau đó kéo thả tập tin vào đây là xong.

– XML Resource y xì như phần internal Storage nên Tôi không đưa vào đây, bạn xem Source code Activity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package tranduythanh.com;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity implements OnClickListener{
Button btnread,btnwrite;
 EditText editdata;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 btnread=(Button) findViewById(R.id.btnreaddata);
 btnwrite=(Button) findViewById(R.id.btnwritedata);
 editdata=(EditText) findViewById(R.id.editdata);
 btnread.setOnClickListener(this);
 btnwrite.setOnClickListener(this);
 }
 public void onClick(View v) {
 if(v.getId()==R.id.btnreaddata)
 {
 readData();
 }
 else if(v.getId()==R.id.btnwritedata)
 {
 writeData();
 }
 }
 /*
 * đọc từ SD Card
 * Environment.getExternalStorageDirectory().getAbsolutePath()
 * để lấy đường dẫn trên SD Card
 */
 public void readData()
 {
 String sdcard=Environment
 .getExternalStorageDirectory()
 .getAbsolutePath()+"/myfile.txt";
 try {
 Scanner scan=new Scanner(new File(sdcard));
 String data="";
 while(scan.hasNext())
 {
 data+=scan.nextLine()+"\n";
 }
 scan.close();
 editdata.setText(data+"");
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 }
 }
 /**
 * ghi tập tin trên SD Card
 */
 public void writeData()
 {
 String sdcard=Environment
 .getExternalStorageDirectory()
 .getAbsolutePath()+"/myfile.txt";
 try {
 OutputStreamWriter writer=
 new OutputStreamWriter(
 new FileOutputStream(sdcard));
 writer.write(editdata.getText()+"");
 writer.close();
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }
}

– Vì có sử dụng Permission nên bạn xem AndroidManifest:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="utf-8"?>
 package="tranduythanh.com"
 android:versionCode="1"
 android:versionName="1.0" >
<uses-sdk
 android:minSdkVersion="14"
 android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
 android:allowBackup="true"
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/AppTheme" >
 <activity
 android:name="tranduythanh.com.MainActivity"
 android:label="@string/app_name" >
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>
 </application>
</manifest>

– Khi thực thi ứng dụng, bạn sẽ có giao diện như trình bày ở trên, với kết quả như mong muốn.

– Bạn có thể tải coding mẫu ở đây:

http://www.mediafire.com/download/1ydvjc8wvizzjcm/LearnFileExternalStorage.rar

3) Saving cache files:

– Lợi ích của cache files là gì? Để tăng tốc độ xử lý của ứng dụng khi bạn thường xuyên truy cập internet thì bạn nên lưu cache.

– Khi lưu cache thì nó sẽ để ở đâu trong điện thoại? bạn xem hình:

28_file_4

– Khi lưu cache thì mặc định nó sẽ lưu vào thư mục cache như hình bên trên. Hình trên Tôi có tập tin tên là myCachefile.Cache.

– Lưu như thế nào? và xóa như thế nào?

Khi bạn lưu cache, Android thường chỉ cho tối đa file cache là 1MB, khi bạn gỡ bỏ phần mềm thì nó cũng tự động xóa cache của phần mềm này đi.

– Để lấy được đường dẫn của thư mục Cache trong ứng dụng, ta dùng lệnh : getCacheDir() . Sau đó cách lưu cache tương tự như Java thuần túy.

– Dưới đây là phần mềm minh họa Cache, giao diện tương tự như trên:

– XML resource:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/LinearLayout1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 tools:context=".MainActivity" >
<Button
 android:id="@+id/btncreatecache"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Create Cache" />
<EditText
 android:id="@+id/editdata"
 android:layout_width="match_parent"
 android:layout_height="0dip"
 android:layout_weight="2"
 android:ems="10"
 android:gravity="top|left"
 android:inputType="textMultiLine" >
<requestFocus />
 </EditText>
<Button
 android:id="@+id/btnreadcache"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Read Cache" />
</LinearLayout>

– Xử lý code Activity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package tranduythanh.com;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity implements OnClickListener{
Button btncreatecache,btnreadcache;
 EditText editdata;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 btncreatecache=(Button) findViewById(R.id.btncreatecache);
 btnreadcache=(Button) findViewById(R.id.btnreadcache);
 editdata =(EditText) findViewById(R.id.editdata);
 btncreatecache.setOnClickListener(this);
 btnreadcache.setOnClickListener(this);
 }
@Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }
@Override
 public void onClick(View v) {
 // TODO Auto-generated method stub
 if(v.getId()==R.id.btncreatecache)
 {
 createCache();
 }
 else if(v.getId()==R.id.btnreadcache)
 {
 readCache();
 }
 }
 /**
 * Lấy toàn bộ file cache
 */
 public void loadAllCache()
 {
 File pathCacheDir = getCacheDir();
 File []listCache= pathCacheDir.listFiles();
 for(File f :listCache)
 {
 //process f here
 f.delete();
 }
 }
 /**
 * đọc cache file
 * getCacheDir() trả về đúng thư mục cache
 */
 public void readCache() {
 try {
 File pathCacheDir = getCacheDir();
 String strCacheFileName = "myCacheFile.cache";
 File newCacheFile = new
 File(pathCacheDir, strCacheFileName);
 Scanner sc=new Scanner(newCacheFile);
 String data="";
 while(sc.hasNext())
 {
 data+=sc.nextLine()+"\n";
 }
 editdata.setText(data);
 sc.close();
 } catch (FileNotFoundException e) {
 e.printStackTrace();
 }
 }
 /**
 * Lưu cache file
 */
 public void createCache()
 {
 try {
 File pathCacheDir = getCacheDir();
 String strCacheFileName = "myCacheFile.cache";
 String strFileContents = editdata.getText()+"";
 File newCacheFile = new
 File(pathCacheDir, strCacheFileName);
 newCacheFile.createNewFile();
 FileOutputStream foCache =
 new FileOutputStream(
 newCacheFile.getAbsolutePath());
 foCache.write(strFileContents.getBytes());
 foCache.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
}

– Vì giao diện và cách chạy tương tự như ví dụ trước nên Tôi không chụp hình minh họa,

– Bạn có thể tải coding mẫu ở đây: http://www.mediafire.com/download/u0smn6v68xf6uc5/LearnCacheFile.rar

– Như vậy tôi đã giới thiệu xong tương tác tập tin trong Android: internal Storage, external storage, caching file

– Trong bài tập kế tiếp Tôi sẽ hướng dẫn các bạn cách tương tác với XML file trong Android, trong bài tập này Tôi muốn trình bày về 2 kỹ thuật duyệt tập tin XML đó là : DOM và SAX. Tôi thấy nó rất hay, các bạn nên chú ý theo dõi

Nguồn: http://duythanhcse.wordpress.com/category/l%E1%BA%ADp-trinh-android/