当前位置: 首页 > article >正文

字节流的介绍与使用

什么是流

在Java中,对数据读写操作, 需要使用流来操作(流是指一连串流动的数据信号,是以先进先出的方式发送和接收数据的通道) , 换句话说,想要对数据进行读和写操作,就得利用流去完成 。

流的分类

⊙ : \odot: :根据流动方向的不同,流分为输入流和输出流;

⊙ : \odot: :对于输入和输出流,由于传输格式的不同,又分为字节流和字符流:

A : \mathbb{A}: A:字节流是指8位的通用字节流,以字节为基本单位,在java.io包中,对于字节流进行操作的类大部分继承于InputStream(输入字节流)类和OutputStream(输出字节流)类;

B : \mathbb{B}: B:字符流是指16位的Unicode字符流,以字符(两个字节)为基本单位,非常适合处理字符串和文本,对于字符流进行操作的类大部分继承于Reader(读取流)类和Writer(写入流)类。

IO流体系结构介绍

InputStream和OutputStream

InputStream

字节输入流的父类,抽象类,无法实例化
• available() :获取到当前字节流对象的内容长度
• close() :关闭流资源
• reset() :重置指针的位置,回到最初的位置
• skip(long n) :往前或者往后移动指定长度个位置
• read() :读取指定的文件内容,每次读取一个字节
• read(byte[] b) :读取指定的文件内容,每次读取一个字节数组
• read(byte[] b, int off, int len) :读取指定的文件内容,每次读取一个字节数组,从数组的off的位置开始读取,读取len长度

OutputStream

字节输出流的父类,抽象类,无法实例化
• flush() :刷新缓冲区,让缓冲区里的内容强制输出
• close() :关闭流资源
• write() :读取指定的文件内容,每次读取一个字节

字节流的介绍:输入流(读)

⊙ : \odot: :FileInputStream类称为文件输入流,继承于InputStream类,是进行文件读操作的最基本类;

⊙ : \odot: :它的作用是将文件中的数据输入到内存中,我们可以利用它来读文件;

⊙ : \odot: :由于它属于字节流,因此在读取Unicode字符(如中文)的文件时可能会出现问题

一个一个字节读

/**
 * 
 * 进行输入流的基本操作:一个字节的操作
 *
 */
public class FileInputStreamDemo {
    public static void main(String[] args) {
        File file = new File("t1.txt");
        // 创建一个字节流的对象
        InputStream is = null;
        try {
            is = new FileInputStream(file);
            // 通过这字节流来进行读取文件
            for (int i = 0; i < file.length(); i++) {
                // 读取每一个字节,然后进行强转成char
                char ch = (char) is.read();
                // 输出
                System.out.println(ch);
            }
            // 当已经把文件完成了读取之后,此时的指针的位置应该在最后,那么我再进行读取的话,会怎么样
            System.out.println(is.read());// 已经读完了的话,会返回-1
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (is != null)
                    is.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

字节数组作为读的缓冲区

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * 
 * 	使用字节数组作为它的缓冲区的读操作
 *
 */
public class FileInputStreamDemo1 {
	public static void main(String[] args) {
		// 创建一个字节流的对象
		InputStream is = null;
		try {
			is = new FileInputStream("t1.txt");
			// 构建一个字节数组作为缓冲区,这里默认使用文件大小作为缓冲区大小
			// 在真实开发过程中,要根据实际情况来调整缓冲区的大小
//				byte [] buff = new byte[512*1024];//512K
			byte[] buff = new byte[is.available()];// 512K
			// 使用缓冲区来进行读文件
			is.read(buff);
			// 把缓冲区里面的内容通过String的构造函数的形式来获取出来
			String content = new String(buff);
			// 内容的输出
			System.out.println(content);
			// 当已经把文件完成了读取之后,此时的指针的位置应该在最后,那么我再进行读取的话,会怎么样
			System.out.println(is.read());// 已经读完了的话,会返回-1
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (is != null)
					is.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
}

小字节数组循环读取

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
 * 
 * 	使用字节数组作为它的缓冲区的读操作,使用循环来完成所有文件的读取工作
 * 字节流+自定义大小的缓冲区这种读取的方式,就是我们工作中使用最为频繁的方式
 *
 */
public class FileInputStreamDemo2 {
	public static void main(String[] args) {
		// 创建一个字节流的对象
		InputStream is = null;
		try {
			is = new FileInputStream("t1.txt");
			//定义一个缓冲区,大小是小于文件大小的,所以我们要使用循环来进行读取
			byte[] buff = new byte[2];// 512K
			//定义一个用来判断下标的int类型的变量index
			int index;
			//使用while循环来进行判断是否读到了末尾
			while((index = is.read(buff))!=-1) {
				System.out.println(new String(buff));
			}
			// 当已经把文件完成了读取之后,此时的指针的位置应该在最后,那么我再进行读取的话,会怎么样
			System.out.println(is.read());// 已经读完了的话,会返回-1
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (is != null)
					is.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}
}

字节流的介绍:输出流(写)

输出流概述

⊙ : \odot: :FileOutputStream类称为文件输出流,继承于OutputStream类,是进行文件写操作的最基本类;

⊙ : \odot: :它的作用是将内存中的数据输出到文件中,我们可以利用它来写文件。

一个一个字节写

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo {
	public static void main(String[] args) {
		//定义一个字符串,用来进行写入到文件里面去
		String source = "Hello World!";
		//构建一个文件输出流对象
		FileOutputStream fos = null;
		try {
			File file = new File("t2.txt");
			//第二个参数代表你是否进行内容的追加操作,默认是false:不追加
			fos = new FileOutputStream(file,true);
			//使用循环来进行内容的写入操作
			for(int i = 0;i<source.length();i++) {
				fos.write(source.charAt(i));
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if(fos!=null)
					fos.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

字节数组作为写的缓冲区

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo1 {
	public static void main(String[] args) {
		//定义一个字符串,用来进行写入到文件里面去
		String source = "I love Java!";
		//构建一个文件输出流对象
		FileOutputStream fos = null;
		try {
			//第二个参数代表你是否进行内容的追加操作,默认是false:不追加
			fos = new FileOutputStream("t2.txt",true);
			//构建一个缓冲区
			byte [] buff = source.getBytes();
			//进行缓冲区的写入
			fos.write(buff);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if(fos!=null)
					fos.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

过滤流之缓冲流

过滤流的介绍

我们直接使用字节流(也称之为节点流)操作文件的时候,默认操作是一个个的字节,但是很多时候,我们希望读写的不仅仅是一个字节,而是一个字符串、一个double类型的数据等等能够直接用的数据,那么此时,我们就需要借助过滤流来进行操作了,过滤流又称之为处理流、包装流等名词,不管怎么称呼它,它都是在字节流的基础上方便我们操作文件的间接流,它不能直接操作文件。

缓冲流的介绍

在内存与硬盘之间创建一个大小合适的缓冲区,当内存和硬盘进行数据访问时,能够减少访问硬盘的次数,提高效率。缓冲分为字节缓冲流(BufferedInputStream 和 BufferedOutputStream)以及字符缓冲流(BufferedReader 和 BufferedWriter)。

注意:缓冲流其实就是自动帮我们创建了一个缓冲区而已,你想灵活使用的话,仍然可以使用字节流+缓冲区的方式来操作。

一边读一边写

自定义字符数组作缓冲区

	private static void testBufferedArea(String path) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream(path);
			fos = new FileOutputStream("d:api.chm");
			byte[] buff = new byte[1024*512];
			//代表的是指针的位置
			int index;
			while((index = fis.read(buff))!=-1) {
				//index作为写的长度来避免最后一次写得过多
				//fos.write(buff)最后一次写的长度也是1024*512B,但最后面肯很多空字符
				fos.write(buff,0,index);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fis != null)
					fis.close();
				if(fos!=null)
					fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

使用缓冲流(无需自定义缓冲区)

使用缓冲流内部创建字符数组,无需我们手动实现

	private static void testBufferedStream(String path) {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(path));
			bos = new BufferedOutputStream(new FileOutputStream("d:api1.chm"));
			//data代表的就是一个缓冲区的数据
			int data;
			while((data = bis.read())!=-1) {
				bos.write(data);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (bis != null)
					bis.close();
				if(bos!=null)
					bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

完整代码

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 
 * 该类用来对比字节流+缓冲区以及字节流+过滤流(缓冲流)的写法区别
 * 思考:他们的效率区别,注意多调整下缓冲区的大小
 *
 */
public class BufferedStreamDemo {
	public static void main(String[] args) {
		String path = "C:\\Users\\Desktop\\JDK_API_1_6_zh_CN.CHM";
//		testBufferedArea(path);
		testBufferedStream(path);
	}

	private static void testBufferedStream(String path) {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			bis = new BufferedInputStream(new FileInputStream(path));
			bos = new BufferedOutputStream(new FileOutputStream("d:api1.chm"));
			//data代表的就是一个缓冲区的数据
			int data;
			while((data = bis.read())!=-1) {
				bos.write(data);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (bis != null)
					bis.close();
				if(bos!=null)
					bos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static void testBufferedArea(String path) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream(path);
			fos = new FileOutputStream("d:api.chm");
			byte[] buff = new byte[1024*512];
			//代表的是指针的位置
			int index;
			while((index = fis.read(buff))!=-1) {
				//index作为写的长度来避免最后一次写得过多
				//fos.write(buff)最后一次写的长度也是1024*512B,但最后面肯很多空字符
				fos.write(buff,0,index);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fis != null)
					fis.close();
				if(fos!=null)
					fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

http://www.kler.cn/a/547686.html

相关文章:

  • PAT乙组(1016 部分A+B 1017 A除以B)C语言超详细
  • LM Studio笔记
  • 【人工智能】如何选择合适的大语言模型,是能否提高工作效率的关键!!!
  • 云计算——AWS Solutions Architect – Associate(saa)7.放置群组
  • print(f“Random number below 100: {random_number}“)的其他写法
  • 了解rtc_time64_to_tm()和rtc_tm_to_time64()
  • Biopython PDB模块的PDBParser和MMCIFParser介绍
  • 如何使用CSS画一个三角形,原理是什么?
  • DeepSeek操作Excel,实现图表自动化生成
  • LLaMA-Factory DeepSeek-R1 模型 微调基础教程
  • 【ISO 14229-1:2023 UDS诊断全量测试用例清单系列:第十二节】
  • PLC跨平台通信困难?DeepSeek边缘计算网关实现数据无缝连接!
  • 【PSIM】RS触发器的使用
  • 08模拟法 + 技巧 + 数学 + 缓存(D2_技巧)
  • 【自学笔记】深度学习基础知识点总览-持续更新
  • 《Spring实战》(第6版)第2章 开发Web应用
  • 基于STM32的智能鱼塘养殖监控系统
  • 【动态路由】系统Web URL资源整合系列(后端技术实现)【nodejs实现】
  • 免费deepseek的API获取教程及将API接入word或WPS中
  • 安装 Docker Desktop 修改默认安装目录到指定目录