IO流:用来操作文件内容的技术,IO流(输入输出):输入输出都是针对于程序而言的
IO分类:
1.按照数据流向分:输入输出流
输入流:将文件中的内容读取到程序中
输出流:将程序中的数据写到文件中
2.按照数据类型:字节流/字符流
字节流:以字节为单位进行的
字符流:以字符为单位进行的,操作中文字符更方便
输入流 输出流
字节流 字符流
字节输入流(InputStream) 字节输出流(OutputStream)
字符输入流(Reader)读 字符输出流(Writer)写
3.按照流的角色:节点流 处理流
节点流:程序用于直接操作目标设备所对应的流
例如:程序用于直接操作文件对应的流;文件流是一种直接用于操作文件的节点流
文件字符输入流(FileReader)读 文件字节输入流(FileInputStream)
文件字符输出流(FileWriter)写 文件字节输出流(FileOutputStream)
处理流:通过一个间接流去调用节点流,以达到更加灵活方法的读写操作,
这个间接的流就是处理流
Buffered缓冲流是一种处理流,
缓冲字符输入流 BufferedReader 缓冲字节输入流 BufferedInputStream
缓冲字节输出流 BufferedWriter 缓冲字节输出流 BufferedOutputStream
1.缓冲流不能直接操作文件,必须包装文件流,通过文件流访问
2.缓冲流的效率要比文件缓流效率高
涉及到流,直接按照这几部操作
案例:
将一个123.txt文件中的内容,读到程序,然后通过程序写出到另一个123_copy.txt文件中,
文件内容中涉及中文,建议使用字符流
案例使用:文件字符流
字符流一般用于处理文本内容 : txt java word .c等文件
import java.io.*;
public class FileIODemo01 {
public static void main(String[] args){
//为了在finally实现流的关闭,所以设置为全局变量
FileReader fileReader=null;
FileWriter fileWriter=null;
try {
//1.创建文件对象路径 注意编码格式,默认新建文件的格式是utf-8
File file=new File("D:\\123.txt");//源文件
File descFile=new File("D:\\123_copy.txt");//目标文件
//2.创建流(源文件进行读,目标文件进行写)
fileReader=new FileReader(file);
fileWriter=new FileWriter(descFile);
//FileReader fileReader1=new FileReader("D:\\123.txt");//读取源文件 等价于上面两步
//3.开始数据读写
/*
输入流中的方法
int read();返回读入的一个字符(返回字符对应的码),如果达到文件末尾,返回-1
输出流中的方法
void write(int c);向文件中写入一个字符
*/
//循环读取源文件中的内容,如果没有读到末尾,就将读到内容写到的内容写出到目标文件
// int data;//用于存储每次读取到的内容
// while((data=fileReader.read())!=-1){//如果读到内容不等于-1表示没有到文件末尾
// //向目标文件写入读取的内容
// fileWriter.write(data);
// }
/*
int read(char[] chs)返回读入到数组字符的个数,如果达到文件末尾,返回-1 int代表返回类型
void write(char[] chs,int off,int length);写入字符数组中chs的一部分,off是从哪个位置开始写,length表示要写多长
*/
char[] chars=new char[10];//容器,用来装字符
int length;//用于存储每次读取到数组中的字符的个数
while ((length=fileReader.read(chars))!=-1) {
//将字符数组中的内容写出到目标文件
fileWriter.write(chars,0,length);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//4.流的关闭
if (fileReader!=null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileWriter!=null){
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字节流一般用于处理非文本文件(.png .mp3 .mp4 .avi等)
案例:
复制110.mp4到110_copy.mp4
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class FileIODemo02 {
public static void main(String[] args) throws Exception {
//1.创建文件对象
//创建路径,确定路径是存在的
File file=new File("D:\\图片和视频\\110.mp4");
File file1=new File("D:\\图片和视频\\110_copy.mp4");
//2.创建流
FileInputStream fileInputStream=new FileInputStream(file);
FileOutputStream fileOutputStream=new FileOutputStream(file1);
//3.读写
/*
int read;读一个字节返回,若为-1表示读到文件末尾
void write(int data);写一个字节
*/
/*
int read(byte[] bs);返回每次输入到数组中的字节个数如果到了文件末尾则返回-1
void write(byte[] bs,int off,int length)
写入字节数组bs的一部分,off表示从哪里开始写length表示写多长
*/
byte[] bs=new byte[10];
int length;
while((length=fileInputStream.read(bs))!=-1){
fileOutputStream.write(bs,0,length);
}
//4.关闭
fileInputStream.close();
fileOutputStream.close();
}
}
在使用文件字节流做复制的时候,速度很慢, 通常建议使用缓冲字节流来实现复制
import java.io.*;
import java.nio.Buffer;
public class BufferedDemo01 {
public static void main(String[] args) throws Exception {
//1.创建文件
File file=new File("D:\\图片和视频\\110.mp4");
File file1=new File("D:\\图片和视频\\110_copy.mp4");
//2.创建流(最终使用的是缓冲流)
//2.1先创建文件流(文件字节流)
FileInputStream fis=new FileInputStream(file);
FileOutputStream fos=new FileOutputStream(file1);
//2.2根据文件流创建缓冲流
BufferedInputStream bis=new BufferedInputStream(fis);
BufferedOutputStream bos=new BufferedOutputStream(fos);
//3.读写
byte[] bs=new byte[1024];
int length;
while((length=bis.read(bs))!= -1) {//重复多次,知道写完
bos.write(bs,0,length);
}
//4.关闭流
//直接关闭外层流
bos.close();
bis.close();
}
}
随机流:
RandomIOAccessFile类支持随机访问,
程序可以直接跳到文件的任意地方来进行读或写
RandomAccessFile对象包含一个记录指针,用于标记当前读写的位置
RandomAccessFile可以自由的移动记录指针
关于指针的方法:
Long getFilePointer();获取文件记录指针的当前位置
void seek(int pos);将文件记录指针定位到pos位置
构造器
public RandomAccessFile(File file,String mode);
mode参数:该参数指定RandomAccessFile的访问模式
r:以只读方式打开
rw:以读写方式打开
rwd:以读写方式打开,同步文件内容
rws:以读写方式打开,同步文件内容和元数据更新
(元数据:描写数据的数据,对数据及信息资源的描述性信息)
操作的文件是事先建好的,里面内容如下图,文件格式为ANSI (ANSI可以深入了解一下)
import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.util.RandomAccess;
public class RandomIODemo01 {
public static void main(String[] args) throws Exception {
//写入的文件编码格式为ANSI 文件里面的内容为123456789 插入后的内容为1234056789
//1.创建文件路径
File file=new File("D:\\test.txt");
//2.创建流
RandomAccessFile raf=new RandomAccessFile(file,"rw");
//3.读写
//3.1移动记录指针到4位置后一位
raf.seek(4);
//3.2将4以后的内容存储起来,需要读取文件中的内容,然后将内容拼接;字符串的拼接
//3.2.1创建StringBuilder对象来存储后续内容
StringBuilder sb=new StringBuilder();
//3.2.2读取4以后的文件内容
byte[] bs=new byte[10];
int length;
while((length=raf.read(bs))!=-1){
//3.2.3将读取到内容转换成字符串拼接到sb中
String str=new String(bs,0,length);
sb.append(str);
}
//3.3再将指针移到4位置
raf.seek(4);
//3.4 将0写入
raf.write('0');
//3.5将存储到sb中内容写入到文件中
//3.5.1先将sb中的内容转为String
String s=sb.toString();
//3.5.2再把String转为byte数组
byte[] s_bs=s.getBytes();
//3.5.3再把byte数组写入到文件中
raf.write(s_bs);
//4.关闭
raf.close();
}
}
执行后:
seek的方法介绍
一个小案例:

package work.day0309;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.io.RandomAccessFile;
/**
* 1.接受用户输入的内容
* 2.创建文件
* 2.1指定文件路径
* 2.2判断
* 3.创建随机流
* 4.写入
* 5.移动指针
* 6.写入
* 7.关闭流
*
*/
public class RandomAccessFileTest {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
File file=null;
RandomAccessFile raf = null;
byte[] bs=null;
//文件路径
// if (!file.exists())
// try {
// //当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。
// file.createNewFile();
// }catch (IOException e){
// e.printStackTrace();
// }
try {
file=new File("test.txt");
if (!file.exists()){//不存在,创建一个
file.createNewFile();
}
raf=new RandomAccessFile(file,"rwd");
System.out.println("请输入你的姓名:");
String name=scan.next();
bs=name.getBytes(StandardCharsets.UTF_8);//设置编码格式
raf.write(bs);
System.out.println("请输入你的手机号:");
String phone=scan.next();
bs=phone.getBytes(StandardCharsets.UTF_8);
raf.seek(12);//将指针移到名字后面
raf.write(bs);
System.out.println("请输入身份证号:");
String idNum=scan.next();
bs=idNum.getBytes(StandardCharsets.UTF_8);
raf.seek(12+11);//将指针移到名字+手机号后一位
raf.write(bs);
System.out.println("请输入你的资费信息:");
String money=scan.next();
bs=money.getBytes(StandardCharsets.UTF_8);
raf.seek(12+11+18);//将指针移到姓名+手机号+身份证后一位
raf.write(bs);
} catch (IOException e) {
e.printStackTrace();
}
finally {
//关流
try{
if (raf!=null) {
raf.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
scan.close();
}
}
实现效果: