File
4.1 Pengantar
C# memandang setiap file sebagai aliran
byte sekuensial. Setiap file diakhiri dengan penanda end-of-file. Ketika file dibuka, C# menciptakan sebuah objek dan
kemudian mengaitkan sebuah aliran dengan objek tersebut. Ada tiga objek aliran,
masing-masing dapat diakses lewat properti Console.Out,
Console.In, dan Console.Error. Ketiga objek tersebut memfasilitasi komunikasi
antara program dan file atau divais tertentu. Properti Console.In menghasilkan objek aliran masukan standar, yang
memampukan sebuah program untuk membaca data dari keyboard. Properti Console.Out
menghasilkan objek aliran keluaran standar, yang memampukan sebuah program
untuk menampilkan data pada monitor. Properti Console.Error menghasilkan objek aliran error standard, yang
memampukan sebuah program untuk menampilkan pesan error pada layar. Anda telah
menggunakan Console.Out dan Console.In pada beberapa aplikasi
konsol sebelumnya, dimana metode-metode Console,
Write dan WriteLine menggunakan Console.Out
dalam menampilkan keluaran, dan metode-metode Read dan ReadLine
menggunakan Console.In dalam membaca
masukan.
Untuk melakukan pemrosesan file dalam
C#, namespace System.IO harus direferensi. Namespace ini mencakup beberapa
definisi untuk kelas-kelas aliran seperti StreamReader
(untuk membaca teks dari sebuah file), StreamWriter
(untuk menulis teks ke dalam sebuah file), dan FileStream (untuk kedua pembacaan dan penulisan file). File dibuka
dengan menciptakan objek dari kelas aliran tersebut, yang mewarisi kelas MustInherit TextReader, TextWriter,
dan Stream. Sebenarnya, Console.In dan Console.Out merupakan properti dari kelas TextReader dan TextWriter.
Kedua kelas tersebut adalah MustInherit;
StreamReader dan StreamWriter adalah kelas yang
diderivasi dari kelas TextReader dan
TextWriter.
C# menyediakan kelas BinaryFormatter, yang digunakan dengan
sebuah objek Stream untuk melakukan pembacaan dan penulisan objek. Serialisasi
melibatkan konversi sebuah objek menjadi format yang dapat ditulis ke dalam
sebuah file tanpa harus kehilangan data objek. Deserialisasi memuat pembacaan
format tersebut dari sebuah file dan merekonstruksi objek asli darinya. Sebuah BinaryFormatter dapat menserialisasi
objek dan mendeserialisasi objek. Kelas System.IO.Stream
menyediakan fungsionalitas untuk merepresentasikan aliran sebagai byte. Kelas
ini adalah MustInherit, jadi
objek-objek kelas ini tidak dapat diinstansiasi. Kelas FileStream, MemoryStream,
dan BufferedStream (semua dari namespace System.IO) mewarisi kelas Stream.
4.2
Kelas File dan Kelas Directory
Informasi pada komputer disimpan dalam
file, yang diorganisasi dalam direktori. Kelas File disediakan untuk memanipulasi file, dan kelas Directory disediakan untuk memanipulasi
direktori. Kelas File tidak dapat
menulis ke atau membaca dari file secara langsung.
Perhatikan bahwa karakter separator \ memisahkan direktori dan file pada
sebuah path. Pada sistem UNIX, karakter separator adalah /. Visual Basic dapat memproses kedua karakter tersebut. Ini
berarti bahwa, jika Anda menspesifikasi path c:\C#/README, yang menggunakan kedua karakter separator tersebut,
maka C# masih bisa memproses file itu secara benar.
Gambar 4.1 mencantumkan beberapa metode
pada kelas File untuk memanipulasi
dan menentukan informasi tentang file tertentu. Kelas File hanya memuat metode-metode static, jadi Anda tidak bisa menginstansiasi objek bertipe File. Beberapa dari metode tersebut
akan dipakai dalam contoh pada Gambar 4.3.
Metode static
|
Penjelasan
|
AppendText
Copy
Create
CreateText
Delete
GetCreationTime
GetLastAccessTime
GetLastWriteTime
Move
Open
OpenRead
OpenText
OpenWrite
|
Menghasilkan sebuah StreamWriter yang dikaitkan pada sebuah file yang sudah ada atau
menciptakan sebuah file jika file yang dimaksud belum ada.
Menyalin sebuah file ke dalam file baru.
Menghasilkan sebuah FileStream yang dikaitkan dengan file yang baru saja diciptakan.
Menghasilkan sebuah StreamWriter yang dikaitkan dengan file teks baru.
Menghapus file yang diinginkan.
Menghasilkan sebuah objek DateTime yang merepresentasikan waktu ketika file diciptakan.
Menghasilkan sebuah objek DateTime yang merepresentasikan waktu ketika file terakhir kali
diakses.
Menghasilkan sebuah objek DateTime yang merepresentasikan waktu ketika file terakhir kali
dimodifikasi.
Memindahkan file tertentu ke lokasi tertentu.
Menghasilkan sebuah FileStream yang dikaitkan dengan file tertentu dan dilengkapi
dengan ijin pembacaan/penulisan.
Menghasilkan sebuah FileStream read-only yang
dikaitkan dengan file tertentu.
Menghasilkan sebuah StreamReader yang dikaitkan dengan file tertentu.
Menghasilkan sebuah FileStream read/write yang
dikaitkan dengan file tertentu.
|
Gambar 4.1 Beberapa metode static kelas File
Kelas Directory menyediakan beberapa kapabilitas untuk memanipulasi
direktori dengan .NET Framework.
Gambar 4.2 mencantumkan beberapa metode static
yang dapat dipakai untuk manipulasi direktori. Beberapa dari metode tersebut
dipakai dalam contoh pada Gambar 4.3.
Objek DirectoryInfo yang dijadikan nilai balik oleh metode CreateDirectory memuat informasi
tentang sebuah direktori. Informasi yang dimuat pada kelas ini dapat pula
diakses via metode-metode Directory.
Metode static
|
Penjelasan
|
CreateDirectory
Delete
Exists
GetLastWriteTime
GetDirectories
GetFiles
GetCreationTime
GetLastAccessTime
GetLastWriteTime
Move
|
Menghasilkan objek DirectoryInfo yang dikaitkan dengan direktori yang baru saja
diciptakan.
Menghapus direktori tertentu.
Menghasilkan True
jika direktori tertentu eksis; sebaliknya, ia menghasilkan False.
Menghasilkan sebuah objek DateTime yang merepresentasikan waktu ketika direktori tertentu
terakhir kali dimodifikasi.
Menghasilkan array String yang merepresentasikan nama-nama direktori di dalam
direktori tertentu.
Menghasilkan array String yang merepresentasikan nama-nama direktori di dalam file
tertentu.
Menghasilkan sebuah objek DateTime yang merepresentasikan waktu ketika direktori tertentu
diciptakan.
Menghasilkan sebuah objek DateTime yang merepresentasikan waktu ketika direktori tertentu
terakhir kali diakses.
Menghasilkan sebuah objek DateTime yang merepresentasikan waktu ketika item-item terakhir
kali dituliskan ke dalam direktori.
Memindahkan direktori tertentu ke lokasi tertentu.
|
Gambar 4.2 Beberapa metode
static kelas Directory
Menganalisa Kelas File dan Kelas Directory
Kelas UjiFileForm (Gambar 4.3) menggunakan berbagai metode yang
dideskripsikan pada Gambar 4.1 dan Gambar 4.2 untuk mengakses file dan
informasi direktori. Kelas ini memuat TextBox
masukanTextBox, yang memampukan
pengguna untuk memasukkan sebuah file atau nama direktori.
Untuk setiap kunci yang ditekan
pengguna pada kotak teks, program akan memanggil masukanTextBox_KeyDown (baris 19-75). Jika pengguna menekan kunci Enter (baris 22), metode ini akan
menampilkan file atau isi direktori, tergantung dari masukan pengguna pada TextBox (Perhatikan bahwa, jika
pengguna tidak menekan kunci Enter,
maka metode ini tidak akan menampilkan isi apapun).
Baris 28 menggunakan metode Exists dari kelas File untuk menentukan apakah teks yang diberikan pengguna adalah
sebuah file. Jika pengguna menspesifikasi sebuah file yang sudah ada, maka
baris 31 akan memanggil metode private
GetInformasi (baris 79-97), yang memanggil metode GetCreationTime (baris 88), GetLastWriteTime
(baris 92), dan GetLastAccessTime
(baris 96) dari kelas File untuk
mengakses informasi pada file.
Ketika metode GetInformasi selesai dieksekusi, baris 38 menginstansiasi sebuah StreamReader untuk membaca teks dari
file. Konstruktor StreamReader
memerlukan sebuah argumen String
yang memuat nama file yang akan dibuka. Baris 40 memanggil metode ReadToEnd dari kelas StreamReader untuk membaca isi file dan
menampilkannya.
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
|
// Gambar 4.3: UjiFileForm.cs
// Menggunakan kelas File dan
Directory.
using System;
using
System.Windows.Forms;
using System.IO;
namespace UjiFile
{
// menampilkan isi file dan direktori
public partial class
UjiFileForm : Form
{
//konstruktor tanpa parameter
public UjiFileForm()
{
InitializeComponent();
}
// dipanggil ketika pengguna menekan kunci
private void masukanTextBox_KeyDown(object sender, KeyEventArgs e)
{
// menentukan apakah pengguna
menekan kunci Enter
if ( e.KeyCode == Keys.Enter )
{
// mendapatkan file atau
direktori yang ditetapkan pengguna
string namaFile = masukanTextBox.Text;
// menentukan apakan
namaFile adalah sebuah file
if ( File.Exists( namaFile ) )
{
// mendapatkan waktu penciptaan, modifikasi, dsb dari file
GetInformasi( namaFile );
StreamReader
aliran = null; // mendeklarasikan StreamReader
// menampilkan isi file
dengan StreamReader
try
{
// mendapatkan reader
dan isi file
using (aliran = new
StreamReader(namaFile))
{
keluaranTextBox.AppendText(aliran.ReadToEnd());
} // akhir using
} // akhir try
catch ( IOException )
{
MessageBox.Show(
"Error pembacaan dari file",
"File Error", MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir catch
} // akhir if
// menentukan apakan namaFile
adalah sebuah direktori
else if (
Directory.Exists( namaFile ) )
{
// mendapatkan tanggal
penciptaan,
// tanggal modifikasi,
dll dari direktori.
GetInformasi(namaFile);
// mendapatkan daftar file/direktori dari direktori tertentu
string[] daftarDirektori =
Directory.GetDirectories(namaFile);
keluaranTextBox.AppendText( "Isi
direktori:\n" );
// menampilkan isi
daftarDirektori
foreach ( var
directori in daftarDirektori )
keluaranTextBox.AppendText(directori + "\n");
} // akhir else if
else
{
// memberitahu pengguna bahwa file dan direktori tidak ada
MessageBox.Show(
masukanTextBox.Text +
" tidak ada", "File Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir else
} // akhir if
} // akhir metode masukanTextBox_KeyDown
// mendapatkan informasi file atau direktori,
// dan menampilkannya pada keluaranTextBox
private void GetInformasi (string namaFile)
{
keluaranTextBox.Clear();
// menampilkan bahwa file atau
direktori ada
keluaranTextBox.AppendText(namaFile + " ada\n");
// menampilkan kapan file atau
direktori diciptakan
keluaranTextBox.AppendText("Diciptakan: " +
File.GetCreationTime( namaFile )
+ "\n" );
// menampilkan kapan file atau
direktori terakhir dimodifikasi
keluaranTextBox.AppendText("Terakhir dimodifikasi: " +
File.GetLastWriteTime( namaFile )
+ "\n" );
// menampilkan kapan file atau
direktori terakhir diakses
keluaranTextBox.AppendText("Terakhir diakses: " +
File.GetLastAccessTime( namaFile
) + "\n" );
} // akhir metode GetInformasi
} // akhir kelas UjiFileForm
} // akhir
namespace UjiFile
|
Jika baris 28 menentukan bahwa teks
yang dimasukkan pengguna bukanlah sebuah file, maka baris 51 memutuskan bahwa
ia adalah sebuah direktori menggunakan metode Exists dari kelas Directory.
Jika pengguna memasukkan direktori yang sudah ada, maka baris 55 memanggil
metode GetInformasi untuk mengakses
informasi direktori. Baris 59 memanggil metode GetDirectories dari kelas Directory
untuk mendapatkan array string yang
memuat nama-nama subdirektori di dalam direktori yang dispesifikasi. Baris
64-65 menampilkan setiap elemen di dalam array string. Perhatikan bahwa, jika baris 51 menentukan bahwa teks yang
dimasukkan pengguna bukanlah file atau direktori, maka baris 70-72 akan
memberitahu pengguna (lewat MessageBox)
bahwa file atau direktori tidak ada.
Mencari Direktori dengan LINQ
Sekarang akan disajikan contoh lain
yang menggunakan kapabilitas manipulasi direktori dan file pada Visual Basic.
Kelas LINQToFileDirektoriForm
(Gambar 4.4) menggunakan LINQ dengan kelas File,
Path dan Directory untuk
melaporkan jumlah file untuk tipe file di dalam path direktori yang
dispesifikasi. Program juga berperan untuk utilitas “pembersihan”, ketika
program menjumpai sebuah file berekstensi
.bak (backup file). Program
menampilkan sebuah MessageBox untuk
menanyakan apakah file tersebut perlu dihapus dan merespon sesuai masukan
pengguna. Contoh ini uga menggunakan LINQ terhadap objek untuk menghapus file backup.
Ketika pengguna menekan kunci Enter atau mengklik tombol Cari Direktori, program akan memanggil cariButton_Click (baris 25-65), yang
mencari secara rekursif melalui path direktori yang disediakan pengguna. Jika
pengguna memasukkan teks di dalam TextBox,
baris 29 akan memanggil metode Exists
dari kelas Directory untuk
menentukan apakah teks tersebut mengindikasikan direktori yang valid. Jika
pengguna menspesifikasi direktori yang tak valid, maka baris 32-33 akan
memberitahu pengguna tentang error yang terjadi.
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
// Gambar 4.4:
LINQToFileDirektoriForm.cs
// Menggunakan
LINQ untuk melakukan pencarian direktori dan menentukan tipe-tipe file.
using System;
using
System.Collections.Generic;
using System.Linq;
using
System.Windows.Forms;
using System.IO;
namespace
LINQToFileDirektori
{
public partial class
LINQToFileDirektoriForm : Form
{
string direktoriSekarang;
// directori yang akan dijelajah
// menyimpan ekstensi ditemukan, dan jumlah tiap ekstensi ditemukan
Dictionary<string, int> ditemukan = new
Dictionary<string, int>();
// konstruktor tanpa parameter
public LINQToFileDirektoriForm()
{
InitializeComponent();
} // akhir konstruktor tanpa parameter
// menangani event Click pada tombol Cari Direktori
private void cariButton_Click(object sender, EventArgs e)
{
// memeriksa apakah pengguna
menetapkan path yang ada
if ( pathTextBox.Text != string.Empty
&&
!Directory.Exists(
pathTextBox.Text ) )
{
// menampilkan error jika pengguna tidak menetapkan path yang valid
MessageBox.Show( "Direktori Tak-Valid",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir if
else
{
// menggunakan direktoriSekarang jika
tidak ada direktori yang ditetapkan
if ( pathTextBox.Text == string.Empty )
direktoriSekarang = Directory.GetCurrentDirectory();
else
direktoriSekarang =
pathTextBox.Text;
direktoriTextBox.Text =
direktoriSekarang; // menampilkan direktori
// membersihkan TextBox
pathTextBox.Clear();
hasilTextBox.Clear();
CariDirektori(
direktoriSekarang ); // mencari direktori
// memampukan pengguna untuk
menghapus file .bak
HapusDirektori(
direktoriSekarang );
// menyimpulkan dan
menampilkan hasil
foreach ( var sekarang
in ditemukan.Keys)
{
// menampilkan jumlah
file dengan ekstensi
hasilTextBox.AppendText(string.Format(
"* Ditemukan {0} {1} file.\r\n",
ditemukan[
sekarang ], sekarang ) );
} // akhir foreach
ditemukan.Clear();
// menghapus hasil dari pencarian baru
} // akhir else
} // akhir method cariButton_Click
// pencarian direktori menggunakan LINQ
private void CariDirektori(string folder)
{
// file-file yang dimuat di dalam
direktori
string[] file2 =
Directory.GetFiles( folder );
// sub-sudirektori di dalam
direktori
string[]
direktori2 = Directory.GetDirectories( folder );
// menemukan semua ekstensi file
pada direktori ini
var ekstensi2 =
( from
file in file2
select
Path.GetExtension( file ) ).Distinct();
// menghitung jumlah file
foreach ( var ekstensi
in ekstensi2 )
{
var temp = ekstensi;
// menghitung jumlah file
dengan ekstensi
var hitungEkstensi =
( from file in file2
where Path.GetExtension( file
) == temp
select file ).Count();
// jika Dictionary telah memuat kunci
untuk ekstensi
if ( ditemukan.ContainsKey( ekstensi ) )
ditemukan[
ekstensi ] += hitungEkstensi; // perbarui
perhitungan
else
ditemukan.Add(
ekstensi, hitungEkstensi ); // tambahkan
} // akhir foreach
// pemanggilan rekursif terhadap
sub-sub direktori
foreach ( var
subdirektori in direktori2 )
CariDirektori(subdirektori);
} // akhir metode CariDirektori
// memampukan pengguna untuk menghapus filebackup (.bak)
private void HapusDirektori( string folder )
{
// file-file yang dimuat di dalam
direktori
string[] file2 =
Directory.GetFiles( folder );
// sub-sub direktori di dalam
direktori
string[]
direktori2 = Directory.GetDirectories( folder );
// memilih semua file backup pada
direktori ini
var file2Backup =
from file in file2
where Path.GetExtension( file
) == ".bak"
select file;
// beriterasi menjelajahi semua
file backup (.bak)
foreach ( var backup in file2Backup )
{
DialogResult
hasil = MessageBox.Show( "Ditemukan file backup " +
Path.GetFileName( backup ) + ". Hapus?", "Hapus Backup",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question );
// menghapus file jika
pengguna mengklik 'yes'
if ( hasil == DialogResult.Yes )
{
File.Delete(
backup ); // menghapus file backup
--ditemukan[
".bak" ]; // mendekremen
ditemukan
// jika tidak ada file
.bak, hapus kunci dari Directory
if ( ditemukan[ ".bak"
] == 0 )
ditemukan.Remove(
".bak" );
} // akhir if
} // akhir foreach
// pemanggilan rekursif untuk
menghapus sub-subdirektori
foreach (var
subdirektori in direktori2)
HapusDirektori(
subdirektori );
} // akhir metode
HapusDirektori
} // akhir kelas LINQToFileDirektoriForm
} // akhir namespace LINQToFileDirektori
|
Metode CariDirektori
Baris 38-41 mendapatkan direktori
terkini (jika pengguna tidak menetapkan path)
atau direktori yang ditetapkan pengguna. Baris 49 melewatkan nama direktori
kepada metode rekursif CariDirektori
(baris 68-102). Baris 107 memanggil metode GetFiles
dari kelas Directory untuk
mendapatkan suatu array string yang
memuat nama-nama file pada direktori tertentu. Baris 74 memanggil GetDirectories dari kelas Directory untuk mendapatkan sebuah
array string yang memuat nama-nama
subdirektori pada direktori tertentu.
Baris 78-79 menggunakan LINQ untuk
mendapatkan ekstensi-ekstensi file pada array file2. Metode GetExtension
dari kelas Path mendapatkan ekstensi
untuk nama file tertentu. Untuk tiap ekstensi file yang dihasilkan oleh LINQ query, baris 82-97 menentukan jumlah
kemunculan ekstensi tersebut pada array file2.
LINQ query pada baris 88-90 membandingkan
tiap ekstensi file pada array file2
dengan ekstensi yang sedang diproses (baris 89). Semua kecocokan dicantumkan
pada hasil. Anda kemudian menggunakan metode Count untuk menghitung jumlah total file yang cocok dengan ekstensi
terkini.
Kelas LINQToFileDirektoriForm menggunakan sebuah Directory (dideklarasikan pada baris 16) untuk menyimpan setiap
ekstensi file dan jumlah dari nama file yang terkait dengan ekstensi itu.
Sebuah Directory (namespace System.Collections.Generic) merupakan suatu koleksi pasangan
kunci/nilai, dimana di dalamnya setiap kunci memiliki nilai tertentu. Kelas Directory merupakan sebuah kelas
generik seperti kelas List. Baris 16
mengindikasikan bahwa Dictionary ditemukan memuat pasangan-pasangan string dan int, yang merepresentasikan ekstensi file dan jumlah filenya. Baris
93 menggunakan metode ContainsKey
dari kelas Dictionary untuk
menentukan apakah ekstensi file tertentu telah ditempatkan pada Dictionary. Jika metode ini
menghasilkan true, maka baris 94
akan menambahkan hitungEkstensi yang
ditentukan pada baris 88-90 pada jumlah ekstensi terkini yang disimpan pada Dictionary. Sebaliknya, baris 96
menggunakan metode Add dari kelas Dictionary untuk menyisipkan sebuah
pasangan kunci/nilai ke dalam Dictionary
untuk ekstensi file yang baru dan hitungEkstensinya.
Baris 100-101 secara rekursif memanggil CariDirektori
untuk tiap subdirektori di dalam direktori terkini.
Metode HapusDirektori
Ketika metode CariDirektori selesai dieksekusi, baris 52 memanggil HapusDirektori (didefinisikan pada
baris 105-141) untuk melakukan pencarian terhadap semua file yang berekstensi .bak. Baris 108 dan 111 mendapatkan
daftar nama file dan daftar nama direktori pada direktori terkini. LINQ query pada baris 115-117 mencari lokasi
semua nama file pada direktori terkini yang memiliki ekstensi .bak. Baris 120-136 beriterasi
menjelajah hasil-hasil query dan
meminta pengguna untuk menentukan apakah tiap file perlu dihapus. Jika pengguna
mengklik Yes pada dialog, maka baris
129 menggunakan metode Delete dari
kelas File untuk menghapus file dari
disk, dan baris 130 mengurangkan 1
dari jumlah total file .bak.
4.3
Menciptakan File Akses-Sekuensial
C# tidak memaksakan struktur apapun
pada sebuah file. Ini berarti bahwa, programer harus menstrukturisasi file
untuk memenuhi persyaratan aplikasi.
Kelas
BankUIForm
Kelas BankUIForm (Gambar 4.5) memuat empat Label dan empat TextBox.
Metode BersihTextBox (baris 28-40), SetNilaiTextBox (baris 43-64), dan GetNilaiTextBox (baris 67-78)
menghapus, menetapkan nilai-nilai, dan mendapatkan nilai-nilai teks di dalam TextBox.
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
|
// Gambar 4.5: BankUIForm.cs
// Windows Form yang dapat didaur-ulang
untuk beberapa contoh pada buku ini.
using System;
using
System.Windows.Forms;
namespace PustakaBank
{
public partial class
BankUIForm : Form
{
protected int JumlahTextBox = 4; // jumlah
TextBoxes pada Form
// konstanta-konstanta enumerasi untuk menetapkan indeks-indeks
TextBox
public enum IndeksTextBox
{
AKUN,
PERTAMA,
AKHIR,
SALDO
} // akhir enum
// konstruktor tanpa-parameter
public BankUIForm()
{
InitializeComponent();
}
// menghapus semua TextBox
public void BersihTextBox()
{
// menjelajah setiap Control pada
form
foreach ( Control guiControl in
Controls )
{
// menentukan apakan Control
adalah TextBox
if ( guiControl is
TextBox )
{
// menghapus TextBox
( ( TextBox ) guiControl
).Clear();
} // akhir if
} // akhir for
} // akhir metode BersihTextBox
// menetapkan nilai-nilai TextBox menjadi nilai-nilai array string
public void SetNilaiTextBox(string[]
nilai2)
{
// menentukan apakah array string
memiliki panjang yang tepat
if ( nilai2.Length != JumlahTextBox )
{
// melempar eksepsi jika
panjang tidak tepat
throw ( new
ArgumentException( "Harus ada " +
( JumlahTextBox + 1 ) +
" string pada array" )
);
} // akhir if
// menetapkan
nilai-nilai array jika array memiliki panjang yang tepat
else
{
// menetapkan nilai-nilai
array menjadi nilai-nilai TextBox
akunTextBox.Text =
nilai2[ ( int ) IndeksTextBox.AKUN ];
namaPertamaTextBox.Text =
nilai2[ ( int ) IndeksTextBox.PERTAMA ];
namaAkhirTextBox.Text =
nilai2[ ( int ) IndeksTextBox.AKHIR ];
saldoTextBox.Text =
nilai2[ ( int ) IndeksTextBox.SALDO ];
} // akhir else
} // akhir metode SetNilaiTextBox
// menghasilkan nilai-nilai TextBox sebagai array string
public string[] GetNilaiTextBox()
{
string[] nilai2 = new string[ JumlahTextBox ];
// menyalin semua bidang TextBox
ke array string
nilai2[ ( int ) IndeksTextBox.AKUN
] = akunTextBox.Text;
nilai2[ ( int ) IndeksTextBox.PERTAMA
] = namaPertamaTextBox.Text;
nilai2[ ( int ) IndeksTextBox.AKHIR
] = namaAkhirTextBox.Text;
nilai2[ ( int ) IndeksTextBox.SALDO ] = saldoTextBox.Text;
return nilai2;
} // akhir metode GetNilaiTextBox
} // akhir kelas BankUIForm
} // akhir
namespace PustakaBank
|
Dengan menggunakan pewarisan, Anda
dapat mewarisi kelas ini untuk menciptakan GUI pada beberapa contoh pada bab
ini. Ingat bahwa untuk mengdaur-ulang kelas BankUIForm, Anda harus mengkompilasi GUI tersebut menjadi sebuah
pustaka kelas, kemudian menambahkan referensi ke pustaka kelas yang baru itu
pada tiap projek yang menggunakannya.
Kelas
Rekaman
Gambar 4.6 memuat kelas Rekaman untuk menuliskan ke atau
membaca dari sebuah file.
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
|
//
Gambar 4.6: Rekaman.cs
//
Kelas yang merepresentasikan sebuah rekaman data.
namespace
PustakaBank
{
public
class Rekaman
{
// properti Akun implementasi-diri
public int Akun
{ get; set; }
// properti NamaPertama implementasi-diri
public string
NamaPertama { get; set; }
// properti NamaAkhir implementasi-diri
public string
NamaAkhir { get; set; }
// properti Saldo implementasi-diri
public decimal
Saldo { get; set; }
// konstruktor tanpa parameter
menetapkan nilai-nilai default
public
Rekaman()
: this( 0, string.Empty,
string.Empty, 0M )
{
} // akhir konstruktor
// konstruktor teroverload menetapkan
nilai-nilai parameter
public
Rekaman( int nilaiAkun, string nilaiNamaPertama,
string nilaiNamaAkhir, decimal
nilaiSaldo )
{
Akun = nilaiAkun;
NamaPertama = nilaiNamaPertama;
NamaAkhir = nilaiNamaAkhir;
Saldo = nilaiSaldo;
} // akhir konstruktor
} // akhir kelas Rekaman
} // akhir namespace PustakaBank
|
Kelas
BankUIForm Terperbarui
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
|
// Gambar 4.7: BankUIForm.cs
// Windows Form yang dapat didaur-ulang
untuk beberapa contoh pada buku ini.
using System;
using
System.Windows.Forms;
using
System.IO;
namespace PustakaBank
{
public partial class
BankUIForm : Form
{
protected int JumlahTextBox = 4; // jumlah
TextBoxes pada Form
private StreamWriter
penulisFile; // writes data to text file
// konstanta-konstanta enumerasi untuk menetapkan indeks-indeks
TextBox
public enum IndeksTextBox
{
AKUN,
PERTAMA,
AKHIR,
SALDO
} // akhir enum
// konstruktor tanpa-parameter
public BankUIForm()
{
InitializeComponent();
}
// menghapus semua TextBox
public void BersihTextBox()
{
// menjelajah setiap Control pada
form
foreach (Control guiControl in
Controls)
{
// menentukan apakan Control
adalah TextBox
if (guiControl is
TextBox)
{
// menghapus TextBox
((TextBox)guiControl).Clear();
} // akhir if
} // akhir for
} // akhir metode BersihTextBox
// menetapkan nilai-nilai TextBox menjadi nilai-nilai array string
public void SetNilaiTextBox(string[]
nilai2)
{
// menentukan apakah array string
memiliki panjang yang tepat
if (nilai2.Length != JumlahTextBox)
{
// melempar eksepsi jika
panjang tidak tepat
throw (new
ArgumentException("Harus ada " +
(JumlahTextBox + 1) + " string pada array"));
} // akhir if
// menetapkan
nilai-nilai array jika array memiliki panjang yang tepat
else
{
// menetapkan nilai-nilai array menjadi nilai-nilai TextBox
akunTextBox.Text =
nilai2[(int)IndeksTextBox.AKUN];
namaPertamaTextBox.Text =
nilai2[(int)IndeksTextBox.PERTAMA];
namaAkhirTextBox.Text =
nilai2[(int)IndeksTextBox.AKHIR];
akunTextBox.Text =
nilai2[(int)IndeksTextBox.SALDO];
} // akhir else
} // akhir metode SetNilaiTextBox
// menghasilkan nilai-nilai TextBox sebagai array string
public string[] GetNilaiTextBox()
{
string[] nilai2 = new
string[JumlahTextBox];
// menyalin semua bidang TextBox
ke array string
nilai2[(int)IndeksTextBox.AKUN] = akunTextBox.Text;
nilai2[(int)IndeksTextBox.PERTAMA] = namaPertamaTextBox.Text;
nilai2[(int)IndeksTextBox.AKHIR] = namaAkhirTextBox.Text;
nilai2[(int)IndeksTextBox.SALDO] = saldoTextBox.Text;
return nilai2;
} // akhir metode GetNilaiTextBox
// menangani event Click untuk simpanButton
private void simpanButton_Click(object sender, EventArgs e)
{
// menciptakan dan menampilkan
kotak dialog untuk menyimpan file
DialogResult hasil; // hasil dari
SaveFileDialog
string namaFile; // nama file yang memuat data
using ( SaveFileDialog
pemilihFile = new SaveFileDialog()
)
{
pemilihFile.CheckFileExists = false; // menciptakan file
hasil = pemilihFile.ShowDialog();
namaFile = pemilihFile.FileName; // nama file untuk disimpan
} // akhir
using
// memastikan bahwa pengguna
mengklik "OK"
if ( hasil == DialogResult.OK )
{
// menampilkan error jika pengguna menetapkan file tak-valid
if ( namaFile == string.Empty
)
MessageBox.Show( "Nama Tak Valid",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
else
{
// menyimpan file via FileStream jika pengguna menetapkan file valid
try
{
// membuka file
dengan akses write
FileStream
keluaran = new FileStream(
namaFile,
FileMode.OpenOrCreate,
FileAccess.Write );
// menetapkan file
tempat penulisan
penulisFile
= new StreamWriter( keluaran );
// menon-aktifkan tombol Simpan dan mengaktifkan tombol Enter
simpanButton.Enabled = false;
enterButton.Enabled =
true;
} // akhir try
// menangani eksepsi jika
ada masalah pembukaan file
catch ( IOException )
{
// memberitahu
pengguna jika file tidak ada
MessageBox.Show(
"Error pembukaan file",
"Error",
MessageBoxButtons.OK, MessageBoxIcon.Error );
} // akhir catch
} // akhir else
} // akhir if
} // akhir metode simpanButton_Click
//menangani event Click untuk enterButton
private void enterButton_Click(object sender, EventArgs e)
{
// menyimpan nilai-nilai TextBox
string[] nilai2 = GetNilaiTextBox();
// Rekaman memuat nilai-nilai
TextBox yang akan ditampilkan
Rekaman rekaman = new Rekaman();
// menentukan apakah bidang akun
kosong
if ( nilai2[ ( int )
IndeksTextBox.AKUN ] != string.Empty
)
{
// menyimpan nilai-nilai TextBox dalam Rekaman dan menampilkannya
try
{
// mendapatkan nilai
nomor-akun dari TextBox
int nomorAkun = Int32.Parse(
nilai2[(int)IndeksTextBox.AKUN]);
// menentukan apakah
nomorAkun valid
if ( nomorAkun > 0 )
{
// menyimpan bidang-bidang TextBox di dalam Rekaman
rekaman.Akun =
nomorAkun;
rekaman.NamaPertama = nilai2[ ( int )
IndeksTextBox.PERTAMA];
rekaman.NamaAkhir =
nilai2[ ( int )
IndeksTextBox.AKHIR];
rekaman.Saldo =
Decimal.Parse(
nilai2[(int)IndeksTextBox.SALDO]);
// menuliskan Rekaman ke file, bidang-bidang dipisahkan dengan koma
penulisFile.WriteLine(
rekaman.Akun + "," + rekaman.NamaPertama + "," +
rekaman.NamaAkhir + "," +
rekaman.Saldo );
} // akhir if
else
{
// memberitahu
pengguna jika nomor akun tak-valid
MessageBox.Show(
"Nomor Akun Tak-Valid",
"Error",
MessageBoxButtons.OK, MessageBoxIcon.Error );
} // akhir else
} // akhir try
// memberitahu pengguna jika error terjadi selama operasi penampilan
catch ( IOException )
{
MessageBox.Show( "Error Penulisan ke File", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir catch
// memberitahu pengguna jika error terjadi akibat format parameter
catch ( FormatException )
{
MessageBox.Show( "Format Tak-Valid", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir catch
} // akhir if
BersihTextBox(); // membersihkan
nilai-nilai TextBox
} // akhir metode enterButton_Click
// menangani event Click untuk keluarButton
private void keluarButton_Click(object sender, EventArgs e)
{
// menentukan apakah file ada
if ( penulisFile != null
)
{
try
{
// menutup StreamWriter
penulisFile.Close();
} // akhir try
// memberitahu pengguna
tentang error penutupan file
catch ( IOException )
{
MessageBox.Show( "Tidak bisa membuka file", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir catch
} // akhir if
Application.Exit();
} // akhir metode keluarButton_Click
} // akhir kelas BankUIForm
} // akhir namespace PustakaBank
|
Kelas BankUIForm terperbarui menciptakan atau membuka sebuah file
(tergantung dari apakah file ada atau tidak), kemudian memampukan pengguna
untuk menuliskan rekaman-rekaman ke dalam file tersebut. GUI pada kelas ini
sekarang memuat tombol Simpan, Enter, dan Keluar.
Metode
simpanButton_Click
Ketika pengguna mengklik tombol Simpan,
program akan memanggil event handler simpanButton_Click. Metode ini
menginstansiasi sebuah objek dari kelas SaveFileDialog
(namespace System.Windows.Form). Dengan menempatkan objek ini pada sebuah
statemen using, Anda dapat
memastikan bahwa metode Dispose
dipanggil untuk melepaskan sumberdayanya setelah program membaca masukan dari
pengguna. Objek-objek SaveFileDialog
dipakai untuk memilih file. Baris 91 mengindikasikan bahwa dialog tidak
memeriksa jika nama yang disediakan pengguna telah ada atau tidak. Baris 92
memanggil metode ShowDialog dari
kelas SaveFileDialog untuk
menampilkan dialog. Ketika ditampilkan, objek SaveFileDialog akan mencegah pengguna untuk berinteraksi dengan
jendela lain pada program sampai pengguna menutup SaveFileDialog dengan mengklik Save
atau Cancel. Pengguna memilih drive, direktori, dan nama file,
kemudian mengklik Save. Metode SaveDialog menghasilkan sebuah objek DialogResult yang menetapkan tombol
mana (Save atau Cancel) yang diklik pengguna untuk menutup dialog. Objek ini
ditugaskan kepada variabel hasil
pada baris 92. Baris 93 membaca nama file dari dialog. Baris 97 menguji apakah
pengguna mengklik OK dengan
membandingkan nilai ini dengan DialogResult.OK.
Jika kedua nilai sama, metode simpanButton_Click
akan berlanjut.
Anda dapat membuka file untuk melakukan
pemanipulasian teks dengan menciptakan objek dari kelas FileStream. Pada contoh ini, Anda ingin file dibuka untuk
ditampilkan, jadi baris 109-110 mencitptakan sebuah objek FileStream. Konstruktor FileStream
yang digunakan menerima tiga argumen, yaitu sebuah string yang memuat path
dan nama file yang akan dibuka, sebuah konstanta yang menjelaskan bagaimana
membuka suatu file, dan sebuah konstanta yang menjelaskan ijin file. Konstanta FileMode.OperOrCreate (baris 110)
mengindikasikan bahwa objek FileStream
membuka file jika file itu ada atau menciptakan file jika ia belum ada.
Perhatikan bahwa isi dari file yang sudah ada akan ditimpa oleh StreamWriter. Untuk mempertahankan isi
asli dari sebuah file, Anda bisa menggunakan FileMode.Append. Ada beberapa konstanta FileMode lain yang menjelaskan bagaimana membuka file; Konstanta FileAccess.Write mengindikasikan bahwa
program hanya dapat melakukan operasi penulisan dengan objek FileStream. Ada dua konstanta lain
untuk parameter ketiga pada konstruktor, yaitu FileAccess.Read untuk akses read-only dan FileAccess.ReadWrite untuk akses pembacaan dan penulisan. Baris 120
menangkap sebuah eksepsi IOException
jika terdapat masalah dalam pembukaan file atau penciptaan StreamWriter. Jika ya, program akan menampilkan sebuah pesan error
(baris 123-124). Jika tidak ada terjadi eksepsi, maka file dapat dibuka untuk
ditulis.
Metode
enterButton_Click
Setelah mengetikkan informasi ke dalam
tiap TextBox, pengguna mengklik
tombol Enter, yang memanggil event handler enterButton_Click (baris 130-188) untuk menyimpan dari dari tiap TextBox ke dalam file yang dipilih
pengguna. Jika pengguna memasukkan nomor akun yang valid (misalnya, integer
yang lebih besar dari nol), maka baris 153-159 akan menyimpan nilai-nilai TextBox di dalam sebuah objek bertipe Rekaman (diciptakan pada baris 137).
Jika pengguna memasukkan data yang tak-valid pada salah satu TextBox (misalnya, karakter tak-numerik
pada bidang Saldo), maka program
akan melemparkan sebuah eksepsi FormatException.
Blok catch pada baris 180-184 akan
menangani eksepsi semacam itu dengan memberitahu pengguna (melalui sebuah MessageBox).
Jika pengguna memasukkan data valid,
maka baris 162-164 akan menulis rekaman ke dalam file dengan memanggil metode WriteLine dari objek StreamWriter yang diciptakan pada baris
113. Metode WriteLine menuliskan serangkaian
karakter ke dalam sebuah file. Objek StreamWriter
dikonstruksi dengan sebuah argumen FileStream
yang menetapkan file tempat penulisan. Kelas StreamWriter berada di dalam namespace
System.IO.
Metode
keluarButton_Click
Ketika pengguna mengklik Keluar, maka event handler keluarButton_Click
(baris 191-210) akan dieksekusi. Baris 199 menutup StreamWriter, yang secara otomatis menutup FileStream. Kemudian, baris 209 menghentikan program. Perhatikan
bahwa metode Close dipanggil di
dalam sebuah blok try. Metode Close akan melemparkan sebuah eksepsi IOException jika file atau aliran tidak
dapat ditutup dengan benar. Pada kasus ini, adalah penting untuk memberitahu
pengguna bahwa informasi di dalam file bisa jadi terkorupsi.
4.4
Membaca Data dari Sebuah File Teks Akses-Sekuensial
Pada bagian sebelumnya telah
didemonstrasikan bagaimana menciptakan sebuah file agar dapat digunakan pada
aplikasi-aplikasi akses-sekuensial. Pada bagian ini, Akan didiskusikan
bagaimana membaca data secara sekuensial dari sebuah file. Kelas BacaFileAksesSekuensialForm (Gambar 4.9)
membaca rekaman-rekaman yang dibaca dari file yang diciptakan oleh program pada
Gambar 4.7, kemudian menampilkan isi tiap rekaman. Banyak bagian kode pada
contoh ini mirip dengan yang ada pada Gambar 4.7, jadi yang akan dibahas hanya
aspek-aspek unik dari aplikasi.
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
|
//
Gambar 4.8: Rekaman.cs
//
Kelas yang merepresentasikan sebuah rekaman data.
namespace BacaFileAksesSekuensial
{
public
class Rekaman
{
// properti Akun implementasi-diri
public int Akun { get; set; }
// properti NamaPertama implementasi-diri
public string NamaPertama { get;
set; }
// properti NamaAkhir implementasi-diri
public string NamaAkhir { get;
set; }
// properti Saldo implementasi-diri
public decimal Saldo { get; set; }
// konstruktor tanpa parameter
menetapkan nilai-nilai default
public
Rekaman()
: this( 0, string.Empty,
string.Empty, 0M )
{
} // akhir konstruktor
// konstruktor teroverload menetapkan
nilai-nilai parameter
public
Rekaman( int nilaiAkun, string nilaiNamaPertama,
string nilaiNamaAkhir, decimal
nilaiSaldo )
{
Akun = nilaiAkun;
NamaPertama = nilaiNamaPertama;
NamaAkhir = nilaiNamaAkhir;
Saldo = nilaiSaldo;
} // akhir konstruktor
} // akhir kelas Rekaman
} // akhir namespace BacaFileAksesSekuensial
|
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
// Gambar 4.9:
BacaFileAksesSekuensialForm.cs
// Membaca sebuah file
akses-sekuensial.
using System;
using
System.Windows.Forms;
using System.IO;
namespace
BacaFileAksesSekuensial
{
public partial class
BacaFileAksesSekuensialForm : Form
{
protected int JumlahTextBox = 4; // jumlah
TextBoxes pada Form
private
StreamReader pembacaFile; // membaca data dari file teks
// konstanta-konstanta enumerasi untuk menetapkan indeks-indeks
TextBox
public enum IndeksTextBox
{
AKUN,
PERTAMA,
AKHIR,
SALDO
} // akhir enum
// konstruktor tanpa-parameter
public
BacaFileAksesSekuensialForm()
{
InitializeComponent();
} // akhir konstruktor tanpa-parameter
// menghapus semua TextBox
public void BersihTextBox()
{
// menjelajah setiap Control pada
form
foreach (Control guiControl in
Controls)
{
// menentukan apakan Control adalah
TextBox
if (guiControl is
TextBox)
{
// menghapus TextBox
((TextBox)guiControl).Clear();
} // akhir if
} // akhir for
} // akhir metode BersihTextBox
// menetapkan nilai-nilai TextBox menjadi nilai-nilai
array string
public void SetNilaiTextBox(string[]
nilai2)
{
// menentukan apakah array string
memiliki panjang yang tepat
if (nilai2.Length != JumlahTextBox)
{
// melempar eksepsi jika
panjang tidak tepat
throw (new
ArgumentException("Harus ada " +
(JumlahTextBox + 1) +
" string pada array"));
} // akhir if
// menetapkan
nilai-nilai array jika array memiliki panjang yang tepat
else
{
// menetapkan nilai-nilai array menjadi nilai-nilai TextBox
akunTextBox.Text =
nilai2[(int)IndeksTextBox.AKUN];
namaPertamaTextBox.Text =
nilai2[(int)IndeksTextBox.PERTAMA];
namaAkhirTextBox.Text =
nilai2[(int)IndeksTextBox.AKHIR];
akunTextBox.Text =
nilai2[(int)IndeksTextBox.SALDO];
} // akhir else
} // akhir metode SetNilaiTextBox
//dipanggil ketika pengguna mengklik tombol Buka File
private void bukaFileButton_Click(object sender, EventArgs e)
{
// menciptakan dan menampilkan kotak dialog untuk membaca file
DialogResult hasil; // hasil dari
SaveFileDialog
string namaFile; // nama file yang memuat data
using (OpenFileDialog pemilihFile = new OpenFileDialog())
{
hasil =
pemilihFile.ShowDialog();
namaFile =
pemilihFile.FileName; // nama file untuk disimpan
} // akhir using
// memastikan bahwa pengguna
mengklik "OK"
if (hasil == DialogResult.OK)
{
BersihTextBox();
// menampilkan error jika
pengguna menetapkan file tak-valid
if (namaFile == string.Empty)
MessageBox.Show("Nama Tak Valid", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
else
{
try
{
// menciptakan FileStream untuk mendapatkan akses membaca
FileStream
masukan = new FileStream(
namaFile, FileMode.Open,
FileAccess.Read);
// menetapkan file
tempat pembacaan
pembacaFile
= new StreamReader(masukan);
// menon-aktifkan tombol Simpan dan mengaktifkan tombol Enter
bukaFileButton.Enabled = false;
rekamanBerikutnyaButton.Enabled = true;
} // akhir try
// menangani eksepsi jika ada masalah
pembukaan file
catch (IOException)
{
// memberitahu
pengguna jika file tidak ada
MessageBox.Show("Error
pembacaan file", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
} // akhir catch
} // akhir else
} // akhir if
} // akhir metode bukaFileButton_Click
//dipanggil ketika pengguna mengklik tombol Rekaman Berikutnya
private void rekamanBerikutnyaButton_Click(object sender, EventArgs e)
{
try
{
// mendapatkan rekaman
berikutnya dari file
string
rekamanMasukan = pembacaFile.ReadLine();
string[] bidangMasukan; // menyimpan
potongan individual data
if ( rekamanMasukan != null
)
{
bidangMasukan =
rekamanMasukan.Split( ',' );
Rekaman rekaman = new Rekaman(
Convert.ToInt32( bidangMasukan[ 0 ] ), bidangMasukan[ 1 ],
bidangMasukan[ 2 ],
Convert.ToDecimal(
bidangMasukan[ 3 ] ) );
// menyalin nilai-nilai array-string ke nilai-nilai TextBox
SetNilaiTextBox(
bidangMasukan );
} // akhir if
else
{
// menutup StreamReader
pembacaFile.Close();
bukaFileButton.Enabled = true; // mengaktifkan tombol Buka File
// menonaktifkan tombol
Rekaman Berikutnyan
rekamanBerikutnyaButton.Enabled = false;
BersihTextBox();
// memberitahu pengguna jika tidak ada rekaman di dalam
MessageBox.Show( "Tidak ada rekaman lagi di dalam
file",
string.Empty,
MessageBoxButtons.OK,
MessageBoxIcon.Information
);
} // akhir else
} // akhir try
catch ( IOException )
{
MessageBox.Show( "Error Pembacaan dari File",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir catch
} // akhir metode rekamanBerikutnyaButton_Click
} // akhir kelas BacaFileAksesSekuensialForm
} // akhir namespace BacaFileAksesSekuensial
|
Metode
bukaFileButton_Click
Ketika pengguna mengklik tombol Buka
File, program memanggil event handler
bukaFileButton_Click. Baris 75
menciptakan suatu OpenFileDialog,
dan baris 77 memanggil metode ShowDialog
untuk menampilkan dialog Open. Watak
dan GUI dari dialog Open dan Save indentik, kecuali bahwa dialog Save diganti dengan Open. Jika pengguna memilih suatu nama
file yang valid, maka baris 95-96 akan menciptakan sebuah objek FileStream dan menugaskannya untuk
mereferensi masukan. Anda melewatkan
konstanta FileMode.Open sebagai
argumen kedua kepada konstruktor FileStream
untuk mengindikasikan bahwa FileStream
harus membuka file jika file memang ada atau melemparkan eksepsi FileNotFoundException jika file tidak
ada. Pada contoh ini, konstruktor FileStream
tidak melempar eksepsi FileNotFoundException,
karena OpenFileDialog dikonfigurasi
untuk memeriksa apakah file ada atau tidak. Pada contoh terakhir (Gambar 4.7),
Anda menuliskan teks ke dalam file menggunakan sebuah objek FileStream dengan akses write-only. Pada contoh ini, Anda menetapkan akses read-only terhadap
file dengan melewatkan konstanta FileAccess.Read
sebagai argumen ketiga pada konstruktor FileStream.
Objek FileStream ini dipakai untuk
menciptakan suatu objek StreamReader
pada baris 99. Objek FileStream
menetapkan file yang akan dibaca oleh objek StreamReader.
Metode
rekamanBerikutnyaButton_Click
Ketika pengguna
mengklik tombol Rekaman Berikutnya,
program memanggil event handler rekamanBerikutnyaButton_Click (baris
117-158), yang membaca rekaman berikutnya dari file yang dipilih pengguna.
Pengguna perlu mengklik tombol Rekaman
Berikutnya setelah membuka file untuk melihat rekaman pertama. Baris 122
memanggil metode ReadLine dari kelas
StreamReader untuk membaca rekaman
berikutnya. Jika suatu error terjadi saat pembacaan file, maka eksepsi IOException akan dilemparkan (ditangkap
pada baris 106). Sebaliknya, baris 125 akan menentukan apakah metode ReadLine menghasilkan null atau tidak
(apakah masih ada teks di dalam file atau tidak). Jika tidak ada lagi, maka
baris 77 menggunakan metode Split
dari kelas string untuk memisahkan
aliran karakter-karakter yang telah dibaca dari file menjadi string-string yang merepresentasikan properti-properti Rekaman. Semua properti ini kemudian
diurutkan dengan mengkonstruksi suatu objek Rekaman menggunakan properti-properti sebagai argumen (baris
129-132). Baris 135 menampilkan nilai-nilai Rekaman pada setiap TextBox.
Jika ReadLine menghasilkan null, maka program menutup objek StreamReader (baris 140), yang secara
otomatis akan menutup objek FileStream,
kemudian memberitahu pengguna bahwa tidak ada lagi rekaman (baris 148-150).
4.5
Studi Kasus: Program Kredit
Untuk membaca data secara sekuensial
dari sebuah file, program biasanya memulai dari awal file, membaca secara
berurutan sampai data yang diinginkan ditemukan. Hal ini biasanya diperlukan
untuk memproses file (dari awal file) berulang kali selama eksekusi sebuah
program. Sebuah objek FileStream
dapat memposisikan-ulang pointernya. Ketika suatu objek FileStream dibuka, pointer posisi-filenya ditetapkan ke posisi byte
0 (awal file).
Sekarang akan disajikan suatu program
yang memakai konsep-konsep yang diterapkan pada Gambar 4.9. Kelas KreditForm (Gambar 4.11) merupakan
program kredit yang memampukan seorang manajer kredit untuk melakukan pencarian
dan menampilkan informasi akun bagi para konsumen (yaitu konsumen yang
menyimpan uangnya pada perusahaan (saldo kredit), konsumen yang tidak memiliki
hutang (saldo nol), dan konsumen yang memiliki hutang (saldo debit)).
Anda akan menggunakan sebuah RichTextBox pada program untuk
menampilkan informasi akun. RichTextBox
menyediakan fungsionalitas yang lebih daripada TextBox biasa. Sebagai contoh, RichTextBox
menawarkan metode Find untuk
melakukan pencarian string dan metode LoadFile
untuk menampilkan isi file. Kedua kelas TextBox
dan RichTextBox mewarisi kelas System.Windows.Forms.TextBoxBase. Pada
contoh ini, Anda memilih RichTextBox,
karena ia menampilkan beberapa baris teks secara default, sedangkan TextBox biasa hanya menampilkan satu
baris secara default. Tetapi, sebenarnya Anda bisa saja menetapkan objek TextBox untuk menampilkan baris jamak
dengan mengatur properti Multiline-nya
menjadi true.
Program menampilkan tombol-tombol yang
memampukan seorang manajer kredit untuk mendapatkan informasi kredit. Tombol Buka File membuka sebuah file. Tombol Saldo Kredit untuk menampilkan daftar
akun yang memiliki saldo kredit, tombol Saldo
Debit untuk menampilkan daftar akun yang memiliki saldo debit, dan tombol Saldo Nol untuk menampilkan daftar akun
yang memiliki saldo nol. Tombol Selesai
akan menghentikan aplikasi.
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
|
//
Gambar 4.10: Rekaman.cs
//
Kelas yang merepresentasikan sebuah rekaman data.
namespace Kredit
{
public
class Rekaman
{
// properti Akun implementasi-diri
public int Akun { get; set; }
// properti NamaPertama implementasi-diri
public string NamaPertama { get;
set; }
// properti NamaAkhir implementasi-diri
public string NamaAkhir { get;
set; }
// properti Saldo implementasi-diri
public decimal Saldo { get; set; }
// konstruktor tanpa parameter
menetapkan nilai-nilai default
public
Rekaman()
: this( 0, string.Empty,
string.Empty, 0M )
{
} // akhir konstruktor
// konstruktor teroverload menetapkan
nilai-nilai parameter
public
Rekaman( int nilaiAkun, string nilaiNamaPertama,
string nilaiNamaAkhir, decimal
nilaiSaldo )
{
Akun = nilaiAkun;
NamaPertama = nilaiNamaPertama;
NamaAkhir = nilaiNamaAkhir;
Saldo = nilaiSaldo;
} // akhir konstruktor
} // akhir kelas Rekaman
} // akhir namespace Kredit
|
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
// Gambar 4.11: KreditForm.cs
// Membaca sebuah file secara
sekuensial dan menampilkan isinya
// berdasarkan tipe akun yang
ditetapkan pengguna.
using System;
using
System.Windows.Forms;
using System.IO;
namespace Kredit
{
public partial class
KreditForm : Form
{
private FileStream masukan;
// menetapkan koneksi ke file
private StreamReader
pembacaFile; // membaca data dari file teks
// nama file yang menyimpan saldo kredit, saldo
debit, dan saldo nol
private string namaFile;
// konstruktor tanpa-parameter
public KreditForm()
{
InitializeComponent();
}
// menangani event jika tombol Buka File diklik
private void bukaButton_Click(object sender, EventArgs e)
{
// menciptakan kotak dialog
untuk membuka file
DialogResult hasil;
using ( OpenFileDialog pemilihFile = new OpenFileDialog() )
{
hasil =
pemilihFile.ShowDialog();
namaFile =
pemilihFile.FileName;
} // akhir using
// keluar dari event handler jika
pengguna mengklik Cancel
if ( hasil == DialogResult.OK )
{
// menampilkan error jika
pengguna menetapkan file tak-valid
if ( namaFile == string.Empty )
MessageBox.Show( "Nama File Tak-Valid", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
else
{
// menciptakan FileStream
untuk mendapatkan akses baca
masukan = new FileStream( namaFile,
FileMode.Open, FileAccess.Read );
// menetapkan file dari
mana data dibaca
pembacaFile
= new StreamReader( masukan );
// mengaktifkan semua
tombol, kecuali tombol Buka File
bukaButton.Enabled = false;
kreditButton.Enabled = true;
debitButton.Enabled = true;
nolButton.Enabled = true;
} // akhir else
} // akhir if
} // akhir metode bukaButton_Click
// dipanggil ketika tombol Saldo Kredit, Saldo Debit,
// dan Saldo Nol diklik pengguna
private void getSaldo_Click(object sender, EventArgs e)
{
// mengkonversi sender secara eksplisit menjadi objek dengan tipe tombol
Button tombolSender = ( Button )
sender;
// mendapatkan
teks dari Button yang diklik, yang menyimpan tipe akun
string tipeAkun = tombolSender.Text;
// membaca dan menampilkan
informasi file
try
{
// kembali ke awal file
masukan.Seek(
0, SeekOrigin.Begin );
tampilTextBox.Text = "Akun adalah:\r\n";
// menjelajah file sampai
akhir file
while ( true )
{
string[] bidangMasukan; // menyimpan
potongan data individual
Rekaman rekaman; // menyimpan setiap Rekaman ketika file dibaca
decimal saldo; // menyimpan saldo tiap Rekaman
// mendapatkan
rekamanBerikutnya pada file
string rekamanMasukan =
pembacaFile.ReadLine();
// di akhir file, keluar
metode
if ( rekamanMasukan == null
)
return;
bidangMasukan = rekamanMasukan.Split( ',' ); // memecah masukan
// menciptakan Rekaman
dari masukan
rekaman = new Rekaman(
Convert.ToInt32( bidangMasukan[ 0 ] ), bidangMasukan[ 1 ],
bidangMasukan[ 2 ], Convert.ToDecimal(bidangMasukan[ 3 ]));
// menyimpan bidang
terakhir pada saldo
saldo = rekaman.Saldo;
// menentukan apakah
menampilkan saldo
if (HarusTampil(saldo, tipeAkun))
{
//
menampilkan rekaman
string keluaran = rekaman.Akun + "\t\t" +
rekaman.NamaPertama + "\t\t" +
rekaman.NamaAkhir + "\t\t";
// menampilkan saldo
dengan format moneter
keluaran +=
String.Format( "{0:F}", saldo ) + "\r\n";
// menyalin keluaran
pada layar
tampilTextBox.AppendText( keluaran );
} // akhir if
} // akhir while
} // akhir try
// handle exception when file
cannot be read
catch ( IOException )
{
MessageBox.Show( "Tidak
dapat membaca file", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir catch
} // akhir metode getSaldo_Click
// menentukan apakah menampilkan rekaman atau tidak
private bool HarusTampil(decimal saldo, string
tipeAkun)
{
if ( saldo > 0M )
{
// menampilkan saldo kredit
if ( tipeAkun == "Saldo
Kredit" )
return true;
} // akhir if
else if ( saldo <
0M )
{
// menampilkan saldo debit
if ( tipeAkun == "Saldo
Debit" )
return true;
} // akhir else if
else // saldo == 0
{
// menampilkan saldo nol
if ( tipeAkun == "Saldo
Nol" )
return true;
} // akhir else
return false;
} // akhir metode harusTampil
//dipanggil ketika tombol Selesai diklik
private void selesaiButton_Click(object sender, EventArgs e)
{
if ( masukan != null )
{
// menutup file dan
StreamReader
try
{
// menutup StreamReader
pembacaFile.Close();
} // akhir try
// menangani eksepsi jika
FileStream tidak ada
catch ( IOException )
{
// memberitahu pengguna
ttg error penutupan file
MessageBox.Show( "Tidak dapat menutup file",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error );
} // akhir catch
} // akhir if
Application.Exit();
} // akhir metode selesaiButton_Click
}
}
|
Ketika pengguna mengklik tombol Buka File, program memanggil event handler bukaTombol_Click (baris 24-59). Baris 30 menciptakan sebuah OpenFileDialog, dan baris 32 memanggil
metode ShowDialog untuk menampilkan
dialog Open, dimana di dalamnya
pengguna memilih file yang akan dibuka. Baris 46-47 menciptakan sebuah objek FileStream dengan akses read-only
dan menugaskannya kepada referensi masukan.
Baris 50 menciptakan sebuah objek StreamReader
yang Anda gunakan untuk membaca teks dari FileStream.
Ketika pengguna mengkli tombol Saldo Kredit, Saldo Debit, atau Saldo Nol,
program akan memanggil metode getSaldo_Click
(baris 63-124). Baris 66 mengkonversi paksa parameter sender, yang merupakan sebuah referensi object yang menunjuk ke kendali yang dibangkitkan oleh event, menjadi sebuah objek Button. Baris 69 mengekstrak teks pada
objek Tombol, yang dipakai program
untuk menentukan apa tipe akun. Baris 75 menggunakan metode Seek dari kelas FileStream untuk mereset
pointer kembali ke awal file. Metode Seek
ini memampukan Anda untuk memposisikan-ulang pointer dengan menetapkan jumlah
byte (dari awal file, dari akhir file, atau dari posisi sekarang). Konstanta
enumerasi SeekOrigin.Begin untuk
menetapkan pointer ke awal file. Baris 80-116 mendefiniskan sebuah loop while yang menggunakan metode HarusTampil (baris 127-149) untuk
menentukan apakah menampilkan setiap rekaman pada file. Loop while membaca setiap rekaman secara
berulang dengan memanggil metode ReadLine
dari kelas StreamReader (baris 87)
dan memecah teks menjadi token-token (baris 92) yang dipakai untuk
menginisialisasi objek rekaman
(baris 95-97). Baris 89 menentukan apakah pointer telah meraih akhir file atau
tidak. Jika pointer telah meraih akhir file, maka ReadLine menghasilkan null.
Dengan demikian, program akan keluar dari metode getSaldo_Click (baris 90).
4.6
Serialisasi
Telah didemonstrasikan bagaimana
menuliskan bidang-bidang individual dari sebuah objek Rekaman ke suatu file teks dan telah didemonstrasikan bagaimana
membaca bidang-bidang itu dari suatu file dan menempatkan nilai-nilainya di
dalam suatu objek Rekaman pada
memori. Pada contoh-contoh itu, Rekaman
dipakai untuk mengumpulkan informasi pada tiap rekaman. Ketika
variabel-variabel instans untuk sebuah objek Rekaman dituliskan ke file, informasi tertentu akan hilang, seperti
tipe data dari tiap nilai. Sebagai contoh, jika nilai “3” dibaca dari sebuah
file, maka tidak diketahui apakah nilai itu berasal dari sebuah int, string, atau decimal.
Yang dimiliki hanya data, bukan tipe informasi, pada media penyimpanan. Jika
program yang membaca data ini mengetahui tipe objek apa dari data terkait, maka
data tersebut dapat dibaca secara langsung. Sebagai contoh, pada contoh
sebelumnya, Anda telah mengetahui bahwa Anda menempatkan sebuah int (nomor akun), diikuti dengan dua string (nama pertama dan nama akhir)
dan sebuah decimal (saldo). Anda
juga mengetahui bahwa nilai-nilai ini dipisahkan dengan koma, dengan satu
rekaman per baris. Jadi, Anda dapat mengkonversi string-string dan
mengkonversi nomor akun menjadi int
dan saldo menjadi decimal.
C# menyediakan mekanisme, yang dikenal
dengan serialisasi objek. Objek terserialkan merupakan sebuah objek yang
direpresentasikan sebagai suatu runtun byte yang memuat data objek, berikut
dengan informasi tentang tipe objek dan tipe data yang disimpan di dalam objek.
Setelah objek terserialkan ditulis ke dalam sebuah file, ia dapat dibaca dari
file dan dideserialisasi. Dengan demikian, informasi tipe dan byte-byte yang
merepresentasikan objek dan datanya dapat dipakai untuk menciptakan-ulang objek
di dalam memori.
Kelas BinaryFormatter (namespace
System.Runtime.Serialization.Formatters.Binary) memampukan semua objek ditulis ke
atau dibaca dari sebuah aliran. Metode Serialize
dari kelas BinaryFormatter
menuliskan suatu representasi objek ke file. Metode Deserialize dari kelas BinaryFormatter
membaca representasi ini dari file dan mengkonstruksi objek semula. Kedua
metode itu melemparkan eksepsi SerializationException
jika error terjadi selama serialisasi atau deserialisasi. Kedua metode itu
memerlukan sebuah objek Stream
(misalnya, FileStream) sebagai
parameter sehingga BinarryFormatter
dapat mengakses aliran yang benar.
4.7
Menciptakan File Akses-Sekuensial Menggunakan Serialisasi
Objek
Akan dimulai dengan menciptakan dan
menulis objek-objek terserialkan ke sebuah file akses-sekuensial. Pada bagian
ini, Anda akan mendaur-ulang kode dari bagian 4.3, sehingga Anda hanya fokus
pada fitur-fitur baru.
Mendefiniskan
Kelas RekamanTerserialkan
Akan dimulai dengan memodifikasi kelas Rekaman sehingga objek-objek dari kelas
ini dapat diserialkan. Kelas RekamanTerserialkan
(Gambar 4.12) dibubuhi atribut [Serializable]
pada baris 7, yang mengindikasikan bahwa objek-objek dari kelas RekamanTerserialkan dapat diserialkan.
Kelas-kelas untuk objek-objek yang akan menulis ke atau membaca dari suatu
aliran harus mencantumkan atribut ini pada deklarasinya atau harus mewarisi
implementasi ISerializable.
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
|
//
Gambar 4.12: RekamanTerserialkan.cs
//
Kelas yang merepresentasikan sebuah rekaman data.
using
System;
namespace CiptakanFileTerserialkan
{
[Serializable]
public
class RekamanTerserialkan
{
// properti Akun implementasi-diri
public
int Akun { get; set; }
// properti NamaPertama
implementasi-diri
public
string NamaPertama { get; set; }
// properti NamaAkhir
implementasi-diri
public
string NamaAkhir { get; set; }
// properti Saldo implementasi-diri
public
decimal Saldo { get; set; }
// konstruktor tanpa parameter
menetapkan nilai-nilai default
public
RekamanTerserialkan()
: this(0, string.Empty, string.Empty, 0M)
{
} // akhir konstruktor
// konstruktor teroverload menetapkan
nilai-nilai parameter
public
RekamanTerserialkan(int nilaiAkun,
string nilaiNamaPertama,
string nilaiNamaAkhir, decimal
nilaiSaldo)
{
Akun = nilaiAkun;
NamaPertama = nilaiNamaPertama;
NamaAkhir = nilaiNamaAkhir;
Saldo = nilaiSaldo;
} // akhir konstruktor
} // akhir kelas RekamanTerserialkan
} // akhir namespace CiptakanFileTerserialkan
|
Pada sebuah kelas yang membubuhkan
atribut [Serializable] atau yang
mengimplamentasikan antarmuka ISerializable,
Anda perlu memastikan bahwa setiap variabel instans dari kelas itu juga serializable. Semua variabel
tipe-sederhana dan string juga serializable.
Untuk variabel bertipe referensi, Anda perlu memeriksa deklarasi kelas untuk
memastikan bahwa tipe tersebut terserialkan. Secara default, objek array adalah
serializable.
Menggunakan
Aliran Serialisasi untuk Menciptakan File
Selanjutnya, akan diciptakan sebuah
file akses-sekuensial dengan serialisasi (Gambar 4.13). Untuk menguji program
ini, digunakan data yang sama pada contoh sebelumnya untuk menciptakan file.
Baris 14 menciptakan sebuah objek BinaryFormatter
untuk menuliskan objek-objek terserialkan. Baris 112-113 membuka FileStream, sehingga program dapat
menuliskan objek-objek terserialkan ke dalamnya. Argumen string yang dilewatkan kepada konstruktor FileStream merepresentasikan nama dan path dari file yang akan dibuka.
Program ini mengasumsikan bahwa data
dituliskan secara benar dan dengan urutan yang sesuai dengan nomor-rekaman. Event handler enterButton_Click (baris 131-186) melakukan operasi penulisan.
Baris 137 menciptakan sebuah objek RekamanTerserialkan,
yang ditugasi nilai-nilai pada baris 153-159. Baris 162 memanggil metode Serialize untuk menuliskan objek RekamanTerserialkan ke file keluaran.
Metode Serialize memerlukan objek FileStream sebagai argumen pertama
sehingga BinaryFormatter dapat
munuliskan argumen keduanya ke file yang tepat. Hanya satu statemen yang
diperlukan untuk keseluruhan objek. Jika terjadi masalah selama serialisasi,
eksepsi SerializationException akan
dilemparkan, yang ditangkap pada baris 178-182.
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
// Gambar 4.13:
CiptakanFileTerserialkan.cs
// Menciptakan sebuah file
akses-sekuensial dengan serialisasi.
using System;
using
System.Windows.Forms;
using System.IO;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Runtime.Serialization;
namespace
CiptakanFileTerserialkan
{
public partial class
CiptakanFileTerserialkanForm : Form
{
protected int JumlahTextBox = 4; // jumlah
TextBoxes pada Form
private
BinaryFormatter formatter = new
BinaryFormatter();
private FileStream
keluaran; // aliran untuk menuliskan ke file
// konstanta-konstanta enumerasi untuk menetapkan indeks-indeks
TextBox
public enum IndeksTextBox
{
AKUN,
PERTAMA,
AKHIR,
SALDO
} // akhir enum
// konstruktor tanpa-parameter
public
CiptakanFileTerserialkanForm()
{
InitializeComponent();
} // akhir konstruktor tanpa-parameter
// menghapus semua TextBox
public void BersihTextBox()
{
// menjelajah setiap Control pada
form
foreach (Control guiControl in
Controls)
{
// menentukan apakan Control
adalah TextBox
if (guiControl is
TextBox)
{
// menghapus TextBox
((TextBox)guiControl).Clear();
} // akhir if
} // akhir for
} // akhir metode BersihTextBox
// menetapkan nilai-nilai TextBox
menjadi nilai-nilai array string
public void SetNilaiTextBox(string[] nilai2)
{
// menentukan apakah array string
memiliki panjang yang tepat
if (nilai2.Length != JumlahTextBox)
{
// melempar eksepsi jika
panjang tidak tepat
throw (new ArgumentException("Harus ada " +
(JumlahTextBox + 1) +
" string pada array"));
} // akhir if
// menetapkan
nilai-nilai array jika array memiliki panjang yang tepat
else
{
// menetapkan nilai-nilai array menjadi nilai-nilai TextBox
akunTextBox.Text =
nilai2[(int)IndeksTextBox.AKUN];
namaPertamaTextBox.Text =
nilai2[(int)IndeksTextBox.PERTAMA];
namaAkhirTextBox.Text = nilai2[(int)IndeksTextBox.AKHIR];
akunTextBox.Text =
nilai2[(int)IndeksTextBox.SALDO];
} // akhir else
} // akhir metode SetNilaiTextBox
// menghasilkan nilai-nilai TextBox sebagai array string
public string[] GetNilaiTextBox()
{
string[] nilai2 = new string[JumlahTextBox];
// menyalin semua bidang TextBox
ke array string
nilai2[(int)IndeksTextBox.AKUN] = akunTextBox.Text;
nilai2[(int)IndeksTextBox.PERTAMA] = namaPertamaTextBox.Text;
nilai2[(int)IndeksTextBox.AKHIR] = namaAkhirTextBox.Text;
nilai2[(int)IndeksTextBox.SALDO] = saldoTextBox.Text;
return nilai2;
} // akhir metode GetNilaiTextBox
// menangani event Click untuk simpanButton
private void simpanButton_Click(object sender, EventArgs e)
{
// menciptakan dan menampilkan kotak dialog untuk menyimpan file
DialogResult hasil; // hasil dari
SaveFileDialog
string namaFile; // nama file yang memuat data
using (SaveFileDialog pemilihFile = new SaveFileDialog())
{
pemilihFile.CheckFileExists =
false; // menciptakan file
hasil =
pemilihFile.ShowDialog();
namaFile =
pemilihFile.FileName; // nama file untuk disimpan
} // akhir using
// memastikan bahwa pengguna
mengklik "OK"
if (hasil == DialogResult.OK)
{
// menampilkan error jika pengguna menetapkan file tak-valid
if (namaFile == string.Empty)
MessageBox.Show("Nama Tak Valid",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
else
{
// menyimpan file via FileStream jika pengguna
menetapkan file valid
try
{
// membuka file
dengan akses write
keluaran =
new FileStream(namaFile,
FileMode.OpenOrCreate, FileAccess.Write);
// menon-aktifkan tombol Simpan dan mengaktifkan tombol Enter
simpanButton.Enabled
= false;
enterButton.Enabled =
true;
} // akhir try
// menangani eksepsi jika
ada masalah pembukaan file
catch (IOException)
{
// memberitahu
pengguna jika file tidak ada
MessageBox.Show("Error
pembukaan file", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
} // akhir catch
} // akhir else
} // akhir if
} // akhir metode simpanButton_Click
// menangani event Click untuk enterButton
private void enterButton_Click(object sender, EventArgs e)
{
// menyimpan nilai-nilai TextBox
string[] nilai2 = GetNilaiTextBox();
// RekamanTerserialkan
memuat nilai-nilai TextBox untuk diserialkan
RekamanTerserialkan
rekaman = new
RekamanTerserialkan();
// menentukan apakah bidang akun kosong
if (nilai2[(int)IndeksTextBox.AKUN]
!= string.Empty)
{
// menyimpan nilai-nilai TextBox dalam RekamanTerserialkan dan
menyerialkannya
try
{
// mendapatkan nilai
nomor-akun dari TextBox
int nomorAkun = Int32.Parse(
nilai2[(int)IndeksTextBox.AKUN]);
// menentukan apakah
nomorAkun valid
if (nomorAkun > 0)
{
// menyimpan
bidang-bidang TextBox di dalam Rekaman
rekaman.Akun =
nomorAkun;
rekaman.NamaPertama =
nilai2[(int)
IndeksTextBox.PERTAMA];
rekaman.NamaAkhir =
nilai2[(int)
IndeksTextBox.AKHIR];
rekaman.Saldo =
Decimal.Parse(
nilai2[(int)IndeksTextBox.SALDO]);
// menuliskan RekamanTerserialkan ke
FileStream
formatter.Serialize(keluaran,
rekaman);
} // akhir if
else
{
// memberitahu
pengguna jika nomor akun tak-valid
MessageBox.Show("Nomor
Akun Tak-Valid", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
} // akhir else
} // akhir try
// memberitahu pengguna jika error terjadi selama operasi penampilan
catch (SerializationException)
{
MessageBox.Show("Error Penulisan ke File", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
} // akhir catch
// memberitahu pengguna jika error terjadi akibat format parameter
catch (FormatException)
{
MessageBox.Show("Format Tak-Valid", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
} // akhir catch
} // akhir if
BersihTextBox(); // membersihkan
nilai-nilai TextBox
} // akhir metode enterButton_Click
// event handler untuk tombol Keluar
private void keluarButton_Click(object sender, EventArgs e)
{
// menentukan apakah file ada
if (keluaran != null)
{
try
{
// menutup FileStream
keluaran.Close();
} // akhir try
// memberitahu pengguna
tentang error penutupan file
catch (IOException)
{
MessageBox.Show("Tidak bisa membuka file", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
} // akhir catch
} // akhir if
Application.Exit();
} // akhir metode keluarButton_Click
} // akhir kelas CiptakanFileTerserialkanForm
} // akhir namespace
CiptakanFileTerserialkan
|
4.8
Membaca dan Mendeserialisasi Data dari File Biner
Gambar 4.15 membaca dan menampilkan isi
dari file yang diciptakan oleh program pada Gambar 4.13. Program ini
menciptakan objek BinaryFormatter
yang akan dipakai untuk membaca objek. Program membuka file dengan menciptakan
sebuah objek FileStream. Nama file
yang akan dibuka ditetapkan sebagai argumen pertama kepada konstruktor FileStream.
Program membaca objek-objek dari sebuah
file pada event handler rekamanBerikutnyaButton_Click. Anda menggunakan metode Deserialize
(dari BinaryFormatter yang
diciptakan) untuk membaca data. Perhatikan bahwa Anda mengkonversi paksa (cast) hasil dari Deserialize menjadi tipe RekamanTerserialkan.
Hal ini diperlukan, karena Deserialize
menghasilkan sebuah referensi dari tipe object dan Anda perlu mengakses
properti-properti yang ada pada kelas Rekaman-Terserialkan.
Jika error terjadi selama serialisasi, maka eksepsi SerializationException akan dilemparkan, dan objek FileStream akan ditutup.
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
|
//
Gambar 4.14: RekamanTerserialkan.cs
// Kelas
yang merepresentasikan sebuah rekaman data.
using
System;
namespace CiptakanFileTerserialkan
{
[Serializable]
public
class RekamanTerserialkan
{
// properti Akun implementasi-diri
public
int Akun { get; set; }
// properti NamaPertama
implementasi-diri
public
string NamaPertama { get; set; }
// properti NamaAkhir
implementasi-diri
public
string NamaAkhir { get; set; }
// properti Saldo implementasi-diri
public
decimal Saldo { get; set; }
// konstruktor tanpa parameter
menetapkan nilai-nilai default
public
RekamanTerserialkan()
: this(0, string.Empty, string.Empty, 0M)
{
} // akhir konstruktor
// konstruktor teroverload menetapkan
nilai-nilai parameter
public
RekamanTerserialkan(int nilaiAkun,
string nilaiNamaPertama,
string nilaiNamaAkhir, decimal
nilaiSaldo)
{
Akun = nilaiAkun;
NamaPertama = nilaiNamaPertama;
NamaAkhir = nilaiNamaAkhir;
Saldo = nilaiSaldo;
} // akhir konstruktor
} // akhir kelas RekamanTerserialkan
} //
akhir namespace BacaFileTerserialkan
|
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
// Gambar 4.15:
BacaFileTerserialkanForm.cs
// Membaca sebuah file akses-sekuensial
dengan deserialisasi.
using System;
using
System.Windows.Forms;
using System.IO;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Runtime.Serialization;
namespace
BacaFileTerserialkan
{
public partial class
BacaFileTerserialkanForm : Form
{
protected int JumlahTextBox = 4; // jumlah
TextBoxes pada Form
// objek untuk deserialisasi RekamanTerserialkan dalam format biner
private
BinaryFormatter pembaca = new
BinaryFormatter();
private FileStream masukan;
// aliran untuk pembacaan file
// konstanta-konstanta enumerasi untuk menetapkan indeks-indeks
TextBox
public enum IndeksTextBox
{
AKUN,
PERTAMA,
AKHIR,
SALDO
} // akhir enum
// konstruktor tanpa-parameter
public
BacaFileTerserialkanForm()
{
InitializeComponent();
} // akhir konstruktor
// menghapus semua TextBox
public void BersihTextBox()
{
// menjelajah setiap Control pada
form
foreach (Control guiControl in
Controls)
{
// menentukan apakan Control
adalah TextBox
if (guiControl is
TextBox)
{
// menghapus TextBox
((TextBox)guiControl).Clear();
} // akhir if
} // akhir for
} // akhir metode BersihTextBox
// menetapkan nilai-nilai TextBox menjadi nilai-nilai array string
public void SetNilaiTextBox(string[]
nilai2)
{
// menentukan apakah array string
memiliki panjang yang tepat
if (nilai2.Length != JumlahTextBox)
{
// melempar eksepsi jika
panjang tidak tepat
throw (new
ArgumentException("Harus ada " +
(JumlahTextBox + 1) +
" string pada array"));
} // akhir if
// menetapkan
nilai-nilai array jika array memiliki panjang yang tepat
else
{
// menetapkan nilai-nilai array menjadi nilai-nilai TextBox
akunTextBox.Text =
nilai2[(int)IndeksTextBox.AKUN];
namaPertamaTextBox.Text =
nilai2[(int)IndeksTextBox.PERTAMA];
namaAkhirTextBox.Text = nilai2[(int)IndeksTextBox.AKHIR];
akunTextBox.Text =
nilai2[(int)IndeksTextBox.SALDO];
} // akhir else
} // akhir metode SetNilaiTextBox
//dipanggil ketika
pengguna mengklik tombol Buka File
private void bukaFileButton_Click(object sender, EventArgs e)
{
// menciptakan dan menampilkan kotak dialog untuk membaca file
DialogResult hasil; // hasil dari
SaveFileDialog
string namaFile; // nama file yang memuat data
using (OpenFileDialog pemilihFile = new OpenFileDialog())
{
hasil =
pemilihFile.ShowDialog();
namaFile = pemilihFile.FileName;
// nama file untuk disimpan
} // akhir using
// memastikan bahwa pengguna
mengklik "OK"
if (hasil == DialogResult.OK)
{
BersihTextBox();
// menampilkan error jika pengguna menetapkan file tak-valid
if (namaFile == string.Empty)
MessageBox.Show("Nama Tak Valid", "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
else
{
// menciptakan
FileStream untuk mendapatkan akses baca
masukan = new FileStream(
namaFile,
FileMode.Open, FileAccess.Read );
// menon-aktifkan tombol Simpan dan mengaktifkan tombol Enter
bukaFileButton.Enabled = false;
rekamanBerikutnyaButton.Enabled = true;
} // akhir else
} // akhir if
} // akhir metode bukaFileButton_Click
//dipanggil ketika pengguna mengklik tombol Rekaman Berikutnya
private void rekamanBerikutnyaButton_Click(object sender, EventArgs e)
{
try
{
// mendapatkan
RekamanTerserialkan berikutnya pada file
RekamanTerserialkan rekaman =
(RekamanTerserialkan)
pembaca.Deserialize(masukan);
// menyimpan nilai-nilai RekamanTerserialkan pada array string sementara
string[] nilai2 = new
string[] {
rekaman.Akun.ToString(),
rekaman.NamaPertama.ToString(),
rekaman.NamaAkhir.ToString(),
rekaman.Saldo.ToString()
};
// menyalin nilai-nilai array-string
ke nilai-nilai TextBox
SetNilaiTextBox( nilai2 );
} // akhir try
// menangani eksepsi ketika tidak
ada RekamanTerserialkan pada file
catch ( SerializationException )
{
masukan.Close(); // menutup FileStream
bukaFileButton.Enabled = true; // mengaktifkan tombol Buka
File
// menonaktifkan tombol
Rekaman Berikutnya
rekamanBerikutnyaButton.Enabled = false;
BersihTextBox();
// memberitahu pengguna jika tidak ada RekamanTerserialkan pada file
MessageBox.Show( "Tidak ada rekaman lain pada file", string.Empty,
MessageBoxButtons.OK,
MessageBoxIcon.Information );
} // akhir catch
} // akhir metode rekamanBerikutnyaButton_Click
} // akhir kelas BacaFileTerserialkanForm
} akhir namespace BacaFileTerserialkan
|
No comments:
Post a Comment