一、引言
1.实验目的
可以增加文件(文本文件)、修改文件(文本文件)、删除文件、列出文件;统计该文件夹具有多少个文件、占用磁盘空间的总大小;可以给出关键词,检索与该关键词相关的所有文件夹和文件。
2.环境配置
- 操作系统:Windows 10 X64
- 编程工具:Intellij IDEA
二、具体过程
1.准备阶段
(1)新建Java项目:File->New->Project
(2)点击Next
(3)点击Next
(4)设置项目名称以及项目存储位置,点击Finish
2.代码步骤
(1)远程接口定义
定义用于远程对象的接口 FileService。这个接口定义了客户机能够远程地调用的方法。远程接口和本地接口的主要差异在于,远程方法必须能抛出 RemoteException。具体方法如下:
FileService.java:
import java.rmi.RemoteException;
import java.rmi.Remote;
import java.util.List;
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;
//读取文件内容
public String readFile(String name) throws RemoteException;
//统计文件信息
public long[] fileInformation() throws RemoteException;
//检索关键字文件
public List<String> findFile(String keyword) throws RemoteException;
}
(2)实现远程接口
编写一个实现FileService接口的类 FileServiceImpl。
FileServiceImpl.java:
import java.io.*;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
public class FileServiceImpl extends UnicastRemoteObject implements FileService{
public FileServiceImpl() throws RemoteException {
super();
}
// 列出文件
@Override
public String[] play() throws RemoteException {
File file = new File("G://RMI");
String[] names=file.list();
return names;
}
// 增加文件
@Override
public boolean addFile(String name) throws RemoteException {
File file = new File("G://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("G://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("G://RMI/"+name);
}catch(IOException e1){
e1.printStackTrace();
}
try{
fw.write(content,0,content.length());
}catch (IOException e2){
e2.printStackTrace();
}
//关闭流
try{
fw.close();
return true;
}catch (IOException e3){
e3.printStackTrace();
}
return false;
}
//读取文件内容
@Override
public String readFile(String name) throws RemoteException {
FileReader fr = null;
try{
fr = new FileReader("G://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;
}
//统计该文件夹具有多少个文件、占用磁盘空间的总大小
@Override
public long[] fileInformation() throws RemoteException {
File file = new File("G://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;
}
// 检索与该关键词相关的所有文件夹和文件
@Override
public List<String> findFile(String keyword) throws RemoteException {
File file = new File("G://RMI");
String[] names=file.list();
List<String> result = new ArrayList<>();
for(int i = 0;i<names.length;i++){
if(names[i].toLowerCase().contains(keyword)){
result.add(names[i]);
}
}
return result;
}
}
(3) 编写服务端程序 Server.java:
创建服务器对象的初始实例,然后将对象的名称写到RMI命名注册表。
//创建服务器对象实例
FileService fileService = new FileServiceImpl();
//注册服务的端口
LocateRegistry.createRegistry(3333);
//绑定本地地址和服务器的路径
Naming.rebind("rmi://192.168.88.176:3333/FileService",fileService);
RMI命名注册表允许您将URL名称分配给对象以便客户机查找它们。要注册名称,需要调用在Naming类上定义的静态rebind方法。这个方法接受对象的URL名称以及对象引用。
名称字符串包含 rmi:// 前缀、运行RMI对象的服务器的计算机主机名和对象本身的名称。这里用了本机地址192.168.88.176。
完整代码如下:
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();
//注册服务的端口
LocateRegistry.createRegistry(3333);
//绑定本地地址和服务器的路径
Naming.rebind("rmi://192.168.88.176:3333/FileService",fileService);
System.out.println("开始服务!");
}catch(Exception e){
e.printStackTrace();
}
}
}
(4)编写客户端程序 Client.java。
使用RMI注册表查找远程对象。
//调用远程对象,RMI路径与接口必须与服务器配置一致
FileService fileService = (FileService) Naming.lookup("rmi://192.168.88.176:3333/FileService");
根据选择的操作,调用有远程接口定义的方法。完整代码如下:
Client.java:
import java.rmi.Naming;
import java.util.List;
import java.util.Scanner;
public class Client {
public Client(){}
public static void main(String[] args){
try{
//调用远程对象,RMI路径与接口必须与服务器配置一致
FileService fileService = (FileService) Naming.lookup("rmi://192.168.88.176:3333/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.统计文件");
System.out.println("6.检索关键字查找文件");
while(true){
System.out.println("请选择要进行的操作:");
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("请输入要新增文件的名称:");
String name = input.next();
boolean flag = fileService.addFile(name);
if(flag == true){
System.out.println("创建成功!");
}
else{
System.out.println("创建失败!");
}
}
else if(choose == 3){
System.out.println("请输入要修改文件的名称:");
String name = input.next();
String filecontent = fileService.readFile(name);
System.out.println(filecontent);
System.out.println("请输入修改内容:");
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("请输入要删除文件的名称:");
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]+"个.");
System.out.println("大小总计:"+information[1]+"KB.");
}
else if(choose == 6){
System.out.println("请输入要检索的关键字信息:");
String keyword = input.next();
List<String> filename = fileService.findFile(keyword);
for(int i = 0;i < filename.size();i++){
System.out.println(filename.get(i));
}
}
else{
System.out.println("无效操作!");
}
}
}catch (Exception ex){
ex.printStackTrace();
}
}
}
三、运行过程
1. 打开Server.java,点击绿色三角运行。
运行结果:
2. 打开Client.java,点击绿色三角运行,同上。
运行结果:
输入1,显示所有文件:
输入2,新增文件;输入文件名:
输入3,修改文件;输入文件名:
输入4,删除文件;输入文件名:
输入5,显示文件个数和所占磁盘大小:
输入6,按关键字检索相关文件和文件夹:
四、总结
在本次实验中有一些问题需要注意,在远程接口定义中,定义的这些方法必须能抛出RemoteException,如果客户机和服务器之间的通信错误,则客户机将捕获此异常。并且该接口本身继承了java.rmi包中定义的Remote接口。Remote接口本身没有定义方法,但通过继承它,我们说明该接口可以被远程地调用。在FileService接口的实现类中,在对文件进行读写操作后必须关闭用close()函数关闭流,不然可能会影响到delete操作,导致不能删除文件。