文件中的字符大小
一个英语字母占1个字节
一个中文占3个字节
IO流原理和流的分类
字节流适用于读取二进制文件,比如图片,视频,音频等
字符流适用于读取文本文件
Io体系结构图
InputStream
FileInputStream
类图
一次读取一个字节
package inputStream;
import org.junit.Test;
import java.io.*;
public class FileInputStreamTest {
@Test
public void test1() {
FileInputStream fileInputStream = null;
try {
//定义指定的文件
fileInputStream = new FileInputStream("G:\\javabase\\io-stream\\src\\main\\resources\\hello.txt");
//接收数据
int read = 0;
//当读完后返回-1
while ((read = fileInputStream.read()) != -1) {
System.out.println((char) read);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
//关闭流,释放资源
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
一次读取多个字节
@Test
public void test2() {
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream("G:\\javabase\\io-stream\\src\\main\\resources\\hello.txt");
byte[] bytes =new byte[3];
//读取bytes.length长度的数据,并存到bytes数组里
//读取正常返回读入缓冲区的总字节数,如果没有更多的数据,因为文件的结尾已经到达,则返回-1.
//每一次读取新数据旧的数据就会被覆盖
while (fileInputStream.read(bytes) != -1) {
System.out.println(new String(bytes));
}
System.out.println(new String(bytes));//输出最后获取的数据
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
outputStream
FileOutputStream
类图
一次写入一个字节
//将小写字母a-z写入文件
@Test
public void test1(){
FileOutputStream fileOutputStream = null;
try {
File file = new File("G:\\javabase\\io-stream\\src\\main\\resources\\output.txt");
if (!file.exists()){ //文件不存在,创建该文件
file.createNewFile();
}
fileOutputStream = new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\output.txt");
for (int i = 97; i < 123; i++) {
fileOutputStream.write(i);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
写字符串和字节
//写字符串,字节
//写字符串,字节
@Test
public void test2(){
FileOutputStream fileOutputStream = null;
try {
File file = new File("G:\\javabase\\io-stream\\src\\main\\resources\\output2.txt");
if (!file.exists()){ //文件不存在,创建该文件
file.createNewFile();
}
//如果希望以追加的方式加入数据怎么办? 指定第二个参数为true即可
//fileOutputStream = new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\output2.txt",true);
fileOutputStream = new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\output2.txt");
//开始写数据
fileOutputStream.write('H'); //写一个比特
fileOutputStream.write('\n'); //换行
fileOutputStream.write(49);
fileOutputStream.write('\n'); //换行
fileOutputStream.write("hello".getBytes(StandardCharsets.UTF_8));
fileOutputStream.write('\n');
byte[] world = "world".getBytes();
fileOutputStream.write(world,1,world.length);//从指定的位置读取指定个字节数
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
文件拷贝(图片)
//拷贝图片
@Test
public void test3(){
FileInputStream is = null;
FileOutputStream os = null;
byte[] bytes = new byte[1024];
try {
is = new FileInputStream("F:\\images\\02.jpg");
os = new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\image.jpg");
while (is.read(bytes) != -1){
os.write(bytes); //如果传送的过程中出错,就会只显示已经完成的数据大的图片
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
Reader
FileReader
类图
一次读取一个字符
//字符输入流
@Test
public void test4(){
FileReader fr=null;
try {
int read = 0;
fr = new FileReader("G:\\javabase\\io-stream\\src\\main\\resources\\reader.txt");
while((read = fr.read()) != -1){ //读取一个字符,如果是中文则读取一个中文,读到末尾则返回-1
System.out.print((char)read);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
结果:
一次读取多个字符
//字符输入流,读取多个字符
@Test
public void test5(){
FileReader fr=null;
try {
char[] chars = new char[5];
fr = new FileReader("G:\\javabase\\io-stream\\src\\main\\resources\\reader.txt");
while(fr.read(chars,3,chars.length-3) != -1){
//读取chars.length-2个字符,并且放在数组的指定的下标里,没有指定的下标用空字符填充
for (int i = 0; i < chars.length; i++) {
System.out.print(chars[i]);
}
System.out.println("");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
Writer
FileWriter
类图
写入数据
1.写入一个整型3
//字符输出流
@Test
public void test6() {
FileWriter fw = null;
try {
char[] chars = new char[5];
//当文件不存在会自动地帮我们创建文件
fw = new FileWriter("G:\\javabase\\io-stream\\src\\main\\resources\\writer1.txt");
fw.write(97);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
// fw.flush(); //刷新流,否则不会将数据写入到文件
fw.close(); //关闭流,释放资源,关闭的时候也会自动刷新流
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
2.写入字符串和char数组
//字符输出流
@Test
public void test7() {
FileWriter fw = null;
try {
fw = new FileWriter("G:\\javabase\\io-stream\\src\\main\\resources\\writer2.txt",true);
String str1 = "zhenghaowen";
fw.write(str1,1,str1.length()-1);//从指定的下标开始写入数据
fw.write("\n");
String str2 = "zhangguorong";
char[] chars1 = new char[str2.length()];
str2.getChars(0,str2.length(),chars1,0);
fw.write(chars1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
// fw.flush(); //刷新流,否则不会将数据写入到文件
fw.close(); //关闭流,释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
flush方法和close方法看源码看法都会走到writeBytes方法,该方法才会真正把数据存到文件中
private void writeBytes() throws IOException {
bb.flip();
int lim = bb.limit();
int pos = bb.position();
assert (pos <= lim);
int rem = (pos <= lim ? lim - pos : 0);
if (rem > 0) {
if (ch != null) {
if (ch.write(bb) != rem)
assert false : rem;
} else {
out.write(bb.array(), bb.arrayOffset() + pos, rem);
}
}
bb.clear();
}
节点流和处理流
public class BufferedReader extends Reader {
private Reader in; //可以接收一个reader的具体实现类
......
}
处理器可以对节点流进行封装,即无视了数据的来源
@Test
public void test1() throws IOException {
CharArrayReader car = new CharArrayReader("林青霞".toCharArray());
StringReader sr = new StringReader("张国荣");
FileReader fr= new FileReader("G:\\javabase\\io-stream\\src\\main\\resources\\writer2.txt");
//可以将上面的任一一个reader传入bufferedReader中,无视了数据的来源
BufferedReader br = new BufferedReader(fr);
System.out.println((char)br.read());
}
处理流和包装流的区别
bufferReader
类图
读取数据无视数据源
@Test
public void test1() throws IOException {
CharArrayReader car = new CharArrayReader("zhegnhaowen".toCharArray());
StringReader sr = new StringReader("张国荣");
String line;
//将节点流传入包装流
BufferedReader br = new BufferedReader(new FileReader("G:\\javabase\\io-stream\\src\\main\\resources\\writer2.txt"));
//一次读取一行
while( (line = br.readLine()) != null ){
System.out.println(line);
}
//关闭流
car.close();
sr.close();
br.close();//底层会自动关闭传入的节点流
}
bufferedReader的close方法
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close(); //关闭传入的节点流
} finally {
in = null;
cb = null;
}
}
}
bufferedWriter
类图
将诗写入文件
@Test
public void test1() throws IOException {
String[] strs = {"君不见黄河之水天上来","奔流到海不复回","君不见高堂明镜悲白发","朝如青丝暮成雪","人生得意须尽欢","莫使金樽空对月","天生我材必有用","千金散尽还复来"};
BufferedWriter bw = new BufferedWriter(new FileWriter("G:\\javabase\\io-stream\\src\\main\\resources\\bufferedWriter.txt",true));
for (String str : strs) {
bw.write(str);//插入数据
bw.newLine();//插入换行符
}
bw.close(); //刷新并关闭流
}
@Test
public void test2() throws IOException {
StringWriter out = new StringWriter();
BufferedWriter bw = new BufferedWriter(out);
bw.write("落花有意随流水,");//向out内写入数据
bw.write("而流水无心恋落花".toCharArray());
bw.close(); //刷新并关闭流,完成写入工作
System.out.println(out.toString());
}
buffered完成文件拷贝
1.从文本文件拷贝到stringwriter
@Test
public void test() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("G:\\javabase\\io-stream\\src\\main\\resources\\bufferedWriter.txt"));
StringWriter out = new StringWriter();
BufferedWriter bw = new BufferedWriter(out);
String line;
while ((line = br.readLine()) != null){
bw.write(line);
}
br.close();
bw.close();
String s = out.toString();
System.out.println(s);
}
bufferedInputStream和bufferOutputStream
类图
字节缓冲流文件拷贝
@Test
public void test1() throws IOException {
//创建字节输入缓冲流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("F:\\images\\02.jpg"));
//创建字节输出缓冲流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\image.jpg"));
//接受的数据大小
byte[] bytes = new byte[10240];
while (bis.read(bytes) != -1){
bos.write(bytes);
}
//关闭流
bis.close();
bos.close();
}
对象流(序列化和反序列化)
ObjectOutputStream和ObjectInputStream
该类是一个处理流,需要包装节点流
public class Dog implements Serializable { //实现序列化接口
private String name;
private String color;
public Dog(String name, String color) {
this.name = name;
this.color = color;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}
序列化示例
@Test
public void test1() throws IOException {
//1.要序列化的对象
Dog dog = new Dog("小明", "黑");
//2.创建对象处理流并且包装节点流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\object.txt"));
//3.写入数据
oos.writeObject(dog);
//4.刷新并关闭流
oos.close();
}
反序列化示例
@Test
public void test1() throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\object.txt"));
oos.writeObject(new Dog("小明", "黑"));
oos.writeInt(97);
oos.writeChar(97);
oos.writeLong(700l);
oos.close();
//反序列化的顺序不要出错,要保持一致
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("G:\\javabase\\io-stream\\src\\main\\resources\\object.txt"));
System.out.println(ois.readObject()); //底层会自动封装成存储的类型
System.out.println(ois.readInt());
System.out.println(ois.readChar());
System.out.println(ois.readLong());
}
注意事项
标准输入输出流
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Please inout a String");
String next = scanner.next();
System.out.println(next);
scanner.close();
}
转换流
1.文本文件的默认编码
2.读取非UTF-8编码的数据
@Test
public void test1() throws IOException {
BufferedReader br = new BufferedReader(new FileReader("G:\\javabase\\io-stream\\src\\main\\resources\\hello.txt"));
System.out.println(br.readLine());
}
指定读取数据的解码方式
读取文件
@Test
public void test2() throws IOException {
InputStreamReader isr = new InputStreamReader(new BufferedInputStream(new FileInputStream("G:\\javabase\\io-stream\\src\\main\\resources\\outputstreamwriter.txt")), "gbk");
char[] bytes = new char[10000];
isr.read(bytes);
for (char aByte : bytes) {
System.out.print(aByte);
}
}
写入文件
@Test
public void test2() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\outputstreamwriter.txt",true)),"gbk");
osw.write("君不见黄河之水天上来");
osw.close();//写入完成
}
打印流
printStream
printWriter
@Test
public void test1() throws IOException {
//打印到文件,打印流就是将数据输出到自定的字节流
PrintWriter pw = new PrintWriter(new FileWriter("G:\\javabase\\io-stream\\src\\main\\resources\\b.txt"));
pw.write("hello你好");
pw.close();
PrintStream ps = new PrintStream(new FileOutputStream("G:\\javabase\\io-stream\\src\\main\\resources\\c.txt"));
ps.write("你好".getBytes());
ps.close();
}