Java Client/Server 上传文件到服务器与保存文件到本地
Posted 一身千寻瀑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Client/Server 上传文件到服务器与保存文件到本地相关的知识,希望对你有一定的参考价值。
新年第一章,祝大家新年快乐。
-----------------------------------------------------------------------
这个是我们的Java期末考试题,圣诞节的考试庆典。考试时长三个小时,晚上19:00-22:00。
包括考试要求到最后的源程序,都会搬到这里。
三个小时还是比较紧张的,虽然经过一学期学习,还是会有BUG以及其他缺点。
这次是基于JavaSocket使Client与Server通信,以文本文档的形式上传一个查询结果到服务器的功能。
查询是基于Sql Server中的一个很简易的数据库中的一个简单表。
-----------------------------------------------------------------------
出现的问题:
需要用到JDBC驱动,当时导出的jar文件怎么都不能连到数据库,添加external library的时候有些问题,再次加载项目导入的jdbc就没有了。
这应该是一点没有完成考试要求的地方,毕竟只有三个小时,时间上还是非常紧张的。
-----------------------------------------------------------------------
一点反思:
1.以后做项目的时候,会不会因为赶工期而使项目很多bug或者不安全的地方被忽略,导致项目质量的低下,进而加重后期维护系统的难度?
2.jdbc驱动问题导致的导出jar文件不能连接数据库是什么问题?考后询问老师只得到项目文件.classpath有问题的反馈。
-----------------------------------------------------------------------
下面贴考试内容:
这是第一题,分值20分。
考查点其实就是小黑窗下java文件的编译与运行,加上了package,需多使用“ -d . ”而已。
小黑窗的反馈结果直接贴在word里,这20分应该来说还是很容易的。
有一点需要说的是,其实第一遍调试我是出错误的,因为直接把代码贴到txt里也没有修改。
激动地差点举手找监考,然而提示里都说了需要修改。导入one.MyTest就好了。
五分钟,第一题20分送到手。
剩下的近三小时就是第二题的Java项目了。
-------------------------------------------------------分--割--线-------------------------------------------------------
二:综合应用题(80分)
请在DBMS中按下面的要求定义表结构。(DBMS任选,建议:SQLServer版本与实验室一致)
数据库结构(注意:建立的数据库名称、结构等必须和下面的描述完全一致):
数据库名称:examdb
包括一个表:
课程信息表,表名称:mycourse
属性 | 类型 | 长度 | 含义 | 是否空值 |
cno | varchar | 7 | 课程号 | 否 |
cname | varchar | 20 | 课程名 | 是 |
cred | float | (3,1) | 课程学分 | 是 |
iscom | varchar | 2 | 是否选修 | 是 |
tech | varchar | 10 | 授课教师 | 是 |
注意:(数据库设计的运用!)
2使用Java Swing组件开发一个图形界面,界面布局及控件如下图所示
实现具体要求与分值分配:
1 请严格按照Java的代码规范进行代码组织(15%)
例如: 类名、包名、方法名、接口等的命名规范,注释、代码格式规范等。
注意:主项目(project)名称为学号,一级包名为姓名的拼音。
2 请选择合适的布局、组件、容器、事件、事件监听器等实现题目要求的功能(25%),其中:
GUI组件选择与界面实现(10%)
面向对象的结构及代码的一些优化处理(15%), 包括:类结构设计、功能优化设计(10%),异常处理、错误提示界面(5%)。
3 功能实现部分(35%)
功能1,查询(15%):单击查询按钮,可以实现按照用户选择的“课程号”或者“课程名”与文本框输入的具体内容到数据库端进行查询,并将结果返回到窗口的组件中显示出来。
提示:注意提供中文的查询支持!
功能2,保存至文件(10%):获取窗口组件中显示得满足条件的记录,选择合适的IO API将其保存成文件形式。
文件名:(保存路径为项目文件夹或者使用图形化界面进行选择)
chaxunno.txt,(按照课程号查询的结果保存的文件)。
chaxunname.txt(按照课程名称查询的结果保存的文件)。
功能3,保存至服务器(10%):请将上述功能2中存储的两个文件上传到服务器上存储。(保存路径为项目文件夹或者使用图形化界面进行选择)
注意:此处服务器就是本机。
服务器端口号统一使用8993.
文件名分别是:chaxunnoser.txt、chaxunnameser.txt
4 将项目生成可执行的jar文件(5%)
提交说明:
请将项目文件夹(若干)、保存结果的文件(若干)、可执行jar文件、考试文件(包含第一题答案)并附带一个说明.txt (内容为:学号、姓名、联系方式;数据库连接URL中的用户名、密码、数据库产品名称等;以及自己认为有必要说明的其它问题),全部打包到自己学号命名的rar文件中,上传至ftp。
----------------------------------------------------------------------------------------------------------------------------------------------------
乍一看都是lecture和experiment上讲过练过的,思路很清晰,但是代码量多,任务重。
这是最后的上传的结果:
2014****文件夹中是client端的实现,myserver中是server端的实现,最后的查询结果在三个txt文件中,说明txt中是对项目的ReadMe。
生成的jar文件是服务器.jar和客户端.jar,打开服务器端才能上传txt文件。
sqljdbc42是jdbc驱动。
java题稿是我从word里的题目要求提炼,与项目无关。
最后全部打包成2014****.zip上交,考试完毕。
----------------------------------------------------------------------分--割--线------------------------------------------------------------------------
sql server
很简单的一个examdb,没什么可说的。
----------------------------------------------------------------------分--割--线------------------------------------------------------------------------
eclipse Java项目,分两个。
-------------------------
以下是源代码:
ps:以前自己写的小程序不爱加注释,这次不仅仅是给自己看,所以必要的地方添加了注释。
---------------
myserver
my.ser
MyServerSocket.java
package my.ser;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JOptionPane;
public class MyServerSocket
ServerSocket ss = null;
Socket s = null;
InputStream in = null;
FileOutputStream fos = null;
public void recFile()
try
ss = new ServerSocket(8893);
JOptionPane.showMessageDialog(null,"端口已打开","提示",JOptionPane.INFORMATION_MESSAGE);
//System.out.println("Opening the port.");
//服务器8893端口打开,输出一个提示消息
s = ss.accept();
in = s.getInputStream();
fos = new FileOutputStream(new File("c://test//server//chaxunser.txt")); //上传到服务器指定位置文件夹
byte[] buf = new byte[1024];
int len = 0;
while((len = in.read(buf)) != -1)
fos.write(buf, 0, len);
fos.flush();
catch (IOException e)
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(null,"未知错误","错误",JOptionPane.ERROR_MESSAGE);
public void myclose()
try
if(fos!=null)
fos.close();
if(in!=null)
in.close();
if(s!=null)
s.close();
if(ss!=null)
ss.close();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
my.test
MainTest.java
package my.test;
import my.ser.MyServerSocket;
public class MainTest
public static void main(String[] s)
//打开服务器
new MyServerSocket().recFile();
new MyServerSocket().myclose();
--------------------------------------------------------------------------------------
client端
2014****
ycx.cli
MyClientSocket.java
package ycx.cli;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import ycx.savefile.MyFile;
public class MyClientSocket
Socket s = null;
FileInputStream fis = null;
OutputStream out = null;
public int sendFile(ArrayList<String> list,int cic)
//list是查询结果,cic代表按照课程号(cic=1)或课程名(cic=2)查询的标识
try
s = new Socket("127.0.0.1",8893); //尝试连接目标服务器8893端口
//将list的内容保存到本地项目文件,准备向服务器上传文件
if(cic==0)
MyFile myfile = new MyFile();
myfile.saveMyFile("img/chaxunno.txt",list);
fis = new FileInputStream("img/chaxunno.txt");
if(cic==1)
MyFile myfile = new MyFile();
myfile.saveMyFile("img/chaxunname.txt",list);
fis = new FileInputStream("img/chaxunname.txt");
out = s.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while((len = fis.read(buf)) != -1)
out.write(buf, 0, len);
out.flush();
s.shutdownOutput();
return 1;
catch (UnknownHostException e)
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(null,"未知主机错误","错误",JOptionPane.ERROR_MESSAGE);
return 0;
catch (IOException e)
// TODO Auto-generated catch block
JOptionPane.showMessageDialog(null,"发生错误:请先建立连接","错误",JOptionPane.ERROR_MESSAGE);
return 0;
public void myclose()
try
if(fis!=null)
fis.close();
if(out!=null)
out.close();
if(s!=null)
s.close();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
ycx.savefile
MyFile.java
package ycx.savefile;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
public class MyFile
public void saveMyFile(String filePath, ArrayList<String> result)
//参数为filePath和result,实现将result的内容写到filePath指定路径的文件中。
try
File myFile = new File(filePath.toString());
if(myFile.exists())
// 如果该文件存在,则删除原文件
myFile.delete();
if (!myFile.exists())
// 如果该文件不存在,则创建
myFile.createNewFile();
FileWriter resultFile = new FileWriter(myFile, true);
PrintWriter myFileWrite = new PrintWriter(resultFile);
myFileWrite.println(" 课程号 课程名 学分 选修 授课教师");
//不覆盖先前内容,并追加后续内容到文件里。每次追加在txt中都有[..Content..]标识。
myFileWrite.println(result);
resultFile.close();
catch (Exception e)
e.printStackTrace();
ycx.gui
EnterWindow.java
package ycx.gui;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Font;
public class EnterWindow
/**
* @wbp.parser.entryPoint
*/
public void showEnterWindow()
JFrame jf = new JFrame();
jf.setTitle("\\u6B22\\u8FCE\\u754C\\u9762");
JLayeredPane layeredPane = new JLayeredPane();
jf.getContentPane().add(layeredPane, BorderLayout.CENTER);
JLabel label = new JLabel("\\u6B22\\u8FCE\\u60A8\\u767B\\u9646\\u672C\\u7CFB\\u7EDF");
label.setFont(new Font("宋体", Font.PLAIN, 13));
label.setForeground(Color.BLACK);
label.setBounds(185, 56, 132, 39);
layeredPane.add(label);
JButton button = new JButton("\\u8FDB\\u5165");
button.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
jf.setVisible(false);
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
MyWindow mw = new MyWindow();
mw.showMyWindow();
);
button.setBounds(191, 126, 93, 23);
layeredPane.add(button);
jf.setVisible(true);
jf.setSize(500,300);
jf.setLocation(400,200);
MyWindow.java
package ycx.gui;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import ycx.cli.MyClientSocket;
import ycx.jtmodel.MyTableModel;
import ycx.savefile.MyFile;
public class MyWindow
private JTextField textField;
Connection ct = null;
Statement ps = null;
ResultSet rs = null;
ArrayList<String> list = new ArrayList<String>();
int cic = 0;
/**
* @wbp.parser.entryPoint
*/
public void showMyWindow()
JFrame jf = new JFrame();
jf.setTitle("\\u64CD\\u4F5C\\u7A97\\u53E3");
JLayeredPane layeredPane = new JLayeredPane();
jf.getContentPane().add(layeredPane, BorderLayout.CENTER);
JLabel label = new JLabel("\\u8BF7\\u8F93\\u5165\\uFF1A");
label.setBounds(219, 25, 65, 15);
layeredPane.add(label);
JTable jt = new JTable(0,5);
JScrollPane jspa = new JScrollPane(jt);
jspa.setBounds(20, 66, 438, 124);
layeredPane.add(jspa);
JComboBox<String> comboBox = new JComboBox<String>();
comboBox.setBounds(108, 22, 93, 21);
comboBox.addItem("课程号");
comboBox.addItem("课程名");
layeredPane.add(comboBox);
textField = new JTextField("在此输入查询内容");
textField.setBounds(266, 22, 109, 21);
layeredPane.add(textField);
textField.setColumns(10);
try
//连接Sql Server数据库
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
ct = DriverManager.getConnection
("jdbc:sqlserver://127.0.0.1:1433;DatabaseName=examdb","sa","");
ps = ct.createStatement();
catch (ClassNotFoundException e2)
// TODO Auto-generated catch block
e2.printStackTrace();
JOptionPane.showMessageDialog(null,"连接数据库失败","错误",JOptionPane.ERROR_MESSAGE);
catch (SQLException e1)
// TODO Auto-generated catch block
e1.printStackTrace();
JOptionPane.showMessageDialog(null,"连接数据库失败","错误",JOptionPane.ERROR_MESSAGE);
JButton button = new JButton("\\u67E5\\u8BE2");
button.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
//当单击"查询"按钮时,响应该事件
cic = comboBox.getSelectedIndex();
String str = textField.getText().trim();
try
if(cic==0) //按课程号查询
rs = ps.executeQuery("select * from mycourse where cno like '%" + str + "%'");
else if(cic==1) //按课程名查询
rs = ps.executeQuery("select * from mycourse where cname like '%" + str + "%'");
MyTableModel mtm = new MyTableModel(rs);
jt.setModel(mtm);
list.clear(); //每次查询时先清空list缓存区
//将数据预缓存到list中,后续利用list上传到服务器或保存到本地
list.add("\\r\\n");
//通过JTable.getValueAt(int row,int column)方法使list得到查询得结果
for(int i = 0; i < jt.getRowCount(); ++i)
if(i!=0)
list.add("\\r\\n");
for(int j = 0; j < jt.getColumnCount(); ++j)
list.add(String.valueOf(jt.getValueAt(i, j)));
list.add("\\r\\n");
if(rs.isAfterLast()==false)
JOptionPane.showMessageDialog(null,"未能查询到学生的信息","错误",JOptionPane.ERROR_MESSAGE);
catch (SQLException e1)
// TODO Auto-generated catch block
e1.printStackTrace();
JOptionPane.showMessageDialog(null,"不正确的选择语句","错误",JOptionPane.ERROR_MESSAGE);
);
button.setBounds(385, 21, 73, 23);
layeredPane.add(button);
JButton button_1 = new JButton("\\u4FDD\\u5B58\\u5230\\u672C\\u5730");
button_1.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
//当单击"保存到本地"按钮时,响应该事件
if(jt.getRowCount()==0) //若JTable为空
JOptionPane.showMessageDialog(null,"请先查询信息","提示",JOptionPane.INFORMATION_MESSAGE);
else //若JTable不为空
//发出确认消息
int YesOrNo = JOptionPane.showConfirmDialog(null, "确定要保存到本地吗?", "提示", JOptionPane.INFORMATION_MESSAGE);
if(YesOrNo==JOptionPane.YES_OPTION)
//再把list的内容保存到文件中
if(cic==0) //按照课程号查询的结果保存文件
new MyFile().saveMyFile("chaxunno.txt",list);
JOptionPane.showMessageDialog(null,"保存成功","提示",JOptionPane.INFORMATION_MESSAGE);
if(cic==1) //按照课程名称查询的结果保存文件
new MyFile().saveMyFile("chaxunname.txt",list);
JOptionPane.showMessageDialog(null,"保存成功","提示",JOptionPane.INFORMATION_MESSAGE);
);
button_1.setBounds(92, 211, 120, 23);
layeredPane.add(button_1);
JButton button_2 = new JButton("\\u4FDD\\u5B58\\u5230\\u670D\\u52A1\\u5668");
button_2.addActionListener(new ActionListener()
public void actionPerformed(ActionEvent e)
//当单击"上传到服务器"按钮时,响应该事件
if(jt.getRowCount()==0) //若JTable为空
JOptionPane.showMessageDialog(null,"请先查询信息","提示",JOptionPane.INFORMATION_MESSAGE);
else //若JTable不为空
//发出确认消息
int YesOrNo = JOptionPane.showConfirmDialog(null, "确定要上传到服务器吗?", "提示", JOptionPane.INFORMATION_MESSAGE);
if(YesOrNo==JOptionPane.YES_OPTION)
int flag = 0; //用于接收上传是否成功的反馈,成功为1,失败为0
//向服务器上传文件
MyClientSocket mcs = new MyClientSocket();
flag = mcs.sendFile(list,cic);;
mcs.myclose();
if(flag==1)
JOptionPane.showMessageDialog(null,"上传成功","提示",JOptionPane.INFORMATION_MESSAGE);
else
JOptionPane.showMessageDialog(null,"上传失败","提示",JOptionPane.INFORMATION_MESSAGE);
);
button_2.setBounds(255, 211, 120, 23);
layeredPane.add(button_2);
JLabel label_1 = new JLabel("\\u9009\\u62E9\\u67E5\\u8BE2\\u6761\\u4EF6\\uFF1A");
label_1.setBounds(20, 25, 99, 15);
layeredPane.add(label_1);
jf.setVisible(true);
jf.setSize(500,300);
jf.setLocation(400,200);
ycx.jtmodel
这里主要是为了设计一个JTable的模板,把查询结果显示在JTable中,比JTextArea好,更具美观性,最主要的是方便操作,想取哪个元素取哪个元素。
MyTableModel.java
package ycx.jtmodel;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
@SuppressWarnings("serial")
public class MyTableModel extends AbstractTableModel
ResultSet rs = null;
int rowcount;
ArrayList<String[]> list = new ArrayList<String[]>();
public MyTableModel(ResultSet rs)
this.rs = rs;
try
while(rs.next())
rowcount++;
String[] line = new String[]
rs.getString(1),rs.getString(2),String.valueOf(rs.getFloat(3)),rs.getString(4),rs.getString(5)
;
list.add(line);
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
@Override
public int getRowCount()
// TODO Auto-generated method stub
return rowcount;
@Override
public int getColumnCount()
// TODO Auto-generated method stub
int colcount = 0;
try
colcount = rs.getMetaData().getColumnCount();
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
return colcount;
@Override
public Object getValueAt(int rowIndex, int columnIndex)
// TODO Auto-generated method stub
return list.get(rowIndex)[columnIndex];
public String getColumnName(int column)
/*String name = null;
try
name = rs.getMetaData().getColumnName(column+1);
catch (SQLException e)
// TODO Auto-generated catch block
e.printStackTrace();
*/
String[] colname = new String[]
"课程号","课程名","课程学分","是否选修","授课教师"
;
return colname[column];
ycx.test
MainTest.java
package ycx.test;
import ycx.gui.EnterWindow;
public class MainTest
public static void main(String[] s)
EnterWindow ew = new EnterWindow();
ew.showEnterWindow();
以上是所有代码。
--------------------------------------------------------分--割--线--------------------------------------------------------
说明.txt
数据库产品版本: Sql Server 2014
关于数据库的说明:
登录时应选择SQL Server身份验证模式。
用户名:sa
密码:空
Sql服务器身份验证模式应设置为:混合验证模式。
需使用SQL Server身份验证模式,不能使用Windows身份验证模式。
对于考试所要求内容完成情况的说明:
1.命名规范和适当注释:
(1)工程名、包名、类名均按照Java编程规范命名。
(2)关键位置标有注释,如单击事件如何响应、何种方法导出数据、如何保存文件、按何种条件查询等。
2.页面设计:
(1)两个界面包括一个欢迎界面,一个操作界面。
(2)欢迎界面有欢迎消息与进入按钮。
(3)操作界面包括三个按钮(查询、保存、上传),一个输入框,一个表格显示框,若干文本框。
3.优化处理:
(1)运用了面向对象的方法,封装了若干个类如MyTableModel,MyFile,MyWindow,MyClientSocket,MyServerSocket等方法,详见工程文件。
(2)及时使用.close()方法关闭对象,释放了资源。
(3)运用了更多API中的接口、方法以完成功能设计。
(4)若server端成功打开,则会显示一条提示框“端口已打开”。
(5)将main方法单独迁移到MainTest类中测试。
4.图形界面的异常处理提示等友好交互:
(1)在进行查询前不可以点击保存到本地和上传服务器按钮。
(2)保存或上传失败会有提示,查询无结果会有提示,查询条件输入错误会有提示,不按顺序操作会有提示。
5.功能实现情况:
(1)查询按钮的单击事件使结果显示在JTable表格框中,支持模糊查询。
(2)实现了两个存储按钮的功能。保存是不覆盖的,且每次追加有标识。
*对功能的另外说明:
因JFileChooser未能正式实现,所以保存在服务器的文件统一命名为chaxunser.txt。
没有按照较繁琐的两次连接保存的方法存储为两个文件chaxunnoser.txt和chaxunnameser.txt。
但保存在本地的文件实现分为两个文件chaxunno.txt和chaxunname.txt。
以上是ReadMe说明。
--------------------------------------------------------分--割--线--------------------------------------------------------
具体GUI界面就不贴了,大体如此。
本来是想使用JFileChooser保存文件,由于只听了lecture,experiment上没有练习JFileChooser也就未使用。
考试难度不大,但是三个小时,时间紧张,还好是基本完成了。
自评:第一题完成度100%。第二题完成度85%。平时实验按时完成,质量无法自评。平时/考试三七开,希望最后能上90分。
------------------------------------------
临近数据结构考试,对一些二叉线索化、balance tree、多重邻接、十字链表等等算法还一知半解。
最近有点嗜睡,典型的考试月疲懒症。
以上是关于Java Client/Server 上传文件到服务器与保存文件到本地的主要内容,如果未能解决你的问题,请参考以下文章