当前位置: 代码迷 >> 综合 >> JAVAOOP-16 IO流
  详细解决方案

JAVAOOP-16 IO流

热度:3   发布时间:2023-11-27 11:04:07.0

  • JAVAOOP-16 IO流
    • 一. 流的概念
    • 二. 流的分类
    • 三. 流的体系结构
    • 四. 字节流
      • 1. FileOutputStream 和 FileInputStream
      • 2. 文件太大,如何读取?
      • 3. 写入时如何在文件末尾追加而不是覆盖?
      • 4. DataOutputStream 和 DataInputStream
      • 5. 练习: 如何实现文件复制功能?

JAVAOOP-16 IO流

一. 流的概念

流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
? 一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
? 流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。
? 实际上,流的源端和目的端可简单地看成是字节的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。

? 形象的比喻——水流 ,文件**======**程序 ,文件和程序之间连接一个管道,水流就在之间形成了,自然也就出现了方向:可以流进,也可以流出.便于理解,这么定义流: 流就是一个管道里面有流水,这个管道连接了文件和程序。

二. 流的分类

  1. 按输入输出分:

    ? 输入流: Reader, InputStream类型的子类

    ? 输出流: Writer, OutputStream类型的子类

  2. java.io包中的类对应两类流,一类流直接从指定的位置(如磁盘文件或内存区域)读或写,这类流称为结点流(node stream),其它的流则称为过滤器(filters)。过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后再以新的输入流的形式提供给用户,过滤器输出流的原理也类似

  3. java.io包中的stream类根据它们操作对象的类型是字符还是字节可分为两大类: 字符流和字节流。

  • Java的字节流

InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。

  • Java的字符流

Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。

字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

注意: 输入输出流是相对于内存来说的,

? 输入内存也就是 读取的过程 输入流就是读取操作

? 从内存输出也就是写入过程 输出流也就是写入操作

三. 流的体系结构

JAVA字节流

  • **FileInputStream和FileOutputStream

    **这两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。如:
    FileInputStream infile = new FileInputStream(“myfile.dat”);
    FileOutputStream outfile = new FileOutputStream(“results.dat”);

要注意的是,构造FileInputStream, 对应的文件必须存在并且是可读的,而构造FileOutputStream时,如输出文件已存在,则必须是可覆盖的。

  • BufferedInputStream和BufferedOutputStream
    它们是过滤器流,其作用是提高输入输出的效率。
  • DataInputStream和DataOutputStream
    这两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出。

Java的字符流

字符流主要是用来处理字符的。Java采用16位的Unicode来表示字符串和字符,对应的字符流按输入和输出分别称为readers和writers。

  • InputStreamReader和OutputStreamWriter
    在构造这两个类对应的流时,它们会自动进行转换,将平台缺省的编码集编码的字节转换为Unicode字符。对英语环境,其缺省的编码集一般为ISO8859-1。
  • BufferedReader和BufferedWriter
    这两个类对应的流使用了缓冲,能大大提高输入输出的效率。这两个也是过滤器流,常用来对InputStreamReader和OutputStreamWriter进行处理。

四. 字节流

1. FileOutputStream 和 FileInputStream

OutputStream 输出流 抽象类 不能直接使用 使用子类FileOutputStream 从某个文件里面读取

普通方法:

abstract void write(int b) 将指定的字节写入此输出流。
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
void close() 关闭此输出流并释放与此流有关的所有系统资源。

InputStream 输入流 抽象类 不能直接使用 使用子类FileInputStream 写入到某个文件里

普通方法:

abstract int read() 从输入流中读取数据的下一个字节。

int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
void close() 关闭此输入流并释放与该流关联的所有系统资源。

FileOutputStream:
FileOutputStream(File file)
? 创建一个向指定 File 对象表示的文件中写入数据的文件输出流
FileOutputStream(File file, boolean append)
? 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name)
? 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
? 创建一个向具有指定 name 的文件中写入数据的输出文件流。
void write(int b)
? 将指定字节写入此文件输出流。

FileInputStream:

FileInputStream(File file)
? 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(String name)
? 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

int read()
? 从此输入流中读取一个数据字节。

思路:

  1. 构建输入输出流对象
  2. 读取或者写入数据
  3. 关闭流
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class TesrRW {
    public static void main(String[] args) throws IOException {
    TesrRW rw=new TesrRW();rw.doWrite();rw.doRead();}//写信息到文件
public void doWrite() throws IOException{
    //建立管道,构建(打开)输出流OutputStream out=new FileOutputStream("D:\\day17\\aaa.txt");//针对输入输出流进行操作(写入信息)out.write(8);out.write('a');out.write('b');//写完之后,关闭输出流(关闭资源)out.close();
}
//读取文件
public void doRead(){
    //打开输入流InputStream in=null;try {
    in=new FileInputStream("D:\\day17\\aaa.txt");int one=in.read();int two=in.read();int three=in.read();System.out.println(one+" "+(char)two+" "+(char)three);}catch (IOException e) {
    // TODO Auto-generated catch blocke.printStackTrace();}//关闭输入流finally{
    if(in!=null){
    try {
    in.close();} catch (IOException e) {
    // TODO Auto-generated catch blocke.printStackTrace();}}}}
}

2. 文件太大,如何读取?

思路: 通过循环来实现

public int read() throws IOException从此输入流中读取一个数据字节。如果没有输入可用,则此方法将阻塞。

指定者:类 InputStream 中的 read
返回:下一个数据字节;如果已到达文件末尾,则返回 -1。
抛出: IOException - 如果发生 I/O 错误。

当读取到最后的时候, int read() 返回值为-1 ,此时则为判断条件

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;public class TestRFile {
    public static void main(String[] args) throws IOException {
    readFile();}public static void readFile() throws IOException{
    String filePath="D:\\2015.7.27初级班\\day17\\TesrRW.java";InputStream in=new FileInputStream(filePath);//文件太大,不知道有多少字节int data=-1;//当读完的时候,返回值为-1,data表示读取道德字节while((data=in.read())!=-1){
    System.out.print((char)data);}in.close();}}

3. 写入时如何在文件末尾追加而不是覆盖?

构造方法:

FileOutputStream(File file, boolean append)
? 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

FileOutputStream(String name, boolean append)
? 创建一个向具有指定 name 的文件中写入数据的输出文件流。

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class TestWF {
    public static void main(String[] args) throws IOException {
    doWrite();}public static void doWrite() throws IOException{
    OutputStream out=new FileOutputStream("D:\\day17\\b.txt",true);out.write('z');out.close();}}

4. DataOutputStream 和 DataInputStream

? 属于过滤流,在其他输入输出流的基础之上增加新的功能

DataInputStream:

DataInputStream(InputStream in)
? 使用指定的底层 InputStream 创建一个 DataInputStream。

int read(byte[] b)
? 从包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组 b 中。
int read(byte[] b, int off, int len)
? 从包含的输入流中将最多 len 个字节读入一个 byte 数组中。
boolean readBoolean()
? 参见 DataInput 的 readBoolean 方法的常规协定。
byte readByte()
? 参见 DataInput 的 readByte 方法的常规协定。
char readChar()
? 参见 DataInput 的 readChar 方法的常规协定。
double readDouble()
? 参见 DataInput 的 readDouble 方法的常规协定。
float readFloat()
? 参见 DataInput 的 readFloat 方法的常规协定。
int readInt()
? 参见 DataInput 的 readInt 方法的常规协定。
long readLong()
? 参见 DataInput 的 readLong 方法的常规协定。
short readShort()
? 参见 DataInput 的 readShort 方法的常规协定。
int readUnsignedShort()
? 参见 DataInput 的 readUnsignedShort 方法的常规协定。
String readUTF()
? 参见 DataInput 的 readUTF 方法的常规协定。

DataOutputStream:

DataOutputStream(OutputStream out)
? 创建一个新的数据输出流,将数据写入指定基础输出流。
void flush()
? 清空此数据输出流。
void write(byte[] b, int off, int len)
? 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入基础输出流。
void write(int b)
? 将指定字节(参数 b 的八个低位)写入基础输出流。
void writeBoolean(boolean v)
? 将一个 boolean 值以 1-byte 值形式写入基础输出流。
void writeByte(int v)
? 将一个 byte 值以 1-byte 值形式写出到基础输出流中。
void writeBytes(String s)
? 将字符串按字节顺序写出到基础输出流中。
void writeChar(int v)
? 将一个 char 值以 2-byte 值形式写入基础输出流中,先写入高字节。
void writeChars(String s)
? 将字符串按字符顺序写入基础输出流。
void writeDouble(double v)
? 使用 Double 类中的 doubleToLongBits 方法将 double 参数转换为一个 long 值,然后将该 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。
void writeFloat(float v)
? 使用 Float 类中的 floatToIntBits 方法将 float 参数转换为一个 int 值,然后将该 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。
void writeInt(int v)
? 将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。
void writeLong(long v)
? 将一个 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。
void writeShort(int v)
? 将一个 short 值以 2-byte 值形式写入基础输出流中,先写入高字节。
void writeUTF(String str)
? 以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class TestData {
    public static void main(String[] args) throws IOException {
    writeData();readData();}public static void writeData() throws IOException{
    OutputStream out=new FileOutputStream("D:\\day17\\bbb.txt");DataOutputStream dos=new DataOutputStream(out);//过滤流,包装一个基本输入输出流,在基本IO流的基础上增加新的功能,提高效率//管道建立成功,接着传输数据//DataOutputStream dos2=new DataOutputStream(new FileOutputStream("D:\\day17\\bbb.txt"));//也可以写成上面那样//写入8中基本数据类型byte b=1;short s=2;int i=3;long l=4;float f=5.0f;double d=6;char c='7';boolean bl=false;String str="开心点吧";dos.writeByte(b);dos.writeShort(s);dos.writeInt(i);dos.writeLong(l);dos.writeFloat(f);dos.writeDouble(d);dos.writeChar(c);dos.writeBoolean(bl);dos.writeUTF(str);dos.close();}public static void readData() throws IOException{
    InputStream in=new FileInputStream("D:\\2015.7.27初级班\\day17\\bbb.txt");DataInputStream  dis=new DataInputStream(in);//包装输入流//读取文件,一定要遵从当初写的顺序byte b=dis.readByte();short s=dis.readShort();int i=dis.readInt();long l=dis.readLong();float f=dis.readFloat();double d=dis.readDouble();char c=dis.readChar();boolean bl=dis.readBoolean();String str=dis.readUTF();System.out.println(b+" "+s+" "+i+" "+l+" "+f+" "+d+" "+c+" "+bl +" "+str);dis.close();}
}

5. 练习: 如何实现文件复制功能?

思路: 复制文件其实就是边读边写的过程

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;public class TestCopy {
    public static void main(String[] args) throws IOException {
    String src="D:\\TesrRW.java";String tar="D:\\day17\\b.txt";doCopy(src, tar);}public static void doCopy(String src,String tar) throws IOException{
    InputStream fis=new FileInputStream(src);OutputStream fos=new FileOutputStream(tar);//复制文件其实就是边读边写的过程int data=-1;while((data=fis.read())!=-1){
    fos.write(data);}fis.close();fos.close();}}