Có 3 kiểu stream được sử dụng để đọc ghi file trong java đó là byte stream, character stream và buffered stream. Ngoài ra bạn còn có thể sử dụng Scanning (đọc) và Formatting (ghi).
Nội dung chính
1. Đọc nghi file trong java với byte stream
Các chương trình sử dụng Byte Stream để đọc ghi dữ liệu theo từng byte(8bit). Tất cả các class Byte Stream có nguồn gốc từ InputStream và OutputStream.
Sử dụng Byte Stream
Có rất nhiều class Byte Stream, để hình dung Byte Stream hoạt động như thế nào, chúng ta sẽ tập trung vào FileInputStream và FileOutputStream, ví dụ:
public class CopyFileByte { public static void main(String [] args) throws IOException { FileInputStream inputStream = null; FileOutputStream outputStream = null; try { inputStream = new FileInputStream("inStream.txt"); outputStream = new FileOutputStream("outStream.txt"); int c; while ((c = inputStream.read()) != -1) { outputStream.write(c); } } finally { if (inputStream != null) { inputStream.close(); } if (outputStream != null) { outputStream.close(); } } } }
Việc đóng một Stream khi mà không có nhu cầu sử dụng nó nữa là một việc rất quan trong - tránh bị leak tài nguyên. Ví dụ trên sử dụng khối finally để đảm bảo cả 2 Streams (input, output) đều được đóng ngay cả khi có lỗi xảy ra.
2. Đọc ghi file trong java với character stream
Byte Stream trong Java được sử dụng để thực hiện input và output của các byte (8 bit), trong khi đó, Character Stream trong Java được sử dụng để thực hiện input và output cho Unicode 16 bit. Tất cả các class Character Stream có nguồn gốc từ Reader và Writer.
Sử dụng Character Stream
Mặc dù có nhiều lớp liên quan tới Character Stream nhưng các lớp thường dùng nhất là FileReader và FileWriter, ví dụ:
ublic class CopyFileCharacter { public static void main(String [] args) throws IOException { FileReader in = null; FileWriter out = null; try { in = new FileReader("input.txt"); out = new FileWriter("output.txt"); int c; while ((c = in.read()) != -1) { out.write(c); } }finally { if (in != null) { in.close(); } if (out != null) { out.close(); } } } }
3. Đọc ghi file trong java với buffered stream
Các ví dụ trên không sử dụng Buffered Streams, điều này có nghĩa là việc đọc và xuất dữ liệu được thực hiện trực tiếp dưới quyền điều khiển của hệ điều hành, gây lãng phí thời gian và tài nguyên. Để giảm thiểu những trên, Buffered Streams đã được sinh ra. Buffered Streams được sử dụng để tăng tốc độ hoạt động I/O, bằng cách đơn giản là tạo ra một khoảng nhớ đệm với kích thước cụ thể nào đó. Vì vậy chúng ta không cần phải truy cập vào ổ đĩa cứng khi thực hiện I/O. Một chương trình có thể chuyển đổi từ không sử dụng buffered stream (Byte Stream và Chracter Stream sang sử dụng buffered stream bằng việc sử dụng ý tưởng "Wrapping"
Lớp wrapper cho byte stream
Lớp wrapper cho character stream
Sử dụng buffered stream để đọc ghi file
Ví dụ: Sử dụng Wrapper cho byte stream
public class CopyFileBuffer1 { public static void main(String [] args) throws IOException { BufferedInputStream bufferIn = null; BufferedOutputStream bufferOut = null; try { InputStream inputStream = new FileInputStream("input.txt"); OutputStream outputStream = new FileOutputStream("output.txt"); bufferIn = new BufferedInputStream(inputStream); bufferOut = new BufferedOutputStream(outputStream); int c; while ((c = bufferIn.read()) != -1) { bufferOut.write(c); } } finally { if (bufferIn != null) { bufferIn.close(); } if (bufferOut != null) { bufferOut.close(); } } } }
Ví dụ: Sử dụng Wrapper cho character stream
public class CopyFileBuffer2 { public static void main(String [] args) throws IOException { BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { Reader reader = new FileReader("input.txt"); Writer writer = new FileWriter("output.txt"); bufferedReader = new BufferedReader(reader); bufferedWriter = new BufferedWriter(writer); int c; while ((c = bufferedReader.read()) != -1) { bufferedWriter.write(c); } } finally { if (bufferedReader != null) { bufferedReader.close(); } if (bufferedWriter != null) { bufferedWriter.close(); } } } }
4. Đọc ghi file trong java với Scanning và Formatting
Scanning
Lớp Scanner có thể phân tích được các kiểu dữ liệu nguyên thủy và kiểu String bằng việc sử dụng biểu thức chính quy (regular expressions). Mặc định các khoảng trắng được Scanner dùng để phân biệt các ký tự trong một chuỗi.
Sử dụng Scanner
Scanner có thể được sử dụng để nhập dữ liệu từ bàn phím, phân tích chuỗi ký tự, nhập dữ liêu từ file.
Ví dụ 1: Đoạn code này cho phép người dùng đọc ký tự số từ bàn phím bằng cách khởi tạo Scanner sử dụng System.in:
Scanner sc = new Scanner(System.in); int i = sc.nextInt();
Ví dụ 2: Đoạn code này lấy tất cả các số có kiểu long từ file myNumbers.txt:
Scanner sc = new Scanner(new File("myNumbers.txt")); while (sc.hasNextLong()) { long aLong = sc.nextLong(); }
Ví dụ 3: Scanner cũng có thể sử dụng dụng bộ phân cách (Delimiters) khác do người dùng tự định nghĩa, đoạn code sau đọc và phân tích thành các mục từ một chuỗi.
String input = "1 fish 2 fish red fish blue fish"; Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*"); System.out.println(s.nextInt()); System.out.println(s.nextInt()); System.out.println(s.next()); System.out.println(s.next()); s.close();
Một số phương thức của lớp Scanner
Phương thức | Mô tả |
---|---|
nextInt() | trả về kiểu int |
nextFloat() | trả về kiểu float |
nextBoolean() | trả về kiểu boolean |
nextByte() | trả về kiểu byte |
nextLine() | trả về kiểu String |
Formatting
Ngoài 2 phương thức print và println. Java cung cấp 2 phương thức định dạng in cho chúng ta là printf và format và 2 phương thức này có chức năng tương tự nhau. Bạn có thể gọi phương thức này ở bất kỳ nơi đâu trong code của bạn.
Ví dụ: định dạng in cho các biến số:
System.out.format("The value of " + "the float variable is " + "%f, while the value of the " + "integer variable is %d, " + "and the string is %s", floatVar, intVar, stringVar);
Một điều nữa là ta có thể in theo hệ thống định dạng Pháp, ngăn cách phần nguyên và phần thập phân của số thực thập phân bằng định dạng Locale.FRANCE, ví dụ:
System.out.format(Locale.FRANCE, "The value of the float " + "variable is %f, while the " + "value of the integer variable " + "is %d, and the string is %s%n", floatVar, intVar, stringVar);
Ví dụ: một chương trình đơn giản:
public class TestFormat { public static void main(String[] args) { long n = 461012; System.out.format("%d%n", n); // --> "461012" System.out.format("%08d%n", n); // --> "00461012" System.out.format("%+8d%n", n); // --> " +461012" System.out.format("%,8d%n", n); // --> " 461,012" System.out.format("%+,8d%n%n", n); // --> "+461,012" double pi = Math.PI; System.out.format("%f%n", pi); // --> "3.141593" System.out.format("%.3f%n", pi); // --> "3.142" System.out.format("%10.3f%n", pi); // --> " 3.142" System.out.format("%-10.3f%n", pi); // --> "3.142" System.out.format(Locale.FRANCE, "%-10.4f%n%n", pi); // --> "3,1416" Calendar c = Calendar.getInstance(); System.out.format("%tB %te, %tY%n", c, c, c); // --> "May 29, 2006" System.out.format("%tl:%tM %tp%n", c, c, c); // --> "2:34 am" System.out.format("%tD%n", c); // --> "05/29/06" } }
Bảng sau thông kê một vài "Converters" và "Flags" được sử dụng trong ví dụ trên:
Converter | Flag | Giải thích |
---|---|---|
d | Một số nguyên thập phân. | |
f | Một số float. | |
n | Một ký tự dòng mới phù hợp với nền tảng chạy ứng dụng. Bạn nên luôn luôn sử dụng %n , hơn là \n . |
|
tB | In ra tên tháng trong biến date & time, ví dụ: April. | |
td, te | In ra ngày trong biến date & time, 2 số của ngày trong tháng. td sẽ in ra cả số 0 chẳng hạn như ngày 07, te thì không. | |
ty, tY | In ra năm trong biến date & time, ty = 2-số cuối của năm, tY = 4-số của năm. | |
tl | In ra giờ trong biến date & time, theo định dạng 12-giờ. | |
tM | In ra phút trong biến date & time, bao gồm 2 số, cả số 0 nếu cần thiết. | |
tp | In ra date & time dưới dạng am/pm (chữ thường). | |
tm | In ra tháng của biến date & time, gồm 2 số, cả số 0 nếu cần thiết. | |
tD | In ra ngày của biến date & time như định dạng %tm%td%ty | |
08 | Chỉ định chiều rộng là 8 ký tự, bao gồm cả số 0 nếu cần thiết. | |
+ | In ra ký tự +. | |
, | Nhóm các số bằng dấu ',' thay vì '.', ví dụ 10,000,900 thay vì 10.000.900 . | |
- | Căn trái. | |
.3 | Ba số sau dấu thập phân. | |
10.3 | Rộng 10 ký tự, căn phải, với 3 số sau dấu thập phân. |