So sánh size của 2 file txt trong java năm 2024
Lớp của Java `BufferedWriter`ghi văn bản vào luồng ký tự đầu ra, đệm các ký tự để ghi các ký tự, mảng và chuỗi một cách hiệu quả. Bạn có thể chuyển kích thước bộ đệm cho hàm tạo làm đối số thứ hai. Nhà xây dựng:
Show
phương pháp:
BufferedReaderĐây là một ví dụ về việc sử dụng các lớp và Java BufferedWriter:Viết vào một tập tin:
3ngay lập tức ghi dữ liệu vào đĩa. Mỗi khi chúng tôi truy cập nó, bộ đệm bao quanh nó sẽ tăng tốc ứng dụng của chúng tôi. Bộ đệm sẽ ghi dữ liệu bên trong, sau đó ghi các khối tệp lớn vào đĩa. Chúng tôi đọc dữ liệu từ bàn điều khiển và ghi nó vào một tệp:
John Selawsky Tại A senior Java developer and Java tutor at Learning Tree International programming courses. Sometimes I write some stupid programmi ... [Đọc toàn bộ tiểu sử] Hầu hết các chương trình ứng dụng hoạt động với dữ liệu được lưu trữ trong các tệp cục bộ hoặc đến từ máy tính qua mạng. Java làm việc với luồng dữ liệu. Một luồng là một chuỗi dữ liệu. Nó cũng có thể được định nghĩa là một thực thể logic tạo ra hoặc tiêu thụ thông tin. Một luồng dữ liệu là một kênh thông qua đó dữ liệu di chuyển từ nguồn đến đích. Nguồn hoặc đích này có thể là thiết bị đầu vào hoặc đầu ra, phương tiện lưu trữ hoặc máy tính trên mạng. Một bộ nhớ lưu trữ dữ liệu vật lý được ánh xạ thành một luồng logic và sau đó, một chương trình Java đọc dữ liệu từ luồng này theo chuỗi – một byte sau một byte, hoặc ký tự sau ký tự. Nói cách khác, một tệp vật lý có thể được đọc bằng cách sử dụng các loại luồng khác nhau, ví dụ: FileTnputStream, hoặc Fi leReader. Java sử dụng các luồng như vậy để thực hiện các hoạt động đầu vào và đầu ra khác nhau. Sự cần thiết của Các Lớp và Giao diện Stream Trong Java, luồng là bắt buộc để thực hiện tất cả các hoạt động đầu vào/đầu ra (I/O). Một luồng đầu vào nhận dữ liệu từ một nguồn vào chương trình và một luồng đầu ra gửi dữ liệu đến một đích từ chương trình. Do đó, các lớp và giao diện luồng giúp hữu ích trong các tác vụ:
Mục lục Các Lớp và Giao diện LuồngLuồng đầu/ra tiêu chuẩn trong Java được biểu diễn bởi ba trường của lớp System:
Luồng đầu vào tiêu chuẩn được sử dụng để đọc ký tự dữ liệu. Luồng này phản hồi đến đầu vào bàn phím hoặc bất kỳ nguồn đầu vào nào được chỉ định bởi môi trường hoặc người dùng. Nó đã được định nghĩa như sau:
Luồng đầu ra tiêu chuẩn được sử dụng để hiển thị đầu ra trên màn hình hoặc bất kỳ phương tiện đầu ra nào khác. Nó đã được định nghĩa như sau:
Đây là luồng lỗi tiêu chuẩn. Theo mặc định, đây là console của người dùng. Nó đã được định nghĩa như sau:
Để đọc hoặc ghi dữ liệu bằng cách sử dụng các luồng Đầu vào/Đầu ra, cần thực hiện các bước sau:
InputStream và OutputStream là các lớp trừu tượng và được sử dụng để đọc và ghi các chuỗi byte không có cấu trúc. Các luồng đầu vào và đầu ra khác là các lớp con của các lớp trừu tượng này và được sử dụng để đọc và ghi vào tệp. Các loại luồng byte khác nhau có thể được sử dụng có thể sử dụng chung vì chúng kế thừa cấu trúc của lớp Input/OutputStream. Để đọc hoặc ghi byte, phải sử dụng một lớp con của lớp InputStream hoặc OutputStream tương ứng. Luồng Phản ứng (Reactive Stream)Lập trình phản ứng là một mô hình lập trình, tương tự như cách lập trình hướng đối tượng hoặc lập trình hàm là các mô hình lập trình. Theo Chương trình phản ứng (một hướng dẫn xây dựng kiến trúc hiện đại, linh hoạt và có quy mô lớn), bất kỳ ứng dụng phản ứng nào phải tuân theo bốn đặc điểm chính:
Trong Java, Reactive Streams cung cấp một API chung để triển khai lập trình phản ứng. RxJava và Akka Streams là hai phiên bản phổ biến của Reactive Streams. RxJavaRxJava giúp thực hiện multithreading trong ứng dụng. RxJava là một trong những API được sử dụng cho Java. RxJava là một hiện thực Java của Reactive Extensions, là một thư viện cho các chương trình không đồng bộ và dựa trên sự kiện. Điều này được thực hiện bằng cách sử dụng mẫu Iterator, quan sát và lập trình hàm. Trong thế giới Rx (lập trình phản ứng), có hai loại chính:
Akka ConceptsAkka là một thư viện mã nguồn mở giúp phát triển dễ dàng các ứng dụng đồng thời và phân tán với Java, Akka là cả một nguyên tắc thiết kế và một nền tảng đồng thời. Akka sử dụng mô hình Actor, mô hình/thiết kế trong đó “một actor” đại diện cho một thực thể tính toán độc lập. Actor tương tác chỉ thông qua các tin nhắn không đồng bộ và không tương tác thông qua các cuộc gọi phương thức trực tiếp. Không có phương thức nào có thể được gọi trên các đối tượng bên ngoài, nhưng việc truyền các actor dưới dạng đối tượng là có thể. Trong hầu hết các trường hợp, một trường hợp lớp được sử dụng cho điều này. Hỗ trợ Reactive Streams được giới thiệu trong Java 9 thông qua java.util.concurrent.Flow API. Luồng Phản ứng Java 9 Reactive Streams liên quan đến việc xử lý luồng theo cách không đồng bộ. Nó yêu cầu một nhà xuất bản để xuất bản luồng dữ liệu và một người đăng ký để tiêu thụ dữ liệu. Đôi khi dữ liệu được chuyển đổi giữa nhà xuất bản(publisher) và người đăng ký (subcriber). Cuối cùng, bộ xử lý chuyển đổi dữ liệu nhận được từ nhà xuất bản để người đăng ký hiểu được. Do đó, có thể có một loạt các bộ xử lý. Triển khai Luồng Phản ứng bằng Flow APIJava Flow API từ phiên bản 9 trở đi triển khai đặc tả Reactive Streams. Sự kết hợp giữa mẫu Iterator và Observer tạo nên Flow API. Nếu một ứng dụng rút các mục từ nguồn, đó được gọi là mô hình rút theo Iterator. Nếu nguồn đẩy một mục đến ứng dụng, đó được gọi là mô hình đẩy theo Observer. Trong quá trình đăng ký, người đăng ký Java Flow API có thể yêu cầu N mục. Sau đó, các mục được đẩy đến người đăng ký cho đến khi tất cả các mục được thực hiện hoặc một lỗi xuất hiện. Các lớp và giao diện của Flow APIDưới đây là các lớp và giao diện của Flow API:
Lớp này của Flow API là lớp chính và bao gồm các giao diện quan trọng của Flow API được lồng trong lớp này. Nó là một lớp cuối cùng và không thể được mở rộng.
Đây là một giao diện chức năng và mọi nhà xuất bản phải triển khai phương thức subscribe () để thêm người đăng ký để nhận thông điệp.
Mỗi người đăng ký phải thực hiện giao diện này. Các phương thức của người đăng ký được thực hiện theo thứ tự tuần tự nghiêm ngặt. Bốn phương thức trong giao diện này được mô tả trong Bảng dưới. Phương thứcMô tảsubscribeNhư người đăng ký, đăng ký để nhận thông điệp, phương thức này được khởi tạo bởi nhà xuất bản. Để bắt đầu nhận các mục từ bộ xử lý, subscription.request() được gọi trong cài đặt của phương thức này, nơi subscription là một trường hợp của giao diện Flow.Subscription.onContextSau khi nhận được một mục từ một nhà xuất bản, logic nghiệp vụ được triển khai để xử lý luồng. Phương thức onContext được triển khai để yêu cầu thêm dữ liệu từ nhà xuất bản.onErrorKhi xảy ra lỗi không thể phục hồi, phương thức onError được khởi chạy. Phương thức này cho phép các công việc dọn dẹp, chẳng hạn như kết thúc/đóng kết nối cơ sở dữ liệu trước khi kết thúc nhiệm vụ.onCompleteSau khi sản xuất tất cả các mục, nhà xuất bản sẽ được đóng. Sau đó, cuối cùng, phương thức onComplete được khởi chạy. Nó cũng được sử dụng để gửi thông báo khi luồng được xử lý một cách hiệu quả.Các phương thức của giao diện Subscriber
Người đăng ký sử dụng giao diện này để đăng ký vào một nhà xuất bản. Giao diện này xây dựng các liên kết không đồng bộ không chặn giữa một nhà xuất bản và người đăng ký. Nó cung cấp một phương thức request để người đăng ký yêu cầu các mục từ nhà xuất bản. Nó cũng cung cấp một phương thức hủy bỏ để kết thúc việc đăng ký.
Giao diện này giúp biến đổi tin nhắn giữa nhà xuất bản và người đăng ký và mở rộng đến cả hai.
Nó sử dụng khung Executor để phát hành các mục được gửi đến người đăng ký hiện tại một cách không đồng bộ cho đến khi nó được đóng. Ví dụ, người ta nên sử dụng lớp này trong các ví dụ luồng phản ứng để thêm một người đăng ký và sau đó, gửi các mục. Ghi chú: Phát triển bằng cách sử dụng luồng Phản ứng được khuyến nghị chỉ trong các ứng dụng Java tiên tiến và phức tạp. takeWhile(), dropWhile(), ofNullable(), và iterate với ConditionTrong Java, có thể thực hiện các hoạt động toàn diện với mẫu đối tượng khi sử dụng luồng (streams). Các phương thức sau đây làm tinh chỉnh luồng: takeWhile(Predicate Interface) Cú pháp:
Phương thức takeWhile nhận giá trị cho đến khi điều kiện trả về false. Phương thức takeWhile chọn tiền tố dài nhất của các phần tử từ một luồng phù hợp với điều kiện đã cho trong một luồng được sắp xếp. Ví dụ:
0 dropWhile(Predicate Interface) Phương thức dropWhile loại bỏ toàn bộ dải giá trị ban đầu cho đến khi điều kiện trả về true. Trong một luồng được sắp xếp, phương thức này trả về các phần tử còn lại sau khi loại bỏ tiền tố dài nhất của các phần tử phù hợp với điều kiện đã cho. Cú pháp:
1 Ví dụ:
2 iterate() Phương thức lặp dừng vòng lặp khi vị từ hasNext hiển thị giá trị là false. Cú pháp:
3 Ví dụ:
4 Output:
5 ofNullable() Phương thức ofNullable ngăn chặn NullPointerException và phù hợp với các luồng kiểm tra giá trị null. Nếu đối tượng không phải là null, phương thức này trả về một Stream có thứ tự bao gồm một phần tử duy nhất; ngược lại trả về một Stream trống. Cú pháp:
6 Ví dụ:
7 Output:
8 Lớp File và Các Phương thức của lớp FileKhác với các lớp khác làm việc với luồng (stream), lớp File tương tác trực tiếp với các tệp và hệ thống tệp. Các tệp được đặt tên bằng cách sử dụng quy ước đặt tên tệp của hệ điều hành máy chủ. Những quy ước này được đóng gói bằng cách sử dụng các hằng số của lớp File. Một đường dẫn có thể là tuyệt đối hoặc tương đối. Trong một đường dẫn tuyệt đối, không cần thông tin bổ sung nào để xác định tệp cần thiết vì đường dẫn là hoàn chỉnh. Trong một đường dẫn tương đối, thông tin được thu thập từ một đường dẫn khác. Các lớp trong gói java.io giải quyết đường dẫn tương đối đối với thư mục người dùng hiện tại, được đặt bởi thuộc tính hệ thống user.dir. Lưu ý: Điều này thường là thư mục mà JVM được gọi. getParent() là phương thức được sử dụng để có được thư mục cha của một đường dẫn trừu tượng. Điều này bao gồm tiền tố của đường dẫn và mỗi tên trong chuỗi tên của đường dẫn. Lưu ý rằng tên cuối cùng không được bao gồm. Đường dẫn tuyệt đối của mỗi thư mục là một tổ tiên của bất kỳ đối tượng File nào có đường dẫn trừu tượng tuyệt đối. Ví dụ, “/use” là một tổ tiên của thư mục được chỉ định bằng đường dẫn /usr/local/bin. Lưu ý: Trong đường dẫn, /usr/local/bin là một tổ tiên của thư mục đường dẫn /usr/local/bin. Khái niệm tiền tố được sử dụng để xử lý thư mục gốc trên các nền tảng như UNIX. Bảng 5.2 mô tả tiền tố mà mỗi nền tảng sử dụng. Nền tảngTiền tốMô tảUNIX“/”là tiền tố cho một đường dẫn tuyệt đối. Không có tiền tố cho đường dẫn tương đối. Đường dẫn trừu tượng chỉ định thư mục gốc có tiền tố “/” và một chuỗi tên trống.Microsoft Windows:Tiền tố của đường dẫn chứa chỉ định ổ đĩa bao gồm một chữ cái ổ đĩa theo sau là “:”. Điều này được theo sau bởi “\” nếu đường dẫn là tuyệt đối. Trong đường dẫn tương đối, không có tiền tố khi không có ổ đĩa được chỉ định. Khi các đối tượng của lớp File được tạo, đường dẫn trừu tượng được biểu diễn bởi một đối tượng File không bao giờ thay đổi. Nói cách khác, đối tượng của lớp File là không thay đổi. Lớp File đóng gói quyền truy cập thông tin về một tệp hoặc thư mục. Nó lưu trữ đường dẫn và tên của một thư mục hoặc tệp. Tất cả các hoạt động thông thường với tệp và thư mục được thực hiện bằng cách sử dụng các phương thức truy cập do lớp File cung cấp. Các phương thức của lớp này cho phép tạo, xóa và đổi tên tệp, cung cấp quyền truy cập đến đường dẫn của tệp, xác định xem đối tượng nào là tệp hay thư mục và kiểm tra quyền truy cập đọc và ghi. Các phương thức thư mục trong lớp File cho phép tạo, xóa, đổi tên và liệt kê các thư mục. Các giao diện và lớp được định nghĩa bởi gói java.nio.file giúp máy ảo Java truy cập tệp tin hệ thống và thuộc tính của tệp. Phương thức toPath() giúp có được một Path sử dụng đường dẫn trừu tượng. Một đối tượng File sử dụng đường dẫn này để định vị một tệp. Để chẩn đoán lỗi khi một hoạt động trên tệp thất bại, Path có thể được sử dụng với lớp Files. Lưu ý: Khi Path được sử dụng với lớp Files, có sự truy cập hào phóng đến các ngoại lệ, hoạt động tệp bổ sung và thuộc tính tệp. Các hàm khởi tạo của lớp File như sau: File(String dirPath) Hàm tạo File(String dirPath) tạo một đối tượng File với đường dẫn của tệp được chỉ định bởi biến chuỗi dirPath thành một đường dẫn trừu tượng. Nếu chuỗi trống, kết quả là một đường dẫn trừu tượng trống. Chữ ký của nó như sau:
9 File(String parent, String child) Hàm khởi tạo File(String parent, String child) tạo một đối tượng File với đường dẫn của tệp được chỉ định bởi các biến chuỗi parent và child. Nếu chuỗi cha là null, thì một thể hiện mới của File được tạo ra bằng cách sử dụng chuỗi đường dẫn con cung cấp. Hàm tạo này sẽ hoạt động giống như hàm tạo File một đối số với chuỗi đường dẫn con được cung cấp. Ngược lại, chuỗi đường dẫn cha được xem xét là trỏ đến một thư mục, và chuỗi đường dẫn con được xem xét là trỏ đến một thư mục hoặc tệp. Nếu chuỗi đường dẫn con là tuyệt đối, nó được chuyển đổi thành đường dẫn tương đối theo cách phụ thuộc vào hệ thống. Chữ ký của nó như sau:
0 File(File fileObj, String fileName) Hàm khởi tạo File(File fileObj, String fileName) tạo một đối tượng File mới từ một đối tượng File khác được chỉ định bởi biến fileObj, và tên tệp được chỉ định bởi biến chuỗi fileName. Nếu cha là null, thì một thể hiện mới của File được tạo ra bằng cách sử dụng chuỗi đường dẫn con cung cấp. Hàm tạo của File một đối số với chuỗi đường dẫn con được gọi và một thể hiện mới của File được tạo ra. Nếu điều này không xảy ra, đường dẫn trừu tượng cha được coi là trỏ đến một thư mục và chuỗi đường dẫn con được xem xét là trỏ đến một thư mục hoặc tệp. Chuỗi đường dẫn con được chuyển đổi thành đường dẫn tương đối theo cách phụ thuộc vào hệ thống nếu nó là tuyệt đối. Nếu cha là đường dẫn trừu tượng trống, một thể hiện mới của File được tạo ra. Điều này xảy ra bằng cách chuyển đổi con thành một đường dẫn trừu tượng và giải quyết kết quả so với một thư mục mặc định phụ thuộc vào hệ thống. Nếu không có điều này xảy ra, mỗi chuỗi đường dẫn được chuyển đổi thành một đường dẫn trừu tượng và đường dẫn trừu tượng con được giải quyết đối với cha. Chữ ký của nó như sau:
1 File(URL urlObj) Hàm khởi tạo File(URL urlObj) chuyển đổi URL được chỉ định thành một đường dẫn trừu tượng và tạo một thể hiện mới của File. Đối với môi trường của URL là phụ thuộc hệ thống. Sự chuyển đổi bởi hàm tạo này cũng phụ thuộc vào hệ thống. Chữ ký của nó như sau:
2 Ví dụ:
3 Các phương thức trong lớp FileCác phương thức trong lớp File giúplàm việc với tệp trên hệ thống tệp. Một số phương thức bao gồm:
4
5
6
7
8
9
0
1
2 Ví dụ:
3 Ví dụ sử dụng lớp triển khai từ interface FilenameFilter để lọc file với các đuôi mở rộng xác định: Tạo lớp FileFilter
4 Tạo lớp DirList
5 Lớp FileDescriptorLớp FileDescriptor cung cấp truy cập đến các bản mô tả tệp mà hệ điều hành duy trì khi tệp và thư mục được truy cập. Trong việc sử dụng thực tế, một bản mô tả tệp được sử dụng để tạo FileInputStream hoặc FileOutputStream để chứa nó. Bản mô tả tệp không nên được tạo ra độc lập bởi ứng dụng vì chúng liên quan đến hệ điều hành. Lớp FileDescriptor có các trường công khai sau:
6 Trường tĩnh FileDescriptor err hoạt động như một cánh cửa đến luồng lỗi tiêu chuẩn.
7 Trường tĩnh FileDescriptor in hoạt động như một cánh cửa đến luồng nhập tiêu chuẩn.
8 Trường tĩnh FileDescriptor out hoạt động như một cánh cửa đến luồng xuất tiêu chuẩn. Constructor và Phương thức của FileDescriptorCác constructor và phương thức của lớp FileDescriptor như sau: FileDescriptor() Constructor tạo ra một đối tượng FileDescriptor không hợp lệ.
9 sync() Phương thức sync() xóa bộ đệm hệ thống và ghi nội dung mà chúng chứa xuống phần cứng thực tế.
0 valid() Phương thức valid() kiểm tra xem bản mô tả tệp có hợp lệ không. Do bản mô tả tệp liên quan đến các tệp mở, chúng trở thành không hợp lệ khi tệp được đóng.
1 Ví dụ:
2 Giao diện DataInput và DataOutputLuồng dữ liệu hỗ trợ đầu ra/nhập của các kiểu dữ liệu nguyên thủy và giá trị chuỗi. Các luồng dữ liệu triển khai giao diện DataInput hoặc DataOutput. Giao diện DataInput có các phương thức để: Đọc các byte từ một luồng nhị phân và chuyển đổi dữ liệu thành bất kỳ kiểu nguyên thủy Java nào. Chuyển đổi dữ liệu từ định dạng Java Unicode sửa đổi (UTF)-8 thành chuỗi. UTF-8 là một định dạng đặc biệt để mã hóa giá trị Unicode 16 bit. Lưu ý: UTF-8 giả định rằng trong hầu hết các trường hợp, tám bit cao của một Unicode sẽ là không và tối ưu hóa tương ứng. Giao diện DataOutput có các phương thức để: Chuyển đổi dữ liệu hiện có trong kiểu nguyên thủy của Java thành một loạt byte và ghi chúng vào một luồng nhị phân, Chuyển đổi dữ liệu chuỗi thành định dạng UTF-8 được sửa đổi bởi Java và ghi vào một luồng. Phương thức của Giao diện DataInputGiao diện DataInput có một số phương thức để đọc đầu vào, chẳng hạn như dữ liệu nhị phân từ luồng đầu vào và xây dựng lại dữ liệu từ byte thành bất kỳ kiểu nguyên thủy Java nào. Một IOException sẽ được kích hoạt nếu các phương thức không thể đọc bất kỳ byte nào từ luồng hoặc nếu luồng đầu vào đã đóng. Các phương thức trong giao diện DataInput như sau: readBoolean() Phương thức readBoolean() đọc một byte đầu vào từ một luồng và trả về true nếu byte không phải là không và false nếu ngược lại.
3 readByte() Phương thức readByte() đọc một byte từ một luồng, là giá trị có dấu trong khoảng từ -128 đến 127.
4 readInt() Phương thức readInt() đọc bốn byte từ một luồng và trả về giá trị int của các byte đã đọc.
5 readDouble() Phương thức readDouble() đọc 8 byte từ một luồng và trả về giá trị double của các byte đã đọc.
6 readChar() Phương thức readChar() đọc hai byte từ một luồng và trả về giá trị char.
7 readLine() Phương thức readLine() đọc một dòng văn bản từ luồng đầu vào. Nó đọc một byte mỗi lần và sau đó chuyển đổi byte thành một ký tự và tiếp tục đọc cho đến khi nó gặp kết thúc dòng hoặc kết thúc tệp. Các ký tự sau đó được trả về dưới dạng một chuỗi.
8 readUTF() Phương thức readUTF() đọc một dòng văn bản trong định dạng UTF-8 được sửa đổi từ một luồng.
9 Ví dụ sử dụng lớp DataInputStream được triển khai từ giao diện DataInput:
0 Phương thức của giao diện DataOutputGiao diện DataOutput có nhiều phương thức để ghi đầu ra, chẳng hạn như dữ liệu nhị phân vào luồng đầu ra. Một IOException có thể được kích hoạt nếu byte không thể được ghi vào luồng. Các phương thức quan trọng trong giao diện này như sau: writeBoolean(boolean b) Phương thức writeBoolean(boolean b) ghi giá trị boolean được đưa vào làm tham số vào một luồng đầu ra. Nếu đối số có giá trị là true, thì sẽ được ghi 1, ngược lại, giá trị được ghi.
1 writeByte(int value) Phương thức writeByte(int value) ghi giá trị byte của số nguyên được đưa vào làm tham số vào một luồng đầu ra.
2 writeInt(int value) Phương thức writeInt(int value) ghi bốn byte biểu diễn giá trị số nguyên được đưa vào làm tham số vào một luồng đầu ra.
3 writeDouble(double value) Phương thức writeDouble(double value) ghi tám byte biểu diễn giá trị số thực double được đưa vào làm tham số vào một luồng đầu ra.
4 writeChar(int value) Phương thức writeChar(int value) ghi giá trị char của số nguyên được đưa vào làm tham số vào một luồng.
5 writeChars(String value) Phương thức writeChars(String value) ghi chuỗi được đưa vào làm tham số vào một luồng.
6 writeUTF(String value) Phương thức writeUTF(String value) ghi một chuỗi dưới dạng UTF-8 được sửa đổi được đưa vào làm tham số vào một luồng.
7 Đoạn mã dưới hiển thị việc sử dụng giao diện DataOutput thông qua lớp DataOutputStream, lớp này thực hiện giao diện này. Mã giả định rằng đã có một thể hiện outStream đã được tạo và khởi tạo.
8 Gói (Package) java.ioMột luồng (stream) đại diện cho nhiều nguồn và đích, như tệp trên đĩa và mảng trong bộ nhớ. Đó là một chuỗi dữ liệu. Một luồng I/O đại diện cho một nguồn đầu vào hoặc một đích đầu ra. Các luồng hỗ trợ nhiều hình thức dữ liệu, như các byte đơn giản, kiểu dữ liệu nguyên thủy, ký tự cục bộ và các loại dữ liệu khác. Một số luồng cho phép dữ liệu trôi qua và một số luồng biến đổi dữ liệu một cách hữu ích. Tuy nhiên, tất cả các luồng đều cung cấp một mô hình đơn giản để chương trình sử dụng chúng. Một chương trình sử dụng một luồng đầu vào để đọc dữ liệu từ một nguồn. Nó đọc một mục mỗi lần. Một chương trình sử dụng một luồng đầu ra để khi dữ liệu tới nguồn. Nó viết mộ mục mỗi lần Chú ý: Các chương trình sử dụng byte streams để thực hiện đầu vào và đầu ra của byte 8-bit. Tất cả các lớp byte stream đều xuất phát từ InputStream và OutputStream. Có nhiều lớp byte stream. Chúng hoạt động theo cùng một cách nhưng khác nhau về cách xây dựng. Đoạn mã dưới mô tả cách byte streams hoạt động bằng cách sử dụng lớp FileInputStream và lớp FileOutputStream.
9 Trong Đoạn mã trên, phương thức read() đọc một ký tự và trả về một giá trị int. Điều này cho phép phương thức read() chỉ ra rằng đã đến cuối luồng bằng cách trả về một giá trị là -1. Bằng cách sử dụng phương pháp này, toàn bộ nội dung của Hello.txt được đọc và sau đó, sao chép vào outagain.txt. Lưu ý rằng đường dẫn cho outagain.txt không được chỉ định. Điều này có nghĩa là nó sẽ được tạo trong thư mục hiện tại, tức là thư mục chứa tệp java này. Khi một luồng không còn cần thiết nữa, quan trọng là phải đóng luồng, như được hiển thị ở đây trong khối finally. Điều này giúp tránh rò rỉ tài nguyên. Nền tảng Java sử dụng quy ước Unicode để lưu trữ giá trị ký tự. I/O dòng ký tự chuyển đổi định dạng này vào và ra khỏi bộ ký tự địa phương. Lưu ý rằng trong các vùng địa phương phương Tây, bộ ký tự địa phương thường là một siêu tập hợp 8-bit của ASCII. Đối với hầu hết các ứng dụng, đầu vào và đầu ra được thực hiện bằng các lớp dòng tự động dịch từ và sang bộ ký tự địa phương. Một chương trình sử dụng các lớp dòng ký tự sẽ thích ứng với bộ ký tự địa phương và sẵn sàng cho quốc tế hóa. Tất cả các lớp dòng ký tự được xuất phát từ các lớp Reader và Writer. Có các lớp dòng ký tự chuyên biệt trong các hoạt động I/O tệp như FileReader và FileWwriter. Đoạn mã dưới thể hiện việc đọc và ghi các luồng ký tự bằng cách sử dụng lớp FileReader và FileWriter:
0 Các luồng ký tự hoạt động như các lớp bọc cho luồng byte. Luồng ký tự quản lý việc chuyển đổi giữa ký tự và byte và sử dụng luồng byte để thực hiện các hoạt động I/O vật lý. Ví dụ, FileWriter sử dụng lớp FileOutputStream để ghi dữ liệu. Khi không có lớp luồng ký tự đã đóng gói sẵn nào được yêu cầu, các luồng chuyển đổi từ byte sang ký tự, InputStreamReader và OutputStreamWriter, được sử dụng để tạo ra các luồng ký tự. I/O ký tự thường xảy ra ở đơn vị lớn hơn so với từng ký tự một, chẳng hạn như một dòng bao gồm một chuỗi ký tự với một ký tự kết thúc dòng ở cuối. Ký tự kết thúc dòng có thể là bất kỳ trong số các dạng sau:
Các phương thức BufferedReader.readLine() và PrintWriter.println() giúp đầu vào và đầu ra của một dòng mỗi lần. Phương thức readLine() trả về một dòng văn bản với dấu kết thúc dòng. Phương thức println() đưa ra mỗi dòng trên một dòng mới khi nó thêm ký tự kết thúc dòng cho hệ điều hành hiện tại. Lưu ý rằng các ký tự kết thúc dòng trong tệp đầu vào và đầu ra có thể khác nhau. Lớp InputStream và Các Lớp ConLớp
52 là một lớp trừu tượng xác định cách các luồng nhận dữ liệu và là lớp cha của tất cả các lớp luồng. Lớp này bao gồm các phương thức để đọc byte hoặc mảng byte, đánh dấu vị trí trong luồng, xác định số byte đã đọc hoặc có sẵn để đọc, và nhiều hơn nữa. Nó được sử dụng để đọc dữ liệu từ một luồng nhập. Hình dưới mô tả cấu trúc lớp InputStream Các phương thức lớp InputStreamLớp InputStream cung cấp một số phương thức để quản lý việc đọc dữ liệu từ một luồng. Một số phương thức này bao gồm:
1
2
3
4
5
6 Lớp FileInputStreamĐối tượng luồng tệp có thể được tạo bằng cách truyền tên của tệp, hoặc một đối tượng File, hoặc một đối tượng FileDescriptor tương ứng. Lớp FileInputStream được sử dụng để đọc các byte từ một tệp. Khi một đối tượng của lớp FileInputStream được tạo, nó cũng được mở để đọc. Lớp FileInputStream ghi đè tất cả các phương thức của lớp InputStream ngoại trừ các phương thức mark() và reset(). Phương thức reset() sẽ sinh ra một ngoại lệ IOException. Các hàm khởi tạo phổ biến của lớp này bao gồm:
7
8
9 Đoạn mã dưới mô tả cách tạo đối tượng FileInputStream.
0 Đoạn mã dưới minh họa cách tạo một đối tượng FileInputStream
1 Lớp ByteArrayInputStreamLớp ByteArrayInputStream (ByteArrayInputStream) chứa một bộ đệm lưu trữ các byte được đọc từ luồng. Lớp ByteArrayInputStream sử dụng một mảng byte làm nguồn. Lớp ByteArrayInputStream có một bộ đếm nội bộ, giữ theo dõi byte tiếp theo sẽ được đọc. Lớp này không hỗ trợ bất kỳ phương thức mới nào, chỉ ghi đè các phương thức của lớp InputStream như read(), skip(), available(), và reset(). Các thuộc tính quan trọng của lớp ByteArrayInputStream:
Các hàm khởi tạo của lớp này bao gồm:
Đoạn mã dưới mô tả cách sử dụng lớp ByteArrayInputStream.
2 Trong ví dụ này, chương trình tạo một mảng byte từ chuỗi “Hello, World!” và sau đó sử dụng ByteArrayInputStream để đọc từng byte từ mảng và in ra màn hình. Lớp OutputStream và Các Lớp ConLớp OutputStream là một lớp trừu tượng định nghĩa cách mà byte hoặc mảng byte được ghi vào luồng. ByteArrayOutputStream và FileOutputStream là các lớp con của lớp OutputStream. Các Phương thức trong Lớp OutputStreamCó một số phương thức trong lớp OutputStream được sử dụng để ghi byte dữ liệu vào một luồng. Tất cả các phương thức của lớp này đều ném ra một ngoại lệ IOException. Một số phương thức của lớp này bao gồm:
Lớp FileOutputStreamLớp FileOutputStream tạo ra một OutputStream được sử dụng để ghi byte vào một tệp tin. FileOutputStream có thể hoặc không tạo ra tệp tin trước khi mở nó để ghi, điều này phụ thuộc vào nền tảng cụ thể. Một số nền tảng chỉ cho phép một đối tượng ghi tệp tin mở một tệp tin để ghi. Do đó, nếu tệp tin đã được mở, các constructor trong lớp này sẽ thất bại (một FileNotFoundException sẽ được ném ra) chỉ khi một tệp tin chỉ được mở để đọc. Các constructor phổ biến của lớp này bao gồm:
Ví dụ FileOutputStream:
3 Lớp ByteArrayOutputStreamLớp ByteArrayOutputStream tạo ra một luồng đầu ra trong đó dữ liệu được ghi bằng cách sử dụng một mảng byte. Nó cho phép mảng đầu ra mở rộng kích thước để chứa dữ liệu mới được ghi. Lớp ByteArrayOutputStream định nghĩa hai constructor:
Các Phương thức trong Lớp ByteArrayOutputStreamLớp ByteArrayOutputStream kế thừa tất cả các phương thức của lớp OutputStream. Các phương thức của lớp này cho phép truy xuất hoặc chuyển đổi dữ liệu. Các phương thức của lớp này có thể được gọi ngay cả sau khi luồng đầu ra đã được đóng và sẽ không tạo ra IOException. Một số phương thức trong lớp ByteArrayOutputStream bao gồm:
Ví dụ dưới mô tả việc sử dụng lớp ByteArrayOutputStream.
4 Lọc luồng (Filter Stream)Lớp FilterInputStream cung cấp chức năng bổ sung bằng cách sử dụng một luồng đầu vào làm nguồn dữ liệu cơ bản của nó. Lớp FilterOutputStream tạo luồng trên các luồng đầu ra hiện tại. Chúng có thể biến đổi dữ liệu trên đường đi hoặc cung cấp chức năng bổ sung. Lớp FilterInputStreamNó cũng có thể biến đổi dữ liệu trên đường đi. Lớp này ghi đè tất cả các phương thức của lớp InputStream để chuyển tất cả các yêu cầu đến luồng đầu vào chứa. Các lớp con cũng có thể ghi đè một số phương thức và có thể cung cấp các phương thức và trường bổ sung. Dưới đây là các trường và constructor cho lớp java.io.FilterInputStream:
Dưới đây là các phương thức của lớp này:
Ví dụ sử dụng lớp FilterInputStream:
5 Lớp FilterOutputStreamLớp FilterOutputStream ghi đè tất cả các phương thức của lớp OutputStream mà chuyển tất cả các yêu cầu đến luồng đầu ra cơ bản. Các lớp con của FilterOutputStream cũng có thể ghi đè một số phương thức và cung cấp các phương thức và trường bổ sung. Lớp java.io.FilterOutputStream bao gồm trường protected OutputStream out, đây là luồng đầu ra cần được lọc. FilterOutputStream (OutputStream out) là constructor của lớp này. Nó tạo ra một luồng đầu ra bộ lọc tồn tại qua luồng đầu ra đã được xác định. Ví dụ sử dụng lớp FilterOutputStream:
6 Luồng đệm (Buffered Stream)Bộ đệm là một khu vực lưu trữ tạm thời cho dữ liệu. Bằng cách lưu trữ dữ liệu trong bộ đệm, thời gian được tiết kiệm vì dữ liệu được nhận ngay từ bộ đệm thay vì quay lại nguồn gốc của dữ liệu. Trong Java, sử dụng đầu vào và đầu ra đệm để tạm thời lưu trữ dữ liệu được đọc từ hoặc được ghi vào một luồng. Điều này giúp chương trình đọc hoặc ghi lượng dữ liệu nhỏ mà không ảnh hưởng xấu đến hiệu suất của hệ thống. Bộ đệm cho phép bỏ qua, đánh dấu và thiết lập lại luồng. Bộ lọc hoạt động trên bộ đệm, nằm giữa chương trình và đích của luồng được đệm. Lớp BufferedInputStreamLớp BufferedInputStream cho phép người lập trình bọc bất kỳ lớp InputStream nào thành một luồng được đệm. BufferedInputStream hoạt động như một bộ nhớ đệm cho đầu vào bằng cách tạo ra mảng byte được sử dụng cho việc đọc trong tương lai. Cách đơn giản nhất để đọc dữ liệu từ một đối tượng của lớp BufferedInputStream là gọi phương thức read() của nó. Lớp BufferedInputStream cũng hỗ trợ các phương thức mark() và reset(). Phương thức markSupported() sẽ trả về true nếu nó được hỗ trợ. Lớp BufferedInputStream định nghĩa hai constructor:
7
8 Một số phương thức của lớp này được liệt kê trong bảng dưới Phương thứcMô tảint available()Phương thức trả về số byte đầu vào có sẵn để đọc.void mark(int readlimit)Phương thức đặt một đánh dấu tại vị trí hiện tại trong luồng đầu vào.int read()Phương thức đọc dữ liệu từ luồng đầu vào cơ bản. Nó ném một ngoại lệ nếu có lỗi I/O.int read(byte[] b)Phương thức đọc byte vào mảng byte được chỉ định từ vị trí bắt đầu. Nó ném ngoại lệ I/O nếu có lỗi.void reset()Phương thức đặt lại con trỏ trong luồng đến điểm mà phương thức mark được gọi lần cuối. Ví dụ:
9 Lớp BufferedOutputStreamBufferedOutputStream tạo ra một bộ đệm được sử dụng cho một luồng đầu ra. Nó cung cấp cùng lợi ích về hiệu suất như BufferedInputStream. Khái niệm chính vẫn giống nhau, tức là thay vì mỗi lần đi đến hệ điều hành để ghi một byte, nó được lưu vào bộ đệm. Nó giống như OutputStream, ngoại trừ việc phương thức flush() đảm bảo rằng dữ liệu trong bộ đệm được ghi vào thiết bị đầu ra vật lý thực sự. Các constructor của lớp này như sau:
0
1 Bảng dưới liệt kê các phương thức của lớp BufferedOutputStream. Phương thứcMô tảvoid flush()Phương thức này đẩy bộ đệm của luồng đầu ra để đảm bảo dữ liệu được ghi vào thiết bị đầu ra thực tế. Ví dụ:
2 Luồng ký tự (Character Streams)Các lớp luồng byte cung cấp các phương thức để xử lý bất kỳ loại thao tác I/O nào ngoại trừ ký tự Unicode. Luồng ký tự cung cấp chức năng để xử lý các thao tác đầu vào/đầu ra dựa trên ký tự. Chúng hỗ trợ ký tự Unicode và có thể được quốc tế hóa. Reader và Writer là các lớp trừu tượng ở đầu của thứ bậc lớp mà hỗ trợ đọc và viết các luồng ký tự Unicode. Tất cả các lớp luồng ký tự được xuất phát từ Reader và Writer. Hình dưới mô tả các lớp luồng ký tự Các Lớp ReaderLớp Reader là một lớp trừu tượng được sử dụng để đọc các luồng ký tự. Các lớp con của lớp này ghi đè một số phương thức trong lớp này để tăng hiệu suất và chức năng của chúng. Tất cả các phương thức của lớp này đều ném một ngoại lệ IOException. Phương thức read() trả về -1 khi gặp cuối tệp. Có hai constructor cho lớp Reader. Chúng là như sau:
3
4 Bảng dưới liệt kê một số phương thức của lớp Reader. Phương thứcMô tảint read()Phương thức đọc một ký tự duy nhất.int read(char[] buffer, int offset, int count)Phương thức đọc ký tự vào một phần của mảng và trả về số ký tự đã đọc.int read(char[] buffer)Phương thức đọc ký tự vào một mảng và trả về số lượng ký tự đã đọc.long skip(long count)Phương thức bỏ qua một số lượng ký tự cụ thể.boolean ready()Phương thức trả về true nếu độc giả đã sẵn sàng để đọc.void close()Phương thức đóng luồng đầu vào và giải phóng tài nguyên hệ thống.boolean markSupported()Phương thức thông báo xem luồng có hỗ trợ phương thức mark() không.void mark(int readAheadLimit)Phương thức đánh dấu vị trí hiện tại trong luồng.void reset()Phương thức đặt lại luồng. Các Lớp WriterLớp Writer là một lớp trừu tượng và hỗ trợ việc viết các ký tự vào luồng thông qua các phương thức có thể được ghi đè bởi các lớp con của nó. Các phương thức của lớp java.io.Writer giống như các phương thức của lớp java.io.OutputStream. Tất cả các phương thức của lớp này đều ném một ngoại lệ IOException trong trường hợp có lỗi. Có hai constructor cho lớp Writer. Chúng là như sau:
5
6 Bảng dưới liệt kê một số phương thức của lớp Writer. Phương thứcMô tảvoid write(int c)Phương thức viết một ký tự.void write(char[] text)Phương thức viết một mảng đầy đủ các ký tự vào luồng đầu ra.void write(char[] text, int offset, int length)Phương thức viết một phần của một mảng ký tự vào luồng đầu ra, bắt đầu từ vị trí offset. Biến length chỉ định số lượng ký tự cần viết.void write(String s)Phương thức viết một chuỗi vào luồng đầu ra.void write(String s, int offset, int length)Phương thức viết một phần của một chuỗi vào luồng đầu ra, bắt đầu từ vị trí offset. Biến length chỉ định số lượng ký tự cần viết.void flush()Phương thức làm sạch luồng đầu ra để xóa bộ đệm.void close()Phương thức đóng luồng đầu ra. Lớp PrintWriterLớp PrintWriter là một lớp dựa trên ký tự hữu ích cho việc xuất ra màn hình console. Nó thực hiện tất cả các phương thức in của lớp PrintStream và không có phương thức nào để viết các byte nguyên thô. Trong trường hợp đó, một chương trình sử dụng các luồng byte không mã hóa. Lớp PrintWriter khác biệt từ lớp PrintStream vì có thể xử lý đúng nhiều byte và các bộ ký tự khác. Lớp này ghi đè phương thức write() của lớp Writer với sự khác biệt là không có phương thức nào ném bất kỳ IOException nào. Đầu ra được in kiểm tra lỗi bằng cách sử dụng phương thức checkError(). Lớp PrintWriter cũng hỗ trợ việc in các loại dữ liệu nguyên thủy, mảng ký tự, chuỗi và đối tượng. Nó cung cấp đầu ra được định dạng thông qua các phương thức print() và println(). Phương thức toString() sẽ cho phép in giá trị của các đối tượng. Các constructor cho lớp PrintWriter như sau:
7
8
9
0 Ưu điểm chính của các phương thức print() và println() là bất kỳ đối tượng Java hoặc hằng số hoặc biến nào cũng có thể được in bằng cách truyền nó như một đối số. Nếu tùy chọn autoFlush được đặt thành true, thì việc xả tự động sẽ xảy ra khi phương thức println() được gọi. Phương thức print() không tự động xả luồng. Nếu không, cả hai phương thức này đều giống nhau. Một số phương thức được nạp chồng của lớp này được liệt kê trong bảng Phương thứcMô tảboolean checkError()Phương thức xả luồng nếu nó mở và kiểm tra trạng thái lỗi.void print(boolean b)Phương thức in giá trị boolean.void print(char c)Phương thức được sử dụng để in một ký tự.void print(char[] s)Phương thức được sử dụng để in một mảng các ký tự.void print(double d)Phương thức in số thực kiểu double.void print(float f)Phương thức in số thực kiểu float.void print(int i)Phương thức được sử dụng để in một số nguyên.void print(long l)Phương thức được sử dụng để in số nguyên dài.void print(Object obj)Phương thức in một đối tượng và gọi phương thức toString() trên đối số.void print(String s)Phương thức in một chuỗi.void println()Phương thức kết thúc dòng hiện tại bằng cách sử dụng dấu phân cách dòng.void println(boolean x)Phương thức in giá trị boolean và sau đó, kết thúc dòng.void flush()Phương thức xả luồng đầu ra để xóa bộ đệm.void close()Phương thức đóng luồng đầu ra. Lớp PrintWriter thực hiện và ghi đè phương thức trừu tượng write() từ lớp Writer. Sự khác biệt duy nhất là rằng không có phương thức write() nào của lớp PrintWriter ném một IOException vì nó được bắt trong lớp và một cờ lỗi được đặt. Ví dụ:
1 Lớp CharArrayReaderLớp CharArrayReader là một lớp con của lớp Reader. Lớp này sử dụng một mảng ký tự làm nguồn văn bản để đọc. Lớp CharArrayReader có hai constructor và đọc chuỗi ký tự từ một mảng ký tự. Các constructor của lớp này như sau: CharArrayReader(char arr[]) Constructor CharArrayReader(char arr[]) tạo một CharArrayReader từ mảng ký tự được chỉ định, arr. CharArrayReader(char arr[], int start, int num) Constructor CharArrayReader(char arr[], int start, int num) tạo một CharArrayReader từ một phần của mảng ký tự, bắt đầu từ ký tự được chỉ định bởi chỉ mục start, và có độ dài num ký tự. Một số phương thức của lớp này được liệt kê trong Bảng dưới Phương thứcMô tảlong skip(long n)Phương thức bỏ qua n ký tự trước khi đọc.void mark(int num)Phương thức đánh dấu vị trí hiện tại trong luồng.int read()Phương thức đọc một ký tự.int read(char[] cbuf, int off, int len)Phương thức đọc các ký tự vào mảng ký tự đã chỉ định từ vị trí off.void reset()Phương thức đặt lại con trỏ trong luồng đến vị trí mà phương thức mark được gọi cuối cùng hoặc đến đầu luồng nếu nó chưa được đánh dấu.boolean ready()Phương thức được sử dụng để xác nhận xem luồng này có sẵn để đọc không.void close()Phương thức đóng luồng đầu vào. Ví dụ:
2 Lớp CharArrayWriterLớp CharArrayWriter là một lớp con của lớp Writer. Lớp này sử dụng một mảng ký tự trong đó các ký tự được ghi. Kích thước của mảng mở rộng theo cần. Các phương thức toCharArray(), toString(), và writeTo() có thể được sử dụng để truy xuất dữ liệu. Lớp CharArrayWriter kế thừa các phương thức được cung cấp bởi lớp Writer. Các constructor của lớp này như sau: CharArrayWriter() Constructor CharArrayWriter() tạo một CharArrayWriter với một bộ đệm có kích thước mặc định là 32 ký tự. CharArrayWriter(int num) Constructor CharArrayWriter(int num) tạo một CharArrayWriter với một bộ đệm có kích thước được chỉ định bởi biến num. Một số phương thức của lớp này được liệt kê trong Bảng dưới Phương thứcMô tảvoid close()Phương thức đóng luồng.void flush()Phương thức xả luồng.void write(char c)Phương thức ghi một ký tự vào mảng.void write(char[] cbuf, int off, int length)Phương thức ghi các ký tự vào bộ đệm.void reset()Phương thức đặt lại con trỏ trong bộ đệm đến vị trí mà phương thức mark được gọi cuối cùng hoặc đến đầu bộ đệm nếu nó chưa được đánh dấu.int size()Phương thức trả về kích thước hiện tại của bộ đệm.char[] toCharArray()Phương thức trả về một bản sao của dữ liệu.String toString()Phương thức được sử dụng để chuyển đổi dữ liệu đầu vào thành chuỗi.void writeTo(Writer out)Phương thức được sử dụng để ghi nội dung của bộ đệm vào một luồng ký tự. Ví dụ:
3 Ví dụ 2:
4 Serialization (Tuần tự hóa)Sự bền vững (persistence) là quá trình lưu trữ dữ liệu vào một bộ nhớ lưu trữ cố định. Một đối tượng bền vững có thể được lưu trữ trên đĩa hoặc gửi đến máy khác để lưu trữ dữ liệu của nó. Ngược lại, một đối tượng không bền vững tồn tại miễn là JVM đang chạy. Java là một ngôn ngữ hướng đối tượng và do đó cung cấp các tiện ích để đọc và viết đối tượng. Serialization là quá trình đọc và viết đối tượng vào một luồng byte. Một đối tượng triển khai giao diện Serializable sẽ lưu trạng thái của nó và khôi phục lại bằng cách sử dụng các tiện ích serialization và deserialization. Khi một lớp hoặc lớp cha của đối tượng Java thực hiện giao diện java.io.Serializable hoặc là subinterface của nó, java.io.Externalizable, đối tượng Java trở nên có thể tuần tự hóa. Giao diện java.io.Serializable không định nghĩa bất kỳ phương thức nào. Nó chỉ cho biết rằng lớp nên được xem xét để tuần tự hóa. Nếu một lớp cha có thể tuần tự hóa, thì các lớp con của nó cũng có thể tuần tự hóa. Ngoại trừ duy nhất khi một biến là transient và static; trạng thái của nó không thể được lưu trữ bằng các tiện ích serialization. Khi dạng tuần tự của một đối tượng được chuyển đổi trở lại thành một bản sao của đối tượng, quá trình này được gọi là deserialization. Khi một đối tượng được tuần tự hóa, tệp lớp không được ghi lại. Tuy nhiên, thông tin xác định lớp của nó được ghi lại trong luồng tuần tự hóa. Hệ thống deserialization chỉ định cách định vị và tải các tệp lớp cần thiết. Ví dụ, một ứng dụng Java có thể tải định nghĩa lớp bằng cách sử dụng thông tin được lưu trữ trong thư mục. Việc tuần tự hóa là bắt buộc để triển khai Phương thức Gọi Phương thức từ xa (RMI), nơi một đối tượng Java trên một máy có thể gọi phương thức của một đối tượng khác có mặt trên một máy khác. Trong cuộc gọi phương thức từ xa này, máy nguồn có thể tuần tự hóa đối tượng và truyền nó, trong khi máy nhận sẽ deserialization đối tượng. Nếu nhà cung cấp dịch vụ cơ sở hạ tầng hỗ trợ, một đối tượng có thể tuần tự hóa được lưu trữ trong thư mục. Một ngoại lệ, NotSerializableException, được ném khi một trường có tham chiếu đối tượng chưa triển khai java.io.Serializable. Các trường được đánh dấu bằng từ khóa transient không nên được tuần tự hóa. Giá trị được lưu trữ trong các trường static không được tuần tự hóa. Khi một đối tượng được deserialization, các giá trị trong các trường static được đặt thành các giá trị được khai báo trong lớp và các giá trị trong các trường transient không phải static được đặt thành giá trị mặc định của chúng. Một số thể hiện của lớp serialVersionUID được liên kết với một lớp có thể tuần tự hóa khi nó không rõ ràng khai báo số phiên bản. Số phiên bản được tính toán dựa trên các khía cạnh khác nhau của lớp. Một lớp có thể tuần tự hóa có thể khai báo số phiên bản của chính nó bằng cách khai báo một trường có tên là serialVersionUID của kiểu static, long và final. Lớp ObjectOutputStreamLớp ObjectOutputStream mở rộng từ lớp OutputStream và triển khai giao diện ObjectOutput. Nó ghi các loại dữ liệu nguyên thủy và đối tượng vào luồng đầu ra. Các hàm khởi tạo của lớp này như sau: ObjectOutputStream() Hàm khởi tạo ObjectOutputStream() ngăn chặn các lớp con mà hoàn toàn cài đặt ObjectOutputStream từ cấp phát dữ liệu riêng tư chỉ được sử dụng bởi cài đặt này của ObjectOutputStream. Chữ ký của nó như sau:
5 ObjectOutputStream(OutputStream out) Hàm tạo ObjectOutputStream(OutputStream out) tạo ra một ObjectOutputStream ghi vào OutputStream được chỉ định. Chữ ký của nó như sau:
6 Các Phương Thức trong Lớp ObjectOutputStreamCác phương thức trong lớp ObjectOutputStream giúp ghi đối tượng vào luồng đầu ra. Các phương thức trong lớp ObjectOutputStream bao gồm:
7 Phương thức writeFloat(float value) ghi giá trị kiểu float vào luồng đầu ra. Chữ ký của nó như sau:
8
9 Phương thức writeObject(Object obj) ghi một đối tượng obj vào luồng đầu ra. Chữ ký của nó như sau:
00
01 Phương thức defaultWriteObject() ghi các trường không phải là static và không phải là transient vào luồng đầu ra. Chữ ký của nó như sau:
02 Ví dụ:
03 Lớp ObjectInputStreamLớp ObjectInputStream mở rộng lớp InputStream và triển khai giao diện ObjectInput. Giao diện ObjectInput mở rộng giao diện DataInput và có các phương thức hỗ trợ việc tuần tự hóa đối tượng. Lớp ObjectInputStream chịu trách nhiệm đọc các đối tượng và kiểu dữ liệu nguyên thủy từ một luồng đầu vào cơ sở. Nó có phương thức readObject() để khôi phục một đối tượng chứa các trường không phải là static và không phải là transient. Các constructor của lớp này như sau: ObjectInputStream() Constructor ObjectInputStream() giúp các lớp con tái hiện lớp ObjectInputStream để tránh phải cấp phát dữ liệu riêng tư được sử dụng bởi việc triển khai của ObjectInputStream. Chữ ký của nó như sau:
04 ObjectInputStream(InputStream in) Constructor ObjectInputStream(InputStream in) tạo ra một ObjectInputStream đọc từ InputStream đã chỉ định. Các đối tượng được tuần tự hóa được đọc từ luồng đầu vào in. Chữ ký của nó như sau:
05 Các Phương thức trong Lớp ObjectInputStreamCác phương thức trong lớp ObjectInputStream giúp đọc đối tượng từ luồng. Một số phương thức trong lớp ObjectInputStream là như sau: readFloat() Phương thức readFloat() đọc và trả về một số thực từ luồng đầu vào. Chữ ký của nó như sau:
06 readBoolean() Phương thức readBoolean() đọc và trả về một giá trị boolean từ luồng đầu vào. Chữ ký của nó như sau:
07 readByte() Phương thức readByte() đọc và trả về một byte từ luồng đầu vào. Chữ ký của nó như sau:
08 readChar() Phương thức readChar() đọc và trả về một ký tự từ luồng đầu vào. Chữ ký của nó như sau:
09 readObject() Phương thức readObject() đọc và trả về một đối tượng từ luồng đầu vào. Chữ ký của nó như sau:
10 Ví dụ:
11 Lớp ConsoleJava cung cấp lớp Console để cải thiện và đơn giản hóa quá trình phát triển các ứng dụng dòng lệnh. Lớp Console là một phần của gói java.io và có khả năng đọc văn bản từ terminal mà không hiển thị nó trên màn hình. Đối tượng Console cung cấp đầu vào và đầu ra của các luồng ký tự thông qua các lớp Reader và Writer của nó. Lớp Console cung cấp các phương thức khác nhau để truy cập thiết bị dòng lệnh dựa trên ký tự. Không có hàm tạo công khai cho lớp Console. Để có một thể hiện của lớp Console, bạn cần gọi phương thức System.console(). Phương thức System.console() trả về đối tượng Console nếu nó khả dụng; nếu không, nó trả về null. Hiện tại, các phương thức của lớp Console chỉ có thể được gọi từ dòng lệnh và không thể từ Môi trường Phát triển Tích hợp (IDEs) như Eclipse, NetBeans, và như vậy. Lớp Console cung cấp các phương thức để thực hiện các thao tác đầu vào và đầu ra trên các luồng ký tự. Phương thức readLine() đọc một dòng văn bản từ bảng điều khiển. Phương thức readPassword() đọc mật khẩu từ bảng điều khiển mà không hiển thị trên màn hình. Phương thức trả về một mảng ký tự và không phải là một đối tượng String để cho phép sửa đổi mật khẩu. Mật khẩu được xóa khỏi bộ nhớ khi không còn cần thiết nữa. Bảng dưới liệt kê các phương thức khác nhau có sẵn trong lớp Console. Phương thứcMô tảformat(String fmt, Object… args)Phương thức hiển thị dữ liệu được định dạng trên đầu ra của bảng điều khiểnprintf(String fmt, Object… args)Phương thức hiển thị dữ liệu được định dạng trên đầu ra của bảng điều khiển một cách thuận tiện hơnreader()Phương thức trả về một đối tượng java.io.Reader duy nhất liên kết với bảng điều khiểnreadLine()Phương thức chấp nhận một dòng văn bản từ bảng điều khiểnreadLine(String fmt, Object… args)Phương thức cung cấp đầu ra được định dạng và chấp nhận một dòng văn bản từ bảng điều khiển Ví dụ:
12 Các Lớp trong java.util.zipJava SE 6 đã giới thiệu một số thay đổi trong các tệp JAR và ZIP. Trong các phiên bản trước của các tệp JAR, timestamp (ngày và giờ) của các tệp được giải nén thường được đặt là thời gian hiện tại thay vì thời gian được lưu trữ trong tệp nén. Trong Java SE 6, công cụ JAR đã được cải tiến để timestamp của các tệp được giải nén phù hợp với thời gian lưu trữ. Điều này là cần thiết vì các công cụ giải nén khác phụ thuộc vào thời gian lưu trữ chứ không phải thời gian hiện tại để giải nén các tệp. Tên tệp ZIP hiện có thể dài hơn 256 ký tự trong các phiên bản gần đây của hệ điều hành Windows. Sau khi sử dụng các tệp ZIP hàng ngày, các tệp quan trọng nên được lưu trữ và nén để tiết kiệm không gian đĩa quan trọng. Các tệp có thể được nén và giải nén bằng cách sử dụng các tiện ích phổ biến như WinRar và WinZip. Trong gói java.util.zip, Java cung cấp các lớp có thể nén và giải nén tệp. Bảng 5.11 liệt kê một số lớp trong gói java.util.zip cùng với mô tả của chúng. Tên LớpMô TảCheckedInputStreamDuy trì checksum của dữ liệu đang được đọcCheckedOutputStreamDuy trì checksum của dữ liệu cần được ghiDeflaterThực hiện việc nén dữ liệuDeflaterInputStreamĐọc dữ liệu nguồn và sau đó nén nó theo định dạng nén ‘deflate’DeflaterOutputStreamĐọc dữ liệu nguồn, nén nó theo định dạng nén ‘deflate’ và sau đó ghi dữ liệu nén vào dòng đầu raInflaterThực hiện việc giải nén dữ liệuInflaterInputStreamĐọc dữ liệu được nén và sau đó giải nén nó theo định dạng nén ‘deflate’InflaterOutputStreamĐọc dữ liệu được nén, giải nén nó theo định dạng nén ‘deflate’ và sau đó ghi dữ liệu giải nén vào dòng đầu raZipInputStreamThực hiện một bộ lọc dòng đầu vào để đọc các tệp trong định dạng tệp ZIP. Hỗ trợ cả các mục được nén và không được nén.ZipOutputStreamĐọc dữ liệu nguồn, nén nó theo định dạng tệp ZIP và ghi dữ liệu vào dòng đầu ra Ví dụ:
13 Lớp Deflater và InflaterCác lớp Deflater và Inflater là các lớp mở rộng từ lớp Object. Các lớp này được sử dụng để nén và giải nén dữ liệu. Lớp DeflaterLớp Deflater nén dữ liệu có sẵn trong một luồng đầu vào. Nó nén dữ liệu bằng cách sử dụng thư viện nén ZLIB. Constructor của lớp Deflater được sử dụng để tạo các thể hiện của lớp Deflater. Cú pháp:
14 Constructor tạo một thể hiện với mức nén mặc định. Các Phương thức: Bảng dưới liệt kê các phương thức khác nhau trong lớp Deflater cùng với mô tả của chúng. Phương ThứcMô Tảdeflate(byte[] buffer)Điền bộ đệm đầu ra bằng dữ liệu được nén và trả về kích thước thực tế của dữ liệu được nén dưới dạng số nguyên.deflate(byte[] buffer, int offset, int len)Điền bộ đệm đầu ra bằng dữ liệu được nén và trả về kích thước thực tế của dữ liệu được nén dưới dạng số nguyên. Ở đây, buffer là bộ đệm được chỉ định để lưu trữ dữ liệu được nén, offset là vị trí bắt đầu của dữ liệu và len là số byte tối đa của dữ liệu được nén.setInput(byte[] buffer)Đặt dữ liệu đầu vào có sẵn trong bộ đệm để nén.setInput(byte[] buffer, int offset, int len)Đặt dữ liệu đầu vào có sẵn trong bộ đệm để nén. Ở đây, buffer là bộ đệm được chỉ định để lưu trữ các byte dữ liệu đầu vào, offset là vị trí bắt đầu của dữ liệu và len là độ dài của dữ liệu đầu vào.finish()Cho biết rằng quá trình nén nên kết thúc với nội dung hiện tại của bộ đệm đầu vào.end()Đóng máy nén và loại bỏ dữ liệu đầu vào chưa được xử lý. Ví dụ:
15 Lớp InflaterLớp Inflater giải nén dữ liệu đã được nén. Lớp này hỗ trợ giải nén bằng cách sử dụng thư viện nén ZLIB. Cú pháp:
16 Constructor tạo một thể hiện với mức nén mặc định. Bảng dưới liệt kê các phương thức khác nhau trong lớp Inflater cùng với mô tả của chúng. Phương ThứcMô Tảinflate(byte[] buffer)Điền bộ đệm đầu ra bằng dữ liệu được giải nén và trả về kích thước thực tế của dữ liệu giải nén dưới dạng số nguyên.inflate(byte[] buffer, int offset, int len)Điền bộ đệm đầu ra bằng dữ liệu được giải nén và trả về kích thước thực tế của dữ liệu giải nén dưới dạng số nguyên. Ở đây, buffer là bộ đệm được chỉ định để lưu trữ dữ liệu giải nén, offset là vị trí bắt đầu của dữ liệu và len là số byte tối đa của dữ liệu giải nén.setInput(byte[] buffer)Đặt dữ liệu đầu vào có sẵn trong bộ đệm để giải nén.setInput(byte[] buffer, int offset, int len)Đặt dữ liệu đầu vào có sẵn trong bộ đệm để giải nén. Ở đây, buffer là bộ đệm được chỉ định để lưu trữ các byte dữ liệu đầu vào, offset là vị trí bắt đầu của dữ liệu và len là độ dài của dữ liệu đầu vào.end()Đóng máy giải nén. Ví dụ:
17 Các Lớp DeflaterInputStream và DeflaterOutputStreamCác lớp DeflaterInputStream và DeflaterOutputStream được thừa kế từ các lớp FilterInputStream và FilterOutputStream tương ứng. Lớp DeflaterInputStreamLớp DeflaterInputStream đọc dữ liệu nguồn từ một luồng đầu vào và sau đó nén nó theo định dạng nén ‘deflate’. Lớp này cung cấp các constructor và phương thức của riêng mình. Cú pháp cho một số constructor được giải thích dưới đây. Cú pháp:
18 Constructor tạo một luồng đầu vào của byte để đọc dữ liệu nguồn với một máy nén và bộ đệm mặc định.
19 Constructor tạo một luồng đầu vào mới với kích thước bộ đệm mặc định và máy nén được chỉ định.
20 Constructor tạo một luồng đầu vào mới với kích thước bộ đệm và máy nén được chỉ định. Bảng dưới liệt kê các phương thức khác nhau có sẵn trong lớp DeflaterInputStream cùng với mô tả của chúng. Phương ThứcMô Tảread()Trả về một byte dữ liệu đã được nén đọc từ một luồng đầu vào.read(byte[] buffer, int offset, int bufSize)Trả về số byte dữ liệu đã được nén được đọc vào một mảng byte bắt đầu từ vị trí được chỉ định bởi offset và với kích thước bộ đệm là bufSize.close()Đóng luồng đầu vào sau khi đọc dữ liệu nguồn còn lại.markSupported()Trả về giá trị false. Điều này là do luồng đầu vào không hỗ trợ các phương thức mark() và reset().available()Trả về 0 sau khi đã đọc hết EOF. Nếu chưa đọc hết, nó trả về 1.long skip(long n)Bỏ qua và loại bỏ dữ liệu từ luồng đầu vào. Ví dụ:
21 Ví dụ 2:
22 Lớp DeflaterOutputStreamLớp DeflaterOutputStream đọc dữ liệu nguồn, nén nó theo định dạng nén ‘deflate’ và sau đó, viết dữ liệu nén vào một luồng đầu ra được xác định trước đó. Nó cũng làm nhiệm vụ cơ bản cho các loại bộ lọc nén khác, chẳng hạn như GZIPOutputStream. Cú pháp:
23 Constructor tạo một luồng đầu ra của byte để viết dữ liệu nén vào với máy nén và kích thước bộ đệm mặc định. Bảng dưới liệt kê các phương thức khác nhau có sẵn trong lớp DeflaterOutputStream cùng với mô tả của chúng. Phương ThứcMô Tảwrite(int buffer)Ghi một byte dữ liệu đã được nén vào luồng đầu ra.write(byte[] buffer, int offset, int bufSize)Ghi một mảng byte dữ liệu đã được nén vào luồng đầu ra. Ở đây, buffer là dữ liệu đầu vào cần được ghi dưới dạng byte, offset là vị trí bắt đầu, và bufSize là kích thước của buffer.deflate()Nén dữ liệu nguồn và sau đó, ghi khối dữ liệu nén tiếp theo vào luồng đầu ra.close()Đóng luồng đầu ra sau khi đã ghi xong dữ liệu nén còn lại.finish()Hoàn thành quá trình viết dữ liệu nén vào luồng đầu ra mà không đóng nó. Ví dụ:
24 Ví dụ 2:
25 Lớp InflaterInputStream và InflaterOutputStreamLớp InflaterInputStream và InflaterOutputStream được kế thừa từ các lớp FilterInputStream và FilterOutputStream tương ứng. Lớp InflaterInputStreamLớp InflaterInputStream đọc dữ liệu được nén và giải nén nó trong định dạng nén ‘deflate’. Cú pháp
26 Constructor tạo ra một luồng đầu vào của các byte để đọc dữ liệu được nén với decompressor và kích thước bộ đệm mặc định. Bảng dưới liệt kê các phương thức khả dụng trong lớp InflaterInputStream cùng với mô tả của chúng. Phương thức read()Trả về một byte dữ liệu giải nén được đọc từ luồng đầu vào.read(byte[] buffer, int offset, int buffSize)Trả về số byte dữ liệu giải nén được đọc vào một mảng byte từ vị trí bắt đầu được chỉ định bởi offset và kích thước buffSize. Ví dụ:
27 Lớp InflaterOutputStreamLớp InflaterOutputStream đọc dữ liệu được nén, giải nén dữ liệu được lưu trữ trong định dạng nén ‘deflate’ và sau đó, viết dữ liệu giải nén vào một luồng đầu ra. Lớp này cũng là lớp cơ sở cho lớp giải nén có tên GZIPInputStream. Lớp InflaterOutputStream cung cấp các phương thức để giải nén các tệp được nén. Cú pháp
28 Constructor tạo một luồng đầu ra của các byte để viết dữ liệu giải nén với decompressor và kích thước bộ đệm mặc định. Phương thức:
Ví dụ:
29 Gói java.nioAPI Java New Input/Output (NIO) đã được giới thiệu vào năm 2002 với J2SE 1.4 để tăng cường các nhiệm vụ xử lý đầu vào/đầu ra trong phát triển ứng dụng Java. Mặc dù, nó chưa được sử dụng đến tối đa, Java SE 7 đã giới thiệu thêm API New Input/Output (NIO.2). Java SE 16 tiếp tục hỗ trợ điều này. Mục tiêu chính cho cả NIO và NIO.2 vẫn giữ nguyên, đó là tăng cường các nhiệm vụ xử lý I/O trong phát triển ứng dụng Java. Sử dụng của chúng có thể giảm thời gian cần thiết cho một số thao tác I/O thông thường, Lưu ý: Cả NIO và NIO.2 đều rất phức tạp để làm việc. Cả hai API NIO và NIO.2 đều tiết lộ các điểm nhập hệ thống cấp thấp phụ thuộc vào hệ điều hành (OS). Chúng cũng cung cấp kiểm soát lớn hơn về I/O. Một khía cạnh khác của NIO là sự chú ý đến sự biểu đạt của ứng dụng. NIO phụ thuộc vào nền tảng và khả năng tăng cường hiệu suất ứng dụng của nó phụ thuộc vào các yếu tố sau:
Dưới đây là những tính năng chính của các API NIO: Bảng mã và Bộ giải mã, Bộ mã hóa liên quan của Chúng: Chúng dịch dữ liệu giữa byte và ký tự Unicode. API bảng mã được định nghĩa trong gói java.nio.charset. Gói charset linh hoạt hơn so với phương thức getBytes(), dễ triển khai hơn và mang lại hiệu suất xuất sắc, Bộ đệm: Đây là các container cho dữ liệu. Các lớp bộ đệm được định nghĩa trong gói ong NIO, các đối tượng của lớp và được sử dụng bởi tất cả các API NIO. Các Loại Kênh: Đại diện cho các kết nối với các thực thể có thể thực hiện các hoạt động I/O. Các kênh là các tệp trừu tượng và socket và hỗ trợ I/O không đồng bộ. Bộ chọn và khóa lựa chọn: Cùng với các kênh có thể chọn, chúng xác định một cơ sở dữ liệu I/O không đồng bộ được nhiều lựa chọn. I/O không đồng bộ dựa trên sự kiện, điều này có nghĩa là có một bộ chọn được định nghĩa cho một kênh I/O và sau đó, quá trình xử lý xảy ra. Khi một sự kiện xảy ra như sự xuất hiện của một đầu vào, trên bộ chọn, bộ chọn sẽ thức dậy và thực thi. Điều này có thể thực hiện bằng một luồng đơn. Các API kênh và bộ chọn được định nghĩa trong gói java.nio.channels. Lưu ý: Mỗi gói con có gói cung cấp dịch vụ (SPI) riêng giúp mở rộng triển khai mặc định của nền tảng. Nó cũng giúp xây dựng các triển khai thay thế. Gói java.nio.file và gói java.nio.file.attribute hỗ trợ đầu vào/đầu ra tệp tin. Chúng cũng giúp truy cập hệ thống tệp mặc định. Hệ Thống Tệp, Đường Dẫn và Tệp TinHệ thống tệp lưu trữ và tổ chức các tệp tin trên phương tiện truyền thông, thường là ổ đĩa cứng. Những tệp tin này có thể dễ dàng được truy xuất. Mỗi tệp tin đều có một đường dẫn thông qua hệ thống tệp. Hệ Thống Tệp Thường, các tệp tin được lưu trữ trong một cấu trúc phân cấp, trong đó có một nút gốc. Dưới nút này là các tệp tin và thư mục. Mỗi thư mục có thể chứa các tệp tin và thư mục con, và cứ như vậy. Không có giới hạn về cấu trúc phân cấp. Hệ thống tệp có thể có một hoặc nhiều thư mục gốc. Hệ thống tệp có các đặc điểm khác nhau đối với bộ phân cách đường dẫn. Trong NIO, các đối tượng của lớp java.nio.file.Path đại diện cho vị trí tương đối hoặc tuyệt đối của một tệp hoặc thư mục. Đường Dẫn Mỗi tệp tin được xác định thông qua đường dẫn của nó. Nói cách khác, đường dẫn chỉ định một vị trí duy nhất trong hệ thống tệp. Nó bắt đầu từ nút gốc, Microsoft Windows hỗ trợ nhiều nút gốc. Mỗi nút gốc tương ứng với một ổ đĩa, chẳng hạn như D:. Hệ điều hành Solaris hỗ trợ một nút gốc duy nhất, được biểu thị bằng ký tự gạch chéo, /. Hệ thống tệp bao gồm các đặc điểm khác nhau đối với bộ phân cách đường dẫn. Ký tự phân cách tên thư mục được gọi là ký tự ngăn cách. Điều này là đặc trưng cho hệ thống tệp. Ví dụ, Microsoft Windows sử dụng dấu gạch chéo () và hệ điều hành Solaris sử dụng dấu gạch chéo xuôi (/). hình ảnh dưới mô tả cấu trúc thư mục Dựa trên hình, xem xét những điều sau: Trong hệ điều hành Solaris, đường dẫn cho tệp dailySalesReport sẽ được biểu thị là /home/user/dailySalesReport. Trong Microsoft Windows, đường dẫn cho dailySalesReport sẽ được biểu thị là C:\home\user\dailySalesReport. Một đường dẫn có thể là tương đối hoặc tuyệt đối. Một đường dẫn tuyệt đối bao gồm phần tử gốc và danh sách thư mục đầy đủ để định vị tệp tin. Ví dụ, /home/user/dailySalesReport là một đường dẫn tuyệt đối. Trong đó, tất cả thông tin cần để định vị tệp tin đều được bao gồm trong chuỗi đường dẫn. Một đường dẫn tương đối không bao gồm danh sách thư mục đầy đủ. Ví dụ, user/dailySalesReport. Nó phải được sử dụng với một đường dẫn khác để truy cập một tệp tin. Mà không có thông tin thêm, một chương trình sẽ không thể định vị tệp tin. Tệp Tin Lưu ý: Tất cả các phương thức truy cập hệ thống tệp tin đều ném ra IOException hoặc một lớp con của nó. Sự khác biệt giữa NIO.2 và java.io.File là cách truy cập hệ thống tệp tin. Trong lớp java.io, các phương thức để điều chỉnh thông tin đường dẫn nằm trong cùng một lớp cũng chứa các phương thức để đọc và ghi tệp tin và thư mục. Với NIO.2, hai quá trình đã được tách rời. Trong NIO.2, là giao diện Path giúp tạo và kiểm soát các đường dẫn. Là lớp Files thực hiện các hoạt động trên các tệp tin và thư mục. Lớp Files chỉ hoạt động trên các đối tượng Path. Các phương thức của lớp Files hoạt động trực tiếp trên hệ thống tệp tin sẽ ném IOException. Giao Diện PathĐối tượng giao diện java.nio.file.Path có thể giúp định vị một tệp tin trong hệ thống tệp tin. Thông thường, giao diện đại diện cho một đường dẫn tệp tin phụ thuộc vào hệ thống. Nói cách khác, nó cung cấp điểm nhập cho việc điều chỉnh tệp tin và thư mục. Một đường dẫn là phân cấp. Nó bao gồm một chuỗi các thư mục và tên tệp tin. Những thư mục và tên tệp tin này được phân tách bằng một dấu phân cách. Dưới đây là những đặc điểm của một Path:
Một Path có thể đại diện cho những điều sau:
Một Path là trống nếu nó chỉ bao gồm một thành phần tên trống. Lưu ý: Việc truy cập một tệp tin bằng cách sử dụng một đường dẫn trống tương tự như truy cập thư mục mặc định của hệ thống tệp tin. Gói java.nio.file cũng cung cấp một lớp trợ giúp có tên là Paths. Lớp này là tĩnh và cuối cùng và có phương thức getDefault(). Dưới đây là một số phương thức của giao diện Path có thể được nhóm dựa trên chức năng chung:
Để có được một đối tượng Path, hãy lấy một phiên bản của hệ thống tệp tin mặc định. Tiếp theo, gọi phương thức getPath(). Ví dụ:
30 Đối tượng Path sau khi được tạo ra không thể thay đổi. Nói cách khác, chúng là không thay đổi. Đối với các hoạt động trên Path, nếu hệ thống tệp tin mặc định được sử dụng thì cần sử dụng tiện ích Paths. Hệ thống tệp tin mặc định là hệ thống tệp tin mà JVM đang chạy trên đó. Đó là cách ngắn gọn hơn. Đối với các hệ thống tệp tin khác (không phải hệ thống mặc định), hãy lấy một phiên bản của hệ thống tệp tin và xây dựng các đối tượng Path để thực hiện các hoạt động trên Path. Dưới đây là một số phương thức phổ biến của lớp Path: subpath() Một phần của đường dẫn có thể được lấy bằng cách sử dụng phương thức subpath(). Cú pháp là:
31 Ở đây,
Đoạn mã dưới thể hiện cách sử dụng phương thức subpath():
32 Trong đoạn mã này, tên phần tử gần nhất với root có giá trị index là 0. Phần tử xa root nhất có giá trị index là index count – 1. Do đó, kết quả của đoạn mã sẽ là Java/Hello.txt. resolve() Phương thức resolve() được sử dụng để kết hợp hai đường dẫn. Nó chấp nhận một đường dẫn không đầy đủ và nối đường dẫn không đầy đủ này vào đường dẫn gốc. Đoạn mã dưới sử dụng phương thức resolve() để kết hợp hai đường dẫn.
33 Kết quả của đoạn mã này sẽ là /java/test/bar. Nếu bạn truyền một đường dẫn tuyệt đối cho phương thức resolve(), nó sẽ trả về đường dẫn được truyền. Đoạn mã dưới trả về /java/test:
34 relativize() Phương thức relativize() giúp xây dựng một đường dẫn từ một vị trí trong hệ thống tệp tin đến một vị trí khác. Đoạn mã dưới minh họa điều này.
35 Kết quả sẽ là /sales. Lưu ý: Đường dẫn mới là tương đối với đường dẫn gốc. Đường dẫn bắt nguồn từ đường dẫn gốc và kết thúc tại vị trí được xác định bởi đường dẫn được truyền vào. Theo dõi Thay Đổi Hệ Thống Tệp và Thư Mục bằng lớp java.nio.file.FilesLớp java.nio.file.Files chứa các phương thức tĩnh thực hiện các chức năng chính cho các đối tượng Path. Những phương thức này có thể nhận diện và quản lý các liên kết biểu tượng tự động. Dưới đây là một số thao tác quan trọng: Sao Chép Một Tệp hoặc Thư Mục:Để sao chép một tệp hoặc thư mục, bạn có thể sử dụng phương thức copy(Path, Path, CopyOption…). Cân nhắc những điểm sau khi sao chép:
Tùy Chọn Sao Chép:
36
37 Ví dụ:
38 Chuyển một tập tin hoặc thư mụcĐể thực hiện việc này, sử dụng phương thức
78. Nếu tập tin đích tồn tại, tùy chọn
55 nên được sử dụng. Nếu không, quá trình di chuyển sẽ thất bại. Phương thức này nhận một đối số biến đổi. Các thư mục trống có thể được di chuyển. Nếu thư mục không trống, nó có thể được di chuyển mà không di chuyển nội dung. Phương thức
80 hỗ trợ các hằng số liệt kê
81 sau:
Chú ý:
Cú pháp dưới đây thể hiện phương thức
84.
39 Trong đó:
Dưới đây là các hướng dẫn cho việc di chuyển:
Ví dụ:
40 Kiểm tra một tập tin hoặc thư mụcĐể làm điều này, hệ thống tệp cần được truy cập bằng cách sử dụng các phương thức của
91 để xác định xem một đường dẫn cụ thể có tồn tại không. Các phương thức trong lớp
58 hoạt động trên đối tượng
58. Dưới đây là các phương thức của
91 để kiểm tra sự tồn tại của đối tượng
58:
Một hệ thống tệp có thể sử dụng hai đường dẫn khác nhau để xác định cùng một tập tin. Điều này xảy ra khi hệ thống tệp sử dụng các liên kết tượng trưng. Phương thức
02 có thể giúp so sánh hai đường dẫn để kiểm tra xem chúng có trỏ đến cùng một tập tin trên hệ thống tệp hay không. Ví dụ:
41 Xóa một tập tin hoặc thư mụcPhương thức
03 có thể được sử dụng để xóa một tập tin, thư mục hoặc liên kết. Việc xóa sẽ thất bại nếu thư mục không trống. Phương thức ném một ngoại lệ nếu quá trình xóa thất bại. Nếu tập tin không tồn tại, sẽ được ném một
04. Để xác định lý do thất bại,
42 Ví dụ phương thức deleteIfExists()
43 Liệt kê nội dung thư mụcĐể làm điều này, sử dụng lớp
05 để lặp qua tất cả các tập tin và thư mục từ bất kỳ
58 thư mục nào. Cân nhắc về các điểm sau:
Ví dụ:
44 Tạo mới thư mục
09 là phương thức được sử dụng để tạo một thư mục mới. Phương thức
10 có thể được sử dụng để tạo các thư mục từ trên xuống. Đoạn mã dưới minh họa điều này.
45 Khi thực thi, nó sẽ tạo ra các thư mục theo thứ tự đã cho:
11,
12, và
13. Thư mục
12 sẽ được tạo bên trong
11 và
13 sẽ được tạo bên trong thư mục
12. Để tạo một tập tin, sử dụng phương thức
18. Đọc và ghi tệp tinĐể đọc từ tệp tin, sử dụng các phương thức
19 hoặc
20 để đọc toàn bộ nội dung của tệp. Đoạn mã 46 thể hiện cách sử dụng phương thức
19:
46 Để viết bytes hoặc dòng vào một tệp tin, sử dụng các phương thức sau:
47 Một số
23 hỗ trợ bao gồm
24,
25,
26,
27, và
28.
48 Cả hai phương thức trên đều ném ra các ngoại lệ như
65,
68, và
69. java.nio.file package hỗ trợ I/O theo kiểu channel. Ví dụ:
49 Đọc tệp tin bằng cách sử dụng Buffered StreamPhương thức
33 mở một tệp tin để đọc. Nó trả về một đối tượng
34 giúp đọc văn bản từ một tệp tin một cách hiệu quả. Ví dụ:
50 Ghi tệp tin bằng cách sử dụng Buffered StreamPhương thức
35 có thể được sử dụng để ghi vào một tệp tin bằng cách sử dụng
36. Ví dụ:
51 Đọc ghi chuỗi từ tệp tinLớp
37 được sử dụng để ghi dữ liệu vào các tệp văn bản trong Java. Để đọc dữ liệu từ các tệp văn bản, hãy sử dụng
38. Cả hai lớp này đều thuộc về các lớp dòng ký tự.
39 và
40 không nên được sử dụng để đọc/ghi dữ liệu văn bản vì chúng là các lớp dòng byte không phù hợp cho các hoạt động dựa trên ký tự. FileWriterCác Constructor của
37:
Các Phương thức của FileWriter:
37 ghi một ký tự mỗi lần và tương tự, đọc mỗi ký tự một lần dẫn đến sự tăng của các quy trình I/O. Do đó, nó ảnh hưởng đến hoạt động của hệ thống. Sử dụng
36 với
37 tăng tốc độ thực thi. FileReader
38 đọc từng ký tự từ một tệp văn bản:
Các Constructor của FileReader:
Các Phương thức của
38:
Các tham số cho các phương thức
38 bao gồm:
Ngoài ra, phương thức
63 được sử dụng để đóng người đọc, và phương thức
64 được sử dụng để bỏ qua các ký tự, chặn cho đến khi có một ký tự có sẵn, có lỗi I/O xảy ra, hoặc nó gần cuối |