File类只能操作属性,无法操作文件里面的数据
IO
InputStream——OutputStream
从流向上划分:输入流/输出流
从操作内容上来划分:字节流 字符流
操作文件里面的数据:
- 读取文件里面的数据 --->read 输入流
- 将数据写入文件 –>write 输出流
1.字节流
计算机里面所有文件内存存储都是以字节的形式进行存储,也就是二进制文件。因此字节流就是万能流,可以操作计算机里面任意类型的文件
1.1 字节输入流InputStream
InputStream
是一个抽象类,常用子类:
FileInputStream();//文件字节输入流
BufferedInputStream();//高效字节输入流
DataInputStream();//数据输入流
ObjectInputStream();//对象输入流
InputStream
里面的方法:
abstract int read()
int read(byte[] bytes); 读取字节数组长度的字节内容
FileInputStream 效率低
FileInputStream(File file)
FileInputStream(String name)
read(); 读取一个字节内容
private static void demo1() {
//读取指定文件数据:文件必须存在
String filePath="1129\\1129.iml";
//创建字节输入流对象:
InputStream inputStream=null;
try {
inputStream=new FileInputStream(filePath);
//读取文件数据
int len;
while ((len=inputStream.read())!=-1){
System.out.print((char) len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//但是上面大部分代码都是用于处理异常,我们换下面的方式:
private static void demo2() {
//jdk1.7之后提供了一种更加优雅的方式释放资源(自动释放资源) try...with...resource
try (
//创建的对象(必须实现Closeable接口)
InputStream stream = new FileInputStream("1129\\1129.iml");
) {
//读取数据
int read;
while ((read = stream.read()) != -1) {
System.out.print((char) read);
}
} catch (IOException e) {
e.printStackTrace();
}
}
read(byte[] bytes); 读取字节数组长度的字节内容
//让他来读取给定长度(一般是1024的整数倍)的字节内容,读取的内容会放到该数组里面,想看数据的话得看读取的字节数组
private static void demo3() {
try(
InputStream stream=new FileInputStream("1129\\src\\exercise.java");
){
byte[] bytes = new byte[10];
//这里我给了10,如果文件里面的字节小于10,读取字节数也会小于10
// 文件长度超过10,也会只读10个
System.out.println(stream.read(bytes));
System.out.println(new String(bytes));
//将字节数组转字符串输出,如果是中文,有可能会出现乱码:import jav
System.out.println(stream.read(bytes));
//该字节数组已经装满了,如果再去读byte.length长度个,读取内容会覆盖原先的字节数组
}catch (IOException e){
e.printStackTrace();
}
}
read(byte[] bytes,int startIndex,int lenth) 从起始位置读取数组长度的内容,读取指定字节长度
private static void demo4() {
try(
InputStream stream=new FileInputStream("1129\\src\\exercise.java");
){
byte[] bytes=new byte[1024];
stream.read(bytes,0,1024);
System.out.println(new String(bytes));
}catch (IOException e){
e.printStackTrace();
}
}
1.2.字节输出流
OutputStream
:将数据内容写入文件中 也就是write,常用子类
:
FileOutputStream();//文件字节输出流
BufferedOutputStream();//高效字节输出流
DataOutputStream();//数据输出流
ObjectOutputStream();//对象输出流
outputstream
的构造:
FileOutputStream(File file)
FileOutputStream(File file, boolean append)//给定是拼接原文件还是覆盖源文件,默认覆盖
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
FileOutputStream 效率低
private static void demo5() {
try (
//文件可以不存在,构造方法里面可以加一个布尔来判断是覆盖原文件还是拼接原文件
OutputStream stream = new FileOutputStream("1129\\src\\a.txt");
) {
stream.write(65);
stream.write(49);
stream.write(52);
stream.write("abdcfe".getBytes());
stream.write('\n');
stream.write("学习使我快乐!".getBytes());//给汉字的时候注意编码格式
} catch (IOException e) {
e.printStackTrace();
}
}
模拟用户上传头像
private static void demo6() {
File filePath = new File("E:/肖战.jpg");
File filePath1 = new File("D:/肖战.jpg");
String targetPath = "1129\\src\\image\\" + LocalDate.now().toString();
try (
InputStream inputStream = new FileInputStream(filePath1);
OutputStream outputStream =
new FileOutputStream(targetPath + UUID.randomUUID());
//由于图片名称可能会相同,下载路径一致的时候可能会被覆盖,这里我们用UUID的随机数字符来拼接
) {
int len;
while ((len = inputStream.read()) != -1) {
outputStream.write(len);
}
System.out.println(targetPath);
} catch (IOException e) {
e.printStackTrace();
}
}
//读取大文件的时候,这种读取速度是很慢的:
private static void demo7() {
String filePath="E:\\第一阶段课堂笔记(JavaSE).nyf";
String targetPath = "1129\\src" + LocalDate.now().toString();
try(
InputStream inputStream = new FileInputStream(filePath);
OutputStream outputStream = new FileOutputStream(targetPath + UUID.randomUUID());
) {
int len;
while ((len=inputStream.read())!=-1){
outputStream.write(len);
}
}catch (IOException e){
e.printStackTrace();
}
}
//读取速度很慢,我等了一分钟也没读完
但是上面的读写速度是比较慢的,如果需要传大文件的时候,一个读一个写,这样的速度是很慢的,因此我们可以用带参的write(byte[] bytes)
来加快写入文件的速度:
private static void upLoadFile(String sourceFilePath) {
Objects.requireNonNull(sourceFilePath);
File target = new File(TARGET_PATH, LocalDate.now().toString());
if (!target.exists()) {
target.mkdirs();//判断文件目录是否存在,不存在去创建
}
String filename=UUID.randomUUID().toString()+
sourceFilePath.substring(sourceFilePath.lastIndexOf(File.separator)+1);
File targetPath=new File(target,filename);//创建目标文件路径和目标文件名
try (
InputStream inputStream = new FileInputStream(sourceFilePath);
OutputStream outputStream = new FileOutputStream(targetPath);
) {
int len;
byte[] bytes = new byte[1024 * 100];//一次写入这样多的字节
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);//如果不加这一行最后会多读取1024个字节
}
System.out.println("文件上传成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
上面,file来操作文件夹,而IO来操作文件数据
高效字节流
BufferedInputStream:高效字节输入流 read
BufferedOutputStream:高效字节输出流 write
底层自动提供了字节数组来缓冲,默认长度为8192
private static void demo1() {
try{
BufferedOutputStream stream=new BufferedOutputStream(new FileOutputStream("day1202\\src\\a.txt"));
stream.write(78);
stream.write("hello".getBytes());
//写入的数据都放在缓存区,因为此时的文件不满8192的长度,需要释放资源,或者刷新
//stream.flush();
stream.close();//底层自动调用flush()
}catch (IOException e){
e.printStackTrace();
}
}
若用该方法进行io,并且在代码里面又加了一个临时缓冲区,效率会更快,两个缓存区一起使 ,因此推荐使用自己写一个缓冲区,然后再与BufferedOutputStream
来一起使用 ,效率会很快。
2.字符流
reader
:字符输入流
writer
:字符输入流
字符流不能操作其他的二进制文件,主要用于操作纯文本文件(txt、java、html.etc) ,对于有样式的文本文件,后期会用POI来进行操作。底层:字节流+字符集
,它可以写入一串
public void write(String str, int off, int len) throws IOException {
se.write(str, off, len);
}
reader常用子类:
BufferedReader
FileReader
InputStreamReader
writer常用子类:
BufferedWriter
FileWriter
OutputStreamWriter
用法跟字节流差不多,直接拿来用:
上传文件:
private static void demo2() {
String targetPath="day1202\\src";
File filePath=new File(targetPath,LocalDate.now().toString());
if (!filePath.exists()) {
System.out.println("目标路径目录不存在,已为您创建目录");
filePath.mkdirs();
}
String path= "day1202\\src\\a.txt";
File sourcePath=new File(path);
String name=path.substring(path.lastIndexOf('\\')+1);
File targetFile=new File(filePath,name);//得到文件(文件名+文件类型)
try (
Reader reader = new FileReader(sourcePath);
Writer writer=new FileWriter(targetFile)//参数只能是文件,不能是文件夹
) {
int read;
while ((read = reader.read())!=-1){
writer.write(read);
System.out.println("上传成功");
}
} catch (IOException e) {
e.printStackTrace();
}
}
但是它用来操作其他文件的话得到的是一个破损文件,是打不开的,只能操作文本文件
高效字符流
装饰了基本字符流的读写功能,底层自带缓冲(带一个长度为8192的字符数组) ,他里面有一个方法:
String readLine() //一次读取一行
标签:IO,字节,stream,read,write,File,new
From: https://www.cnblogs.com/Liku-java/p/16945944.html