一期犬、前言
實(shí)驗(yàn)?zāi)康?/h5>
利用RMI技術(shù)對(duì)遠(yuǎn)程文件夾進(jìn)行控制:可以增加文件(文本文件)、修改文件(文本文件)避诽、刪除文件、列出文件璃谨;統(tǒng)計(jì)該文件夾具有多少個(gè)文件沙庐、占用磁盤空間的總大小。
開發(fā)環(huán)境
- 操作系統(tǒng):Windows 10 X64
- IDE:Intellij IDEA
二佳吞、準(zhǔn)備
新建Java項(xiàng)目:File->New->Project
點(diǎn)擊Next:
點(diǎn)擊Next:
設(shè)置項(xiàng)目名稱以及項(xiàng)目存儲(chǔ)位置拱雏,點(diǎn)擊Finish:
三、代碼步驟
1. 遠(yuǎn)程接口定義
定義用于遠(yuǎn)程對(duì)象的接口 FileService底扳。這個(gè)接口定義了客戶機(jī)能夠遠(yuǎn)程地調(diào)用的方法铸抑。遠(yuǎn)程接口和本地接口的主要差異在于,遠(yuǎn)程方法必須能拋出 RemoteException衷模。具體方法如下:
FileService.java:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface FileService extends Remote {
//列出文件
public String[] play() throws RemoteException;
//增加文件
public boolean addFile(String name) throws RemoteException;
//刪除文件
public boolean deleteFile(String name) throws RemoteException;
//修改文件
public boolean alterFile(String name,String content) throws RemoteException;
//讀取文件內(nèi)容
public String readFile(String name) throws RemoteException;
//統(tǒng)計(jì)文件信息
public long[] fileInformation() throws RemoteException;
}
這些方法必須能拋出RemoteException鹊汛,如果客戶機(jī)和服務(wù)器之間的通信錯(cuò)誤,則客戶機(jī)將捕獲此異常阱冶。
注:該接口本身繼承了java.rmi包中定義的Remote接口刁憋。Remote接口本身沒有定義方法,但通過繼承它木蹬,我們說明該接口可以被遠(yuǎn)程地調(diào)用至耻。
2. 實(shí)現(xiàn)遠(yuǎn)程接口
編寫一個(gè)實(shí)現(xiàn)FileService接口的類 FileServiceImpl。
FileServiceImpl.java:
import java.io.*;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* 繼承自UnicastRemoteObject,為遠(yuǎn)程對(duì)象的實(shí)現(xiàn)類
*/
public class FileServiceImpl extends UnicastRemoteObject implements FileService{
public FileServiceImpl() throws RemoteException {
super();
}
// 列出文件
@Override
public String[] play() throws RemoteException {
File file = new File("D://RMI");
String[] names=file.list();
return names;
}
// 增加文件
@Override
public boolean addFile(String name) throws RemoteException {
File file = new File("D://RMI",name);
if(!file.exists()){
try{
file.createNewFile();
return true;
}catch(IOException e){
e.printStackTrace();
}
}
return false;
}
// 刪除文件
@Override
public boolean deleteFile(String name) throws RemoteException {
File file = new File("D://RMI",name);
if(file.exists()){
file.delete();
return true;
}
return false;
}
// 修改文件
@Override
public boolean alterFile(String name, String content) throws RemoteException {
FileWriter fw = null;
try{
fw = new FileWriter("D://RMI/"+name);
}catch(IOException e1){
e1.printStackTrace();
}
try{
fw.write(content,0,content.length());
}catch (IOException e2){
e2.printStackTrace();
}
//關(guān)閉流
try{
fw.close();
return true;
}catch (IOException e3){
e3.printStackTrace();
}
return false;
}
//讀取文件內(nèi)容
@Override
public String readFile(String name) throws RemoteException {
FileReader fr = null;
try{
fr = new FileReader("D://RMI/"+name);
}catch (FileNotFoundException e){
e.printStackTrace();
}
int ch = 0;
String filecontent = "";
try{
while((ch = fr.read())!=-1){
filecontent = filecontent + (char)ch;
}
}catch (IOException e){
e.printStackTrace();
}
//
try{
fr.close();
}catch (Exception e){
e.printStackTrace();
}
return filecontent;
}
//統(tǒng)計(jì)該文件夾具有多少個(gè)文件镊叁、占用磁盤空間的總大小
@Override
public long[] fileInformation() throws RemoteException {
File file = new File("D://RMI");
File[] files = file.listFiles();
long number = files.length;
long size = 0;
for(int i=0;i<number;i++){
size = size + files[i].length()/1024;
}
long[] information = {number,size};
return information;
}
}
注:在對(duì)文件進(jìn)行讀寫操作后必須關(guān)閉用close()函數(shù)關(guān)閉流尘颓,不然可能會(huì)影響到delete操作,導(dǎo)致不能刪除文件晦譬。
3. 編寫在服務(wù)器上運(yùn)行的主程序 Server.java疤苹。
創(chuàng)建服務(wù)器對(duì)象的初始實(shí)例,然后將對(duì)象的名稱寫到RMI命名注冊(cè)表蛔添。
//創(chuàng)建服務(wù)器對(duì)象實(shí)例
FileService fileService = new FileServiceImpl();
//注冊(cè)服務(wù)的端口
LocateRegistry.createRegistry(6600);
//綁定本地地址和服務(wù)器的路徑
Naming.rebind("rmi://127.0.0.1:6600/FileService",fileService);
RMI命名注冊(cè)表允許您將URL名稱分配給對(duì)象以便客戶機(jī)查找它們痰催。要注冊(cè)名稱兜辞,需要調(diào)用在Naming類上定義的靜態(tài)rebind方法。這個(gè)方法接受對(duì)象的URL名稱以及對(duì)象引用夸溶。
名稱字符串包含 rmi:// 前綴逸吵、運(yùn)行RMI對(duì)象的服務(wù)器的計(jì)算機(jī)主機(jī)名和對(duì)象本身的名稱。這里用了本機(jī)地址127.0.0.1缝裁。
完整代碼如下:
Server.java:
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class Server {
public Server(){}
public static void main(String[] args){
try{
FileService fileService = new FileServiceImpl();
//注冊(cè)服務(wù)的端口
LocateRegistry.createRegistry(6600);
//綁定本地地址和服務(wù)器的路徑
Naming.rebind("rmi://192.168.1.102:6600/FileService",fileService);
System.out.println("開始服務(wù)扫皱!");
}catch(Exception e){
e.printStackTrace();
}
}
}
4. 編寫客戶端程序 Client.java。
使用RMI注冊(cè)表查找遠(yuǎn)程對(duì)象捷绑。
//調(diào)用遠(yuǎn)程對(duì)象韩脑,RMI路徑與接口必須與服務(wù)器配置一致
FileService fileService = (FileService)Naming.lookup("rmi://127.0.0.1:6600/FileService");
根據(jù)選擇的操作,調(diào)用有遠(yuǎn)程接口定義的方法粹污。完整代碼如下:
Client.java:
import java.rmi.Naming;
import java.util.Scanner;
public class Client {
public Client(){}
public static void main(String[] args){
try{
//調(diào)用遠(yuǎn)程對(duì)象段多,RMI路徑與接口必須與服務(wù)器配置一致
FileService fileService = (FileService)Naming.lookup("rmi://127.0.0.1:6600/FileService");
int choose;
Scanner input = new Scanner(System.in);
System.out.println("1.列出文件");
System.out.println("2.增加文件");
System.out.println("3.修改文件");
System.out.println("4.刪除文件");
System.out.println("5.統(tǒng)計(jì)文件");
while(true){
System.out.println("請(qǐng)選擇要進(jìn)行的操作:");
choose = input.nextInt();
if(choose == 1){
String[] filename = fileService.play();
for(int i = 0;i < filename.length;i++){
System.out.println(filename[i]);
}
}
else if(choose == 2){
System.out.println("請(qǐng)輸入要新增文件的名稱:");
String name = input.next();
boolean flag = fileService.addFile(name);
if(flag == true){
System.out.println("創(chuàng)建成功!");
}
else{
System.out.println("創(chuàng)建失斪撤浴进苍!");
}
}
else if(choose == 3){
System.out.println("請(qǐng)輸入要修改文件的名稱:");
String name = input.next();
String filecontent = fileService.readFile(name);
System.out.println(filecontent);
System.out.println("請(qǐng)輸入修改內(nèi)容:");
String content = input.next();
boolean flag = fileService.alterFile(name,content);
if(flag == true){
System.out.println("修改成功!");
}
else{
System.out.println("修改失斞夹稹觉啊!");
}
}
else if(choose == 4){
System.out.println("請(qǐng)輸入要?jiǎng)h除文件的名稱:");
String name = input.next();
boolean flag = fileService.deleteFile(name);
if(flag == true){
System.out.println("刪除成功!");
}
else{
System.out.println("刪除失斏虮础杠人!");
}
}
else if(choose == 5){
long[] information = fileService.fileInformation();
System.out.println("總共有文件夾:"+information[0]+"個(gè).");
System.out.println("大小總計(jì):"+information[1]+"KB.");
}
else{
System.out.println("無(wú)效操作!");
}
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
四宋下、運(yùn)行
1. 打開Server.java嗡善,點(diǎn)擊Run,選擇Run,在彈出框中選擇Server学歧。
運(yùn)行結(jié)果:
2. 打開Client.java滤奈,點(diǎn)擊Run,選擇Run,在彈出框中選擇Client撩满。同上蜒程。
運(yùn)行結(jié)果:
輸入1,顯示所有文件:
輸入2伺帘,新增文件昭躺;輸入文件名:
輸入3,修改文件伪嫁;輸入文件名:
輸入4领炫,刪除文件;輸入文件名:
輸入5张咳,顯示文件個(gè)數(shù)和所占磁盤大械酆椤: