(由于I/O流东西较多,我们只说明一些常用的知识)
I/O流:
分类: 字节输入流,字节输出流,字符输入流,字符输出流
前置知识:
创建file类的对象:
package d1_file;
import java.io.File;
public class FileTest1 {
public static void main(String[] args) {
// 1、创建一个File对象,代表具体文档的方案
//
//File f1 = new File("C:\\Users\\24787\\Desktop\\12.txt");
//File f1 = new File("C:/Users/24787/Desktop/12.txt");
File f1 = new File("C:"+ File.separator +"Users"+ File.separator +"24787"+ File.separator +"Desktop"+ File.separator +"12.txt");
f1.length();//文件大小
System.out.println(f1.length());
File f2 = new File("E:\\java");
System.out.println(f2.length());
//注意:File对象可以指向一个不存在的文件路径
File f3 = new File("E:/jjjj");
System.out.println(f3.length());
System.out.println(f3.exists());//false
//定位的文件是在模块中,该怎么定位
//绝对路径
//File f4 = new File("E:\\java\\hight\\untitled6\\untitled6.iml");
//使用相对路径(重点),不用盘符,默认是直接去工程下寻找文件的
File f4 = new File("untitled6\\untitled6.iml");
System.out.println(f4.length());
}
}
注意:File对象既可以代表文件,也可以代表文件夹。
File封装的对象仅仅是一个路径名,这个路径可以是存在的,也可以是不存在的。
绝对路径,相对路径的区别:
绝对路径:从盘符开始:
File file = new File("E:\\java\\01.txt");
相对路径:不带盘符:
File file = new File("模块名字\\01.txt")
file提供的判断文件类型,获取文件信息的功能:
package d1_file;
import java.io.File;
import java.text.SimpleDateFormat;
public class FileTest2 {
public static void main(String[] args) {
//1、创建文件对象,指定文件对象
File f1 = new File("C:/Users/24787/Desktop/12.txt");
//判断当前文件对象,对应的文件路径是否存在,若存在返回true
System.out.println(f1.exists());
//判断当前文件对象指定的是否是文件,是文件返回true,反之
System.out.println(f1.isFile());
//判断当前文件对象指代的是否是文件夹,是文件夹返回true,反之
System.out.println(f1.isDirectory());
//获取文件的名称
System.out.println(f1.getName());
//获取文件的大小,返回字节数
System.out.println(f1.length());
//获取文件的最后修改时间
long time = f1.lastModified();
System.out.println(f1.lastModified());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(time));
//获取创建文件对象时,使用的路径
System.out.println(f1.getPath());
//获取绝对路径
System.out.println(f1.getAbsoluteFile());
}
}
file文件创建文件夹和删除文件夹的功能
创建文件夹:
删除文件夹:
注意:delete方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站
file类提供的遍历文件夹的功能:
使用listFiles方法时的注意事项:
1、当主调是文件,或者路径不存在时,返回null
2、当主调时空文件夹时,返回一个长度为0的数组
3、当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
4、当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在FIle数组中返回,包含隐藏文件
5、当主调是一个文件夹,但是没有权限访问该文件夹时,返回null
字符集:重点
ACSCLL字符集:只有英文,数字,符号等,占一个字节。
GBK字符集:汉字占两个字节,英文数字,占一个字节。
UTF-8字符集:汉字占三个字节,英文,数字占一个字节。
注意:字符编码时使用的字符集,和解码时使用的字符集必须一致,否则会出现乱码,英文,数字,一般不会出现乱码,因为很多字符集都兼容了ASCLL编码
Java代码完成对字符的编码:
Java代码完成对字符的解码:
那么从这里我们就正式开始对I/O流的认识!!!!!
字节输入流:
作用:用于读取二进制数据,如图像,音频,视频文件等。
主要类:
nputStream是所有字节输入流的超类。
常用实现类:
FileInputStream:从文件中读取数据。
ByteArrayInputStream:从字节数组中读取数据。
BufferedInputStream:从缓冲区中读取数据,增强读取效率。
FileInputStream:
package d3_byte_stream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class FileInputStreamTest1 {
public static void main(String[] args) throws Exception {
//创建文件字节输入流管道,与原文件接通
//InputStream is = new FileInputStream(new File("java\\hight\\untitled6\\src\\01.txt"));
//简化写法,推荐使用
InputStream is = new FileInputStream(("untitled6\\src\\01.txt"));
//开始读取文件的字节数据
// int b1 = is.read();
// System.out.println((char)b1);
//
// int b2 = is.read();
// System.out.println((char)b2);
//
// int b3 = is.read();
// System.out.println(b3);
//使用循环改善上述代码
int b;//用于记住读取的字节
while ((b = is.read()) != -1){
System.out.print((char) b);
}
//读取数据的性能很差!
//读取汉字输出会是乱码!!!其无法避免!!!
//流使用完后之后必须关闭!释放系统资源
is.close();
}
}
注意:使用FileInputStream每次都取一个字节的时候,读取性能较差;读取多个字节的时候,性能得到提升,但是两者读取汉字都会出现汉字。
异常处理:
try-catch-finally
try-catch-resource
字节输出流:
作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去
主要类
OutputStream:是所有字节输出流的超类:
实现类
FileOutputStream:用于将数据写入文件。
BufferedOutputStream:装饰类,包装OutputStream对象,并提供了缓冲区来提高写入的性能
DataOutputStream:数据输出流,它可以将Java基本的数据类型,转化为字节流,并将这些字节写入底层的OutputStream。
package d3_byte_stream;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class FileOutputStreamTest4 {
public static void main(String[] args) throws Exception {
//创建一个自己输出流管道与目标文件接通
//覆盖之前文件中的内容
//OutputStream os = new FileOutputStream("untitled6/src/04.txt");
//追加数据的,不覆盖源文件
OutputStream os = new FileOutputStream("untitled6/src/04.txt", true);
//开始写字节数据出去
os.write(97);
os.write('b');
// os.write('赵');
byte[] bytes = "我找不到工作\r\n".getBytes();
os.write(bytes);
os.write(bytes, 0,18);
//换行符
// \r\n
os.close();
}
}
字节流适合做一切文件的复制操作:任何文件的底层都是字节,字节流做复制,是一字不漏地转移玩全部字节,只要复制后的文件格式一致就没有问题!
字符输入流:
作用:以内存为基准,把内存中的数据以字符的形式读到内存中去。
主要类
Reader:是所有字符输入流的抽象基类。
实现类
FileReader:用于文件中读取字符数据的字符输出流实现类。
BufferedReader:具有缓冲功能的字符输入流实现类,可以提高从文件读取数据的性能。
InputStreamReader:将字节输入流转换为字符输入流的桥梁类,可以指定字符编码。
StringReader:从字符串读取字符数据的字符输入流实现类。
CharArrayReader:从字符数组读取祖父数据输入流实现类。
package d5_char_Stream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
public class FileReaderTest01 {
public static void main(String[] args) {
try (//创建一个文件字符输入六管道与源文件接通
Reader fr = new FileReader("untitled6\\src\\05.txt");
){
//读取文本文件的内容
// int c;//记住每次读取的编号
// while((c = fr.read()) != -1){
// System.out.print((char) c);
// }
//每次读取多个字符
char[] buffer = new char[3];
int len;//记录每次读取多少个字符
while((len = fr.read(buffer)) != -1){
System.out.print(new String(buffer,0,len));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符输出流:
作用:以内存为基准,可以把文件中的数据以字符的形式写出到内存中去。
主要类
write:是所有字符输出流的抽象基类。
实现类
FileWriter:用于将字符数据写到文件中的字符输出流实现类。
BufferedWriter:具有缓冲功能的字符输出流实现类,可以提高写入文件的性能。
OutputStreamWriter:将字符输出流转换为字节输出流的桥梁类,可以指定字符编码。
PrintWriter:用于格式化输出字符数据的字符输出流实现类,提供了便捷的写入方法。
package d5_char_Stream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class FileWriterTest02 {
public static void main(String[] args) {
try (
//创建一个文件的字符输出流管道与目标文件接通
//Writer fw = new FileWriter("untitled6\\src\\06.txt");
Writer fw = new FileWriter("untitled6\\src\\06.txt",true);
){
//写一个字符出去
fw.write('a');
fw.write(97);
fw.write('赵');
//写一个字符串出去
fw.write("找不到工作");
fw.write("\r\n");
//写字符串的一部分出去
fw.write("找不到工作",0,3);
fw.write("\r\n");
//写一个字符数组出去
char[] buffer = {'赵','不','到','g','z'};
fw.write(buffer);
fw.write("\r\n");
//写字符数组的一部分出去
fw.write(buffer,0,3);
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符输出流使用时的注意事项:
字符输出流写出数据后必须刷新流,或者关闭流,写出去的数据才能生效
package d5_char_Stream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class FileWriterTest03 {
public static void main(String[] args) throws Exception {
Writer fw = new FileWriter("untitled6\\src\\07.txt");
fw.write('a');
fw.write('b');
fw.write('c');
fw.write('d');
fw.write("\r\n");
fw.write("我的大中国");
fw.write("\r\n");
fw.write("找不到工作");
fw.write("\r\n");
fw.close();//关闭流,自带刷新流,且后续刷新流不可用。
//fw.flush();//刷新流
}
}
字节流、字符流的使用场景小结:
1、字节流适合做一切文件数据的拷贝(音频,视频,文本);字节流不适合读取中文内容的输出。
2、字符流适合做文件文件的操作(读,写)。
字节缓冲流:
作用:提高字节流读写数据的性能
原理:在内存中创建一个缓冲区(通常是一个字节数组),用来暂时存储数据。当数据被写 入缓冲流时,实际上是将数据先写入到内存缓冲区中,而不是直接写入到目标设备。
package d6_buffered_stream;
import java.io.*;
public class BufferedInputStreamTest1 {
public static void main(String[] args) {
try (
InputStream is = new FileInputStream("untitled6\\src\\01.txt");
//定义一个自己缓冲输入流包装原始字节输入流
InputStream bis = new BufferedInputStream(is);
OutputStream os = new FileOutputStream("untitled6\\src\\01_Test.txt");
//定义一个字节缓冲输出流包装原始的字节输出流
OutputStream bos = new BufferedOutputStream(os);
){
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
System.out.println("复制完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符缓冲流:
缓冲输入流:
作用:提高字符输入流读取字符数据的性能
按照行读取字符:
缓冲输出流:
作用:提高字符输出流写字符数据的性能。
换行:
package d6_buffered_stream;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class BuferedWriterTest3 {
public static void main(String[] args) {
try (
Writer fw = new FileWriter("untitled6\\src\\07_Test.txt",true);
//创建一个字符缓冲流输出管道包装原始的字符输出流
BufferedWriter bw = new BufferedWriter(fw);
){
bw.write('a');
bw.write(97);
bw.write('赵');
bw.newLine();
bw.write("我找不到工作abc");
bw.newLine();
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符输入转换流:
作用:解决不同编码时,字符流读取文本内容乱码的问题。
解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流的字符就不会乱码了
package d7_transform_stream;
import java.io.*;
public class InputStreamReaderTest2 {
public static void main(String[] args) {
try (
//得到文件的原始字节流
InputStream is = new FileInputStream("untitled6\\src\\02.txt");
//把原始字节输入流按照指定的字符编码转换成字符输入流
Reader isr = new InputStreamReader(is );
//把字符输入流包装成缓冲字符输入流
BufferedReader br = new BufferedReader(isr);
){
String line;
while((line =br.readLine()) != null){
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
字符输出转换流:
作用:可以控制写出取得字符使用什么字符集编码。
解决思路:获取字节输出流,再按照指定的字符集编码将其转换成字符输出流,以后写出的字符就会用该字符集编码了。
package d7_transform_stream;
import java.io.*;
public class OutputStreamWriterTest2 {
public static void main(String[] args) {
try (
//创建一个文件字节输出流
OutputStream os = new FileOutputStream("untitled6\\src\\08.txt");
//把原始的字节输出流,按照值得字符集编码转换成字符输出流的转换流。
Writer osw = new OutputStreamWriter(os,"GBK");
//把字符输出流包装成缓冲字符输出流
BufferedWriter bw = new BufferedWriter(osw);
){
bw.write("找不到工作");
bw.write("的人是我");
} catch (Exception e) {
e.printStackTrace();
}
}
}
打印流:
作用:打印流可以实现更方便,更高效的打印数据出去,能实现打印什么出去就是什么。
PrintStream提供的打印数据的方案:
PrintWriter提供的打印数据的方案:
PrintStream和printWriter的区别:
1、打印数据的功能是一模一样:都是使用方便,性能高效。
2、PrintStream继承自字节输出流OutputStream,因此支持写字节数据的方法。
3、PrintWriter继承自字符输出流Writer,因此支持写字符数据出去。
数据输出流:
DataOutputStream(数据输出流)
允许数据和其类型一并写出去。
package d9_data_stream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class DataOutputStreamTest1 {
public static void main(String[] args) {
try(
//1、创建一个数据输出流包装低级的字节输出流
DataOutputStream dos= new DataOutputStream(new FileOutputStream("untitled6/src/10.txt"));
) {
dos.writeInt(97);
dos.writeDouble(99.9);
dos.writeBoolean(true);
dos.writeUTF("找不到工作666");
} catch (Exception e) {
e.printStackTrace();
}
}
}
数据输入流:
DataInputStream(数据输入流)
用于读取数据输出流写出去的数据
package d9_data_stream;
import java.io.DataInputStream;
import java.io.FileInputStream;
public class DataInputStreamTested {
public static void main(String[] args) {
try (
DataInputStream dis =
new DataInputStream(new FileInputStream("untitled6\\src\\10.txt"));
){
int i = dis.readInt();
System.out.println(i);
double d = dis.readDouble();
System.out.println(d);
boolean b = dis.readBoolean();
System.out.println(b);
String s = dis.readUTF();
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
对象字节输出流:
ObjectOutputStream(对象字节输出流):
可以把Java对象进行序列化:把Java对象存入到文件中去
注意:对象如果要参与序列话,必须实现序列化接口
package d10_object_stream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Test1ObjectOutputStream {
public static void main(String[] args) {
try (
//创建一个对象字节输出流包装原始的字节输出流
ObjectOutputStream oss = new ObjectOutputStream(new FileOutputStream("untitled6/src/11.txt"));
){
//创建一个java对象
User u = new User("hhhh","哇哈哈哈",12,"asdasd12");
//序列化对象到文件中去
oss.writeObject(u);
} catch (Exception e) {
e.printStackTrace();
}
}
}
对象字节输入流:
ObjectInputStrea(对象字节输入流):
可以把Java对象进行反序列化:把存储在文件中的Java对象读入到内存中来。
package d10_object_stream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Test2ObjectInputStream {
public static void main(String[] args) {
try (//创建对象字节输入流管道,包装低级的字节输入流与源文件接通
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("untitled6/src/11.txt"));
){
User u = (User)ois.readObject();
System.out.println(u);
} catch (Exception e) {
e.printStackTrace();
}
}
}
拓展:如果要一次序列化多个对象:用一个ArrayList集合存储多个对象,然后直接对接进行序列化即可。
注意:ArrayList集合已经实行按了序列化接口!