流的分类是基于数据源的如:
1.FileInputStream的数据源就是文件。
2.DateInputStream的数据源就是数据。
3.不同的流拥有不同的数据源,流以数据源作为分类标准。
首先输入输出流是相对于程序而言的而不是相对于数据源。
输入流:从数据源到程序-------以inputStream-------Reader结尾的流。
输出流:从程序到数据源-------以OutputStream------Writer结尾的流。
=========================================================================
1.文件字节流:FileInputStream(不需传入流)
文件字节流的基本应用
package IO流;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* 首先输入流输出流是相对于程序而言的而不是相对于数据源
* 输入流:从数据源到程序--以inputStream--Reader结尾的流
* 输出流:从程序到数据源--以OutPutStream--Writer结尾的流
*
* 按处理数据单元分类
* 1.字节流:以字节为单位--以Stream结尾的流一般是字节流--FileInputStream--FileOutputStream
* 字节流用于英语
* 2.字符流:以字符为单位获取数据--以Reader和Writer结尾的流一般是字符流--FileReader--FileWriter
* 一般用于处理文本文件。txt 中文
*
*
* 按处理对象不同分类
* 节点流:可以字节从数据源或目的地读写数据,如FileInputStream(处理file),FileReader,DateInputStream(处理Date)
* 处理流:处理流的流,不直接练级恩数据源,而是通过其他流间接的连接数据源,相当于将流变成一个对象,然后就可以通过对象调用流的方法
* BufferedInputStream
* BufferedReader也可以看成把流建对象
* 就像int和Integer的关系
* 处理流 处理其他流的流就叫处理流可以叠加
*/
public class 流概念的细分 {
public static void main(String[] args) {
//readFile();
//readFile2();
//writeFile();
//writeFile2();
//copyFile("d:/图片01.jpg","d:/图片02.jpg");
copyFileBuffer("d:/图片01.jpg","d:/图片03.jpg");
}
//读文件 try-catch-finally方法实现
private static void readFile() {
FileInputStream fis = null;
try {
fis = new FileInputStream("d:/b.txt");
StringBuilder sb=new StringBuilder();
int temp=0;//temp用来存储返回的整数
while ((temp=fis.read())!=-1){
sb.append((char)temp);
}//通过循环遍历文件内容
System.out.println(sb);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (fis!=null){
fis.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
//读文件 try-catch-resource方法实现
//就是将流对象的定义放到try里面,相当于自动添加finally
private static void readFile2(){
try(FileInputStream fis = new FileInputStream("d:/b.txt");) {
StringBuilder sb=new StringBuilder();
int temp=0;//temp用来存储返回的整数
while ((temp=fis.read())!=-1){
sb.append((char)temp);
}//通过循环遍历文件内容
System.out.println(sb);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//写文件操作 try-catch-finally方法实现
private static void writeFile() {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("d:/b.txt");
fos.write("abcdefg".getBytes(StandardCharsets.UTF_8));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
//写文件操作 try-catch-resource方法实现
private static void writeFile2() {
try(FileOutputStream fos=new FileOutputStream("d:/b.txt");) {
fos.write("abcdefg".getBytes(StandardCharsets.UTF_8));
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//拷贝文件 使用字节流 读一个字节写一个字节
//只适用于小的文件,效率比较低
private static void copyFile(String copy,String get){
//这里的 copy是传入的文件地址 get是复制后的文件地址
try(FileInputStream fis=new FileInputStream(copy);
FileOutputStream fos=new FileOutputStream(get);){
int temp=0;
while ((temp=fis.read())!=-1){
fos.write(temp);//每读一个写进去
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//增加一个缓存 使用缓存提高拷贝效率
//缓冲区其实就是数组,当数组装满缓冲区后再进行操作
//有自定义缓冲区和Buffer类中系统给定的大小的缓冲区
//效率的差异是巨大的
private static void copyFileBuffer(String copy,String get){
//这里的 copy是传入的文件地址 get是复制后的文件地址
try(FileInputStream fis=new FileInputStream(copy);
FileOutputStream fos=new FileOutputStream(get);){
byte[] buffer=new byte[1024];//缓冲区
while ((fis.read(buffer))!=-1){//将读的内容放入buffer数组
fos.write(buffer);//每读一个写进去
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
·2.文件字符流:FileReader(不需传入流)
以字符为为单位进行操作
文件字符流的基本应用
package IO流;
import java.io.*;
/**
* 关于文件字符流的测试
* 拷贝
*
*/
public class 文件字符流 {
public static void main(String[] args) {
try(FileReader fr=new FileReader("d:/d.txt");
FileWriter fw=new FileWriter("d:/d_copy.txt")) {
int temp=0;
char[] buffer=new char[1024];//缓冲区
while ((fr.read(buffer))!=-1){//将读的内容放入buffer数组
fw.write(buffer);//写到流里面,通过流写到文件里面
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} ;
}
}
3.缓冲字节流:BufferInputStream(需传入流)
(1)缓冲其实就是在对文件进行操作的时候用数组存储要操作的数据等数组满了之后在进行读写来避免频繁的读写,提高操作流的效率。
(2)Idea中提供了缓存字节流,给定的缓存数组大小为byte[1024]。
代码是对缓存字节流的基本应用。
缓冲字节流的基本应用
package IO流;
import java.io.*;
/**
*
* 缓冲区就是数组
* 缓冲流
* BufferedInputStream和BufferedOutputStream
* 这两个流是缓冲字节流,通过内部缓存数组来提高操作流的效率
*
*
* 测试缓冲字节流
*
*
*/
public class 缓冲字节流 {
public static void main(String[] args) {
try(
FileInputStream fis=new FileInputStream("d:/图片01.jpg");
FileOutputStream fos=new FileOutputStream("d:/图片04.jpg");
BufferedInputStream bis=new BufferedInputStream(fis);
BufferedOutputStream bos=new BufferedOutputStream(fos);
){
int temp=0;
while ((temp=fis.read())!=-1){
bos.write(temp);//bos自动有个缓存数组满了之后写进去
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
4.缓冲字符流:BufferReader(需传入流)
(1)和缓冲字节流相同,只不过将InputStream改成Reader。
(2)处理文本时,我们使用字符流。
(3)字节流一般用于英文,而字符流用于中文。
缓冲字符流的基本应用
package IO流;
import java.io.*;
/**
* BufferedReader和bufferedWriter
* 增加了缓存机制
* 同时提供了readLine方法//可以读取一行
* 处理文本时我们一般使用缓冲字符流
*
*
*
*/
public class 缓冲字符流 {
public static <bw> void main(String[] args) {
try(
BufferedReader br=new BufferedReader(new FileReader("d:/d.txt"));//bufferreader里面只能传流
BufferedWriter bw=new BufferedWriter(new FileWriter("d:d_copy2.txt"))
){
String temp="";
while ((temp=br.readLine())!=null){
bw.write(temp);
bw.newLine();//新增一个换行符
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}}
5.字节数组流:
(1).ByteArrayInputStream就是把字节数组当做数据源。
字节数组流的基本应用
package IO流;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/**
* 字节数组流
* 用于数组和流之间的转化
* FileInputStream是文件和流之间的转化
* FileInputStream就是把文件当成数据源
* ByteArrayInputStream就是把字节数组当做数据源
*
* 不同的流其实就是数据源不同
*
*/
public class 字节数组流 {
public static void main(String[] args) {
//geyByte可以把字符串转化为字节数组
test01("abcfefg".getBytes(StandardCharsets.UTF_8));
}
private static void test01(byte[] bytes){
int temp=0;
int num=0;//用于表示读取的字节数
try(
ByteArrayInputStream bis=new ByteArrayInputStream(bytes);
){
while ((temp=bis.read())!=-1){
System.out.println((char) temp);
num++;
}
System.out.println("读取的字节数"+num);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
6.数据流:DateInputStream(需传入流)
(1).写入文件的是二进制,需要用OutputStream读且读出的顺序要和输入的顺序保持一致,因为二进制文件是0,1串,顺序不同不能确定是什么数据类型。会发生读出错误。
(2).将基本数据类型与字符串类型作为数据源
(3).允许程序以与机器无关的方式从底层输入输出流中操作java数据类型。
数据流的基本应用
package IO流;
import java.io.*;
/**
*
* 将基本数据类型和字符串类型作为数据源
* 从而实现从底层输入输出流中操作java基本数据类型和字符串类型
* DateInputStream和DateOutputStream提供了可以存取与机器无关的所有Java基础数据类型
* 可以对节点流和处理流进行包装从而获得方法
* 增加灵活性
*
*写进去的是二进制数据
*
*/
public class 数据流 {
public static void main(String[] args) {
writerDate();
readDate();
}
private static void writerDate() {
try (
DataOutputStream dos = new DataOutputStream(new FileOutputStream("d:date.txt"));
) {
dos.writeInt(10);
dos.writeChar('d');
dos.writeDouble(Math.random());
dos.writeBoolean(true);
dos.writeUTF("赵宇晖加油");
//手动刷新缓冲区,将流中的数据写入文件中
//不同数据类型的字节数不一样
dos.flush();
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void readDate(){
try(
DataInputStream dis=new DataInputStream(new FileInputStream("d:/date.txt"));
){
//读取顺序 需要和写入数据时的循序一致,不然不能正确的读取
System.out.println(dis.readInt());
System.out.println(dis.readChar());
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
System.out.println(dis.readUTF());
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
7.对象流和序列化和反序列化ObjectInputStream(需传入流)
(1)以对象为数据源,但是必须将传输的对象进项序列化和反序列化。
(2)首先介绍序列化和反序列化,因为文件在网络上的传输是以二进制文件的方式,那么想要传输数据时就需要将文件转化为二进制文件这个就叫序列化,反序列化就是接受数据的一段将二进制文件转化为原本要传输的数据。
(3)static属性不参与序列化,如果对象中的属性不想被传输也就是不想被序列化不能使用static修饰而是使用transient修饰。
这段代码是定义的数据类型
package IO流;
import java.io.Serializable;
public class user implements Serializable {//Serializable接口表示这个类可以被序列化
private int id;
private String name;
//用transient修饰的数据不会被序列化,不用序列化就不会被写到流里面
transient private String pwd;//密码
public user(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
这段代码是序列化和反序列化的演示
package IO流;
import java.io.*;
import java.util.ArrayList;
/**
*
*
*
*/
public class 序列化和反序列化 {
public static void main(String[] args) {
writeObject();
readObject();
}
private static void writeObject(){
try(
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("d:/object.txt"))
){
ArrayList<user> list=new ArrayList<>();
list.add(new user(1001, "赵宇晖1","123456"));
list.add(new user(1001, "赵宇晖2","123456"));
list.add(new user(1001, "赵宇晖3","123456"));
list.add(new user(1001, "赵宇晖4","123456"));
oos.writeObject(list);
oos.flush();//清空缓冲区
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static void readObject(){
try(
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/object.txt"));
){
ArrayList<user> list=(ArrayList) ois.readObject();
for (user u:list){
System.out.println(u.getId()+"/"+u.getName()+"/"+u.getPwd());
//这里密码没有参与序列化,getpwd为空
}
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
8.转换流InputStreamReader(需传入流)
(1).用来实现字节流转化成字符流。
转换流的简单应用
package IO流;
import java.io.*;
/**
* 将字节流转化为字符流
* InputStreamReader和OutputStreamWriter
*
*
*
*
*/
public class 转化流 {
public static void main(String[] args) {
try(
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));//键盘的输入是字节流
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out))//键盘的输出也是字节流
){
String str =br.readLine();
while (!"exit".equals(str)) {
bw.write("键盘输入:"+str);
bw.newLine();
bw.flush();
str=br.readLine();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
9.随意访问文件流RandomAccessFile(需传入流)
(1)普通的流只能一个一个按照顺序读取文件内容RandomAccessFile可以通过seek方法传入正确的字节数,指针将指向对应字节数的位置开始读取可以通过循环调用seek方法来实现任意位置的存储功能。
随意访问文件流的简单应用
package IO流;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* RandomAccessFile
*1.实现对一个文件做读和写的操作
* 2.可以访问文件任意位置,不像其他流只能按照先后顺序读取
* 可以读任意位置
*
*
*
*/
public class 任意访问文件流 {
public static void main(String[] args) {
try(
RandomAccessFile raf=new RandomAccessFile("d:date2.txt","rw");//rw表示可读可写
){
int[] date={10,20,30,40,50,60,70,80,90,100};
for (int i = 0; i < date.length; i++) {
raf.writeInt(date[i]);
}//将数组数据写入
//直接从date2.txt中读取数据,位置第4 字节开始
raf.seek(4);//写4表明指针调到4 seek方法//因为每个int占据4个字节
System.out.println(raf.readInt());//这个应该是20
//在第八个字节处插入一个新数据 替换以前的数据
raf.seek(8);
raf.writeInt(45);
for (int i = 0; i < 10; i++) {
raf.seek(i*4);
System.out.print(raf.readInt()+"\t");
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}