1. 编写应用程序(SortArray.java),使用字节输入/输出流实现数据的保存和读取。

随机数生成1~100之间的整型数据保存到数组(数组大小为10)中。

将数组排序(由小到大)后的元素保存到指定的文件中。

如果文件不存在,则创建文件。

从文件中读取排序后的元素并按指定格式输出。

利用异常处理机制处理可能发生的错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.io.*;
import java.util.Arrays;

public class SortArray {
public static void main(String[] args) {
// 创建保存整型数据的数组(数组大小10)
int[] data = new int[10];
// 给数组赋随机值,取值范围1~100
for (int i = 0; i < data.length; i++) {
data[i] = (int) (Math.random() * 100) + 1;
}
// 将数组元素按有小到大顺序排列
Arrays.sort(data);
try {
// 创建数据保存文件,如果文件不存在,重新创建
File file = new File("test.txt");
if (!file.exists()) {
file.createNewFile();
}
// 创建FileOutputStream和DataOutputStream 输出流
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
// 利用输出流向文件中写入数组数据
for (int i = 0; i < data.length; i++) {
dos.write(data[i]);
}

// 关闭输出流
dos.close();
fos.close();
// 创建FileInputStream和DataInputStream 输入流
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
// 利用输入流从文件读取数据并输出
int DataInt = dis.read();
for (int i = 0; i < 10; i++) {
System.out.print(DataInt);
if (i != 9) {
System.out.print("<");
}
DataInt = dis.read();
}
// 关闭输入流
dis.close();
fos.close();
} catch (IOException e) {
// 异常处理
System.out.println("读写发生异常");
}
}
}

2. 编写应用程序(Encrypt.java),使用字符输入/输出流实现发送电报的功能。

电报内容经过加密后使用字符输出流存储在指定的文件中。

如果文件不存在,则创建文件。

使用字符输入流从文件中分别读取密文和明文的内容并显示出来。

利用异常处理机制处理可能发生的错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Encrypt {
public static void main(String[] args) throws IOException {
// 指定要发送的电报内容
String data = "今晚10点发动总攻";
// 将电报分割成字符数组
char[] chars = data.toCharArray();
// 打开指定存放电报的文件,如果文件不存在,则创建文件
File file = new File("test2.txt");
if (!file.exists()) {
file.createNewFile();
}
// 循环遍历字符数组,将每个字符加密处理
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) (chars[i] ^ 'q');
}
// 利用字符输出流FileWriter将加密后的字符数组写入文件中
FileWriter out = new FileWriter(file);
out.write(chars);
out.flush();
out.close();
// 利用字符输入流FileReader读取文件,将密文输出
FileReader in = new FileReader(file);
in.read(chars);
System.out.println("密文:");
System.out.println(chars);
in.close();
// 利用字符输入流FileReader读取文件,将密文转换为明文输出
FileReader in2 = new FileReader(file);
char[] chars2 = new char[10];
int n;
System.out.println("明文:");
while ((n = in2.read(chars2)) != -1) {
for (int i = 0; i < n; i++) {
chars2[i] = (char) (chars2[i] ^ 'q');
System.out.print(chars2[i]);
}
}
in2.close();
}
}

3. 使用Socket和ServerSocket进行套接字编程

3.1

简单的图形界面聊天程序,实现在局域网上实现简单的聊天功能。

Server.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

public static void main(String[] args) {
try {
//创建服务器端ServerSocket ,指定端口号8000
ServerSocket ss = new ServerSocket(8000);
while (true) {
Socket s = ss.accept();
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
DataInputStream dis = new DataInputStream(s.getInputStream());
dos.writeUTF("你已经连上服务器了,告诉我你的姓名...");
String name = dis.readUTF();
dos.writeUTF("再见:" + name);
s.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

import javax.swing.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class Client {

public static void main(String[] args) {
try {
//创建客户端Socket,指定服务器端IP地址和端口号
Socket s = new Socket("127.0.0.1", 8000);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println(dis.readUTF());
String name = JOptionPane.showInputDialog("请输入你的姓名:");
dos.writeUTF(name);
System.out.println(dis.readUTF());
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

3.2

运行程序不难发现一个问题,如果服务器在等待某个客户机回答“姓名”时,将因 readUTF() 方法而阻塞主线程的运行。其他客户机不能及时连接服务器了。因此,有必要将与每个客户的通信任务从主线程中分离出去,这就需要为每个客户创建通信线程。

ServerPlus.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerPlus {
public static void main(String[] args) {
try {
//创建服务器端ServerSocket ,指定端口号8000
ServerSocket ss = new ServerSocket(8000);
while(true) {
Socket s = ss.accept();
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
DataInputStream dis = new DataInputStream(s.getInputStream());
ReceiveThread thread = new ReceiveThread(s, dos, dis);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 创建通信线程
class ReceiveThread extends Thread {
DataOutputStream dos;
DataInputStream dis;
Socket s;
public ReceiveThread(Socket s, DataOutputStream dos, DataInputStream dis) {
this.s = s;
this.dos = dos;
this.dis = dis;
}
@Override
public void run() {
try {
dos.writeUTF("你已经连上服务器了,告诉我你的姓名...");
String name = dis.readUTF();
dos.writeUTF("再见:" + name);
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

3.3

上述代码通信线程只能通信一次,要通信线程持续与客户对话,应将通信线程 run() 方法中代码用循环来实现,比如,客户输入一个整数,服务器告诉客户这个数是奇数还是偶数。

ServerPlusPlus.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerPlusPlus {
public static void main(String[] args) {
try {
//创建服务器端ServerSocket ,指定端口号8000
ServerSocket ss = new ServerSocket(8000);
while (true) {
Socket s = ss.accept();
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
DataInputStream dis = new DataInputStream(s.getInputStream());
ReceiveThread thread = new ReceiveThread(s, dos, dis);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

// 创建通信线程
class ReceiveThread extends Thread {
DataOutputStream dos;
DataInputStream dis;
Socket s;

public ReceiveThread(Socket s, DataOutputStream dos, DataInputStream dis) {
this.s = s;
this.dos = dos;
this.dis = dis;
}

@Override
public void run() {
String sname = null;
try {
sname = String.valueOf(s.getInetAddress());
dos.writeUTF("请输入一个整数,我知道是奇数还是偶数");
while (true) {
String num = dis.readUTF();
String result = (Integer.parseInt(num) % 2 == 0) ? "偶数" : "奇数";
dos.writeUTF(num + "是..." + result);
}
} catch (EOFException e) {
System.out.println("客户端" + sname + "已经断开连接");
} catch (IOException e) {
e.printStackTrace();
}
}
}

ClientPlus.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import javax.swing.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;

public class ClientPlus {

public static void main(String[] args) {
try {
//创建客户端Socket,指定服务器端IP地址和端口号
Socket s = new Socket("127.0.0.1", 8000);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
DataInputStream dis = new DataInputStream(s.getInputStream());
System.out.println(dis.readUTF());
while (true) {
String num = JOptionPane.showInputDialog("请输入一个整数");
dos.writeUTF(num);
System.out.println(dis.readUTF());
}
} catch (EOFException e) {
System.out.println("服务器已断开连接");
} catch (IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
}
}
}