一.什么是JAVAIO?
Java 把 Input输入流 和 Output 输出流,统称为IO流。它的核心就是对文件的操作,对于字节或字符类型的输入和输出。
流的概念和作用:
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在设备间传输称之为流。
流的本质是数据传输,根据数据传输的特性将流区分为各种类,方便更直观的进行数据操作。
阻塞型IO和非阻塞型IO(NIO):
阻塞型IO在读取数据时,如果数据未到达,会一直阻塞到读取到数据为止,所以称为阻塞型IO,在高并发的环境下性能不佳。
NIO不是使用 “流” 来作为数据的传输方式,而是使用通道,通道的数据传输是双向的,且NIO的数据写入和读取都是异步的,不会阻塞线程,所以称为非阻塞型IO,在高并发的环境下性能很好。
二.IO流的分类
1.按照流的操作颗粒度划分
IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如图片,视频等,字符流只能处理字符类型的数据。
学习java的方向是使用Java操作文件系统,那么首先要学习的就是文件的表示,然后我们要操作文件。但是IO流的概念不仅仅局限在操作文件上,我们的编程语言是要能操作所有的输入输出,因此,API提供了两个顶层抽象类,用来表示操作所有的输出输出:InputStream,OutputStream,并且这两个类表示字节的输入输出,因为输入输出的本质是字节流。
2.按照流的输入方向(输入输出都是站在程序所在内存的角度划分)
• 输入流:只能从中读取数据【主要由InputStream和Reader作为基类】
• 输出流:只能向其写入数据【主要由outputStream和Writer作为基类】
3.按照流的角色划分
• 节点流:可以从或向一个特定的IO设备(如磁盘,网络)读/写数据的流,也叫低级流。
• 处理流:用于对一个已存在的流进行连接和封装,通过封装后的流来实现数据的读/写功能,也 叫高级流。
三.常见的IO流
1.访问操作文件(FileInputStream/FileReader,FileOutputStream/FileWriter)
(1)使用FileInputStream从文件中读取数据
import java.io.*;
public class TestFileInputStream {
public static void main(String[] args) {
int b=0;
FileInputStream in = null;
try {
in =new FileInputStream("C:\\Users\\41639\\Desktop\\java\\FileText\\src\\TestFileImportStream.java");
}catch(FileNotFoundException e){
System.out.println("file is not found");
System.exit(-1);
}
try {
long num=0;
while ((b=in.read())!=-1) {
System.out.println((char)b);
num++;
}
in.close();
System.out.println();
System.out.println("共读取了"+num+"个字节");
}catch(IOException e) {
System.out.println("IO异常,读取失败");
System.exit(-1);
}
}
(2)使用FileOutputStream往文件中写数据
import java.io.*;
public class TextFileOutputStream {
public static void main(String[] args) {
int b=0;
FileInputStream in = null;
FileOutputStream out = null;
try {
in =new FileInputStream("C:\\Users\\41639\\Desktop\\java\\FileText\\src\\TestFileImportStream.java");
out=new FileOutputStream("C:\\Users\\41639\\Desktop\\java\\temp\\out.java");
}catch(FileNotFoundException e){
System.out.println("file is not found");
System.exit(-1);
}
try {
while ((b=in.read())!=-1) {
out.write(b);
}
in.close();
out.close();
}catch(IOException e) {
System.out.println("IO异常,读取失败");
System.exit(-1);
}
System.out.println("文件复制完成");
}
}
2.缓存流的使用(BufferedInputStream/BufferedOutputStream,BufferedReader/BufferedWriter)
学了文件IO字节流之后,我们会发现原始的字节流对象用起来没那么高效,因为每个读或写请求都由底层操作系统处理,这些请求往往会触发磁盘访问、网络活动或其他一些相对昂贵的操作。不带缓冲区的流对象,只能一个字节一个字节的读,每次都调用底层的操作系统API,非常低效,而带缓冲区的流对象,可以一次读一个缓冲区,缓冲区空了才去调用一次底层API,这就能大大提高效率,因此我们可以使用缓存流。
import java.io.*;
public class TestBufferStream {
public static void main (String[] args) throws IOException{
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
FileInputStream fis = new FileInputStream("C:\\Users\\41639\\Desktop\\java\\FileText\\src\\TestFileImportStream.java");
FileOutputStream fos = new FileOutputStream("C:\\Users\\41639\\Desktop\\java\\temp\\out2.java");
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
byte[] b = new byte[1024];
int off=0;
while ((off=bis.read(b))>0) {
bos.write(b,0,off);
}
bis.close();
bos.close();
}catch (IOException e) {
e.printStackTrace();
}finally {
bis.close();
bos.close();
}
}
}
从代码中可以看到,最基本的其实也是FileInputStream和FileOutputStream,在这个“流”的基础上,又加了缓存的功能流BufferedInputStream和BufferedOutputStream。
3.转换流的使用(InputStreamReader/OutputStreamWriter)
转换流是字节流和字符流之间相互转换的桥梁,把字节流转成字符流,离不开转换流,字符流是对于字符功能的增强可用来处理“文字”。
import java.io.*;
public class TransStreamTest {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\41639\\Desktop\\java\\temp\\test1031.txt"));
String line =null;
while ((line=br.readLine())!=null) {
if ("over".contentEquals(line)) {
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}
4、对象流的使用(FileInputStream/ObjectOutputStream)
在程序设计的过程中,我们都是用类和对象来描述定义,能不能直接把对象进行传输。答案当然是肯定的,对象流其实就是一种特殊的处理流水,也是在基础的字节流上去作封装。
下面程序使用一个对象流,把对象直接写到文件中。
import java.io.*;
public class ObjectStreamTest {
public static void main(String[] args) throws Exception{
try {
Person P=new Person("Jeccica",26);
FileOutputStream fos=new FileOutputStream("C:\\Users\\admin\\Desktop\\Java\\temp\\22.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(P);
oos.flush();
oos.close();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}
FileInputStream fis=new FileInputStream("C:\\Users\\admin\\Desktop\\Java\\temp\\22.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Person P2=(Person)ois.readObject();
System.out.println(P2.name+"的年龄为"+P2.age);
}
}
class Person implements Serializable{
String name=null;
int age=0;
Person(String _name,int _age){
name=_name;
age=_age;
}
}
5、字节数组流的使用(ByteArrayInputStream/ByteArrayOutputStream)【通常结合数据流DataInputStream/DataOutputStream】
我们分析了常见的节点流和常见的处理流等,经常而言我们都是针对文件的操作,然后带上缓冲的节点流进行处理,但有时候为了提升效率,我们发现频繁的读写文件并不是太好,那么于是出现了字节数组流,即存放在内存中,因此有称之为内存流;其中字节数组流也一种节点流;除了节点流外,我们也将学习另外一种处理流,即数据流。数据处理流是用于针对数据类型传输处理的,是一种处理流,即是在节点流之上的增强处理,一般用于序列化和反序列化的时候用到。
import java.io.*;
public class DataStream {
public static void main(String[] args) {
ByteArrayOutputStream baos=new ByteArrayOutputStream();//创建字节数组流,同时会在内存里面创建数组
DataOutputStream dos=new DataOutputStream(baos);//对字节数组流外封装成数据处理流
try {
dos.writeDouble(Math.random());//利用数据流里面的写入方法,写一个Double类型的随机数据
dos.writeBoolean(true);
ByteArrayInputStream bias=new ByteArrayInputStream(baos.toByteArray());//toByteArray()方法是创建一个新分配的字节数组。数组的大小和当前输出流的大小。这里指的是baos这个字节数组
System.out.println(bias.available());
DataInputStream dis=new DataInputStream(bias);
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
dos.close();
dis.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
以上就是我对JAVAIO的初步理解,还望各位指正。
课后总结
通过学长的讲解,我了解了一些预习博客中不完善的知识点,很高兴又学到了很多知识。
1.File类
(1)绝对路径和相对路径
- 绝对路径:是一个完整的路径,以盘符(C:,D:)开始的路如 C:\\Users\itcast\\IdeaProjects\\shungyuan\\123.txt
-
相对路径:
-
是一个简化的路径,相对指的是相对于当前项目的根目录(c:\lUsers\itcastllIdeaProjectsllshungyuan), 如果使用当前项目的根目录,路径可以简化书写C:\\Users\itcast\\IdeaProjects\\shungyuan\\123.txt-->简化为:123.txt(可以省略项目的根目录)
注意:1.路径是不区分大小写。
2.路径中的文件名称分隔符windows使用反斜杠,反斜杠是转义字符,两个反斜杠代表一个普通的反斜杠。
(2)学会通过api查找file类的方法
2.System.in&&System.out&&Scanner
Scanner类是JDK1.5中增加的一个类,用于扫描输入文本的实用程序。如果使用Scanner类,必须使用import语句导入Scanner类,位于java.util包中。
System.in作为InputStream类的对象实现标准输入,可以调用它的read方法来读取键盘数据。
System.out作为PrintStream打印流类的的对象实现标准输出,可以调用它的print、println或write方法来输出各种类型的数据。