IO流
概述:
IO流用来处理设备之间的数据传输,java中对数据的操作是通过流的方式,java用于操作流的对象都在io流包中,(java.io)
分类
按照数据流向,站在内存角度:
- 输入流:从硬盘中读入数据。
- 输出流:给硬盘中写入数据。
按照数据类型:
字节流:可以读写任何类型的文件,比如:音频,视频,文本文件。文件夹不行
字节输入流 InputStream 读
字节输出流 OutputStream 写
字符流:只能读写文本文件。
字符输入流 Reader 读
字符输出流 Writer 写
如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流,其他就用字节流。如果什么都不知道,就用字节流。一切文件数据(文本,图片,视频等)在存储时,都是以二进制数字的形式保存,都有一个一个的字节,传输的时候也是这样,所以字节流可以传输任意文件数据。无论使用怎样的流对象,底层传输的始终为二进制数据
io流的基类
字节流的抽象基类;
InputStream,OutputStream
字符流的抽象基类:
Reader,Writer.
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
例如:InputStream的子类;FileInputStream
Reader的子类FileReader
java.io.OutputStream `抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。
字节流优先于字符流,所以先使用字节流。写数据的时候使用OutputStream,但是这个是一个抽象类,我们不能对其直接进行实例化,可以选择使用子类对其进行实例化,现在操作的是文件,所以采用FileOutputStream。
FileOutputStream写出数据
构造方法
FileOutputStream(File file)
FileOutputStream(String name)
创建字节输出流对象做了几件事:
- 调用系统资源创建a.txt文件
- 创建了一个fos对象
- 把fos对象指向这个文件
为什么一定要close()?
- 通知系统释放关于管理a.txt文件的资源。
- 让io流对象变成垃圾,等待垃圾回收器对其回收。
FileOutputStream的三个write()方法
public void write(int b):写一个字节 超过一个字节 砍掉前面的字节
public void write(byte[] b):写一个字节数组
public void write(byte[] b,int off,int len):写一个字节数组的一部分
FileOutputStream写出数据如何实现数据的换行
windows下的换行符是 \r\n
Linux \n
Mac \r
package com.itheima.demo18;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test1 {
public static void main(String[] args) throws IOException {
FileOutputStream out = new FileOutputStream(new File("a.txt"),true);//加true实现数据的追加写入,false就是默认覆盖
byte[] bytes = "张爱玲说过,我们要好好的爱惜自己的羽毛".getBytes();
out.write(bytes);
out.flush();
out.close();//流使用完毕,记得要关闭
}
}
FileInputStream读取数据一次一个字节
int read():一次读取一个字节
如果没有数据返回的就是-1
字节流复制文本文件
- 创建字节输入流对象
- 频繁的读写操作
- 释放资源
package com.itheima.demo18;
import java.io.*;
public class Test2 {
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("a.txt");
FileOutputStream out = new FileOutputStream("src\\a.txt");
int bye = 0;//定义一个缓冲区,往里面读入数据,随后写入数据
while ((bye = in.read())!=-1){
out.write(bye);
out.flush();
}
out.close();
}
}
BufferedOutputStream写出数据
这是高效字节流
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想,所以提供了字节缓冲区流。
BufferedOutputStream的构造方法
BufferedOutputStream(OutputStream out)这种方式比上述的写入方式要快很多。
BufferedInputStream读取数据
构造方法:BufferedInputStream(InputStream in)
输入流关联的文件如果没有创建出来 关联就会报错。
字符流
字符流出现的原因:由于字节流操作中文不是特别方便,所以java就提供了字符流。
字符流 = 字节流+编码表;
String类中的编码和解码;
编码:就是把字符串转换成字节数组 把看的懂的转换成看不懂的 String—byte[]
public byte[] getBytes();使用平台的默认字符集将此 String编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
public byte[] getBytes(String charsetName) 使用指定的字符集将此String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
解码:把字节数组转换成字符串 把看不懂的转换成看得懂的 byte[]-------string
public String(byte[] bytes):通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。
public String(byte[] bytes, String charsetName) 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。
使用什么字符集编码就使用什么字符集进行解码。默认的字符集是GBK的
String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组
byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组
OutputStreamWriter的使用
OutputStreamWriter:是字符流通向字节流的桥梁,可使用指定的 码表 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
OutputStreamWriter(OutputStream out):根据默认编码(GBK)把字节流的数据转换为字符流
OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
字符流的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) 写一个字符串的一部分
转换流InputStreamReader的使用
InputStreamReader(InputStream is):用默认的编码(GBK)读取数据
InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
字符流的两种读数据的方式
public int read() 一次读取一个字符,如果没有读到 返回-1
public int read(char[] cbuf) 一次读取一个字符数组 如果没有读到 返回-1
字符流复制文本文件
-
```
package com.itheima.demo18;import java.io.*;
public class Test5 {
public static void main(String[] args) throws IOException {
InputStreamReader reader = new InputStreamReader(new FileInputStream(“xiyouji”));
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(“C:\Users\Administrator\Desktop\xiyouji.txt”));
char[] chars = new char[100];
int len = 0;
while((len = reader.read(chars))!=-1){
writer.write(chars,0,len);
writer.flush();
}
reader.close();
writer.close();
}
}
FileWriter和FileReader复制文本文件
转换流的名字比较长,并且常见的操作是按照本地默认编码实现的,所以为了简化书写,转换流提供了对应的子类。FileWriter,FileReader
高效的字符流
高效的字符输出流: BufferedWriter
构造方法: public BufferedWriter(Writer w)
高效的字符输入流: BufferedReader
构造方法: public BufferedReader(Reader e)
字符缓冲流的特有功能
BufferedWriter: public void newLine():根据系统来决定换行符 具有系统兼容性的换行符
BufferedReader: public String readLine():一次读取一行数据 是以换行符为标记的 读到换行符就换行 没读到数据返回null,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
/*从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历集合
分析:
* a: 创建高效的字符输入流对象
* b: 创建一个集合对象
* c: 读取数据(一次读取一行)
* d: 把读取到的数据添加到集合中
* e: 遍历集合
* f: 释放资源
*/
package com.itheima.demo18;
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class Test7 {
public static void main(String[] args) throws IOException {
ArrayList<String> list = new ArrayList<>();
list.add("张无忌");
list.add("赵敏");
list.add("周芷若");
list.add("小昭");
list.add("殷素素");
list.add("金毛狮王");
BufferedWriter writer = new BufferedWriter(new FileWriter("yitian.txt"));
for (String s : list) {
writer.write(s);
writer.newLine();
writer.flush();
}
writer.close();
}
}
/*我有一个文本文件,每一行是一个学生的名字,请写一个程序,每次允许随机获取一个学生名称
* 分析:
* a: 创建一个高效的字符输入流对象
* b: 创建集合对象
* c: 读取数据,把数据存储到集合中
* d: 产生一个随机数,这个随机数的范围是 0 - 集合的长度 . 作为: 集合的随机索引
* e: 根据索引获取指定的元素
* f: 输出
* g: 释放资源
*/
package com.itheima.demo18;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
public class Test8 {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader("yitian.txt"));
ArrayList<String> list = new ArrayList<>();
while (true){
String name = reader.readLine();
if(name!=null){
list.add(name);
}else{
break;
}
}
Random r = new Random();
int i = r.nextInt(list.size());//返回一个伪随机数,它是取自此随机数生成器序列的、在 0(包括)和指定值(不包括)之间均匀分布的 int 值。
System.out.println(i);
String s = list.get(i);
System.out.println(s);
}
}
package com.itheima.demo18;
import java.io.*;
public class Test9 {
public static void main(String[] args) throws IOException {
File a = new File("C:\\Users\\Administrator\\Desktop\\快速排序");
File b = new File("E:\\快速排序");
digui(a, b);
System.out.println("复制成功");
System.out.println("后缀更改成功");
}
private static void digui(File a, File b) throws IOException {
File[] listFiles = a.listFiles();
for (File file : listFiles) {
if (file.exists() && file.isDirectory()) {
File file1 = new File(b, file.getName());
file1.mkdirs();
digui(file, file1);
} else if (file.isFile()) {
File file1 = new File(b, file.getName());
file1.createNewFile();
copy(file, file1);
if (file1.getName().endsWith(".txt")) {
String path = file1.getAbsolutePath();
int i = path.lastIndexOf(".");
String s = path.substring(0, i);
File file2 = new File(s + ".mp3");//截取出来采用拼串的办法
file1.renameTo(file2);
}
}
}
}
private static void copy(File file, File file1) throws IOException {
FileInputStream in = new FileInputStream(file);
FileOutputStream out = new FileOutputStream(file1);
byte[] bytes = new byte[1024 * 8];
int len = 0;
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
out.flush();
}
in.close();
out.close();
}
}
package com.itheima.demo18;
import javax.swing.plaf.synth.SynthUI;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Comparator;
import java.util.Scanner;
import java.util.TreeSet;
public class Test10 {
public static void main(String[] args) throws IOException {
/*需求:键盘录入3个学生信息(姓名,语文成绩(chineseScore),数学成绩(mathScore),英语成绩(englishScore)),按照总分从高到低存入文本文件
- 分析:
- a: 创建一个学生类: 姓名,语文成绩(chineseScore),数学成绩(mathScore),英语成绩(englishScore)
- b: 因为要排序,所以需要选择TreeSet进行存储学生对象
- c: 键盘录入学生信息,把学生信息封装成一个学生对象,在把学生对象添加到集合中
- d: 创建一个高效的字符输出流对象
- e: 遍历集合,把学生的信息写入到指定的文本文件中
- f: 释放资源*/
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.sum() - s2.sum();
int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;
int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;
int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;
return num4;
}
});
System.out.println("开始录入学生信息");
for (int i = 1; i <= 3; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第" + i + "个学生的姓名");
String name = sc.nextLine();
System.out.println("请输入第" + i + "个学生的语文成绩");
String chinense = sc.nextLine();
System.out.println("请输入第" + i + "个学生的数学成绩");
String math = sc.nextLine();
System.out.println("请输入第" + i + "个学生的英语");
String english = sc.nextLine();
Student st = new Student();
st.setName(name);
st.setChinese(Integer.parseInt(chinense));
st.setMath(Integer.parseInt(math));
st.setEnglish(Integer.parseInt(english));
treeSet.add(st);
}
BufferedWriter writer = new BufferedWriter(new FileWriter("student.txt"));
writer.write("学生成绩记录");
writer.newLine();
writer.flush();
writer.write("姓名"+"\t"+"语文成绩"+"\t"+"数学成绩"+"\t"+"英语成绩"+"\t"+"总成绩");
writer.newLine();
writer.flush();
for (Student student : treeSet) {
StringBuilder sb = new StringBuilder();
sb.append(student.getName()+"\t\t").append(student.getChinese()+"\t\t").append(student.getMath()+"\t\t").append(student.getEnglish()+"\t\t").append(student.sum());
writer.write(sb.toString());
writer.newLine();
writer.flush();
}
writer.close();
System.out.println("成绩存储完毕");
}
}
package com.itheima.demo1;
import java.io.*;
import java.util.ArrayList;
//给了一个文本文件是GBK编码。你把这个文件中的4句,复制到另外一个文本文件,这个文件的编码是UTF-8,而且四句诗要反转。
public class Test4 {
public static void main(String[] args) throws IOException {
InputStreamReader in = new InputStreamReader(new FileInputStream("诗.txt"), "GBK");
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("1新诗.txt"), "UTF-8");
char[] chars = new char[100];
int len = 0;
while ((len = in.read(chars)) != -1) {
out.write(chars, 0, len);
out.flush();
}
in.close();
out.close();
reverse();
}
private static void reverse() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("1新诗.txt"));
ArrayList<String> arrayList = new ArrayList<>();
String line;
while ((line = br.readLine()) != null) {
arrayList.add(line);
}
br.close();
BufferedWriter bw = new BufferedWriter(new FileWriter("1新诗.txt"));
for (int i = arrayList.size() - 1; i >= 0; i--) {
bw.write(arrayList.get(i));
bw.newLine();
}
bw.close();
}
}