Java地基(十四)----IO流

1. 流是什么?

在计算机中,流是个抽象的概念,是对输入输出设备的抽象。在Java程序中,对于数据的输入/输
出操作,都是以"流"的方式进行

数据以二进制的形式在程序与设备之间流动传输,就像水在管道里流动一样,所以就把这种数据传输的
方式称之为输入流、输出流。这里描述的设备,可以是文件、网络、内存等

流具有方向性,可以分为输入和输出。

在这里插入图片描述

2. 流的分类

输入流输出流
字节流字节输入流字节输出流
字符流z字符输入流字符输出流

注意,字节指的是byte,字符指的的是char

3. 流的结构

几乎所有的流,都是派生自四个抽象的父类型:

  • InputStream ,代表字节输入流类型
  • OutputStream ,代表字节输出流类型
  • Reader ,代表字符输入流类型
  • Writer ,代表字符输出流类型

在这里插入图片描述

4.一叶知秋:节点流

4.1字节流

三个基本方法

//每次读一个字节,返回值是本次读取的字节值
public abstract int read() throws IOException;
//每次读多个字节,并存放到指定的字节数组中,返回值是本次一共读取了多个字节(字节数)
public int read(byte b[]) throws IOException {
	return read(b, 0, b.length);
} 
//每次读多个字节,并存放到指定的字节数组中,返回值是本次一共读取了多个字节(字节数)
//同时可以指定从数组的什么位置开始存放,以及在数组中最多存放多个字节
public int read(byte b[], int off, int len) throws IOException {
	if (b == null) {
		throw new NullPointerException();
	} else if (off < 0 || len < 0 || len > b.length - off) {
		throw new IndexOutOfBoundsException();
	} else if (len == 0) {
		return 0;
	} 
    int c = read();
	if (c == -1) {
		return -1;
   		b[off] = (byte)c;
		int i = 1;
		try {
			for (; i < len ; i++) {
				c = read();
				if (c == -1) {
					break;
				} 
            	b[off + i] = (byte)c;
			}
		} catch (IOException ee) {
	} 
    return i;
}
  • 控制台的读取与输出

    在System中已经初始化所以不需要new

    InputStream in = System.in;

  • 字节数组的读取与输出

    InputStream in = new ByteArrayInputStream

    将数据写入到了out对象中的属性里面,该属性是一个字节数组
    out.write(buf,0,len);

  • 管道的输入与输出

    用于操作多线程的

    InputStream in =new PipedInputStream

    public class Test {
    	public static void main(String[] args) {
    		PipedReader in = null;
    		PipedWriter out = null;
    		in = new PipedReader();
    		out = new PipedWriter();
    		try {
    			//管道对接
    			in.connect(out);
    			Thread t1 = new WriteThread(out);
    			Thread t2 = new ReadThread(in);
    			t1.start();
    			t2.start();
                t1.join();
    			t2.join();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		} 
            System.out.println();
    		System.out.println("程序运行结束!");
    	}
    } 
    class WriteThread extends Thread{
    	private Writer out;
    	public WriteThread(Writer out){
    		this.out = out;
    	} 
        @Override
    	public void run() {
    		char[] arr = "hello world briup".toCharArray();
    		try {
    			for(int i=0;i<arr.length;i++){
    				out.write(arr[i]);
    				out.flush();
    				Thread.sleep(1000);
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		} finally {
    			if(out!=null) {
    				try {
    					out.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    } 
    class ReadThread extends Thread{
    	private PipedReader in;
    	public ReadThread(PipedReader in){
    		this.in = in;
    	}
        @Override
    	public void run() {
    		int data = -1;
    		try {
    			while((data=in.read())!=-1){
    				//System.out.print(data);
    				System.out.write(data);
    				System.out.flush();
    			} 
                System.out.flush();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			if(in!=null) {
    				try {
    					in.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    	}
    }
    
  • 文件的输入与输出

    InputStream in =new FileInputStream

4.2 文件的操作

File file = new File(pathname);

public String getAbsolutePath() //返回绝对路径

public String getPath() //返回创建时传入的路径可能是相对路径

public boolean exists() //判断此文件或目录是否真的存在

public boolean isDirectory() //判断File表示的是否是一个目录

public boolean isFile() //判断file表示的是否是一个文件

public String[] list() //返回目录中所有的子文件或子目录,返回值是String类型数组

public File[] listFiles() //返回目录中所有的子文件或子目录,返回值是File类型数组

4.3 类比字节流还有字符流

Writer 和Reader只适用于读写字符数据的场景

5. 辅助流:辅助操作流

5.1数据流

java.io.DataOutputStream ,可以将指定类型的数据 转换为 字节,并写出去

//3.使用流
out.writeLong(1000L);
out.flush();
//将写入的数据转为字节数组并返回
byte[] toByteArray = byteArrayOutputStream.toByteArray();
System.out.println(Arrays.toString(toByteArray));
//运行结果
[0, 0, 0, 0, 0, 0, 3, -24]
5.2 缓冲流

提供一个缓冲池即一个数组,做到一次读一次写,节省时间

字符缓冲返回的是String

字节返回的是int

java.io.BufferedInputStream ,负责给字节输入流提供缓冲功能

java.io.BufferedReader ,负责给字符输入流提供缓冲功能

java.io.BufferedWriter ,负责给字符输出流提供缓冲功能 创建新行

java.io.PrintWriter ,一次写一行,写完之后自动加换行,一般和BufferedReader 搭配使用

5.3 转换流

将字节流转换为字符流,注意编码方式

//将字节流转换为字符流
outputStreamWriter = new OutputStreamWriter(newFileOutputStream(file),"UTF-8");
//“包裹”转换流,增强这个字符流的功能,可以一次写出一行字符串,并自动换行
//注意,转换流同时也是一个字符流
out = new PrintWriter(outputStreamWriter);
5.4对象流

将数组 ,创建的对象序列化为字节存储,

前提:该对象实现了java.io.Serializable 接口 ,集合已经实现类

  • 一个字节序列来表示一个对象,该字节序列包含了对象的类型、对象中的数据等
  • java.io.ObjectOutputStream ,将Java对象转换为字节序列,并输出到内存、文件、网络等地方
    注意,具体输出到什么地方,要看 ObjectOutputStream “包裹”的是哪一个节点流

transient :可以修饰类中的属性,它是让对象在进行序列化的时候,忽略掉指定的属性

private transient int age;

序列化版本号:当你没有定义时,每修改一次对象就会更改一次序列化号,那么你存储在文件中的对象反序列化后就会识别序列号报错。所以定义一个固定的序列化号

5.5.随机流

java.io.RandomAccessFile它并没有继承之前介绍到的那四个抽象父类型

创建该类的对象时,需要指定要操作的文件和操作的模式:

  • “r” 模式,以只读方式来打开指定文件夹。如果试图对该RandomAccessFile执行写入方法,都将抛出IOException异常。
  • “rw” 模式,以读写方式打开指定文件。如果该文件尚不存在,则试图创建该文件。
  • “rws” 模式,以读写方式打开指定文件。相对于”rw” 模式,还要求对文件内容或元数据的每个更新都同步写入到底层设备。
  • “rwd” 默认,以读写方式打开指定文件。相对于”rw” 模式,还要求对文件内容每个更新都同步写入到底层设备

使用

public static void main(String[] args) {
    //randomAccessFile负责读取文件内容以及向文件中写内容
    RandomAccessFile randomAccessFile = null;
    try {
        File file = new File("src/main/java/com/briup/demo/a.txt");
        //文件中要替换数据的位置
        int replacePos = 6;
        //文件中要插入的内容
        String replaceContent = "briup";
        //设置randomAccessFile为读写模式
        randomAccessFile = new RandomAccessFile(file,"rw");
        byte[] buf = new byte[1024];
        int len = -1;
        //randomAccessFile定位到要替换数据的位置,准备去写要替换的内容
        //注意,原内容和新内容的字节数恰好相等
        randomAccessFile.seek(replacePos);
        //在指定位置,写入需要替换的内容,覆盖原来此位置上的内容
        randomAccessFile.write(replaceContent.getBytes());
        //randomAccessFile定位到文件的开始位置,准备去读文件中的所有内容,并输出到控制台
        randomAccessFile.seek(0);
        while((len=randomAccessFile.read(buf))!=-1){
            System.out.write(buf,0,len);
        } 
        System.out.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        if(randomAccessFile!=null){
            try {
                randomAccessFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
} 
//运行结果:
    hello briup123
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值