继上一篇文章,我继续分析IO流的学习
3.5字节缓冲流:
概念:
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果。
java本身在设计的时候,也考虑了这样的设计思想,所以提供了字节缓冲区流。
分类:
字节缓冲输出流:BufferedOutputStream
字节缓冲输入流:
BufferedInputStream
构造方法:
public BufferedOutputStream(OutputStream out)
思考:为什么不直接使用文件名,而是使用一个流对象?
原因很简单:字节缓冲流它仅仅提供了缓冲区,实际上读写文件的还是基本流对象。
代码案例:
//缓冲输出流
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
// FileOutputStream fos = new FileOutputStream("1.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("1.txt"));
//写数据
bos.write("hello world".getBytes());
//关闭流
bos.close();
// fos.close();
}
}
//缓冲输入流
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.txt"));
//读取数据
byte [] bytes = new byte[1024];
int len = 0;
while ((len=bis.read(bytes)) != -1){
System.out.println(new String(bytes,0,len));
}
bis.close();
}
}
综合练习:
/**
* 四种读取测试速度:
*/
public class Test {
public static void main(String[] args) throws IOException {
long start =System.currentTimeMillis();
method("1.txt","2.txt");
long end = System.currentTimeMillis();
System.out.println(end-start);
System.out.println("------------------------------");
long start2 =System.currentTimeMillis();
method2("1.txt","2.txt");
long end2 = System.currentTimeMillis();
System.out.println(end2-start2);
System.out.println("-------------------------------");
long start3 =System.currentTimeMillis();
method3(new FileInputStream("1.txt"),new FileOutputStream("2.txt"));
long end3 = System.currentTimeMillis();
System.out.println(end3-start3);
System.out.println("---------------------------------");
long start4 =System.currentTimeMillis();
method4(new FileInputStream("1.txt"),new FileOutputStream("2.txt"));
long end4 = System.currentTimeMillis();
System.out.println(end4-start4);
}
//方法1:
public static void method(String srcString ,String destString ) throws IOException {
FileInputStream fi = new FileInputStream(srcString);
FileOutputStream fo = new FileOutputStream(destString);
int content =0;
while ((content = fi.read())!=-1){
fo.write(content);
}
fi.close();
fo.close();
}
//方法2:
public static void method2(String srcString ,String destString ) throws IOException{
FileInputStream fi = new FileInputStream(srcString);
FileOutputStream fo = new FileOutputStream(destString);
byte [] bytes = new byte[1024];
int len =0;
while ((len =fi.read(bytes))!=-1){
fo.write(bytes,0,len);
}
fi.close();
fo.close();
}
//方法3:
public static void method3(InputStream srcString ,OutputStream destString ) throws IOException{
BufferedInputStream bis = new BufferedInputStream(srcString);
BufferedOutputStream bos = new BufferedOutputStream(destString);
int content = 0;
while ((content = bis.read())!=-1){
bos.write(content);
}
bis.close();
bos.close();
}
//方法4:
public static void method4(InputStream srcString ,OutputStream destString ) throws IOException{
BufferedInputStream bis = new BufferedInputStream(srcString);
BufferedOutputStream bos = new BufferedOutputStream(destString);
byte [] bytes = new byte[1024];
int len =0;
while ((len =bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bis.close();
bos.close();
}
}
3.6转换流
引入:
由于字节流操作中文不是特别方便,所以java就提供了转换流。
字符流=字节流+编码表
概念:
由字符及其对应的数值组成的一张表
常见的编码表:
ASCII 、Unicode 字符集
ISO-8859-1
GB2312 、GBK、GB18030
编码与译码:
编码就是把看的懂的变成看不到的
译码就是把看不懂的变成看的懂的
/**
* 转换流
*/
public class ZhuanHuan {
public static void main(String[] args) throws UnsupportedEncodingException {
String s="我爱编程";
byte [] bytes = s.getBytes();//[-26, -120, -111, -25, -120, -79, -25, -68, -106, -25, -88, -117]
//byte[] bytes = s.getBytes("UTF-8");[-26, -120, -111, -25, -120, -79, -25, -68, -106, -25, -88, -117]
//byte[] bytes = s.getBytes("GBK");[-50, -46, -80, -82, -79, -32, -77, -52]
System.out.println(Arrays.toString(bytes));
//解码
//String ss =new String(bytes,"UTF-8");
String ss =new String(bytes,"GBK");
System.out.println(ss);
}
}
3.7字符输出输入流:
字符输出流:
字符流通向字节流的桥梁:可使用指定的 charset
将要写入流中的字符编码成字节。
public OutputStreamWriter(OutputStream out)//创建使用默认字符编码的 OutputStreamWriter。
public OutputStreamWriter(OutputStream out,String charsetName)//创建使用指定字符集的 OutputStreamWriter。
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("1.txt"));
//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("1.txt"),"UTF-8");
osw.write("我爱编程");
osw.close();
}
}
字符输入流:
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset
读取字节并将其解码为字符
public InputStreamReader(InputStream in)//创建一个使用默认字符集的 InputStreamReader。
public InputStreamReader(InputStream in,String charsetName)//创建使用指定字符集的 InputStreamReader。
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("1.txt"));
//InputStreamReader isr = new InputStreamReader(new FileInputStream("1.txt"),"GBK");
int n=0;
while ((n= isr.read())!=-1){
System.out.print((char)n);
}
isr.close();
}
输出流代码案例:
public class OutputStreamWriterDemo2 {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("1.txt"));
// osw.write(97);
char[] chars = {'我','爱','编','程'};
osw.write(chars,2,2);
//osw.write(chars);
String s="hello world";
osw.write(s,2,3);
//osw.write(s);
osw.close();
}
}
复制文件:
/**
* 字符流复制文件
*/
public class CopyDemo3 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("1.txt");
FileWriter fw = new FileWriter("2.txt");
//方法1:
// int content =0;
// while ((content=fr.read())!=-1){
// fw.write(content);
// }
//方法2:
char [] chars = new char[1024];
int len =0;
while ((len=fr.read(chars))!=-1){
fw.write(chars,0,len);
}
fr.close();
fw.close();
}
}
flush和close区别?
1.flush是刷新缓冲区操作
2.close是关闭流操作,关闭之前为了防止数据丢失,先刷新一次
3.flush之后,我们可以进行流操作,而close之后,就不能继续流操作
问:什么时候使用flush?
一般我们写入大文件时,可以设置写多少数据刷新一下,这样就不会导致内存溢出或者缓慢
简化写法:
FileWrite:字符输出流
FileReader:字符输入流
3.8字符缓冲流:
概念:
BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
BufferedWriter :将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
代码案例:
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("2.txt"));
bw.write("我爱编程");
bw.newLine();//换行
bw.write("我要成为大佬");
bw.close();
}
}
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("2.txt"));
// char [] chars = new char[1024];
// int len =0;
// while ((len=br.read(chars)) !=-1 ){
// System.out.println(new String(chars));
//
// }
String s = br.readLine();//一次输出一行
String s1 = br.readLine();
System.out.println(s);
System.out.println(s1);
br.close();
}
}
复制文件:
/**
* 字符缓冲区复制文件
*/
public class CopyDemo4 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("1.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("2.txt"));
int len =0;
char[] chars = new char[1024];
while ((len = br.read(chars))!=-1){
bw.write(chars,0,len);
bw.flush();
}
br.close();
bw.close();
}
}
特殊方法复制:
/**
* 新方法复制
*/
public class CopyDemo5 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("1.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("2.txt"));
String content = null;
while ((content=br.readLine())!=null){
bw.write(content);
bw.newLine();
bw.flush();
}
br.close();
bw.close();
}
}
总结:
4.1字节流:
字节输入流:InputStream
读取方式:int read():一次读取一个字节
int read(byte[] bytes):一次读取一个字节数组
FileInputStream
字节缓冲输入流:
BufferedInputStream
字节输出流:OutputStream
写出方式:void write(int b):一次写一个字节
void write(byte[] bytes,int i,int len):一次写一个字节数组的指定
FileOutputStream
字节缓冲输出流:
BufferedOutputStream
转换流:
读取:
InputStreamReader(InputStream ip)
写出:
OutputStreamWriter(OutputStream op)
4.2字符流:
字符流=字节流+编码表
字符输入流:FileReader
特殊用法:int readLine():一次读取一行数据
字符输出流:FileWriter
特殊用法:void newLine():添加一个行分隔符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k2JcyJF6-1607230959098)(C:\Users\24582\AppData\Roaming\Typora\typora-user-images\image-20201205160827856.png)]
4.3练习:
练习1:
/**
* 需求:将集合中的内容写到文件中
* 数据源:ArrayList---遍历输出
* 目的地:test.txt---缓冲字符写出
*/
public class WorkDemo {
public static void main(String[] args) throws IOException {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("hello");
arrayList.add("world");
arrayList.add("java");
arrayList.add("Python");
BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
//遍历
for(String s:arrayList){
bw.write(s);
bw.newLine();
bw.flush();
}
//反过来,从文件中读取到集合数组
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
String line=null;
while ((line=br.readLine())!=null){
arrayList.add(line);
}
Iterator<String> iterator = arrayList.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
br.close();
bw.close();
}
}
练习2:
/**
* 随机点名:
* 1.从文件中读取出这些名字放入集合
* 2.随机产生一个随机数(索引)
* 3.根据索引取值
*/
public class WorkDemo2 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("name.txt"));
ArrayList<String> arrayList = new ArrayList<>();
String line =null;
while ((line =br.readLine())!=null){
arrayList.add(line);
}
//产生随机数:(0-6)
int luckNum =(int) (Math.random()*6);
System.out.println(arrayList.get(luckNum));
}
}
练习3:
/**
* 复制单级文件夹:
* 1.包装File对象
* 2.获取该目录下所有文件对象的File数组
* 3.遍历File数组
* 4.创建流对象
* 5.复制
*/
public class WorkDemo3 {
public static void main(String[] args) throws IOException {
File srcFile =new File("D:\\a");
File destFile = new File("D:\\b");
//确保目的地文件夹存在
if(! destFile.exists()){
destFile.mkdir();
}
//获取数据源目录下所有对象
File[] files = srcFile.listFiles();
//遍历:
for(File file:files){
String filename = file.getName();
File newFile = new File(destFile,filename);
copyFile(file,newFile);
}
}
private static void copyFile(File file,File newFile) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
byte [] bytes = new byte[1024];
int len=0;
while ((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bis.close();
bos.close();
}
}
练习4:
/**
* 复制多级文件夹
*/
public class WorkDemo4 {
public static void main(String[] args) throws IOException {
File srcFolder = new File("D:\\a");
File destFolder = new File("D:\\b");
copyMethod(srcFolder,destFolder);
}
private static void copyMethod(File srcFolder,File destFolder) throws IOException {
if(srcFolder.isDirectory()){
File newFolder = new File(destFolder,srcFolder.getName());
newFolder.mkdir();
File [] files= srcFolder.listFiles();
for(File file:files){
copyMethod(file,newFolder);
}
}else {
File newFile = new File(destFolder,srcFolder.getName());
copyFile(srcFolder,newFile);
}
}
private static void copyFile(File file,File newFile) throws IOException{
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
byte [] bytes = new byte[1024];
int len=0;
while ((len=bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bis.close();
bos.close();
}
}
练习5:
/**
* 键盘录入三个学生信息和成绩,姓名,语数英,按成绩从大到小排序
* 分析:
* 1.创建集合,TreeSet<Student>
* 2.用键盘录入对象
* 3.遍历,写入文件中
*/
public class WorkDemo5 {
public static void main(String[] args) throws IOException {
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num =(o2.getMath()+o2.getChinese()+o2.getEnglish())-(o1.getMath()+o1.getChinese()+o1.getEnglish());
int result = num ==0? o1.getName().compareTo(o2.getName()) :num;
return result;
};
});
Scanner input = new Scanner(System.in);
for(int i=0; i<3;i++){
System.out.println("请输入学生信息:");
String name = input.next();
System.out.println("请输入学生数学成绩:");
int math = input.nextInt();
System.out.println("请输入学生英语成绩:");
int english = input.nextInt();
System.out.println("请输入学生语文成绩:");
int chinese = input.nextInt();
Student student = new Student(name,math,english,chinese);
treeSet.add(student);
}
BufferedWriter bw = new BufferedWriter(new FileWriter("Student.txt"));
Iterator<Student> iterator = treeSet.iterator();
while (iterator.hasNext()){
Student next = iterator.next();
StringBuffer stringBuffer =new StringBuffer();
stringBuffer.append(next.getName()+":").append("{").append(next.getMath()+",").append(next.getEnglish()+",").
append(next.getChinese()).append("}");
bw.write(stringBuffer.toString());
bw.newLine();
bw.flush();
}
bw.close();
}
}
标准流:
标准输入流:
/**
* 标准输入流:
* in:
*/
public class SystemDemo {
public static void main(String[] args) throws IOException {
InputStream inputStream= System.in;
// int content =0;
// while ((content=inputStream.read())!=-1){
// System.out.println((char)content);
// }
//包装成字符流:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入:");
String line =br.readLine();
System.out.println(line);
System.out.println("请输入一个整数:");
int num =Integer.parseInt(br.readLine());
System.out.println(num);
}
}
标准输出流:
/**
* 标准输出流:
*/
public class SystemDemo2 {
public static void main(String[] args) {
PrintStream printStream = System.out;
printStream.print('a');
printStream.print(97);
printStream.print("world");
System.out.println();
}
}
序列化与反序列化:
序列化流:
把对象按照流的方式存入到文本文件 或 在网络中传输。 对象—>流数据
反序列化流:
把文本文件 或网络中 的数据 按照流对象 返回。 流数据—>对象
代码:
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
write();
read();
}
//反序列化
private static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
//序列化
private static void write() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
Teacher teacher = new Teacher("tom",20);
oos.writeObject(teacher);
oos.close();
}
}
bw.newLine();
bw.flush();
}
bw.close();
}
}
# 标准流:
#### 标准输入流:
```java
/**
* 标准输入流:
* in:
*/
public class SystemDemo {
public static void main(String[] args) throws IOException {
InputStream inputStream= System.in;
// int content =0;
// while ((content=inputStream.read())!=-1){
// System.out.println((char)content);
// }
//包装成字符流:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入:");
String line =br.readLine();
System.out.println(line);
System.out.println("请输入一个整数:");
int num =Integer.parseInt(br.readLine());
System.out.println(num);
}
}
标准输出流:
/**
* 标准输出流:
*/
public class SystemDemo2 {
public static void main(String[] args) {
PrintStream printStream = System.out;
printStream.print('a');
printStream.print(97);
printStream.print("world");
System.out.println();
}
}
序列化与反序列化:
序列化流:
把对象按照流的方式存入到文本文件 或 在网络中传输。 对象—>流数据
反序列化流:
把文本文件 或网络中 的数据 按照流对象 返回。 流数据—>对象
代码:
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
write();
read();
}
//反序列化
private static void read() throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
//序列化
private static void write() throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
Teacher teacher = new Teacher("tom",20);
oos.writeObject(teacher);
oos.close();
}
}