IO
文章目录
基本概念
序列化与反序列化
序列化:把java对象转换为字节序列的过程
反序列化:把字节序列恢复为java对象的过程
读入与写出的概念是从内存的角度来看的
使用File实例的时候
File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件
File对应的硬盘中的文件如果存在:
- 如果流使用的构造器是:
FileWriter(file, false)/FileWriter(file)
:对原文件的覆盖- 如果流使用的构造器是:
FileWriter(file, true)
:不会对源文件覆盖,而是在原文件基础上追加内容
要注意流资源的关闭,JVM并不会自动回收IO、数据库连接等资源。
并且,因为涉及到资源的关闭,所以要使用
try-catch-finally
来处理异常在关闭外层流的同时,内层流也会被关闭
流的分类
数据单位:字符流和字节流
流向:输入流和输出流
流的角色:节点流和处理流
流的体系
抽象基类 | 字节流(或文件流) | 缓冲流(处理流的一种) |
---|---|---|
InputStream | FileInputStream | BufferedInputStream |
OutputStream | FileOutputStream | BufferedOutputStream |
Reader | FileReader | BufferedReader |
Writer | FileWriter | BufferedWriter |
1、如何创建File类的实例
三种构造方法
File(String filePath)
File(String parentPath, String childPath)
File(File parentFile, String childPath)
注意:使用单元测试相对路径为当前Module;使用main方法时为当前Project
2、FileReader/FileWriter(字符文件的读入和写出)
//将字符写入到一个文件中(以字符流的方式)
@Test
public void test1() {
FileWriter fileWriter = null;
try {
//1、实例化File类型的对象
File file = new File("hello01.txt");
//2、提供具体的流;第二个参数含义为如果文件已存在,是否在原文件上添加
fileWriter = new FileWriter(file,true);
//3、写出的操作
fileWriter.write("hello\n");
fileWriter.write("IO");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、流资源的关闭
try {
if (fileWriter != null){
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//将字符从文件中读取出来(以字符流的方式)
@Test
public void test2() {
FileReader fileReader = null;
try {
fileReader = new FileReader(new File("hello01.txt"));
//read()无参方法;每个字符都要与磁盘通信一次
//将每个字符放到data中
// int data ;
// while ((data = fileReader.read()) != -1){
// System.out.print((char) data);
// }
//read()有参方法;使用一个数组将字符,取出来
//此时的len表示每次读取出字符的个数
char[] cbuf = new char[5];
int len;
while ((len = fileReader.read(cbuf)) != -1){
for (int i = 0; i < len; i++) {
System.out.print(cbuf[i]);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//传入两个路径,将相应路径的字符文件复制到对应路径
public void CopyFile(String address, String Daddress) {
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
//可以使用File指定文件(如下面FileReader中),也可以直接将文件名写到创建流时的参数里(如下面FileWriter中)
fileReader = new FileReader(new File(address));
fileWriter = new FileWriter(Daddress);
//使用一个字符数组将字符文件提取出来,然后直接写入到另一个文件中
int len;
char[] cbuf = new char[10];
while ((len = fileReader.read(cbuf)) != -1){
fileWriter.write(cbuf);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//测试copyFile
@Test
public void test03(){
CopyFile("hello01.txt", "hello02.txt");
}
3、FileInputStream/FileOutputStream(字节文件的读入写出)
//使用字节流的方式,读入文件内容
@Test
public void test04() {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(new File("hello01.txt"));
byte[] bytes = new byte[10];
int len; //每次读取的字节的个数
while ((len = fileInputStream.read(bytes)) != -1){
String s = new String(bytes, 0, len);
System.out.print(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//使用字节流的方式复制图片(字节文件)
@Test
public void test05() {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream("123.jpg");
fileOutputStream = new FileOutputStream("1234.jpg");
int len;
byte[] bytes = new byte[1024];
while ((len = fileInputStream.read(bytes)) != -1){
fileOutputStream.write(bytes);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
//字节流的方式,将指定文件,复制
public void copyStreamFile(String address, String Daddress) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
long start = System.currentTimeMillis();
try {
fileInputStream = new FileInputStream(address);
fileOutputStream = new FileOutputStream(Daddress);
int len;
byte[] bytes = new byte[1024];
while ((len = fileInputStream.read(bytes)) != -1){
fileOutputStream.write(bytes);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null){
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileOutputStream != null){
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println((end - start));
}
//测试copy非字符文件
@Test
public void test06(){
copyStreamFile("123.jpg","12345.jpg");
}
4、缓冲流
可以提高文件存取的速度
内部提供了一个缓冲区(默认大小为8M)
//使用缓冲流的方式复制指定文件
public void copyFileByBuffered(String address, String Daddress) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
long start = System.currentTimeMillis();
try {
//相当于在原来字节流的基础上又套了一层流,在关闭外层流的同时也会关闭内层流
bufferedInputStream = new BufferedInputStream(new FileInputStream(address));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(Daddress));
int len;
byte[] bytes = new byte[1024];
while ((len = bufferedInputStream.read(bytes)) != -1){
bufferedOutputStream.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedInputStream != null){
bufferedInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bufferedOutputStream != null){
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println((end - start));
}
//测试是否使用缓冲流速度的差异
//相比之下,使用缓冲流传输大文件速度更快
@Test
public void test07(){
//739毫秒
// copyStreamFile("A.avi","B.avi");
//130毫秒
copyFileByBuffered("A.avi","B.avi");
}
//图片的加密
public void encryption(String address, String Daddress) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(address);
fileOutputStream = new FileOutputStream(Daddress);
int len;
byte[] bytes = new byte[1024];
while ((len = fileInputStream.read(bytes)) != -1){
for (int i = 0; i < len; i++) {
//利用了二进制两次异或操作数值不变
bytes[i] = (byte) (bytes[i] ^ 5);
}
fileOutputStream.write(bytes);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test08(){
encryption("1234.jpg","12345.jpg");
}
//BufferedReader.readLine()方法
//每次读取一行,读完时返回null
@Test
public void test09() {
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader("hello01.txt"));
String s;
while ((s = bufferedReader.readLine()) != null){
System.out.print(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5、转换流
//字节文件转换为字符文件
public void streamToFile(String address,String preType, String Daddress, String neType) {
InputStreamReader inputStreamReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
//第一个参数为指定文件流,第二个参数为文件编码方式
inputStreamReader = new InputStreamReader(new FileInputStream(address),preType);
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(Daddress),neType);
char[] cbuf = new char[5];
int len;
while ((len = (inputStreamReader.read(cbuf))) != -1){
//将文件内容先输出到控制台,然后保存到文件
String s = new String(cbuf, 0, len);
System.out.println(s);
outputStreamWriter.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStreamReader != null) {
inputStreamReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStreamWriter != null) {
outputStreamWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void test11(){
streamToFile("hello01.txt","gbk","hello03.txt","utf-8");
}
6、对象流
将一个对象序列化到文件里
ObjectInputStream
ObjectOutputStream
不能序列化static或transient修饰的成员变量
序列化:
要想序列化需要满足的三个条件
- 相应对象的类要实现Serializable接口
- 保证内部的所有属性也都是可序列化的
- 需要相应对象的类提供一个全局变量serialVersionUID(用来表明类的不同版本之间的兼容性;如果没有显式地定义,系统将会根据类中的细节自动定义一个,但是在改动类的时候这个值也会改动,所有需要自己显式地定义)
public class Test02 {
@Test
public void ObjectOutputStreamTest() {
ObjectOutputStream objectOutputStream = null;
try {
//准备对象流,确定要序列化到的文件
objectOutputStream = new ObjectOutputStream(new FileOutputStream("Admin.dat"));
//定义需要序列化的对象
Admin admin = new Admin();
admin.setAname("张三");
admin.setApassword("123456");
//将指定对象序列化到文件中
objectOutputStream.writeObject(admin);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (objectOutputStream != null) {
objectOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void ObjectInputStream() {
ObjectInputStream objectInputStream = null;
try {
//准备将文件中的信息,序列化为对象
objectInputStream = new ObjectInputStream(new FileInputStream("Admin.dat"));
//封装为一个对象
Object o = objectInputStream.readObject();
Admin admin = (Admin)o; //将对象强转
System.out.println(admin.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (objectInputStream != null) {
objectInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
7、随机存取对象流(RandomAccessFile)
每次使用read()/write()方法时,读取数据的指针都会下移,可以使用seek()方法指定指针的位置,从而实现对指定位置的数据进行修改
@Test
//随机存取文件流
public void test12() throws IOException {
RandomAccessFile rw = null;
try {
rw = new RandomAccessFile("hello01.txt", "rw");
byte[] bytes = new byte[5];
int len;
while ((len = rw.read(bytes)) != -1){
String s = new String(bytes, 0, len);
System.out.print(s);
}
System.out.println("");
rw.seek(0);
rw.write("asd".getBytes());
rw.seek(0);
while ((len = rw.read(bytes)) != -1){
String s = new String(bytes, 0, len);
System.out.print(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (rw != null){
rw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
8、Socket网络编程
通信的要素:IP和端口号、网络协议
InetAddress代表着一个具体的IP地址
IP与端口号结合在一起得到一个网络套接字Socket
端口号:0-65535
公认端口:0-1023注册端口:1024-49151
动态/私有端口:49152-65535
public class TestSocket {
public static void main(String[] args) throws UnknownHostException {
InetAddress byName = InetAddress.getByName("www.taobao.com");
InetAddress localHost = InetAddress.getLocalHost();
System.out.println(byName);
System.out.println(localHost);
}
}
TCP编程
- 向指定服务端发送文本消息
public class SocketTest {
@Test
public void client() {
Socket socket = null;
OutputStream outputStream = null;
try {
//1、创建Socket对象,指明服务器的ip和端口号
//InetAddress的构造器是私有的,创建对象的时候使用静态的方法,参数可为IP或域名
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
socket = new Socket(inetAddress, 8888);
//2、获取一个输出流,用于写出数据
outputStream = socket.getOutputStream();
//3、写出数据操作
outputStream.write("你好,我是XXX".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//4、关闭资源
if (outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void server() throws IOException {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
//1、创建服务端的ServerSocket,指明自己的端口号
serverSocket = new ServerSocket(8888);
//2、调用accept()表示接收来自于客户端的Socket
socket = serverSocket.accept();
//3、获取输入流
inputStream = socket.getInputStream();
//4、读取输入流的数据
byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[5];
int len;
while ((len = inputStream.read(bytes)) != -1){
byteArrayOutputStream.write(bytes, 0, len);
}
System.out.println(byteArrayOutputStream.toString());
System.out.println("收到来自于" + socket.getInetAddress().getHostName());
} catch (IOException e) {
e.printStackTrace();
} finally {
//5、关闭资源
if (byteArrayOutputStream != null){
byteArrayOutputStream.close();
}
if (inputStream != null){
inputStream.close();
}
if (socket != null){
socket.close();
}
if (serverSocket != null){
serverSocket.close();
}
}
}
}
- 向指定服务器发送一张图片
@Test
public void client() {
Socket socket = null;
OutputStream outputStream = null;
FileInputStream fileInputStream = null;
try {
InetAddress localHost = InetAddress.getLocalHost();
socket = new Socket(localHost, 8888);
outputStream = socket.getOutputStream();
//发送一张图片
fileInputStream = new FileInputStream("123.jpg");
byte[] bytes = new byte[10];
int len;
while ((len = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileInputStream != null){
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null) {
outputStream.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;
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
try {
serverSocket = new ServerSocket(8888);
socket = serverSocket.accept();
inputStream = socket.getInputStream();
fileOutputStream = new FileOutputStream("6.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStream != null) {
inputStream.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();
}
}
}
- 向服务器发送一张图片,服务器端收到后返回文本消息
@Test
public void client1() {
Socket socket = null;
OutputStream outputStream = null;
FileInputStream fileInputStream = null;
InputStream inputStream = null;
try {
InetAddress localHost = InetAddress.getLocalHost();
socket = new Socket(localHost, 8888);
outputStream = socket.getOutputStream();
//发送一张图片
fileInputStream = new FileInputStream("123.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = fileInputStream.read(bytes)) != -1){
outputStream.write(bytes, 0, len);
}
//关闭数据输出
socket.shutdownOutput();
/*
客户端与服务端传输数据的时候,如果不声明发送结束,则read()方法将一致接收,造成阻塞;所以需要表明发送结束
*/
//接收返回信息
inputStream = socket.getInputStream();
while ((len = inputStream.read(bytes)) != -1){
System.out.print(new String(bytes, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileInputStream != null){
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (socket != null){
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void server1() {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream inputStream = null;
OutputStream outputStream = null;
FileOutputStream fileOutputStream = null;
try {
serverSocket = new ServerSocket(8888);
socket = serverSocket.accept();
inputStream = socket.getInputStream();
fileOutputStream = new FileOutputStream("6.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0, len);
}
System.out.println("收到图片");
//返回收到信息
outputStream = socket.getOutputStream();
outputStream.write("收到图片,很好看".getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStream != null) {
inputStream.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();
}
}
}
UDP编程
发送或者接收的数据都封装到一个
DatagramPacket
类的对象中,然后通过DatagramSocket
发送出去
//UDP
@Test
public void udpClient(){
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket();
InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
byte[] bytes = "nihao".getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length, inetAddress, 8888);
//发送
datagramSocket.send(datagramPacket);
} catch (IOException e) {
e.printStackTrace();
} finally {
datagramSocket.close();
}
}
@Test
public void udpServer() {
DatagramSocket datagramSocket = null;
try {
datagramSocket = new DatagramSocket(8888);
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, 0, bytes.length);
//接收
datagramSocket.receive(datagramPacket);
System.out.println(new String(datagramPacket.getData(), 0, datagramPacket.getLength()));
} catch (IOException e) {
e.printStackTrace();
} finally {
datagramSocket.close();
}
}
URL编程
url基本结构:
<传输协议>://<主机名>:<端口号>/<文件名>#片段名?参数列表
//URL
@Test
public void test1() {
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
try {
URL url = new URL("http://localhost:8080/examples/123.jpg");
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()); //获取查询名
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.connect();
inputStream = httpURLConnection.getInputStream();
fileOutputStream = new FileOutputStream("url.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStream != null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
); //获取文件路径
System.out.println(url.getFile()); //获取文件名
System.out.println(url.getQuery()); //获取查询名
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.connect();
inputStream = httpURLConnection.getInputStream();
fileOutputStream = new FileOutputStream("url.jpg");
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
fileOutputStream.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStream != null){
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}