IO流
1.基本概念
IO流就是使用java技术将文件内容读取到java程序中,将程序中的内容保存到java文件中 ,简单来说就是java程序和文件交互的过程。
2.分类
- IO流一定要站在程序的角度,在计算机中,所有的文件都是使用字节来表示大小的。
一.字节流
- Java中所有的IO流的底层全部都是字节流.
1.字节输入流 InputStream
- 使用已知实现子类 FileInputStream
1.1构造方法
- FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
- FileInputStream(FileDescriptor fdObj) 通过使用文件描述符 fdObj 创建一个 FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接。
- FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
1.2常用方法
- int
available() 返回此输入流方法的下一个调用方可以不受阻塞地从此输入流读取(或跳过)的字节数。 - void
close() 关闭此输入流并释放与该流关联的所有系统资源。 - void
mark(int readlimit) 在此输入流中标记当前的位置。
- readlimit - 在标记位置失效前可以读取字节的最大限制。
- boolean
markSupported() 测试此输入流是否支持 mark 和 reset 方法。 - abstract int
read() 从输入流读取下一个数据字节。 - int
read(byte[] b) 从输入流中读取一定数量的字节并将其存储在缓冲区数组 b 中。
- 参数:b - 读入数据的缓冲区。
- 返回:读入缓冲区的总字节数,如果由于流末尾已到达而不再有数据,则返回 -1。
- int
read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入字节数组。
参数:
- b - 读入数据的缓冲区。
- off - 在其处写入数据的数组 b 的初始偏移量。
- len - 要读取的最大字节数。
- void
reset() 将此流重新定位到对此输入流最后调用 mark 方法时的位置。 - long
skip(long n) 跳过和放弃此输入流中的 n 个数据字节。
基本步骤:
- 指定要操作的文件
- 创建输入流,将文件读取到IO流
- 从IO流中获取内容保存到java程序中
- 关闭资源:先开的后关,后开的先关
1.2.1基本读取
@Test
void inputio() {
//指定要操作的文件,使用file
File file=new File("demo.txt");
try {
//将文件读取到io流中
InputStream in=new FileInputStream(file);
//获取文件大小内容
System.out.println("文件内容的长度是:"+in.available());//文件内容的长度是:14
//从io流中获取内容保存到java程序中
//在程序中使用字节数组来保存(要注意数组的长度)
byte[] bytes=new byte[in.available()];//尽量将数组长度与文件内容长度绑定
in.read(bytes);
//使用字符串来显示
String str=new String(bytes);
//关闭资源
in.close();
System.out.println(str);//hello,world!!!
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
1.2.2每一次读一个字节
基本步骤:
- 读取文件的位置
- 创建输入流,将文件读取到io流中
- 一个一个读取
@Test
void readone() {
//读取文件的位置
File file=new File("demo.txt");
try {
//创建输入流,将文件读取到io流中
InputStream in=new FileInputStream(file);
//读取第一个字符
int read = in.read();
//得到第一个字符的unicode编码
System.out.println(read);
//将所得到的unicode强转为字符类型
System.out.println((char)read);
//全部读取到,如果读到最后一个之后返回-1
//已经读取过的不会再次进行读取
int c=-1;
while((c=in.read())!=-1) {
System.out.print((char)c);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.字节输出流 OutputStream
- 使用已知实现子类FileOutputStream
2.1构造方法
- FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
- FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
- FileOutputStream(FileDescriptor fdObj) 创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。
- FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。
- FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。
2.2常用方法
- void
close() 关闭此输出流并释放与此流有关的所有系统资源。 - void
flush() 刷新此输出流并强制写出所有缓冲的输出字节。 - void
write(byte[] b) 将 b.length 个字节从指定的字节数组写入此输出流。 - void
write(byte[] b, int off, int len) 将指定字节数组中从偏移量 off 开始的 len 个字节写入此输出流。 - abstract void
write(int b) 将指定的字节写入此输出流。
基本步骤:
- 要写出去的文件内容
- 写出去的目标文件
- 往出写(创建输出流)
- 关闭资源 (关闭资源前一定要进行先flush在close. )
2.2.1直接创建到根目录
@Test
void outputio() {
//要写出去的内容
String message="世界美好与你环环相扣";
//写出去的目标文件,使用file(文件不存在时会自动创建到根目录下)
File outfile=new File("out.txt");
//往出写,将数据保存到byte数组中
byte[] bytes=message.getBytes();
try {
//创建输出流
OutputStream out=new FileOutputStream(outfile);
out.write(bytes);
//关闭资源,关闭资源前要先进行刷新资源
out.flush();//将io流中的信息刷新到文件中
out.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.2.2创建到其他文件夹
@Test
void outputio01() {
//要写出去的内容
String message="世界美好与你环环相扣";
//写出去的目标文件,使用file,若不想让文件处于根目录
//检查路径是否存在,如果不存在,先创建目录,写出文件的时候不会自动创建目录
File outfile=new File("file\\out.txt");
System.out.println("文件是否存在:"+outfile.exists());
//查看父路径是否存在
File parentFile = outfile.getParentFile();
//创建目录
parentFile.mkdirs();
System.out.println("文件是否存在:"+outfile.exists());
try {
//若没有创建
outfile.createNewFile();
//往出写,将数据保存到byte数组中
byte[] bytes=message.getBytes();
//创建输出流
OutputStream out=new FileOutputStream(outfile);
out.write(bytes);
//关闭资源,关闭资源前要先进行刷新资源
out.flush();//将io流中的信息刷新到文件中
out.close();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.2.3写出操作,追加写出
- \r:回车符,返回到这一行的开头,return的意思。
- \n:换行符,到下一行的同一位置,纵坐标相同。
- \t:制表符,为了在不使用表格的情况下,上下对齐。
- Enter 相当于\n\r,所以Enter的标识为往下,再往前,\n\r等价于\r\n。
@Test
void outfile() {
//指定目标位置
File file=new File("out.txt");
//创建写出内容
String mess="\r\n"+"所念皆星河";
//创建输出流
try {
//覆盖写法
//FileOutputStream fos=new FileOutputStream(file);
//追加写法
FileOutputStream fos=new FileOutputStream(file,true);
//写出去
fos.write(mess.getBytes());
//关闭资源
fos.flush();
fos.close();
System.out.println("文件写出成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
3.使用字节流实现文件的拷贝
3.1先读取完在写出去
基本步骤
- 指定源文件位置
- 目标文件位置
- 创建读取流和写出流
- 创建数组容器
- 使用输入流,将源文件内容保存到数组中
- 将数组中的内容写出到目标文件中
- 关闭资源
@Test
void copy01() {
//指定源文件位置
File sfile=new File("D:\\Java1\\Workspace1\\java02\\src1\\com\\xingyun\\Demo\\StaticTest.java");
//目标文件位置
File dfile=new File("D:\\Java1\\Workspace1\\java02\\src1\\com\\xingyun\\Demo\\newStaticTest.java");
try {
//创建读取流和写出流
FileInputStream fis=new FileInputStream(sfile);
FileOutputStream fos=new FileOutputStream(dfile);
//创建数组容器
byte[] bytes=new byte[fis.available()];
//使用输入流,将源文件内容保存到数组中
fis.read(bytes);
//将数组中的内容写出到目标文件中
fos.write(bytes);
//关闭资源
fos.flush();
fos.close();
fis.close();
System.out.println("文件拷贝成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
3.2一边读取一边写(一个字节一个字节的读取)
@Test
void copy02() {
//指定源文件位置
File sfile=new File("D:\\Java1\\Workspace1\\java02\\src1\\com\\xingyun\\Demo\\StaticTest.java");
//目标文件位置
File dfile=new File("D:\\Java1\\Workspace1\\java02\\src1\\com\\xingyun\\Demo\\newStaticTest.java");
//创建读取流 写出流
try {
//创建读取流 写出流
FileInputStream fis=new FileInputStream(sfile);
FileOutputStream fos=new FileOutputStream(dfile);
//创建数组容器
byte[] bytes=new byte[fis.available()];
int bt=0;//当前读取的字节数
//循环读出写出
while((bt=fis.read(bytes))!=-1) {
//写出去
fos.write(bytes);
}
//关闭资源
fos.flush();
fos.close();
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
3.3使用数组缓冲区的方式
@Test
void copy05() {
//指定源文件位置
File sfile=new File("D:\\java笔记\\hello.txt");
//目标文件位置
File dfile=new File("D:\\java笔记\\newhello.txt");
//创建读取流 写出流
try {
//创建读取流 写出流
FileInputStream fis=new FileInputStream(sfile);
FileOutputStream fos=new FileOutputStream(dfile);
//创建数组容器
byte[] bytes=new byte[fis.available()];
int bt=0;//当前读取的字节数
//循环读出写出
while((bt=fis.read(bytes))!=-1) {
//写出去,只写有效数据
fos.write(bytes,0,bt);
}
//关闭资源
fos.flush();
fos.close();
fis.close();
System.out.println("文件拷贝成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
小例子1
- 根据输入的源文件,来拷贝一份新的文件,文件类型要一致,新文件的名字是源文件的名字+当前时间
@Test
void copy04() {
Scanner input=new Scanner(System.in);
System.out.println("请输入源文件的路径");
String filepath=input.next();
//指定源文件
File sfile=new File(filepath);
//获取源文件的名字
String name=sfile.getName();
System.out.println(name);
//使用.将得到的文件名分隔开
String[] split = name.split("\\.");
System.out.println(split.length);
//获取当前时间
LocalDate lt=LocalDate.now();
System.out.println(lt);
//结果为文件名时间.后缀
String destfile=split[0]+lt+"."+split[1];
File dfile=new File("D:\\java笔记",destfile);
System.out.println(dfile.getName());
try {
//创建读取流和写出流
FileInputStream fis=new FileInputStream(sfile);
FileOutputStream fos=new FileOutputStream(dfile);
//创建数组容器
byte[] bytes=new byte[fis.available()];
//使用输入流,将源文件内容保存到数组中
fis.read(bytes);
//将数组中的内容写出到目标文件中
fos.write(bytes);
//关闭资源
fos.flush();
fos.close();
fis.close();
System.out.println("文件拷贝成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
小例子2
- 输入要上传的文件名.后缀,将该文件上传到项目的file文件夹下面。
//文件上传
@Test
void copy03() {
//指定要查看的文件位置
File file=new File("D:\\Java1\\Workspace1\\java02\\src1\\com\\xingyun\\Demo");
//请输入你要上传的文件名
String name="1111.jpg";
File loadfile=null;
//遍历
File[] listFiles = file.listFiles();
for (File file2 : listFiles) {
//判断是否是个文件,如果是,则输出文件名
if(file2.isFile()) {
System.out.println(file2.getName());
//得到要上传的文件对象
if(file2.getName().equals(name)) {
loadfile=file2;
}
}
}
//指定上传的位置
File loadpath=new File("file",name);
//创建file
if(!loadpath.getParentFile().exists()) {
loadpath.getParentFile().mkdirs();
}
//创建读入写出流
try {
FileInputStream fis=new FileInputStream(loadfile);
FileOutputStream fos=new FileOutputStream(loadpath);
//进行上传
int len=-1;
while((len=fis.read())!=-1) {
fos.write(len);
}
//关闭资源
fos.flush();
fos.close();
fis.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
二.字符流
- 每一次操作最小单位是一个字符,字符流只能用来进行文本文件的操作。
1.Reader
- 使用已知实现子类FileReader
1.1构造方法
- FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
- FileReader(FileDescriptor fd) 在给定从中读取数据的FileDescriptor 的情况下创建一个新 FileReader。
- FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。
1.2常用方法
- abstract void
close() 关闭该流。 - void
mark(int readAheadLimit) 标记流中的当前位置。 - boolean
markSupported() 判断此流是否支持 mark() 操作。 - int
read() 读取单个字符。 - int
read(char[] cbuf) 将字符读入数组。 - abstract int
read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。 - int
read(CharBuffer target) 试图将字符读入指定的字符缓冲区。 - boolean
ready() 判断是否准备读取此流。 - void
reset() 重置该流。 - long
skip(long n) 跳过字符。
//字符输入流
@Test
void charread() {
//源文件
File file=new File("out.txt");
//输入流
try {
Reader reader=new FileReader(file);
//读取到char数组中
// char[] ch=new char[10];
// reader.read(ch);
// String str=new String(ch);
// System.out.println(str);
//一个一个读取
int c=0;
while((c=reader.read())!=-1) {
System.out.println((char)c);
}
//关闭资源
reader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2.Writer
- 使用已知实现子类FileWriter
2.1构造方法
- FileWriter(File file) 在给出 File 对象的情况下构造一个 FileWriter 对象。
- FileWriter(File file, boolean append) 在给出 File 对象的情况下构造一个 FileWriter 对象。
- FileWriter(FileDescriptor fd) 构造与某个文件描述符相关联的 FileWriter 对象。
- FileWriter(String fileName) 在给出文件名的情况下构造一个 FileWriter 对象。
- FileWriter(String fileName, boolean append) 在给出文件名的情况下构造 FileWriter 对象,它具有指示是否挂起写入数据的 boolean 值。
2.2常用方法
- Writer
append(char c) 将指定字符追加到此 writer。 - Writer
append(CharSequence csq) 将指定字符序列追加到此 writer。 - Writer
append(CharSequence csq, int start, int end) 将指定字符序列的子序列追加到此 writer.Appendable。 - abstract void
close() 关闭此流,但要先刷新它。 - abstract void
flush() 刷新此流。 - void
write(char[] cbuf) 写入字符数组。 - abstract void
write(char[] cbuf, int off, int len) 写入字符数组的某一部分。 - void
write(int c) 写入单个字符。 - void
write(String str) 写入字符串。 - void
write(String str, int off, int len) 写入字符串的某一部分。
基本步骤
- 写出目标
- 写出内容
- 输出流
- 输出
- 关闭流
@Test
void charout() {
//写出目标
File file=new File("newout.txt");
//写出内容
String mess="要加油,要努力啊!!!!";
//输出流
try {
//Writer w=new FileWriter(file,true);//追加
Writer w=new FileWriter(file);//不追加
//输出
w.write(mess);
//关闭资源
w.flush();//强制刷新,但不会关闭流
//追加
w.append("相信自己!!!!!");
System.out.println("写出成功");
w.flush();
w.close();//关闭流之后,无法在使用
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
小例子
- 使用字符进行拷贝
// 使用字符进行拷贝
@Test
void charcopy() {
//指定源文件,目标文件
File sfile=new File("demo.txt");
File dfile=new File("newdemo.txt");
//输入输出流
try {
FileReader reader=new FileReader(sfile);
FileWriter writer=new FileWriter(dfile);
//一边读取一边写出
int c=-1;
while((c=reader.read())!=-1) {
writer.write(c);
}
//关闭资源
writer.flush();
writer.close();
reader.close();
System.out.println("复制成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}