流的分类
字符流更适合处理文本数据(16bit就是一个char),非文本数据字节流
然后再根据是输入还是输出,形成抽象基类:字节输入流、字节输出流、字符输入流、字符输出流
节点流:节点流是最底层的流
处理流(包装流):将节点流或处理流包装后又生成的流
如何辨别流是什么类型的流:看流后缀
JVM垃圾回收,对于数据库连接,输入输出流,socket连接这样的物理连接是无能为力的
下面是使用FileReader FileWriter的例子
//在这里有一个难点,如果文件中有7个字符,为abcdefg,然后char数组长度为5
//第一次read cbuf里面,存储的是abcde
//第二次read cbuf里面,存储的是fgcde
//cbuf并不会在每次read的时候做自动清空,所在遍历或者使用String的时候要注意
//不要循环多了,这样就会出问题
import org.junit.Test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileReaderWriterTest {
@Test
public void testFileReader() {
FileReader fileReader = null;
try {
//1.创建文件对象
File file = new File("hello.txt");
System.out.println(file.getAbsolutePath());
//2.创建字符输入流
fileReader = new FileReader(file);
//3.读取操作
//方式一 read()会一直读取,直到读取到-1(代表读取到文件的末尾)
/*int data = fileReader.read();
while (data!=-1){
System.out.print((char) data);
data = fileReader.read();
}*/
//方式二
//read(char[] cbuf):返回每次读获取了几个字符,如果到末尾返回-1
//在这里有一个难点,如果文件中有7个字符,为abcdefg
//第一次read cbuf里面,存储的是abcde
//第二次read cbuf里面,存储的是fgcde
//cbuf并不会在每次read的时候做自动清空,所在遍历或者使用String的时候要注意
//不要循环多了,这样就会出问题
char[] cbuf = new char[5];
int len;
while((len = fileReader.read(cbuf)) != -1){
//使用for循环遍历
/*for(int i=0;i<len;i++){
System.out.print(cbuf[i]);
}*/
//使用String
String str = new String(cbuf,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.最最重要:关闭流,这个很容易忘
try {
if (fileReader != null)
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
从内存中写出数据
*/
@Test
public void testFileWriter(){
FileWriter fw = null;
try {
//1.创建文件对象
File file = new File("hello1.txt");
//2.创建输出流对象
fw = new FileWriter(file,true);
//3.写出的操作
//如果当前file有内容,写出会覆盖该内容,
//如果不想覆盖,在创建FileWriter的时候使用(File file,boolean append)构造器
fw.write("asdasqwe\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭
if (fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//复制文本文件
@Test
public void testReaderWriter(){
FileReader fr = null;
FileWriter fw = null;
try {
File inputfile = new File("hello.txt");
File outputfile = new File("hello2.txt");
fr = new FileReader(inputfile);
fw = new FileWriter(outputfile);
char[] cbuf = new char[5];
int len;
while((len = fr.read(cbuf)) != -1){
fw.write(cbuf,0,len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fw != null){
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流不能处理图片文件资源
fileInputStream、fileOutputStream的基本使用
import org.junit.Test;
import java.io.*;
public class FIleInputOutputStreamTest {
/**
* @Description: 使用字节流复制非文本文件
* @Param: []
* @return: void
* @Date: 2021/2/28
*/
@Test
public void fileInputOutputStreamTest(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
File inputfile = new File("testpic.jpg");
File outputFile = new File("testpic1.jpg");
fileInputStream = new FileInputStream(inputfile);
fileOutputStream = new FileOutputStream(outputFile);
byte[] buffer = new byte[5];
int len;
while ((len = fileInputStream.read(buffer))!= -1){
fileOutputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileInputStream!=null){
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
缓冲流
BufferedReader、BufferedWriter这俩我就不写样例了,同上(BufferedReader可以不使用char[],而是String str = br.readLine(),作为读取结果)
/*
缓冲流:
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
作用:提高读取写入速度
*/
import org.junit.Test;
import java.io.*;
public class BufferTest {
@Test
public void BufferStreamTest() {
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
File srcFile = new File("testpic.jpg");
File destFile = new File("testpic2.jpg");
//造流
//1.造节点流
fis = new FileInputStream(srcFile);
fos = new FileOutputStream(destFile);
//2.造处理流
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
//其他与之前一样
byte[] buffer = new byte[10];
int len;
while((len = bis.read(buffer))!= -1){
bos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//要求:先关闭外层的流,再关闭内层的流
if (bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//在关闭外层流的同时,内层的流也会同时关闭,所以内层流关闭可忽略
/* if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}*/
}
}
}
转换流
字符流和字节流之间的转换
import org.junit.Test;
import java.io.*;
import java.nio.charset.StandardCharsets;
/*
转换流:属于字符流
InputStreamReader:字节输入转字符输入
OutputStreamWriter:字符输出转字节输出
解码:字节-->字符
编码:字符-->字节
*/
public class InputStreamReaderTest {
//字节输入转字符输入
@Test
public void test(){
FileInputStream fis = null;
InputStreamReader isr = null;
try {
fis = new FileInputStream(new File("hello.txt"));
//字节输入转字符输入时要指定字符集
isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
char[] cubf = new char[5];
int len;
while ((len = isr.read(cubf))!= -1){
String str = new String(cubf,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (isr != null){
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/*
综合使用InputStreamReader和OutputStreamWriter
可以实现的事情:将文件编码转变并且保存
*/
@Test
public void outputTest(){
FileInputStream fis = null;
InputStreamReader isr = null;
FileOutputStream fos = null;
OutputStreamWriter osw = null;
try {
fis = new FileInputStream(new File("hello.txt"));
fos = new FileOutputStream(new File("hello_gbk.txt"));
//字节输入转字符输入时要指定字符集
isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
osw = new OutputStreamWriter(fos, "GBK");
char[] cubf = new char[5];
int len;
while ((len = isr.read(cubf))!= -1){
osw.write(cubf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (isr != null){
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (osw != null){
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
对象流与序列化
下面是使用对象流序列和反序列化的例子
/*
对象流:ObjectInputStream\ObjectOutputStream
*/
import org.junit.Test;
import java.io.*;
public class ObjectInputOutputStream {
//序列化
@Test
public void testObjectOutputStream(){
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("object.txt"));
oos.writeObject(new String("阿萨德"));
oos.flush();//刷新
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//反序列化
@Test
public void testInputStream(){
ObjectInputStream ois= null;
try {
ois = new ObjectInputStream(new FileInputStream("object.txt"));
String o = (String) ois.readObject();
System.out.println(o);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (ois != null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
对象的序列化机制
对象序列化允许java将内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,或者通过网络进行传输给另外一个节点
而其他程序获取了这个二进制流之后,可以恢复成原来的java对象。
要给自定义类进行对象序列化,必须实现Serializable接口
serialVersionUID:每一个实现了序列化接口的对象都要加一个public static final long类型的参数,就是serialVersionUID,值可以随便写,就是为了识别你是什么类
有时候这个值不加,序列化反序列化也不会出错,但是这样真的没错吗?
如果不给这个值,一旦类发生改变,之前做过序列化的无法反序列化
如果一个对象可以序列化,那么它其中的所有属性都必须是可序列化的(八大基本类型都实现了序列化接口)
序列化不能序列化static变量
NIO介绍
NIO主要就是一些工具类的变更
网络编程
首先是一些计网的知识
InetAddress类,作为ip地址的对象类
端口号:主要就是记端口号+ip地址可以组合得到唯一socket
三次握手
四次挥手
使用socket示例
import org.junit.Test;
import java.io.ByteArrayOutputStream;
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.nio.charset.StandardCharsets;
public class TCPTest {
@Test
public void client() {
Socket socket = null;
OutputStream os = null;
try {
InetAddress localHost = InetAddress.getLocalHost();
socket = new Socket(localHost,55555);
os = socket.getOutputStream();
os.write("hello,server!".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void server(){
ServerSocket ss = null;
InputStream is = null;
ByteArrayOutputStream baos = null;
Socket socket = null;
try {
ss = new ServerSocket(55555);
socket = ss.accept();
is = socket.getInputStream();
byte[] buffer = new byte[20];
int len;
baos = new ByteArrayOutputStream();
while ((len = is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (baos != null) {
try {
baos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (is!=null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ss!=null) {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
UDP示例
import org.junit.Test;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
public class UDPTest {
@Test
public void sender()throws IOException{
DatagramSocket socket = new DatagramSocket();
String str = "UDP test!!!!";
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
InetAddress localHost = InetAddress.getLocalHost();
DatagramPacket packet = new DatagramPacket(bytes,0,bytes.length,localHost,12345);
socket.send(packet);
socket.close();
}
@Test
public void receiver() throws IOException {
DatagramSocket socket = new DatagramSocket(12345);
byte[] buffer = new byte[100];
DatagramPacket packet = new DatagramPacket(buffer, 0, buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
socket.close();
}
}