341 Chương 8: Đồ họa, đa phương tiện, và in ấn mSpeaker.Show(0); } catch (FileNotFoundException) { MessageBox.Show("Invalid character location", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } // Phương thức thụ lý sự kiện Click của nút Speak. private void cmdSpeak_Click(System.Object sender, System.EventArgs e) { // Nếu txtSpeech rỗng, nhân vật nhắc người dùng nhập text vào txtSpeech. if (txtSpeech.Text == "") { mSpeaker.Speak("Please type the words you want me to speak", ""); } else { mSpeaker.Speak(txtSpeech.Text, ""); } } // Phương thức thụ lý sự kiện Click của agent. private void mainAgent_ClickEvent(object sender, AxAgentObjects._AgentEvents_ClickEvent e) { mSpeaker.Play("Confused"); mSpeaker.Speak("Why are you poking me?", ""); mSpeaker.Play("RestPose"); } // Phương thức thụ lý sự kiện SelectedIndexChanged của characterCombo // (người dùng chọn nhân vật mới). private void characterCombo_SelectedIndexChanged(System.Object sender, System.EventArgs e) 342 Chương 8: Đồ họa, đa phương tiện, và in ấn { ChangeCharacter(characterCombo.Text); } // Ẩn nhận vật hiện tại và hiện nhân vật mới. private void ChangeCharacter(string name) { mSpeaker.Hide(0); mSpeaker = mainAgent.Characters[name]; GetAnimationNames(); // Sinh lại danh sách hành động. mSpeaker.Show(0); } // Thu lấy tên các hành động và đưa vào actionsCombo. private void GetAnimationNames() { // Bảo đảm tính an toàn về tiểu trình. object synclockObject = (this); Monitor.Enter(synclockObject); try { // Lấy tên các hành động. IEnumerator enumerator = mainAgent.Characters.Character(mSpeaker.Name). AnimationNames.GetEnumerator(); string voiceString; // Xóa actionsCombo. actionsCombo.Items.Clear(); mSpeaker.Commands.RemoveAll(); // Thêm tất cả các hành động (cho phép ra lệnh bằng giọng nói). while (enumerator.MoveNext()) { voiceString = Convert.ToString(enumerator.Current); 343 Chương 8: Đồ họa, đa phương tiện, và in ấn voiceString = voiceString.Replace("_", "underscore"); actionsCombo.Items.Add(enumerator.Current); mSpeaker.Commands.Add(Convert.ToString(enumerator.Current), "" voiceString, true, false); } // Thêm lệnh tùy biến. mSpeaker.Commands.Add("MoveToMouse", "MoveToMouse", "Move To Mouse", true, true); } finally { Monitor.Exit(synclockObject); } } // Phương thức thụ lý sự kiện SelectedIndexChanged của actionsCombo // (người dùng chọn hành động mới). private void actionsCombo_SelectedIndexChanged(System.Object sender, System.EventArgs e) { mSpeaker.Stop(null); mSpeaker.Play(actionsCombo.Text); mSpeaker.Play("RestPose"); } // Phương thức thụ lý sự kiện Command của agent. private void mainAgent_Command(System.Object sender, AxAgentObjects._AgentEvents_CommandEvent e) { AgentObjects.IAgentCtlUserInput command = ((AgentObjects.IAgentCtlUserInput)(e.userInput)); // Đổi nhân vật nếu người dùng đọc tên nhân vật. if (command.Voice == "Peedy" || command.Voice == "Robby" || command.Voice == "Merlin" || command.Voice == "Genie") 344 Chương 8: Đồ họa, đa phương tiện, và in ấn { ChangeCharacter(command.Voice); return; } // Gửi agent đến chuột. if (command.Name == "MoveToMouse") { mSpeaker.MoveTo(Convert.ToInt16(Cursor.Position.X - 60), Convert.ToInt16(Cursor.Position.Y - 60), null); return; } // Thực hiện hành động mới. mSpeaker.Stop(null); mSpeaker.Play(command.Name); } } 345 Chương 8: Đồ họa, đa phương tiện, và in ấn Hình 8.16 Ứng dụng thử nghiệm Microsoft Agent 9 346 Chương 9:FILE, THƯ MỤC, VÀ I/O 347 348 Chương 9: File, thư mục, và I/O ác lớp I/O của Microsoft .NET gồm hai loại chính. Loại thứ nhất truy xuất thông tin từ hệ thống file và cho phép thực hiện các thao tác trên hệ thống file (như chép file, chuyển thư mục). Hai lớp tiêu biểu là FileInfo và DirectoryInfo . Loại thứ hai quan trọng hơn, gồm rất nhiều lớp cho phép đọc và ghi dữ liệu từ mọi kiểu stream. Stream có thể tương ứng với một file nhị phân hay văn bản, một file trong không gian lưu trữ riêng, một kết nối mạng, hoặc một vùng đệm bộ nhớ. Trong mọi trường hợp, cách thức tương tác với stream đều như nhau. Trong chương này, chúng ta sẽ xem xét các lớp hệ thống file và các lớp dựa- trên-stream. C Các mục trong chương này trình bày các vấn đề sau: Truy xuất và sửa đổi các thông tin của một file hay một thư mục (các mục 9.1, 9.2, 9.4, 9.5, và 9.16). Chép, di chuyển, xóa file hay thư mục (mục 9.3). Hiển thị động một cây thư mục trong một ứng dụng dựa-trên-Windows (mục 9.6) và sử dụng các hộp thoại file (mục 9.17). Đọc và ghi file văn bản (mục 9.7) và file nhị phân (mục 9.8), cũng như tạo file tạm (mục 9.15) và file trong một không gian lưu trữ riêng của người dùng (mục 9.18). Đọc file một cách bất đồng bộ (mục 9.9). Tìm file (mục 9.10) và kiểm tra hai file có trùng nhau hay không (mục 9.11). Làm việc với các chuỗi có chứa thông tin đường dẫn (mục 9.12 đến 9.14). Theo dõi sự thay đổi của hệ thống file (mục 9.19). Ghi ra cổng COM (mục 9.20). 1. 1. Truy xu t các thông tin v file hay th m cấ ề ư ụ Truy xu t các thông tin v file hay th m cấ ề ư ụ Bạn cần truy xuất các thông tin về một file hay một thư mục, chẳng hạn ngày tạo hay các thuộc tính của chúng. Tạo đối tượng System.IO.FileInfo cho file hay đối tượng System.IO.DirectoryInfo cho thư mục. Sau đó, truyền đường dẫn tới file hay thư mục đó trong phương thức khởi dựng. Các thông tin cần thiết sẽ được truy xuất thông qua các thuộc tính của đối tượng. Để tạo một đối tượng FileInfo hay DirectoryInfo , bạn cần truyền đường dẫn tương đối hay đầy đủ trong phương thức khởi dựng của nó. Bạn có thể lấy các thông tin về file hay thư mục thông qua các thuộc tính của đối tượng tương ứng. Bảng 9.1 liệt kê các thành viên của lớp FileInfo và DirectoryInfo : Bảng 9.1 Các thành viên của FileInfo và DirectoryInfo Thành viên Thuộc lớp Mô tả 349 Chương 9: File, thư mục, và I/O Exists FileInfo và DirectoryInfo Trả về true hay false , tùy thuộc vào file hay thư mục có tồn tại ở đường dẫn được chỉ định hay không. Attributes FileInfo và DirectoryInfo Trả về một hoặc nhiều giá trị thuộc kiểu liệt kê System.IO.FileAttributes , cho biết các thuộc tính của file hay thư mục. CreationTime , LastAccessTime , và LastWriteTime FileInfo và DirectoryInfo Trả về các thể hiện System.DateTime cho biết khi nào một file hay thư mục được tạo ra, truy xuất lần cuối, và cập nhật lần cuối. FullName , Name , và Extension FileInfo và DirectoryInfo Trả về một chuỗi chứa tên đầy đủ, tên thư mục hay tên file (cùng phần mở rộng), và phần mở rộng. Length FileInfo Trả về kích thước file (tính theo byte). DirectoryName và Directory FileInfo DirectoryName trả về chuỗi chứa tên của thư mục cha; Directory trả về đối tượng DirectoryInfo mô tả thư mục cha, cho phép bạn truy xuất thêm thông tin về nó. Parent và Root DirectoryInfo Trả về đối tượng DirectoryInfo mô tả thư mục cha hay thư mục gốc. CreateSubdirectory DirectoryInfo Tạo một thư mục bên trong thư mục được mô tả bởi đối tượng DirectoryInfo , tên thư mục cần tạo được truyền cho phương thức. Trả về đối tượng DirectoryInfo mô tả thư mục con vừa tạo. GetDirectories DirectoryInfo Trả về mảng các đối tượng DirectoryInfo , mỗi đối tượng mô tả một thư mục con trong thư mục này. GetFiles DirectoryInfo Trả về mảng các đối tượng FileInfo , mỗi đối tượng mô tả một file trong thư mục này. Chú ý hai điểm quan trọng khi sử dụng các đối tượng FileInfo và DirectoryInfo : • Tất cả các thuộc tính của đối tượng FileInfo và DirectoryInfo được đọc ngay lần đầu tiên bạn truy xuất một thuộc tính nào đó. Nếu file hay thư mục thay đổi sau thời điểm này, bạn phải gọi phương thức Refresh để cập nhật các thuộc tính. • Sẽ không có lỗi nếu bạn chỉ định một đường dẫn không tương ứng với một file hay thư mục đang tồn tại khi tạo một đối tượng FileInfo hay DirectoryInfo . Thay vào đó, bạn sẽ nhận được một đối tượng mô tả file hay thư mục không tồn tại—thuộc tính Exists của nó có giá trị false . Bạn có thể sử dụng đối tượng này để tạo file hay thư mục bằng cách gọi phương thức Create của nó. Nếu bạn truy xuất thuộc tính khác, ngoại lệ FileNotFoundException hay DirectoryNotFoundException sẽ bị ném. 350 Chương 9: File, thư mục, và I/O Ứng dụng Console dưới đây nhận một đường dẫn file từ dòng lệnh, và rồi hiển thị thông tin về file và thư mục chứa file. . trường hợp, cách thức tương tác với stream đều như nhau. Trong chương này, chúng ta sẽ xem xét các lớp hệ thống file và các lớp dựa- trên-stream. C Các mục trong chương này trình bày các vấn đề. 9.20). 1. 1. Truy xu t các thông tin v file hay th m cấ ề ư ụ Truy xu t các thông tin v file hay th m cấ ề ư ụ Bạn cần truy xuất các thông tin về một file hay một thư mục, chẳng hạn ngày tạo hay các thuộc. Bạn có thể lấy các thông tin về file hay thư mục thông qua các thuộc tính của đối tượng tương ứng. Bảng 9.1 liệt kê các thành viên của lớp FileInfo và DirectoryInfo : Bảng 9.1 Các thành viên