Thứ Bảy, 28 tháng 3, 2015

Bài 38(Java):Sử dụng luồng ký tự trong Java

download
Ở những bài trước, mình đã giới thiệu với các bạn việc sử dụng luồng byte để nhập và xuất dữ liệu ký tự. Nhưng trong nhiều trường hợp luồng byte không phải là cách tốt nhất để quản lý nhập xuất dữ liệu ký tự. Trong lập trình Java có kiểu luồng ký tự phục vụ riêng cho việc nhập xuất dữ liệu trên luồng. Mức trên cùng là 2 lớp trừu tường ReaderWriter. Các lớp dẫn xuất từ Reader Writer hỗ trợ thao tác trên các luồng ký tự Unicode.
- Những phương thức định nghĩa trong lớp trừu tượng


Untitled

Bài này sẽ là nhập xuất ký tự và chuỗi sử dụng luồng ký tự, bài sau mình sẽ giới thiệu cách đọc ghi file dùng luồng ký tự!

1, Nhập Console dùng luồng ký tự:

- Để đọc dữ liệu nhập từ Console thì lớp tốt nhất là lớp BufferdReader. Nhưng ở đây, chúng ta không có cách nào xây dựng 1 lớp BufferedReader trực tiếp từ System.in vì thế nên cần chuyển nó thành luồng ký tự bằng cách dùng InputStreamReader để chuyển byte thành ký tự!
- Để có được một đối tượng InputStreamReader gắn với System.in ta dùng constructor của InputStreamReader.
InputStreamReader(InputStream inputStream)
- Tiếp theo dùng đối tượng InputStreamReader đã tạo ra để tạo ra một BufferedReader dùng constructor BufferedReader.
BufferedReader(Reader inputReader)

**Ví dụ 1: Tạo một đối tượng BufferedReader gắn với bàn phím:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- Sau khi thực hiện câu lệnh trên, br là một luồng ký tự gắn với Console thông qua System.in.
Tiếp theo ta sẽ dùng BufferedReader để đọc từng ký tự từ Console. Việc đọc kết thúc khi gặp dấu chấm (dấu chấm để kết thúc chương trình).
PHP:
package javaandroidvn;
 
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;

public class 
JavaAndroidVn {

    public static 
void main(String[] argsthrows IOException {
        
char c;
        
BufferedReader br = new BufferedReader(
                new 
InputStreamReader(System.in));

        
System.out.println("Nhập chuỗi ký tự, kết thúc bằng dấu chấm .");

        do {
            
= (charbr.read();
            
System.out.println(c);
        } while (
!= '.');

    }
}
**Ví dụ 2: Dùng BufferedReader đọc chuỗi ký tự từ Console. In ký tự vừa nhập vào!
PHP:
package javaandroidvn;
 
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;

public class 
JavaAndroidVn {

    public static 
void main(String[] argsthrows IOException {

        
// Tạo đối tượng BufferedReader sử dụng System.in
        
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
String str;
        
System.out.print("Nhập chuỗi: ");
        
//Nhập chữ không dấu thôi nhé!
        
str br.readLine();
        
System.out.println("Chuỗi vừa nhập là: " str);
    }
}
2, Xuất dữ liệu ra Console dùng luồng ký tự

Tiếp tục sẽ là 1 cách khác để xuất dữ liệu ra Console. Ở đây mình nhắc tới lớp PrinWriter, nó là 1 trong các lớp luồng ký tự. Ta cần phải chỉ định System.out cho luồng xuất.

**Ví dụ 3: Tạo đối tượng PrintWriter để xuất dữ liệu ra Console, dùng lệnh:
PrintWriter pw = new PrintWriter(System.out, true);
Tiếp theo dùng PrintWriter để xuất dữ liệu ra Console
PHP:
package javaandroidvn;
 
import java.io.IOException;import java.io.PrintWriter;

public class 
JavaAndroidVn {

    public static 
void main(String[] argsthrows IOException {
        
int i 2013;
        
String str "Android.Vn ";
        
//Xuất dữ liệu sử dụng PrintWriter
        
PrintWriter pw = new PrintWriter(System.outtrue);
        
pw.println("Using a PrintWriter.");
        
pw.println(str+i);

    }
}

Bài 37( Java):File truy cập ngẫu nhiên (Random Access Files) trong Java

RandomAccessFile-Hierarchy

- Bên cạnh việc xử lý xuất nhập trên file theo kiểu tuần tự thông qua các luồng, java cũng hỗ trợ truy cập ngẫu nhiên nội dung của một file nào đó dùng RandomAccessFile.
- RandomAccessFile không dẫn xuất từ InputStream hay OutputStream mà nó hiện thực các interface DataInput, DataOutput (có định nghĩa các phương thức I/O cơ bản).
- RandomAccessFile hỗ trợ vấn đề định vị con trỏ file bên trong một file dùng phương thức seek(long newPos).

2, Ví dụ:

Bài này lý thuyết ngắn, nhưng ví dụ hơi dài, chủ yếu là đọc code để hiểu! :D
Chương trình sau sẽ ghi 9 số kiểu double xuống file, rồi đọc lên theo thứ tự ngẫu nhiên. Các bạn xem code có chỗ nào không hiểu cứ bình luận phía dưới, mọi người cùng nhau giải quyết! ^^
PHP:
package javaandroidvn;
 
import java.io.*;

class 
JavaAndroidVn {

    public static 
void main(String args[]) throws IOException {
        
double data[] = {11.213.6255.6117.922007.968.99.910.0100.6};
        
double d;
        
RandomAccessFile raf;

        try {
            
raf = new RandomAccessFile("E:\\random.dat""rw");
        } catch (
FileNotFoundException exc) {
            
System.out.println("Cannot open file.");
            return;
        }

        
// Write values to the file.
        
for (int i 0data.lengthi++) {
            try {
                
raf.writeDouble(data[i]);

            } catch (
IOException exc) {
                
System.out.println("Error writing to file.");
                return;
            }
        }

        try {
// Now, read back specific values
            
raf.seek(8); // seek to first double
            
raf.readDouble();
            
System.out.println("First value is " d);
            
raf.seek(1); // seek to second double
            
raf.readDouble();
            
System.out.println("Second value is " d);
            
raf.seek(3); // seek to fourth double
            
raf.readDouble();
            
System.out.println("Fourth value is " d);
            
System.out.println();
 
//Read All data 
            
System.out.println("Read all: ");
            for (
int i 0data.lengthi++) {
                
raf.seek(i); // seek to ith double
                
raf.readDouble();
                
System.out.print(" ");
            }
            
System.out.println("");
 
// Now, read every other value.
            
System.out.println("Here is every other value: ");
            for (
int i 0data.length+= 2) {
                
raf.seek(i); // seek to ith double
                
raf.readDouble();
                
System.out.print(" ");
            }


            
System.out.println("\n");
        } catch (
IOException exc) {
            
System.out.println("Error seeking or reading.");
        }

        
raf.close();
    }
}

Bài 36(Java):Đọc và ghi dữ liệu nhị phân dùng luồng byte trong Java

byte-stream
​Ở bài trước chúng ta đã đọc và ghi các bytes dữ liệu là các ký tự mã ASCII. Để đọc và ghi những giá trị nhị phân của các kiểu dữ liệu trong java, chúng ta sử dụng DataInputStream và DataOutputStream.

1, DataOutputStream:

Dùng để hiện thực interface DataOuput.
Interface DataOutput có các phương thức cho phép ghi tất cả những kiểu dữ liệu cơ sở của java đến luồng (theo định dạng nhị phân).


Untitled1

Contructor: DataOutputStream(OutputStream outputStream)
OutputStream: là luồng xuất dữ liệu. Để ghi dữ liệu ra file thì đối tượng outputStream có thể là FileOutputStream.

2, DataInputStream:

Dùng để hiện thực interface DataInput.
Interface DataInput có các phương thức cho phép đọc tất cả những kiểu dữ liệu cơ sở của java (theo định dạng nhị phân).

Untitled2

Contructor: DataInputStream(InputStream inputStream)
InputStream: là luồng nhập dữ liệu. Để đọ dữ liệu từ file thì đối tượng InputStream có thể là FileInputStream.​

Ví dụ: Dùng DataOutputStream và DataInputStream để ghi và đọc những kiểu dữ liệu khác nhau trên file.
*** Chú ý: Trong ví dụ dưới mình bổ sung thêm cách đọc và ghi chuỗi nữa nhé! (writeUTF và readUTF)
PHP:
package javaandroidvn;
 
import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;

class 
JavaAndroidVn {

    public static 
void main(String args[]) throws IOException {

        
DataOutputStream dataOut;
        
DataInputStream dataIn;
        
int i 2013;
        
double d 3.14;
        
boolean b true;
        
char ch 'A';
        
String str "Android.Vn";

        try {
            
dataOut = new DataOutputStream(new FileOutputStream("E:\\androidvn.dat"));
        } catch (
IOException exc) {
            
System.out.println("Cannot open file.");
            return;
        }

        try {
            
System.out.println("Writing Int: " i);
            
dataOut.writeInt(i);
            
System.out.println("Writing Double: " d);
            
dataOut.writeDouble(d);
            
System.out.println("Writing boolean: " b);
            
dataOut.writeBoolean(b);
            
System.out.println("Writing Double: " 12.2 7.4);
            
dataOut.writeDouble(12.2 7.4);
            
System.out.println("Writing char: " ch);
            
dataOut.writeChar(ch);
            
System.out.println("Writing String: " str);
            
dataOut.writeUTF(str);
        } catch (
IOException exc) {
            
System.out.println("Write error.");
        }

        
dataOut.close();
        
System.out.println();
 
// Next, read and show them from file

        
try {
            
dataIn = new DataInputStream(
                    new 
FileInputStream("E:\\androidvn.dat"));
        } catch (
IOException exc) {
            
System.out.println("Cannot open file.");
            return;
        }


        try {
            
dataIn.readInt();
            
System.out.println("Reading Int: " i);
            
dataIn.readDouble();
            
System.out.println("Reading Boolean: " d);
            
dataIn.readBoolean();
            
System.out.println("Reading Double: " b);
            
dataIn.readDouble();
            
System.out.println("Reading Double: " d);
            
ch dataIn.readChar();
            
System.out.println("Reading char: " ch);
            
str dataIn.readUTF();
            
System.out.println("Reading String: " str);
        } catch (
IOException exc) {
            
System.out.println("Read error.");
        }
        
dataIn.close();
    }
}

Bài 35(Java):Đọc và ghi file dùng luồng byte trong Java

byte-stream
​- Với cách đọc ghi này ta tạo một luồng Byte gắn với file chỉ định dùng FileInputStream và FileOutputStream.
- Để mở một file, đơn giản chỉ cần tạo một đối tượng của những lớp này, tên file cần mở là thông số trong constructor. Khi file mở, việc đọc và ghi dữ liệu trên file được thực hiện một cách bình thường thông qua các phương thức cung cấp trong luồng.

1, Đọc dữ liệu từ file dùng luồng byte:

- Mở một file để đọc dữ liệu FileInputStream(String fileName) throws FileNotFoundException. Nếu file không tồn tại: thì ném ra FileNotFoundException.
- Đọc dữ liệu: dùng phương thức read():
int read( ) throws IOException: đọc từng byte từ file và trả về giá trị của byte đọc được. Trả về -1 khi hết file, và ném ra IOException khi có lỗi đọc.
- Đóng file: dùng phương thức close():
void close( ) throws IOException: sau khi làm việc xong cần đóng file để giải phóng tài nguyên hệ thống đã cấp phát cho file.

Ví dụ:

package javaandroidvn;
 
import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;
 
/*
Tạo file androidvn.txt ở ổ E, gõ nội dung văn bản vào đó rồi lưu lại!
Hiển thị nội dung của một file tên androidvn.txt lưu tại E:\androidvn.txt
*/
public class JavaAndroidVn {

    public static 
void main(String args[]) throws IOException {

        
FileInputStream f;
        try {
            
= new FileInputStream("E:\\androidvn.txt");
        } catch (
FileNotFoundException exc) {
            
System.out.println("File Not Found");
            return;
        } catch (
ArrayIndexOutOfBoundsException exc) {
            
System.out.println("Usage: ShowFile File");
            return;
        }

        
// Đọc cho tới cuối file
        
int i;
        do {
            
f.read();
            if (
!= -1) {
                
System.out.print((chari);
            }
        } while (
!= -1);
        
f.close();
    }
}
2. Ghi dữ liệu xuống file dùng luồng byte:

- Mở một file để ghi dữ liệu FileOutputStream(String fileName) throws FileNotFoundException
Nếu file không tạo được: thì ném ra FileNotFoundException
- Ghi dữ liệu xuống: dùng phương thức write():
void write(int byteval) throws IOException: ghi một byte xác định bởi tham số byteval xuống file, và ném ra IOException khi có lỗi ghi.
- Đóng file: dùng phương thức close():
void close( ) throws IOException: sau khi làm việc xong cần đóng file để giải phóng tài nguyên hệ thống đã cấp phát cho file.

Ví dụ: Chương trình sẽ tự tạo file "E:\\output.txt", ghi vào các ký tự từ a -> z
package javaandroidvn;
 
import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;

class 
JavaAndroidVn {

    public static 
void main(String args[]) throws IOException {
        
FileOutputStream fout;
 
// Tạo file mới!
        
try {
            
fout = new FileOutputStream("E:\\output.txt");
        } catch (
FileNotFoundException exc) {
            
System.out.println("Error Opening OutputFile ");
            return;
        }
 
// Ghi file theo từng ký tự từ a -> z
        
int i 'a';
        
int j 'z';
        for (
'a'<= ji++) {
            
fout.write(i);
        }
        
fout.close();
    }
}
3, Copy file trong Java:

Dưới đây là 1 chương trình đơn giản để copy file trong Java, nó chưa thực sự tối ưu vì mình thấy tốc độ của nó rất chậm. Bạn có thể dùng để copy bất cứ định dạng nào, không phải chỉ riêng file văn bản! Nó dùng cách đọc ghi file dùng luồng byte như trên!
PHP:
package javaandroidvn;
 
import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;

class 
JavaAndroidVn {

    public static 
void main(String args[]) throws IOException {
        
FileInputStream fin;
        
FileOutputStream fout;
        try {
// open input file
            
try {
                
fin = new FileInputStream("E:\\in.mp3");
            } catch (
FileNotFoundException exc) {
                
System.out.println("Input File Not Found");
                return;
            }
 
// open output file
            
try {
                
fout = new FileOutputStream("E:\\out.mp3");
            } catch (
FileNotFoundException exc) {


                
System.out.println("Error Opening OutputFile ");
                return;
            }
        } catch (
ArrayIndexOutOfBoundsException exc) {
            
System.out.println("Usage: CopyFile From To");
            return;
        }
 
// Copy File
        
int i;
        try {
            do {
                
fin.read();
                if (
!= -1) {
                    
fout.write(i);
                }
            } while (
!= -1);
        } catch (
IOException exc) {
            
System.out.println("File Error");
        }
        
fin.close();
        
fout.close();
    }
}

Bài 34(Java):Giới thiệu luồng và tập tin (Streams & Files) trong Java

0
​- Với những kiến thức ở các bài trước, sau khi chương trình kết thúc, dữ liệu sẽ biến mất, vì nó chỉ được lưu tạm trong RAM. Tắt chương trình hoặc máy tắt đột ngột cũng đồng nghĩa với việc mất sạch dữ liệu trong chương trình. Điều đó thực sự sẽ không thể đáp ứng được nhu cầu, vì thực tế hầu như các chương trình đều cần lưu được lại dữ liệu để chúng ta có thể mở lại xem, hoặc tiếp tục chương trình, nạp thêm dữ liệu ...
- Ở bài này, chúng ta sẽ cùng nhau làm quen với khái niệm luồng (streams) và file. Công việc này nó thuộc 1 phần của xử lý các luồng.
Từ đó chúng ta biết các làm cho chương trình có thể đọc, ghi dữ liệu trong bộ nhớ lưu trữ, sau này còn có thể liên quan tới cách xử lý, trao đổi dữ liệu thông qua các kết nối mạng!

1, Luồng (Streams)

a, Khái niệm luồng
- Việc nhập xuất dữ liệu trong thực tế rất đa dạng. Nhập dữ liệu có thể là từ bàn phím, từ trên mạng, máy scan, camera, .v.v..v. Xuất dữ liệu có thể là ghi ra bộ nhớ, in ra màn hình, máy in, ..v..v.. Những hoạt động đó được gọi chung lại 1 khái niệm gọi là luồng (stream). Luồng là nơi có thể “sản xuất” và “tiêu thụ” thông tin.
- Trong lập trình Java, luồng thường được hệ thống xuất nhập gắn kết với một thiết bị vật lý. Thực tế có rất nhiều các thiết bị vật lý khác nhau, nhưng các luồng lại có cùng 1 nguyên tắc giống nhau để chúng ta dễ dàng xử lý. Vì vậy cùng một lớp, phương thức xuất nhập có thể dùng chung cho các thiết bị vật lý khác nhau. Ví dụ cùng là một phương thức có thể dùng để
ghi dữ liệu ra console, đồng thời cũng có thể dùng để ghi dữ liệu xuống một file trên đĩa. Java hiện thực luồng bằng tập hợp các lớp phân cấp trong gói java.io.
- Java định nghĩa 2 kiểu luồng: byte và ký tự (phiên bản gốc chỉ định nghĩa kiểu luồng byte, và sau đó luồng ký tự được thêm vào trong các phiên bản về sau).
- Luồng ký tự được thiết kế hỗ trợ việc nhập xuất dữ liệu kiểu ký tự (Unicode). Trong một vài trường hợp luồng ký tự sử dụng hiệu quả hơn luồng byte, nhưng ở mức hệ thống thì tất cả những xuất nhập đều phải qui về byte. Luồng ký tự hỗ trợ hiệu quả chỉ đối với việc quản lý, xử lý các ký tự.

b, Luồng byte (Byte Streams)
- Các luồng byte được định nghĩa dùng hai lớp phân cấp. Mức trên cùng là hai lớp trừu tượng InputStream và OutputStream. InputStream định nghĩa những đặc điểm chung cho những luồng nhập byte. OutputStream mô tả cách xử lý của các luồng xuất byte.
- Các lớp con dẫn xuất từ hai lớp InputStream và OutputStream sẽ hỗ trợ chi tiết tương ứng với việc đọc ghi dữ liệu trên những thiết bị khác nhau. Có rất nhiều các lớp khác nhau, nhưng khi bạn đã nắm vững, sử dụng thành thạo một luồng byte nào đó thì bạn sẽ dễ dàng làm việc với những luồng còn lại nhanh thôi! :D


1

c, Luồng ký tự (Character Streams)
- Các luồng ký tự được định nghĩa dùng hai lớp phân cấp. Mức trên cùng là hai lớp trừu tượng Reader và Writer.
- Lớp Reader dùng cho việc nhập dữ liệu của luồng, lớp Writer dùng cho việc xuất dữ liệu cua luồng. Những lớp dẫn xuất từ Reader và Writer thao tác trên các luồng ký tự Unicode.

2

d, Những luồng được định nghĩa trước (The Predefined Streams)
- Tất cả các chương trình viết bằng java luôn tự động import gói java.lang. Gói này có định nghĩa lớp System, bao gồm một số đặc điểm của môi trường run-time, nó có ba biến luồng được định nghĩa trước là in, out và err, các biến này là các fields được khai báo static trong lớp System.

- System.out: luồng xuất chuẩn, mặc định là console.
System.out là một đối tượng kiểu PrintStream.
- System.in: luồng nhập chuẩn, mặc định là bàn phím.
System.in là một đối tượng kiểu InputStream.
- System.err: luồng lỗi chuẩn, mặc định cũng là console.
System.out cũng là một đối tượng kiểu PrintStream
giống System.out.

2, Sử dụng luồng Byte

- Như chúng ta đã biết hai lớp InputStream và OutputStream là các lớp cha đối với tất cả những lớp luồng xuất nhập kiểu byte. Những phương thức trong hai lớp cha này ném ra các lỗi kiểu IOException. Những phương thức định nghĩa trong 2 lớp cha này là có thể dùng trong các lớp con của chúng. Vì vậy tập các phương thức đó là tập tối tiểu các chức năng nhập xuất mà những luồng nhập xuất kiểu byte có thể sử dụng.
- Những phương thức định nghĩa trong lớp InputStream và OutputStream:

3

a, Đọc dữ liệu từ Console
Trước đây, khi Java mới ra đời để thực hiện việc nhập dữ liệu từ Console người ta chỉ dùng luồng nhập byte. Về sau thì chúng ta có thể dùng cả luồng byte và luồng ký tự, nhưng trong một số trường hợp thực tế để đọc dữ liệu từ Console người ta thích dùng luồng kiểu ký tự hơn, vì lý do đơn giản và dễ bảo trì chương trình. Ở đây với mục đích minh họa chúng ta dùng luồng byte thực hiện việc nhập xuất Console.
Ví dụ: Chương trình minh họa việc đọc một mảng bytes từ System.in
PHP:
package javaandroidvn;
 
import java.io.IOException;

public class 
JavaAndroidVn {

    public static 
void main(String[] argsthrows IOException {
        
byte duLieu[] = new byte[100];
        
System.out.print("Nhập dòng ký tự vào: ");
        
System.in.read(duLieu);
        
System.out.print("Dòng ký tự vừa nhập: ");
        for (
int i 0duLieu.lengthi++) {
            
System.out.print((charduLieu[i]);
        }

    }
}
b, Xuất dữ liệu ra Console
- Tương tự như nhập dữ liệu từ Console, với phiên bản đầu tiên của java để xuất dữ liệu ra Console tả chỉ có thể sử dụng luồng byte. Kể từ phiên bản 1.1 (có thêm luồng ký tự), để xuất dữ liệu ra Console có thể sử dụng cả luồng ký tự và luồng byte. Tuy nhiên, cho đến nay để xuất dữ liệu ra Console thường người ta vẫn dùng luồng byte.
- Chúng ta đã khá quen thuộc với phương thức print() và println(), dùng để xuất dữ liệu ra Console. Bên cạnh đó chúng ta cũng có thể dùng phương thức write().
Ví dụ: Sử dụng phương thức System.out.write() để xuất ký tự ’x’ và mảng ký tự ch[] ra Console
PHP:
package javaandroidvn;

public class 
JavaAndroidVn {

    public static 
void main(String[] args) {
        
char ch[] = {'a''c''d''e'};
        
int b;
        
'x';
        
System.out.write(b);
        
System.out.write('\n');
        for (
int i 0ch.lengthi++) {
            
System.out.write(ch[i]);
        }

        
System.out.write('\n');

    }
}

khoa hoclap trinh java tai tt itplus-academy.edu.vn