/**
* File类与IO流
*
* 1. 掌握File类的实例化的方式、熟悉常用的方法
* 2. IO的概述:① 流的分类 ② 4个抽象基类 ③ 常见的流
* 3. 文件流:FileReader\FileWriter :处理文本文件
* FileInputStream\FileOutputStream : 处理非文本文件
* 4. 缓冲流:提高数据读写的效率
* BufferedReader \ BufferedWriter
* BufferedInputStream \ BufferedOutputStream
* 5. 转换流:实现字节流与字符流之间的转化。
* InputStreamReader \ OutputStreamWriter
* 编码的过程 vs 解码的过程
* 如何保证不出现文本文件的乱码? 解码使用的字符集要与编码使用的字符集相同!
* 6.其它流:(了解)
* 6.1 System.in:标准的输入流,从键盘输入
* System.out:标准的输出流,从屏幕输出
* 6.2 打印流 PrintStream \ PrintWriter
* 6.3 数据流:DataInputStream \ DataOutputStream
*
* 7. 对象流: 传输对象的流。 ObjectInputStream \ ObjectOutputStream
* 对象的序列化机制!
* 8. 随机存取文件流:RandomAccessFile
*
* 流处理数据的流程:
* ① 创建流(包括File文件的创建)
* ② 数据的读取或写出操作
* ③ 关闭流资源
*
* 凡是涉及到资源关闭的操作,一定需要使用try-catch-finally处理异常。否则可能会出现内存泄漏。
*
*/
1. 其它流的使用
1.1 标准的输入、输出流
@Test
public void test1(){
Scanner scanner = new Scanner(System.in);
int i = scanner.nextInt(); //阻塞式的方法
System.out.println("hello");
scanner.close();
}
1.2 打印流
@Test
public void test2(){
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream(new File("D:\\io\\text.txt"));
// 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
ps = new PrintStream(fos, true);
if (ps != null) {// 把标准输出流(控制台输出)改成文件
System.setOut(ps);
}
for (int i = 0; i <= 255; i++) { // 输出ASCII字符
System.out.print((char) i);
if (i % 50 == 0) { // 每50个数据一行
System.out.println(); // 换行
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null) {
ps.close();
}
}
}
1.3 数据流
//使用DataOutputStream
@Test
public void test3() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(new File("data.dat")));
dos.writeInt(123);
dos.writeInt(456);
dos.writeBoolean(true);
dos.writeUTF("武汉,你好!");
dos.close();
}
//使用DataInputStream读取数据文件
@Test
public void test4() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream(new File("data.dat")));
int num = dis.readInt();
int num1 = dis.readInt();
boolean b = dis.readBoolean();
String info = dis.readUTF();
System.out.println(num);
System.out.println(num1);
System.out.println(b);
System.out.println(info);
dis.close();
}
2. 对象流
2.1 使用对象流
public class ObjectInputOutputStreamTest {
//序列化过程:将内存中的java对象保存在文件中。使用ObjectOutputStream实现
@Test
public void test1() throws IOException {
//1.
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
//2.
oos.writeObject(new String("Tom"));
oos.flush();//刷新
oos.writeObject(new String("Jerry"));
oos.flush();//刷新
oos.writeObject(new Person("荣鹏",23,new Pet("大黄")));
oos.flush();//刷新
//3.
oos.close();
}
//反序列化过程:将磁盘文件中的数据还原为内存中的java对象。 使用ObjectInputStream实现
@Test
public void test2() throws IOException, ClassNotFoundException {
//1.
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.txt"));
//2.
String str1 = (String) ois.readObject();
String str2 = (String) ois.readObject();
Person p = (Person) ois.readObject();
System.out.println(str1);
System.out.println(str2);
System.out.println(p);
//3.
ois.close();
}
}
其中,要求读写的对象对应的类,需要是可序列化的。
import java.io.Serializable;
/**
*
* 自定义类要想实现序列化机制,需要满足:
* 1. 实现接口:Serializable
* 2. 内部声明一个全局常量:serialVersionUID
* 3. 要求此类的属性都必须是可序列化的
*
* 说明:
* 1. 默认情况下,基本数据类型的变量可序列化。
* 2. ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
*
*/
public class Person implements Serializable {
private static final long serialVersionUID = -6849794667710L;
private String name;
private int age;
private Pet pet;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
public Person(String name, int age, Pet pet) {
this.name = name;
this.age = age;
this.pet = pet;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", pet=" + pet +
'}';
}
}
class Pet implements Serializable{
String name;
private static final long serialVersionUID = -684967710L;
@Override
public String toString() {
return "Pet{" +
"name='" + name + '\'' +
'}';
}
public Pet(String name) {
this.name = name;
}
public Pet() {
}
}
2.2 对象的序列化机制
/* 什么是对象的序列化机制?
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
*/
3. 随机存取文件流
/**
* RandomAccessFile:随机存取文件流
*
* 1. 既是一个输入流,又是一个输出流 (因为实现了DataInput、DataOutput接口)
* 2. 作为输出流,要输出的文件不存在,则可以在执行过程中,自动创建此文件。
* 3. 作为输出流,要输出的文件存在,则执行过程中会覆盖原有文件中的内容,而且默认从文件开始的位置覆盖.
* 我们也可以从指定的位置开始写入数据。
*
*/
public class RandomAccessFileTest {
@Test
public void test1() throws Exception {
//1.
RandomAccessFile raf1 = new RandomAccessFile("yangm.png","r");
RandomAccessFile raf2 = new RandomAccessFile("yangm1.png","rw");
//2.
byte[] buffer = new byte[1024];
int len;
while((len = raf1.read(buffer)) != -1){
raf2.write(buffer,0,len);
}
//3.
raf1.close();
raf2.close();
}
@Test
public void test2() throws IOException {
RandomAccessFile raf = new RandomAccessFile("hello.txt","rw");
raf.seek(5);
raf.write("hello".getBytes());
raf.close();
}
}
4. 网络编程概述
/**
* 一、要想实现网络通信,需要解决的两个问题:
* 1. 如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
* 2. 找到主机后如何可靠高效地进行数据传输
*
* 二、实现网络传输的两个要素:
* 要素一:IP地址、端口号
* 要素二:TCP/IP协议
*
* 三、IP地址:使用InetAddress类表示
* 3.1 IP地址分类方式1:IPV4 和 IPV6
* IPV4:4个字节组成,4个0-255。
* IPV6:128位(16个字节),写成8个无符号整数,每个整数用四个十六进制位表示,数之间用冒号(:)分开,
* 如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984
*
* IP地址分类方式2:公网地址(万维网使用)和私有地址(局域网使用)。
* 192.168.开头的就是私有址址,范围即为192.168.0.0--192.168.255.255
*
* 3.2 本地回路地址:127.0.0.1
* 3.3 域名
* www.atguigu.com www.baidu.com www.360.com www.vip.com
* www.mi.com www.jd.com
* 四、端口号:标识正在计算机上运行的进程(程序)
* > 不同的进程有不同的端口号
* > 被规定为一个 16 位的整数 0~65535
*
*/
5. InetAddress的使用
public class InetAddressTest {
public static void main(String[] args) {
try {
InetAddress inetAddress = InetAddress.getByName("192.168.13.57");
System.out.println(inetAddress);
//方式1:getByName(String host)
InetAddress inetAddress1 = InetAddress.getByName("www.atguigu.com");
System.out.println(inetAddress1);//www.atguigu.com/36.156.81.239
//常用方法
//getHostName():获取主机名
System.out.println(inetAddress1.getHostName());
//getHostAddress():获取主机地址
System.out.println(inetAddress1.getHostAddress());
//方式2:getLocalHost()
InetAddress inetAddress2 = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
6. TCP网络编程
- TCP和UDP编程协议的对比:
- 例题1:
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 例题1:客户端发送内容给服务端,服务端将内容打印到控制台上。
*
*/
public class TCPTest1 {
@Test
public void client() { //客户端
Socket socket = null;
OutputStream os = null;
try {
//1. 封装Socket对象
//1.1 指名对方的ip地址
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
//1.2 指名对方的端口号
int port = 8989;
socket = new Socket(inetAddress,port);
//2. 通过socket获取输出流,并写出数据
os = socket.getOutputStream();
os.write("你好,我是客户端".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//3. 关闭相应的资源
try {
if(os != null)
os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void server() { //服务器端
ServerSocket serverSocket = null;
Socket socket = null;//accept():是一个阻塞式的方法。
InputStream is = null;
try {
//1. 封装ServerSocket的对象
int port = 8989;
serverSocket = new ServerSocket(port);
//2. 接收来自于客户端的socket
socket = serverSocket.accept();
//3. 获取客户端发送过来的流数据
is = socket.getInputStream();
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1){
String str = new String(buffer,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4. 关闭资源
try {
if(is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
//通常服务器端不会关闭
try {
if(serverSocket != null)
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 例题2
import com.sun.deploy.trace.SocketTraceListener;
import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 例题2.客户端发送文件给服务端,服务端将文件保存在本地。
*
*/
public class TCPTest2 {
//注意:异常的处理还是应该使用try-catch-finally
@Test
public void client() throws IOException {
//1. 创建Socket
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8989);
//2. 提供输入流、输出流
FileInputStream fis = new FileInputStream(new File("yangm.png"));
OutputStream os = socket.getOutputStream();
//3. 读取和写出的过程
byte[] buffer = new byte[1024];
int len;
while((len = fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
//4.关闭资源
os.close();
fis.close();
socket.close();
}
@Test
public void server() throws IOException {
//1. 创建ServerSocket
ServerSocket serverSocket = new ServerSocket(8989);
//2. 通过ServerSocket,接收来自于客户端的socket
Socket socket = serverSocket.accept();
System.out.println("接收到了来自于" + socket.getInetAddress().getHostAddress() + "的数据");
//3. 创建输入流、输出流
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("yangm4.png"));
//4. 数据的读取和写出的过程
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1){
fos.write(buffer,0,len);
}
//5. 关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
- 例题3
import org.junit.Test;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 例题3.从客户端发送文件给服务端,服务端保存到本地。并返回“发送成功”给客户端。并关闭相应的连接。
*
*/
public class TCPTest3 {
//注意:异常的处理还是应该使用try-catch-finally
@Test
public void client() throws IOException {
//1. 创建Socket
Socket socket = new Socket(InetAddress.getByName("127.0.0.1"), 8989);
//2. 提供输入流、输出流
FileInputStream fis = new FileInputStream(new File("yangm.png"));
OutputStream os = socket.getOutputStream();
//3. 读取和写出的过程
byte[] buffer = new byte[1024];
int len;
while((len = fis.read(buffer)) != -1){
os.write(buffer,0,len);
}
System.out.println("图片发送完成");
//显式执行数据发送完成,告知服务器端
socket.shutdownOutput();
//4.接收来自于服务器端的数据
InputStream is = socket.getInputStream();
byte[] newBuffer = new byte[1024];
int newLen;
while((newLen = is.read(newBuffer)) != -1){
String str = new String(newBuffer,0,newLen);
System.out.print(str);
}
//5.关闭资源
os.close();
fis.close();
socket.close();
}
@Test
public void server() throws IOException {
//1. 创建ServerSocket
ServerSocket serverSocket = new ServerSocket(8989);
//2. 通过ServerSocket,接收来自于客户端的socket
Socket socket = serverSocket.accept();
System.out.println("接收到了来自于" + socket.getInetAddress().getHostAddress() + "的数据");
//3. 创建输入流、输出流
InputStream is = socket.getInputStream();
FileOutputStream fos = new FileOutputStream(new File("yangm7.png"));
//4. 数据的读取和写出的过程
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) != -1){
fos.write(buffer,0,len);
}
System.out.println("Server:图片接收完成");
//5.服务器端发送“接收成功"给客户端
OutputStream os = socket.getOutputStream();
os.write("接收成功".getBytes());
//6. 关闭资源
fos.close();
is.close();
socket.close();
serverSocket.close();
}
}
7. UDP网络编程
import org.junit.Test;
import java.io.IOException;
import java.net.*;
public class UDPTest {
@Test
public void sender() throws IOException {//发送端
//创建socket的实例
DatagramSocket socket = new DatagramSocket();
//封装数据、目的地到数据报中
byte[] buffer = "hello,I am sender!".getBytes();
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length, InetAddress.getLocalHost(),9090);
//发送数据报
socket.send(packet);
//关闭资源
socket.close();
}
@Test
public void receiver() throws IOException {//接收端
//创建socket的实例
DatagramSocket socket = new DatagramSocket(9090);
//封装一个数据报
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
//接收数据到数据报中
socket.receive(packet);
//读取数据并显示到控制台上
String str = new String(packet.getData(),0,packet.getLength());
System.out.println(str);
//关闭资源
socket.close();
}
}
8.URL编程
/**
* URL: 统一资源定位符,它表示 Internet 上某一资源的地址。
*
* 比如:http://192.168.13.136:8080/examples/wbb.png?keyword=apple
* 协议 ip地址 端口号 资源地址 参数列表
*
*/
public class URLTest {
public static void main(String[] args) {
try {
URL url = new URL("http://192.168.13.136:8080/examples/wbb.png?keyword=apple");
// public String getProtocol( ) 获取该URL的协议名
// public String getHost( ) 获取该URL的主机名
// public String getPort( ) 获取该URL的端口号
// public String getPath( ) 获取该URL的文件路径
// public String getFile( ) 获取该URL的文件名
// public String getQuery( ) 获取该URL的查询名
System.out.println(url.getProtocol());
System.out.println(url.getHost());
System.out.println(url.getPort());
System.out.println(url.getPath());
System.out.println(url.getFile());
System.out.println(url.getQuery());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
- 例题:将数据从服务器端下载到本地
public class URLTest1 {
public static void main(String[] args) {
HttpURLConnection urlConnection = null;
InputStream is = null;
FileOutputStream fos = null;
try {
URL url = new URL("http://192.168.13.136:8080/examples/wbb1.png");
urlConnection = (HttpURLConnection) url.openConnection();
is = urlConnection.getInputStream();
fos = new FileOutputStream(new File("wbb.png"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("下载完成");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
if (urlConnection != null)
urlConnection.disconnect();//断开连接
}
}
}
w File("wbb.png"));
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
System.out.println("下载完成");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
if (urlConnection != null)
urlConnection.disconnect();//断开连接
}
}
}