Java基础09-IO流
IO流使用总结
- 流对象太多开发时不知应该使用哪个流对象
- 根据四个明确即可确定开发时使用哪个流对象
- 四个明确
- 明确源和目的地
- 源: InputStream Reader
- 目的地:OutputStream Writer
- 明确数据是否是纯文本数据
- 源:是纯文本数据 Reader
- 不是纯文本数据 InputStream
- 目的地:是纯文本数据 Writer
- 不是纯文本数据 OutputStream
- 此时可以明确使用哪个流体系
- 明确具体的设备
- 源设备:
- 键盘:System.in
- 硬盘:File
- 内存:数组
- 网络:Socket流
- 目的地设备:
- 硬盘:File
- 键盘:System.out
- 内存:数组
- 网络:Socket流
- 源设备:
- 是否需要额外的功能:
- 是否需要高效(缓冲区)
- 加Buffered
- 是否需要高效(缓冲区)
- 什么时候使用转换流呢?
- 提高对文本操作的便捷
- 操作文本涉及到指定编码时,必须使用转换流。
- 明确源和目的地
输入输出流(按方向分)
处理数据输入输出流的方式就是IO技术
- IO流用来处理设备之间的数据传输
- Java对数据的操作是通过流的方式
- Java用于操作流的对象都在IO包中
- 流按照操作数据分为两种:字节流与字符流
- 流按流向分为:输入流,输出流
- 读(输入),写(输出)
- 输入流和输出流是相对于内存设备而言。
- 将外设中的数据读取到内存中:输入
- 将内存中的数据写入到外设中:输出。
字节流,字符流(按内容分)
- 国际标准码表Unicode
- GBK和Unicode两张码表的编码方式不一样
- 字符流的由来:字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字,然后再对这个文字进行操作。简单说:字节流+编码表
IO流常用基类
- 字节流的抽象基类:
InputStream 、 OutputStream - 字符流的抽象基类:
Reader 、 Writer - 注:由这四个类派生出来的子类,名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader
Demo,创建文件写入文件内容
需求:将一些文字存储到硬盘一个文件中
记住:如果要操作文字数据,建议优先考虑字符流
要将数据从内存写到硬盘上,要使用字符流中的输出流:Writer
硬盘中的数据基本体现是文件,希望找到一个可以操作文件的Writer(FileWriter)
package com.gaopeng.IO;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) throws IOException {
/*
* 创建一个可以往文件中写入字符数据的字符输出流对象
* 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的地方)
* 如果文件不存在,自动创建文件
* 如果文件存在,则文件会被覆盖
* */
FileWriter file = new FileWriter("demo.txt");
//写入数据
//数据写入到了临时存储缓冲区中
file.write("哈哈");
//刷新该流的缓冲,将数据写入到目标文件中
file.flush();
//关闭流之前会先进行刷新操作
file.close();
}
}
换行和续写
public class Demo02 {
//获取运行系统的换行符
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
FileWriter file = new FileWriter("demo.txt");
file.write("abcwer"+LINE_SEPARATOR+"haha");
file.flush();
file.close();
//对文件进行续写
FileWriter file1 = new FileWriter("demo.txt",true);
file1.write("这是一个续写");
file1.close();
}
}
读取单个字符(效率低)
读取字符到数组(效率高一些)
public class Demo04 {
public static void main(String[] args) throws IOException {
/*
* 1.创建读取字符数据的流对象
* 2.创建流对象时,必须要确定流对象是存在的,
* 3.用一个读取流关联一个已存在文件
* */
FileReader fileReader = new FileReader("demo.txt");
//按单个字符读取文件
// int chr=0;
// while((chr=fileReader.read())!=-1){
// System.out.println((char)chr);
// }
//读取字符到数组,单个的从硬盘中取字符,一个一个的存到数组中
//一般给予数组空间的大小位1024的整数被,1024个字节为1k
char[] chr2 = new char[1024];
int num=0;
while((num=fileReader.read(chr2))!=-1){
System.out.println(new String(chr2,0,num));
}
//关闭流
fileReader.close();
}
}
复制文件的操作
package com.gaopeng.IO;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo05 {
public static void main(String[] args) throws IOException {
//需求:复制文件
//1.读取源数据 2.写入目的地文件 3.关闭流
FileReader fileReader = new FileReader("demo.txt");
FileWriter fileWriter = new FileWriter("demo01.txt");
//创建临时容器存储字符
char[] temp=new char[1024];
//创建变量存储,读取到的字符个数
int num=0;
while ((num=fileReader.read(temp))!=-1){
fileWriter.write(temp,0,num);
}
fileReader.close();
fileWriter.close();
}
}
字符流缓冲区
- 缓冲区的出现提高了对数据的读写效率
- 对应类
- BufferedWriter
- BufferedReader
- 缓冲区要结合流才可以使用
- 在流的基础上对流的功能进行增强
使用缓冲区写入文件
package com.gaopeng.IO;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Demo06 {
public static void main(String[] args) throws IOException {
FileWriter fileWriter = new FileWriter("demo.txt");
//创建缓冲区对象,需要和被缓冲的流相关联
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//建立了关联之后,写入-刷新-关闭,都使用buffer对象就ok
bufferedWriter.write("hahaha");
//换行操作
bufferedWriter.newLine();
bufferedWriter.write("hahaha");
bufferedWriter.flush();
bufferedWriter.close();
}
}
缓冲区读文件图解及readLine()实现原理
public class Demo07 {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader("demo.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line=null;
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
bufferedReader.close();
}
}
缓冲区实现文件复制
package com.gaopeng.IO;
import java.io.*;
public class Demo08 {
public static void main(String[] args) throws IOException {
//使用缓冲区实现文件复制
FileReader fileReader = new FileReader("demo.txt");
FileWriter fileWriter = new FileWriter("demo02.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
String line=null;
while((line=bufferedReader.readLine())!=null){
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
//关闭流
bufferedReader.close();
bufferedWriter.close();
}
}
自定义缓冲区
package com.gaopeng.IO;
import java.io.FileReader;
import java.io.IOException;
public class MyBufferedReader {
//获取操作对象
//定义缓冲区
//定义缓冲区存在字符个数
//定义缓冲区指针位置
private FileReader reader;
private char[] chrArr=new char[1024];
private int pos=0;
private int count=0;
MyBufferedReader(FileReader reader){
this.reader=reader;
}
public int myRead() throws IOException {
//如果count等于0,就要读取数据存入缓冲区中
if (count==0){
int num = reader.read(chrArr);
if (num==-1){
return -1;
}
count=num;
//每次存完之后就将指针置为零
pos=0;
}
int re=chrArr[pos];
pos++;
count--;
return re;
}
public String myReadLine() throws IOException {
//因为是返回一个字符串,可以将缓冲区定义为StringBuilder
StringBuilder sb = new StringBuilder();
pos=0;
count=0;
//调用单个字符读取方法
int num=0;
while((num=myRead())!=-1){
if ((char)num=='\r'){
continue;
}
if((char)num=='\n'){
return sb.toString();
}
//将字符添加到sb中
sb.append((char)num);
}
//判断是否为空
if (sb.length()!=0){
return sb.toString();
}
return null;
}
public void close() throws IOException {
reader.close();
}
}