IO流(字节流 字符流 转化流 字符缓冲流)
(一)IO流(设备中的数据传输)
1.字符流出现的原因;
字符流出现的原因:由于字节流操作中文不是特别方便,所以,java就提供了字符流。
字符流: 字符流 = 字节流 + 编码表
2.我们是从内存的角度看
InputStream输入流 读入数据 硬盘-------------->内存
OutputStream输出流 写书数据 内存--------------->硬盘
3.流的读取类型
字节流 读写任意类型文件
字符流 只能读取文本文件(用记事本打开可以看 不是乱码)
(二)字节流
(1)、FileOutputStream文件输出流
构造方法
没有空参构造
1.FileOutputStream(File file)
输出流,所关联的文件,如果不存在 会自动帮你创建
2.FileOutputStream(String name)
通过文件输出流,往所关联的文件中,写出数据
FileOutputStream(String name ,ture)
创建一个向具有指定 name
的文件中写入数据的输出文件流。
3写数据
write(Int b) 一次写入一个字节。输入Int类型超过一个字节会丢掉多余的字节
方法重载
write(bytes);一次写入一个字节数组
write(bytes,2,2);一次写入一个字节数组的一部分
要写入String类型,利用getBytes()转成数组(一个汉子3个字节)
(3)流使用必须释放资源掉 不释放就会造成资源泄露.close()
(2)FileInputStream文件输入流
1.输入所关联的文件如果不存在,就会报错
2构造方法
FileIntputStream(File file)
FileIntputStream(String string)
read()最后读不到返回-1
int len=in.read( bytes) 一次读取bytes个字节放到缓冲区里面
3.用完close()
4.字节数组到字符串
new String(bytes)
案例 1.我们使用文件的输入输出流复制文件
方式1.读一个字节写一个字节(太慢了)
(需要循环的读写)
public class Demo {
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("a.txt");
FileOutputStream outputStream = new FileOutputStream("D:\\aas.txt");
int len=0;
while ((len=inputStream.read())!=0){
outputStream.write(len);
outputStream.flush();
}
outputStream.close();
inputStream.close();
}
}
方式2.定义一个字节数组,充当缓冲区(数组不能长度无限大会造成堆内存溢出)
public class Demo4 {
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("G:\\20190714-JavaSE-课件\\视频\\1.常用类Math和System和Random的介绍.mp4");
FileOutputStream out = new FileOutputStream("E:\\qq.mp4");
byte[] bytes = new byte[1024*8];
int len=0;
long start=System.currentTimeMillis();
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
out.flush();
}
long end = System.currentTimeMillis();
out.close();
in.close();
System.out.println(end-start+"毫秒");
}
}
(2)流的异常处理
(idea非空快捷键 .nn)
public class Demo6 {
public static void main(String[] args) {
FileInputStream in=null;
FileOutputStream out=null;
try {
in = new FileInputStream("a.txt");
out = new FileOutputStream("a.txt");
byte[] bytes = new byte[1024*8];
int len=0;
while ((len=in.read(bytes))!=-1) {
out.write(bytes,0,len);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
(三)高效的字节输入输出流
1.BufferedInputStream() BufferedOutputStream()
高效的字节输入输出流(底层自带有缓冲区所以高效)通过有参构造也可以自定义缓冲区的大小
public class MyTest {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
// copyFile1();
copyFile2();
long end = System.currentTimeMillis();
System.out.println("耗时"+(end-start)+"毫秒");
}
private static void copyFile2() throws IOException {
FileInputStream in = new FileInputStream("E:\\java.mp3");
FileOutputStream out = new FileOutputStream("E:\\demo2.mp3");
int len = 0;
byte[] bytes = new byte[1024 * 8];
while ((len = in.read(bytes)) != -1) {
out.write(bytes,0,len);
}
in.close();
out.close();
}
private static void copyFile1() throws IOException {
//高效的字节输入输出流
BufferedInputStream bfr = new BufferedInputStream(new FileInputStream("E:\\java.mp3"));
BufferedOutputStream bfw = new BufferedOutputStream(new FileOutputStream("E:\\demo2.mp3"));
//读取一个字节写入一个字节
int len=0;
byte[] bytes = new byte[1024 * 8];
while ((len=bfr.read(bytes))!=-1){
bfw.write(bytes,0,len);
}
bfr.close();
bfw.close();
}
}
(三)字符流
针对文本文件
字符流=字节流+编码表
1、字符流的继承体系
字符输入流Raeder
字符输出流Write
InputStreamReader OutputStreamWriter
BufferInReader BufferOutWriter
字符输出流Write
编码 :把字符串转化成字节数组,看懂到看不懂
byte[] bytes=str.getBytes(); 空参默认码表
可以自定义码表
字符输入流Raeder
解码:把字节数组转化为字符串 ,看不懂到看懂
String s=new String (bytes);空参默认码表
public class Demo1 {
public static void main(String[] args) {
String str="今天晚上老地方见";
// 编码
byte[] bytes = str.getBytes();
System.out.println(bytes);
// 解码
String s = new String(bytes);
System.out.println(s);
}
}
2.转换流OutputStreamWriter
1:OutputStreamWriter的构造方法
OutputStreamWriter(OutputStream out):根据默认编码(GBK)把字节流的数据转换为字符流
OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
-
2.字符流的5种写数据的方式
-
方法概述
public void write(int c) 写一个字符
public void write(char[] cbuf) 写一个字符数组
public void write(char[] cbuf,int off,int len) 写一个字符数组的 一部分
public void write(String str) 写一个字符串
public void write(String str,int off,int len) 写一个字符串的一部分
out.write('你'); //一次写一个字符
out.write("\r\n");
out.write("今天是大暑,注意放暑假降温");//一次写入一个字符串
out.write("\r\n");
out.write("今天是大暑,注意放暑假降温",0,5);//一次写入字符串的一部分
out.write("\r\n");
out.write(new char[]{'a','你','好'});//一次写入一个字符数组
out.write("\r\n");
out.write(new char[]{'a', '你', '好'},1,2);//一次写入一个字符数组的一部分
2转换流InputStreamReader的使用
1:InputStreamReader的构造方法
InputStreamReader(InputStream is):用默认的编码(GBK)读取数据
InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
2:字符流的2种读数据的方式
方法概述
public int read() 一次读取一个字符
public int read(char[] cbuf) 一次读取一个字符数组 如果没有读到 返回-1
char[] chars = new char[1024];//字符数组,充当缓冲区
int len = in.read(chars, 0, 3); //一次读取3个字符,装入缓冲区中
3:字符流复制文本文件
public class Demo8 {
public static void main(String[] args) {
InputStreamReader in = null;
OutputStreamWriter out = null;
try {
in = new InputStreamReader(new FileInputStream("a.txt"));
out = new OutputStreamWriter(new FileOutputStream("demo5.txt"));
char[] chars= new char[1000];
int len=0;
while ((len=in.read(chars))!=-1){
out.write(chars,0,len);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.字符转化流的子类便捷类
字符流便捷类: 因为转换流的名字太长了,并且在一般情况下我们不需要制定字符集,
于是java就给我们提供转换流对应的便捷类
转换流 便捷类
InputStreamReader 子类-------->FileReader
字节流到字符流的桥梁
OutputStreamWriter 子类-------->FileWriter
字符流到字节流的桥梁
(子类唯一缺点不能指定编码类型)子类没有特有的方法
(四)字符缓冲流
1.字符缓冲流的功能
- 高效的字符流
高效的字符输出流: BufferedWriter
构造方法: public BufferedWriter(Writer w)
高效的字符输入流: BufferedReader
构造方法: public BufferedReader(Reader e)
1.字符缓冲流的特殊功能
BufferedWriter: public void newLine():根据系统来决定换行符 具有系统兼容性的换行符
BufferedReader: public String readLine():一次读取一行数据 是以换行符为标记的 读到换行符就换行 没读到数据返回null
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
案例1随机点名
public class Demo12 {
public static void main(String[] args) throws IOException {
ArrayList<String> list = new ArrayList<>();
\\把集合中的数据存储到文本文件
BufferedReader bfr = new BufferedReader(new FileReader("a.txt"));
String line=null;
while ((line=bfr.readLine())!=null){
list.add(line);
}
Random random = new Random();
int i = random.nextInt(list.size());
System.out.println(list.get(i));
}
}
案例2复制多级文件夹并改名
public class MyTest5 {
public static void main(String[] args) throws IOException {
File srcFolder = new File("E:\\测试图片");
File targetFolder = new File("D:\\" + srcFolder.getName().replace("png","jpg"));
if (!targetFolder.exists()) {
targetFolder.mkdirs();
}
copyFolder(srcFolder, targetFolder);
}
private static void copyFolder(File srcFolder, File targetFolder) throws IOException {
//遍历源文件夹
File[] files = srcFolder.listFiles();
for (File f : files) {
if(f.isFile()){
//复制文件到,目标文件夹里面去
copyFiles(f, targetFolder);
}else{
File targetFolder1 = new File("D:\\测试图片\\f\\" + srcFolder.getName().replace("png","jpg"));
if (!targetFolder1.exists()) {
targetFolder1.mkdirs();}
copyFolder(f,targetFolder1);
//递归// //封装源文件夹
// //封装目标文件夹
}
}
}
//复制文件的操作
private static void copyFiles(File f, File targetFolder) throws IOException {
FileInputStream in = new FileInputStream(f); //
File file = new File(targetFolder, f.getName().replace("png","jpg"));
FileOutputStream out = new FileOutputStream(file);
int len=0;
byte[] bytes=new byte[1024*8];
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
}
in.close();
out.close();
}
}
案例3(键盘录入学生信息按照总分排序并写入文本文件
public class Student {
private String name;
private int shuxue;
private int yuweng;
private int yingyu;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", shuxue=" + shuxue +
", yuweng=" + yuweng +
", yingyu=" + yingyu +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getShuxue() {
return shuxue;
}
public void setShuxue(int shuxue) {
this.shuxue = shuxue;
}
public int getYuweng() {
return yuweng;
}
public void setYuweng(int yuweng) {
this.yuweng = yuweng;
}
public int getYingyu() {
return yingyu;
}
public void setYingyu(int yingyu) {
this.yingyu = yingyu;
}
public int all(){
return this.shuxue+this.yingyu+this.yuweng;}
}
public class Demo8 {
public static void main(String[] args) throws IOException {
TreeSet<Student> Stu = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s2.all() - s1.all();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return num2;
}
});
for (int i = 1; i <= 3; i++) {
Student student = new Student();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入" + i + "个学生的姓名");
String name = scanner.nextLine();
student.setName(name);
System.out.println("请输入" + i + "个学生的语文成绩");
int yw = scanner.nextInt();
student.setYuweng(yw);
System.out.println("请输入" + i + "个学生的数学成绩");
int xs = scanner.nextInt();
student.setShuxue(xs);
System.out.println("请输入" + i + "个学生的英语成绩");
int yy = scanner.nextInt();
student.setYingyu(yy);
Stu.add(student);
}
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));
writer.write("编号"+"\t"+"姓名"+"\t"+"数学"+"\t"+"英语"+"\t"+"外语"+"\t"+"总分");
writer.newLine();
writer.flush();
int index=1;
for (Student student : Stu) {
writer.write(index+"\t"+student.getName()+"\t"+student.getShuxue()+"\t"+student.getYingyu()+"\t"+student.getYuweng()+"\t"+student.all());
writer.newLine();
writer.flush();
index++;
}
writer.close();
}
}