Java学习之I/O流

今天我给大家分享一下Java的I/O流的学习总结。

I/O流:指的是对文件的数据进行读取和写出操作,分别为InputStream(输入)和OutputStream(输出)。

  • InputStream输入:指的是将文件中的数据,从外部的存储设备中的数据,通过程序操作,将数据读取到内存中进行数据信息的处理。
  • OutputStream输出:指的是将程序执行过程中的数据信息,进行持久化。将数据保存下来,用文件进行记录,从内存到外部去输出。

I/O流的分类

I / O { { I n p u t S t r e a m { I n p u t S t r e a m R e a d e r B y t e A r r a y I n p u t S t r e a m D a t a I n p u t S t r e a m O b j e c t I n p u t S t r e a m O u t p u t S t r e a m { O u t p u t S t r e a m R e a d e r B y t e A r r a y O u t p u t S t r e a m D a t a O u t p u t S t r e a m O b j e c t O u t p u t S t r e a m P r i n t S t r e a m { R e a d e r { B u f f e r e d R e a d e r I n p u t S t r e a m R e a d e r W r i t e r { B u f f e r e d W r i t e r O u t p u t S t r e a m W r i t e r P r i n t W r i t e r I/O流 \begin{cases} 字节流 \begin{cases} \bf{InputStream} \begin{cases} \bf{InputStreamReader} \\ \bf{ByteArrayInputStream} \\ \bf{DataInputStream} \\ \bf{ObjectInputStream} \\ \end{cases} \\ \bf{OutputStream} \begin{cases} \bf{OutputStreamReader} \\ \bf{ByteArrayOutputStream} \\ \bf{DataOutputStream} \\ \bf{ObjectOutputStream} \\ \bf{PrintStream} \\ \end{cases} \\ \end{cases} \\ 字符流 \begin{cases} \bf{Reader} \begin{cases} \bf{BufferedReader} \\ \bf{InputStreamReader} \\ \end{cases}\\ \bf{Writer} \begin{cases} \bf{BufferedWriter} \\ \bf{OutputStreamWriter} \\ \bf{PrintWriter} \\ \end{cases}\\ \end{cases} \\ \end{cases}

I/O流的具体分类

字节流:字节输入流、字节输出流

  • 字节输入流:InputStream    实现类:FileInputStream
  • 字节输出流:OutputStream   实现类:FileOutputStream
File file = new File("./log.txt");
//流对象创建之后,该流就已经处于打开状态。数据读完后要关闭流。
//意义:释放流对象所占用的资源、文件
InputStream stream = new FileInputStream(file);
byte[] bts = new byte[3];
stream.read(bts);
System.out.println(new String(bts));	//log.txt文件的内容为:你abc,此时输出为:你

OutputStream stream = new FileOutputStream(file);
//没有追加,表示数据会覆盖原有的数据
byte[] bts = {99,100,101,102};
stream.write(bts);
stream.close();		//log.txt文件的内容为:你abc,修改后文件内容为:cdef

OutputStream stream1 = new FileOutputStream(file1,true);
stream.write(bts);
stream.close();		//log.txt文件的内容为:cdef,修改后文件内容为:cdefcdef

字节流一般用于处理哪种文件呢?
只要不是文本文件,其他的像图片、视频、音频、特殊格式的文件都可处理。

字符流:字符输入流、字符输出流

  • 字符输入流:Reader   实现类:FileReader
  • 字符输出流:Writer     实现类:FileWriter
File file = new File("./log.txt");
Reader reader = new FileReader(file);
char[] chs = new char[10];
int length = 0;
while((length=reader.read(chs)) > 0) {
	System.out.print(new String(chs, 0, length));
}
reader.close();		//log.txt文件的内容为:cdef,最后输出结果为:cdef

Writer writer = new Writer(file);
char[] chs = {'你', '好'};
writer.write(chs);
writer.close();		//log.txt文件的内容为:cdef,最后输出结果为:你好

Writer writer = new Writer(file,true);
writer.write("我很好");
writer.close();		//log.txt文件的内容为:你好,最后输出结果为:你好我很好

总结:如果处理文本文件,不管是读还是写,尽量采用字符流,除此之外的格式,都采用字节流。

包装流

就是将底层的字符流或者字节流在其基础之上进行二次封装,包成一个使用更为方便的二次流。

缓冲流:BufferedReader、BufferedWriter

  • 缓冲输入流:BufferedReader
  • 缓冲输出流:BufferedWriter
      读或者写,并不直接对文件操作,为了提高性能,而是采用了对内存操作的方式。提供了8192个字符的缓冲器,在创建这两个流对象时就需要在内存划分出来了。
      缓冲输入流在对象创建完成之后,就会立刻进行读取操作,读取文件中的信息,将文件中的数据信息读取到内存中的缓冲区中,真正使用流读取操作时,读的数据是来源于内存的缓冲区。如果缓存区中的数据读取完了,缓存流会立刻从文件中再次读取数据,覆盖之前的内容,直到文件读取完毕。
      写也同样不是直接写入到文件,而是写入到缓冲区。缓冲区写满了,缓冲输出流会进行flush清空操作,将缓冲区的数据清空,把数据写入到文件目的地。
      因为程序是直接对内存进行操作,而不是对硬盘或外部存储介质操作,所以提高了性能。
File file = new File("./log.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
while((line=reader.readLine()) != null) {	
	System.out.println(line);	//循环输出文件中每一行的信息
}
reader.close();		

File file = new File("./log.txt");
BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
for(int i=0; i<4; i++) {
	writer.newLine();
	writer.write(String.valueOf(i)+i+i+i+i+i);
}
writer.close();
//缓冲的输出流在关闭操作时会检查缓冲区中是否存在数据,如果发现有,将会把数据写到文件中去。
//也可以使用writer.flush()进行输出

转换流:InputStreamReader、OutputStreamWriter

  • 转换输入流:InputStreamReader
  • 转换输出流:OutputStreamWriter
      将一个字节流转换成一个字符流
File file = new File("./log.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file, true));
BufferedWriter bw = new BufferedWriter(osw);	//把字节流转换成字符流
bw.write("112233");
bw.close();

File file = new File("./log.txt");
InputStreamReader isr = new InputStreamReader(new FileInputStream(file));
char[] data = new char[1024];
int length = isr.read(data);
System.out.println(new String(data, 0, length));
isr.close();

打印流:PrintStream、PrintWriter

  • 字节打印流:PrintStream
  • 字符打印流:PrintWriter
//为什么要使用打印流?打印流和普通的字节或字符流输出有什么区别?我们看一下下面这两个例子:
File file = new File("./log.txt");
OutputStream os = new FileOutputStream(file);
os.write(97);
os.close();		//写入到文件中的为字母a

File file = new File("./log.txt");
PrintStream ps = new PrintStream(new FileOutputStream(file));
ps.print(97);
ps.close();		//写入到文件中的为数字97

总结:字节输出流、字符输出流输出数字到文件中时,会变成相应的字母
   采用打印流往文件中输入数据时,数据就不会再进行转换了

内存流:ByteArrayInputStream、ByteArrayOutputStream

  • 内存输入流:ByteArrayInputStream
  • 内存输出流:ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String value = "你好啊";
baos.write(value.getBytes());	//数据写入到了内存中的一个字节数组中
byte[] data = baos.toByteArray();	//toByteArray()方法:创建一个新分配的字节数组。数组的大小是当前输出流的大小,内容是当前输出流的拷贝。
System.out.println(new String(data));
baos.close();	//输出结果为 你好啊

ByteArrayInputStream bais = new ByteArrayInputStream(data);
byte[] data1 = new byte[20];
int length = bais.read(data1);
System.out.println(new String(data1, 0, length));
bais.close();	//输出结果为 你好啊		

数据流:DataInputStream、DataOutputStream

  • 数据输入流:DataInputStream
  • 数据输出流:DataOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
//数据流可以进行网络间的数据传输
dos.writeFloat(12.4f);
dos.writeDouble(20.45);
dos.writeInt(10);
//数据最终写入到一块内存中
byte[] data = baos.toByteArray();
baos.close();
		
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
//读要跟写保持一致,要规定好读的格式,定义好协议,按照协议的格式去读或者写
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
System.out.println(dis.readInt());
bais.close();

对象流:ObjectInputStream、ObjectOutputStream

  • 对象输入流:ObjectInputStream
  • 对象输出流:ObjectOutputStream
Student stu = new Student();
stu.setStuName("张三");
Teacher tea = new Teacher();
tea.setTeaName("李四");
stu.setTeacher(tea);

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./obj.txt"));
oos.writeObject(stu);	//把对象stu保存到文件当中,并且使用深克隆进行拷贝
oos.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./obj.txt"));
Student stuObj = (Student)ois.readObject();
System.out.println(stuObj.getStuName());
System.out.println(stuObj.getTeacher().getTeaName());
ois.close();

读写流:RandomAccessFile

RandomAccessFile raf = new RandomAccessFile("./log.txt", "rw");
//在进行读取操作时,该对象包含一个记录指针,记录当前操作到哪个字节位置了
raf.seek(3);	//控制指针从开头移动几个字节
int length = raf,getFilePointer();	//length即是指针的当前位置
raf.write("abc".getBytes());
raf.close();
发布了16 篇原创文章 · 获赞 69 · 访问量 7605

猜你喜欢

转载自blog.csdn.net/suiyu_eran/article/details/88911113