在网络编程使用套接字时,有时需要使用Socket传输视频、音频文件。如一个客户端将视频文件发送到服务端。
创建一个服务端窗体类,该类继承JFream类,关键代码如下
下面是服务端窗体类的构造方法,主要作用是创建窗体界面,获取选择文件信息,其中当点击发送按钮后,定义数据输入流对象后,创建输入流对象,分别将文件名、文件大小写入输出流,定义一个字节数组,将文件读取到字节数组中。
public ServerFrame() {
//省略了部分非关键代码
final JButton button = new JButton();//注册按钮监听器
button.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
try {
DataInputStream inStream = null;// 定义数据输入流对象
if (file != null) {
lengths = file.length();// 获得所选择视频文件的大小
inStream = new DataInputStream(
new FileInputStream(file));// 创建输入流对象
} else {
JOptionPane.showMessageDialog(null, "请选择视频文件。");
return;
}
out.writeUTF(fileName);// 写入视频文件名称
out.writeLong(lengths);// 将文件的大小写入输出流
byte[] bt = new byte[(int) lengths];
int len = -1;
// 将视频文件读取到字节数组
while ((len = inStream.read(bt)) != -1) { out.write(bt);// 将字节数组写入输出流
}
//省略了关闭资源部分代码
ta_info.append("发送完成");//在文本域中显示完成操作
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
窗体getServer方法主要用于创建服务端窗体类的套接字以及监听客户端、创建向客户端发送的文件的输出流对象和创建用于接收客户端发送文件的输入流对象。
public void getServer() {
server = new ServerSocket(1998); // 实例化Socket对象
ta_info.append("服务器套接字创建成功\n"); //在文本域显示
ta_info.append("正在连接......\n");
socket = server.accept(); // 实例化Socket对象
ta_info.append("客户机连接成功......\n"); // 输出信息
while (true) {
if (socket != null && !socket.isClosed()) {
// 获得输出流对象
out = new DataOutputStream(socket.getOutputStream()); in = new DataInputStream(socket.getInputStream());// 获得输入流对象
getClientFileInfo(); // 调用getClientInfo()方法
} else {
socket = server.accept(); // 实例化Socket对象
}
}
}
getClientFileInfo()该方法用于接收客户端发送过来的文件,并显示保存文件的对话框
private void getClientFileInfo() {
String name = in.readUTF();// 读取文件名
long lengths = in.readLong();// 读取文件的长度
byte[] bt = new byte[(int) lengths];// 创建字节数组
for (int i = 0; i < bt.length; i++) {
bt[i] = in.readByte();// 读取字节信息并存储到字节数组
}
// 省略了创建、弹出保存对话框部分代码
String path = dialog.getDirectory();// 获得文件的保存路径
String newFileName = dialog.getFile();// 获得保存的文件名
if (path == null || newFileName == null) {
return;
}
String pathAndName = path + "\\" + newFileName;// 文件的完整路径
FileOutputStream fOut = new FileOutputStream(pathAndName);
fOut.write(bt);
fOut.flush();
fOut.close();
ta_info.append("文件接收完毕");
}
创建一个客户端窗体类、关键代码如下,
connect()方法用于连接套接字,注意端口要和服务端一致
private void connect() { //
ta_info.append("尝试连接......\n"); // 文本域中信息信息
try {
socket = new Socket("127.0.0.1", 1998); // 实例化Socket对象
ta_info.append("完成连接。\n"); // 文本域中提示信息
while (true) {
if (socket != null && !socket.isClosed()) {
// 获得输出流对象
out = new DataOutputStream(socket.getOutputStream()); in = new DataInputStream(socket.getInputStream());// 获得输入流对象
getServerFileInfo();// 调用方法
} else {
socket = new Socket("127.0.0.1", 1998); // 实例化Socket对象
}
}
} catch (Exception e) {
e.printStackTrace(); // 输出异常信息
}
}
getServerFileInfo方法跟上面getClientFileInfo()方法大同小异,这里就不给出代码了
创建main主方法,实例化该类对象,调用连接方法
效果
小结:主要使用DataInputStream类的read()方法以及DataOutputStream类的write()方法(其实是从DataOutput类继承过来的方法)实现了对文件的读写操作。