1、Java的输入输出(I/O),Java的输入输出,2,主要内容,Java的基本输入输出 I/O流的类层次 用流读写文件 (1)字节流 FileInputStream、FileOutputStream DataOutputStream、DataInputStream (2)字符流FileReader、FileWriter 用字符流从键盘读数据ReadData.java 标准文件类File FileNameDemo.java用RandomAccessFile读写文件 RandomAccessFileDemo.java,Java的输入输出,3,7.1流,一个程序在运行时通常要和外部设备交互,即从外部
2、设备获取信息或向外部设备发送信息,这就是所谓的输入/输出(I/O)操作。 在Java语言中,输入/输出都是通过流(Stream)来完成的,这样程序无论是要进行输入还是输出,只要针对流进行操作就可以了。 处理输入/输出的类在java.io包和java.nio包中(JDK1.4后增加的非阻塞输入输出的实现-non blocking I/O),Java的输入输出,4,7.1.1流(Stream)的概念,简单地说,流就是指在计算机与输入/输出之间流动的数据序列。 序列中的数据既可以是二进制数据,也可以是其他符合某种格式规定的特定数据,如字符流序列等。 Java语言定义了字节流和字符流两种类型,并通过字
3、节流类和字符流类实现输入/输出操作。,Java的输入输出,5,java.io中的基本流类,说明:它们是抽象类,不能直接创建对象。,Java的输入输出,6,7.1.2字节流类 -InputStream和OutputStream,字节流提供了处理字节的输入/输出方法,如在读写二进制数据时就要使用字节流。顶层的是两个抽象类是: InputStream(输入流) OutputStream(输出流)。 这两个抽象类派生出来的具体子类提供了读写各种不同设备如磁盘文件的功能。,Java的输入输出,7,7.1.3字节输入流类-InputStream,字节输入流类的作用就是从外部设备获取字节数据到计算机内存中。
4、,Java的输入输出,8,InputStream Class的继承关系:,Java的输入输出,9,常用的字节输入流,InputStream,FileInputStream,FilterInputStream,DataInputStream,BufferedInputStream,Java的输入输出,10,字节输入流的子类,FileInputStream读取文件输入流 FilterInputStream建立可过滤的输入流,Java的输入输出,11,字节过滤输入流,FilterInputStream称为字节过滤输入流,是一个常用的字节输入流类,它把另一个输入流作为流的来源。FilterInputS
5、tream的子类: 1、DataInputStream提供一些基于多字节的读取方法,从而可以读取基本类型的数据; 2、BufferedInputStream为其他输入流增加功能,能够提高读取速度,Java的输入输出,12,抽象类InputStream中的方法,int read()从输入流的当前位置读取输入流的下一个字节,返回读入的字节数据;如果已经读取到输入流的末端,返回-1。 int read(byte b )将输入流读到字节数组中,返回读入的字节数 int read(byte b ,int off,int len )从输入流中读取len个字节到字节数组b中,读到的第一个字节放在off处,返
6、回读入的字节数;如果off+len大于b.length,或者off和len中有一个是负数,那么会抛出IndexOutOfBoundsException。,Java的输入输出,13,抽象类InputStream中的方法,long skip(long n )从输入流中跳过n个字节,返回跳过的字节数;执行skip()方法后,接着使用read()方法将会读取第n+1个字节。 abstract void close()关闭输入流,释放资源。对流的读取结束后应显示地调用该方法。,Java的输入输出,14,抽象类InputStream中的方法,reset()方法和mark()方法:成对使用。 mark()方
7、法:给流的当前位置做一个标记 reset()方法:使流回到上次使用mark()方法后的标记处。 并非所有的流都支持reset()方法和mark()方法,使用markSupportted()方法来判断某个流是否支持reset/mark操作 抽象类InputStream中的方法,在发生错误时都会抛出IOException异常,而且这个抽象类定义的方法都可以被它们所有的子类继承使用。,Java的输入输出,15,DataInputStream类和BufferedInputStream类,在Java语言应用程序中,经常会用到DataInputStream类和BufferedInputStream类的构造
8、方法以完成输入操作。 DataInputStream类提供的构造方法如下: DataInputStream(InputStream in); 参数in为底层输入流,通常与一个具体的设备相关联。该方法的功能是建立一个新的数据输入流以从指定的输入流读数据。,Java的输入输出,16,BufferedInputStream类,BufferedInputStream类提供的构造方法如下: (1) public BufferedInputStream(InputStream in); 参数in为底层输入流,通常与一个具体的设备相关联。 该方法的功能是创建一个缓冲输入流并保存在参数in中供以后使用。 同时
9、也建立起来一个缓冲数组并保留在buf中(buf是缓冲输入流类的成员变量,是一个字节类型的数组,用于存储数据的内部缓冲区)。 (2)public BufferedInputStream(InputStream in, int size); 参数in为底层输入流,通常与一个具体的设备相关联,size为缓冲区大小。 该方法的功能是以指定的缓冲区大小创建一个缓冲输入流,并保存在参数in中供以后使用。一个长度为size的内部缓冲区数组也建立起来并保存在buf中。,Java的输入输出,17,7.1.4,字节输出流类-OutputStream 字节输出流类的作用就是将暂存在计算机内存中的数据输出到外部设备。
10、,Java的输入输出,18,字节过滤输出流派生的子类,一、字节过滤输出流派生的子类1、DataOutputStream对这个过滤数据输出流可以写入任何符合Java数据类型的信息,这些信息可以被该类的方法读取2、BufferedOutputStream为输出流提供缓冲式过滤流,缓冲区大小可以通过入口参数指定,也可以固定为512字节 二、FileOutputStream写入文件输出流,Java的输入输出,19,字节输出流的主要方法,void write(int b )将整数b的低8位写入输出流void write(byte b )将字节数组写入输出void write(byte b ,int of
11、f,int len )从字节数组b的off处开始向输出流写入len个字节abstract void flush()强制将输出流保存在缓冲区中的数据写入目标数据源abstract void close()先调用flush()方法,然后关闭输出流,释放资源,Java的输入输出,20,流的异常处理,使用输入输出时,可能会出现IOException异常,通常要使用Java的异常处理机制 try/与流操作相关的代码 catch(IOException e)/处理异常的代码 finallyxxx.close(); ,Java的输入输出,21,OutputStream Class的继承关系:,Java的输入
12、输出,22,常用的字节输出流,Java的输入输出,23,DataOutputStream类,DataOutputStream类提供的构造方法如下: public DataOutputStream(OutputStream out) 参数out为底层输出流,通常与一个具体的设备相关联。 该方法的功能是建立一个新的数据输出流以写数据到指定的底层输出流中。,Java的输入输出,24,BufferedOutputStream类,BufferedOutputStream类提供的构造方法如下: (1) public BufferedOutputStream(OutputStream out) 参数out为
13、底层输出流,通常与一个具体的设备相关联。 该方法的功能是建立一个新的缓冲输出流以写数据到指定的底层输出流,其缓冲区大小默认为512字节。 (2) public BufferedOutputStream(OutputStream out,int size) 参数out为底层输出流,通常与一个具体的设备相关联,参数size为缓冲区大小。 该方法的功能是以指定的缓冲区大小建立一个新的缓冲输出流,用于写数据到指定的底层输出流,Java的输入输出,25,7.2用字节流读写文件,(1)字节流读写文件的四个常用类 FileInputStream FileOutputStream DataOutputStre
14、am DataInputStream,Java的输入输出,26,FileInputStream类,FileInputStream类的对象可以从文件中读取字节 FileInputStream类的构造方法: FileInputStream(File file) ;通过打开一个到实际文件的File类的对象file来创建一个 FileInputStream。例如: File f1=new File(“c:a.txt”); FileInputStream fileInput1=new FileInputStream(f1); FileInputStream(String pathName) ;通过pat
15、hName代表的路径名来创建一个FileInputStream对象。例如:InputStream f =new FileInputStream(“FileInputStreamDemo.java“);,Java的输入输出,27,(1)字节流读写文件的四个常用类 FileInputStream FileOutputStream DataOutputStream DataInputStream,Java的输入输出,28,FileOutputStream类,创建FileOutputStream类的对象,可以将字节数据写到文件中。FileOutputStream类的构造方法: FileOutputSt
16、ream(File file) ;/1 FileOutputStream(String pathName);/2 FileOutputStream(String pathName,boolean append);/3 在创建FileOutputStream的实例时,如果相应的文件并不存在,会自动创建一个空的文件;如果参数file或pathName表示的文件路径尽管存在,但是该路径表示的是一个文件目录,那么回抛出FileNotFoundException。 默认情况下,用1或2的构造方法创建 FileOutputStream类的对象,向文件中写数据时,将覆盖文件中原有的内容。如果用3中构造方法创
17、建FileOutputStream类的对象,用第二个参数append指定在文件末尾添加数据。,Java的输入输出,29,(1)字节流读写文件的四个常用类 FileInputStream FileOutputStream DataOutputStream DataInputStream,Java的输入输出,30,DataOutputStream类详细介绍,DataOutputStream用来将java基本数据类型写入数据目的地。使用其writeXXX()方法: wirteBoolean(boolean v);将一个 boolean 值写入输出流 writeChar(int v);将一个 char
18、 值写入输出流,该值由两个字节组成 writeInt(int v);将一个 int 值写入输出流,该值由四个字节组成 writeDouble(double v) ;将一个 double 值写入输出流,该值由八个字节组成 writeChars(String s);将字符串 s 中的所有字符按顺序写入输出流,每个字符用两个字节表示。 writeFloat(float v) 等,Java的输入输出,31,(1)字节流读写文件的四个常用类 FileInputStream FileOutputStream DataOutputStream DataInputStream,Java的输入输出,32,Dat
19、aInputStream类,DataInputStream类能够从流中读取Java基本类型数据的能力,如int、float、long、double、boolean等。此外, DataInputStream的readUTF方法还能够读取UTF-8编码的字符串。,Java的输入输出,33,DataInputStream类,DataInputStream类的所有的读方法都是以“read”开头,比如: readByte();从输入流中读取一个字节,把它转换为byte类型的数据。 readLong();从输入流中读取8个字节,把它转化为long类型的数据。 readFloat();从输入流中读取4个字节
20、,把它转化为float类型的数据。 readUTF();从输入流中读取1-3个字节,把它转化为采用UTF-8编码的字符串,Java的输入输出,34,三、字符流,Java的输入输出,35,字符流类,字符流提供了处理字符的输入/输出的方法,它们使用Unicode码。 字符流也使用两个类层次定义,在顶层的是两个抽象类:Reader和Writer。 Reader指字符输入流,用于输入,而Writer指字符输出流,用于输出。 从Reader和Writer派生出来的具体子类,它们才能对Unicode字符流进行操作。 字符流与字节流的区别在于前者是基于字符的操作,而后者则基于字节操作。,Java的输入输出,
21、36,字符输入流类,Java的输入输出,37,Reader Class的继承关系,Java的输入输出,38,常用的字符输入流,Reader,BufferedReader,FileReader,InputStreamReader,Java的输入输出,39,字符输入流类的子类,InputStreamReader将字节输入流转化成为字符输入流 子类FileReader 从文件读入的输入流 BufferedReader包含readLine()方法的缓冲输入字符流,Java的输入输出,40,字符输入流类定义的方法,abstract void close()关闭输入流 int read()从输入流读取一个
22、字符。如果到达文件结尾,则返回-1 int read(char buf )从输入流中将指定个数的字符读入到数组buf中,并返回读取成功的实际字符数目。如果到达文件结尾,则返回-1 abstract int read(char buf ,int off,int len)从输入流中将len个字符从bufoff位置开始读入到数组buf中,并返回读取成功的实际字符数目。如果到达文件结尾,则返回-1 boolean ready()判断流是否做好读的准备 long skip(long n)跳过输入中的n个字符,返回实际跳过的字符数目,Java的输入输出,41,InputStreamReader类,Inpu
23、tStreamReader类是从字节流到字符流的桥梁,它读取字节数据并将其转换为指定字符编码的字符。每次调用InputStreamReader对象的read()方法时,都将导致从字节输入流中读取一个或多个字节。,Java的输入输出,42,BufferedReader类,BufferedReader类是从字符输入流中读取字符,再将字符存入缓冲区内,以提供读字符、数组、行的有效方法。缓冲区容量可以指定,也可以使用默认值。 BufferedReader类提供了两个构造方法: (1) public BufferedReader(Reader in) 参数in为一个Reader对象。其功能是创建一个使用
24、默认容量的输入字符流缓冲区。 (2) public BufferedReader(Reader in, int size) 参数in为一个Reader对象,size为输入缓冲区容量。其功能是创建一个指定容量的输入字符流缓冲区。,Java的输入输出,43,同时使用InputStreamReader和BufferedReader,为了提高读取效率,通常将InputStreamReader与BufferedReader封装在一起使用。例如: InputStreamReader stdin = new InputStreamReader(System.in); BufferedReader bufin
25、 = new BufferedReader(stdin);或者BufferedReader bufin = new BufferedReader(new InputStreamReader(System.in);上述语句被执行以后,将创建一个连接到键盘的BufferedReader对象,即bufin将是一个通过System.in连接到控制台的基于字符的输入流。,Java的输入输出,44,BufferedReader类的readLine(),要从键盘读取字符,需要使用BufferedReader类的成员方法readLine()。它的一般语法格式如下: public String readLine
26、() throws IOException 该方法读取一行文本。通常把 n 、 r 或 r 后紧跟 n 看作一行的结束。它返回包含行内容的字符串,并不包含任何终止符,当已读到流的末尾时返回空。如果发生I/O错误,则抛出IOException异常。,Java的输入输出,45,使用InputStreamReader和BufferedReader从键盘读入数据的例子: ReadData.java 、 TestReader.java,Java的输入输出,46,字符输出流,Java的输入输出,47,Writer Class的继承关系,Java的输入输出,48,常用的字符输出流,Writer,Buffer
27、edWriter,FileWriter,OutputStreamWriter,Java的输入输出,49,字符输出流类定义的方法,abstract void close()关闭输出流,如果试图继续写入,将产生一个IOException abstract void flush()强制输出流中的字符输出到指定的输出装置 void write(int ch)写入一个字符到流中 void write(char buf )将一个完整的字符数组写入到输出流中 abstract void write(char buf ,int off,int len)从数组buf的bufoff位置开始,写入len个字符到输出
28、流中 void write(string str)写入一个字符串到输出流中 void write(string str,int off,int len)写入一个字符串到输出流中,off为字符串的起始位置,len为字符串的长度,即写入的字符数,Java的输入输出,50,从文件中读取字符和往文件中写入字符,使用FileReader和FileWriter FileReader:是Reader的子类,用来读取字符文件。构造方法如下: FileReader(File file) ;根据参数file代表的文件创建一个新的FileReader。 FileReader(String fileName) ;根据
29、参数fileName代表的文件创建一个新的FileReader。,Java的输入输出,51,FileWriter类,FileWriter 是Writer的子类,用来向文件中写入字符。构造方法如下: FileWriter(File file) FileWriter(File file, boolean append) FileWriter(String fileName) FileWriter(String fileName, boolean append) append如果是true,将字符数据写入文件末尾; append是false则将字符数据覆盖原文件。,Java的输入输出,52,使用字符
30、流的例子,文本文件的读写: Writer、FileWriter结合使用写入文本文件 Reader、FileReader结合使用读取文本文件 TxtFileDemo.java,Java的输入输出,53,7.3文件访问,文件(File类) 各种文件系统提供的基本服务一样,但实现细节互不相同。 解决java程序与文件系统的沟通。,Java的输入输出,54,标准文件类: File,File类的对象表示的是文件系统中的一个目录或文件。 File类对象描述文件路径、名字、长度、可否读写等属性,可用来命名文件、查询文件属性、对目录进行操作,但不读写文件。 上述操作都是以独立于系统的方式进行。 通过File类
31、对象可以对操作系统的文件进行管理,体现了跨平台不同文件的统一管理,Java的输入输出,55,File类构造方法,File(String path) 创建文件对象(使用相对路径,移植性较好) File f1 = new File(“mydirmyfile.txt”); 创建目录对象(使用绝对路径) File f2 = new File(“d:mydirdir1”); File(String directoryPath, String fileName )File f3 = new File(“d:d1” , “a.java”) File(File dirObj, String filename)
32、 File f4 = new File(f2 , “myfile.txt”);,win unix /,Java的输入输出,56,File类方法获取文件属性,判断目标是否存在 public boolean exists() 判断是文件还是目录 public boolean isFile(); public boolean isDirectory(); 获取文件名称或整个路径 public String getName() 仅返回文件名,文件路径信息被忽略。 public String getPath() 返回整个路径字符串,Java的输入输出,57,File类方法,public boolean
33、isAbsolute() 判断此抽象路径名是否为绝对路径名。绝对路径名的定义与系统有关。在 UNIX 系统上,如果路径名的前缀是 “/”,则该路径名是绝对路径名。在 Microsoft Windows 系统上,如果路径名是C:122.txt 的形式,则该路径名是绝对路径名。 public String getAbsolutePath() 返回抽象路径名的绝对路径名字符串。如果此抽象路径名已经是绝对路径名,则返回该路径名字符串,这与 getPath() 方法一样。,Java的输入输出,58,File类方法获取文件属性,获取文件长度 public long length() 获取文件读写属性 pu
34、blic boolean canRead() public boolean canWrite() 列出目录中的文件和子目录 public String list() public File listFiles(),Java的输入输出,59,File类方法文件/目录操作,重命名 public boolean renameTo(File newName) 删除文件或目录 public boolean delete(); 创建目录 public boolean mkdir() 创建目录及父目录(如果需要的话)public boolean mkdirs();创建此抽象路径名指定的目录,包括创建必需但不
35、存在的父目录。注意,如果此操作失败,可能已成功创建了一些必需的父目录。,Java的输入输出,60,File的方法(续),File类使用一个静态实例变量separator (public static final String)保存了当前的目录分隔符。 为本机操作系统支持的路径分隔符 DOS, Windows “” Unix “/” File f1=new File(“Documents”+File.separator+“data.txt”); 表示的是: Documentsdata.txt,Java的输入输出,61,File类的案例介绍,对文件进行操作 FileDemo.java FileNa
36、meDemo.java 对目录进行操作 DirectoryDemo.java,Java的输入输出,62,7.3.2文件的读写,创建的File对象表示的是文件,如果实际文件存在,则可以读写文件的内容。 对文件进行读写 方式一:使用基于字节的流类进行操作,即使用FileInputStream和FileOutputStream; 方式二:使用基于字符的流类进行操作,即使用FileReader和FileWriter(推荐方式),Java的输入输出,63,7.3.3 RandomAccessFile,对流的操作是按顺序进行。如读取流中的数据、向流中写入数据都是按从头到尾的顺序读或写。 public cl
37、ass RandomAccessFile extends Object implements DataOutput, DataInput, Closeable 该类不是InputStream或OutputStream的子类,可以随机的读写文件。即可以写入文件中的任意位置。 实现了DataOutput、 DataInput接口,故RandomAccessFile可以实现读取或写入基本数据类型的数据和字节数据、字符数据。,Java的输入输出,64,RandomAccessFile,除了实现了DataInput和DataOutput接口中的方法,还增加了几个与文件相关的方法: public long
38、 length() throws IOException;返回文件的长度。 public void seek(long pos) throws IOException; 将下次读写的位置定位到距离文件开始pos字节远的地方。 public long getFilePointer() throws IOException 得到当前读写的位置。,Java的输入输出,65,RandomAccessFile,构造方法如下: RandomAccessFile(File file, String mode) RandomAccessFile(String name, String mode) 第一个参数f
39、ile或name表示文件;第二个参数mode表示对文件的操作方式,mode可以是以下取值,即:,Java的输入输出,66,RandomAccessFile,Java的输入输出,67,RandomAccessFile的使用,RandomAccessFileDemo.java,Java的输入输出,68,I/O小结,流的概念 字节流: InputStream、OutputStream的主要方法 FileInputStream、FileOutputStream DataInputStream、DataOutputSteam 字符流 Reader、Writer FileReader、FileWriter File类的属性和方法 RandomAccess类及其方法、用其读写文件,