Java的IO流是实现输入、输出的基础,它可以方便的实现数据的输入输出操作。在Java中把不同的输入输出源(键盘、文件、网络连接)抽象表述为流(stream)。通过流可以使java程序使用相同的方式访问不同的输入输出源。

一、流的分类

1、按照流的流向分:输入流和输出流

输入流:只能从中读取数据,不能向其写入数据

InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流

输出流:只能向其写入数据,不能从中读取数据

OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流

2、按照流的内容分:字节流和字符流

字节流主要是有InputStream/OutputStream作为基类

字符流主要是有Reader/Writer作为基类

3、按照流的角色分:节点流和处理流

从一个特定的IO设备读/写数据的流称为节点流,在已经存在的流进行连接或封装,封装后的流称为处理流。

二、代码测试

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PushbackReader;
import java.io.RandomAccessFile;
import java.io.Reader;
import org.junit.Test;
public class StreamTest {
/**
* 字节输入流读取文件内容
*
*/
@Test
public void inputStreamTest() {
File f = new File("G://test//a1.txt");
InputStream input = null;
try {
input = new FileInputStream(f);
byte[] bbuf = new byte[1024];
int hasRead = 0;
while((hasRead =input.read(bbuf)) > 0) {
System.out.println(new String(bbuf,0,hasRead));
} } catch (Exception e) {
e.printStackTrace();
}finally {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 字符输入流读取文件内容
*/
@Test
public void fileReaderTest() {
File f = new File("G://test//a1.txt");
Reader reader = null;
try {
reader = new FileReader(f);
char[] cbuf = new char[32];
int hasRead = 0;
while((hasRead = reader.read(cbuf))>0) {
System.out.println(new String(cbuf,0,hasRead));
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 使用FileInputStream输入文件,FileOutPutStream输出文件,实现文件复制
*/
@Test
public void fileOutputStreamTest() {
//字节输入流
FileInputStream fis = null;
byte[] bbuf = new byte[1024];
int hasRead = 0;
//字节输出流
FileOutputStream fos = null;
try {
fis = new FileInputStream("G://test//a1.txt");
fos = new FileOutputStream("G://test//a2.txt");
while((hasRead = fis.read(bbuf))>0) {
fos.write(bbuf, 0, hasRead);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
fos.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 字符输出流
*/
@Test
public void FileWriterTest() {
FileWriter fw =null;
try {
fw = new FileWriter("G://test//a3.txt");
fw.write("窗前明月光");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} /**
* 转换流的使用:InputStreamReader:将字节输入流转换成字符输入流 ,
* OutputStreamWriter将字节输出流转换成字符输出流
*/
public void convertedStreamTest() {
try
(
InputStreamReader reader = new InputStreamReader(new
FileInputStream("G://test//temp.txt"),"UTF-8");
OutputStreamWriter writer = new OutputStreamWriter(new
FileOutputStream("G://test//temp1.txt"),"UTF-8");
)
{
char[] cbuf = new char[32];
int hasRead = 0;
while((hasRead=reader.read(cbuf))>0) {
System.out.print(new String(cbuf, 0, hasRead));
writer.write(cbuf, 0, hasRead);;
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 缓冲流BufferReader:具有缓冲功能,它可以一次读取一行文本(以换行符为标识),如果没有读到换行符,则程序堵塞
* 下面程序键盘输入字符串,只有等到按下回车键后,输入的内容才会打印出来
*/
@Test
public void bufferReaderTest() {
try
(
InputStreamReader reader = new InputStreamReader(System.in);
//用缓存流包装输入流
BufferedReader br = new BufferedReader(reader);
)
{
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 处理流
* 处理流的优势:1、处理流进行输入输出操作更简单 2、使用处理流的效率更高
*
*使用PrintStream 代替 OutputStream
*PrintStream类的输出功能非常强大,通常如果我们要输出文本内容,应该将输出流包装成PrintStream
*/
@Test
public void printStreamTest() { try (
FileOutputStream fos = new FileOutputStream("G://test//a4.txt");
PrintStream ps = new PrintStream(fos);
)
{
//输出字符串
ps.println("使用PrintStream处理流输出文件");
//输出对象
ps.println(new StreamTest());
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 推回输入流PushbackInputStream和PushbackReader
* 推回输入流都带有一个推回缓冲区,当程序调用这两个推回输入流的unread()方法,系统会把指定数组的内容推回到该缓冲区里,而推回输入流每次调用read()方法时总是先
* 从推回缓冲区中读取内容,只有完全读取了缓冲区的内容,但还没有装满read()所需的数组时才会从原输入流中读取。
* 下面程序利用推回缓冲区,返回文件中"rdb"字符串之前的字符串
*/
@Test
public void pushBackTest() {
try
(
//创建PushbackReader对象,指定缓冲区长度为64
PushbackReader pr = new PushbackReader(new FileReader("G://test//a1.txt"),64);
)
{
char[] cbuf = new char[32];
//用于保存上次读取字符串的内容。
String lastContent = "";
int hasRead = 0;
while((hasRead = pr.read(cbuf))>0) {
//将读取内容转换成字符串
String content = new String(cbuf,0,hasRead);
//用于记录 ‘rdb’字符串的位置
int targetIndex = 0;
if((targetIndex = (content + lastContent).indexOf("rdb"))>0) {
//回推包含‘rdb’的字符串
pr.unread((content+lastContent).toCharArray());
int len = targetIndex > 32? 32:targetIndex;
pr.read(cbuf, 0, len);
System.out.print(new String(cbuf,0,len));
System.exit(0);
}else {
System.out.println(lastContent);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 缓冲流BufferReader:具有缓冲功能,它可以一次读取一行文本(以换行符为标识),如果没有读到换行符,则程序堵塞
* 下面程序键盘输入字符串,只有等到按下回车键后,输入的内容才会打印出来
*/
@Test
public void bufferReaderTest() {
try
(
InputStreamReader reader = new InputStreamReader(System.in);
//用缓存流包装输入流
BufferedReader br = new BufferedReader(reader);
)
{
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
} /**
* RandomAcessFile类支持"随机访问的方式".程序可以直接跳转到文件的任意地方来读写数据
* 如果我们只想访问文件的部分内容,使用RandomAcessFile更好
* RandomAcessFile允许自由定位文件记录指针,所以RandomAcessFile可以不从开始的地方开始输出,所以RandomAcessFile可以向已经存在的文件
* 后面追加内容。如果程序想在已存在的文件后追加内容,应该使用RandomAcessFile
*
*/
@Test
public void randomAcessFile() { try (
//创建RandomAccessFile对象时需要一个mode参数
//r:以只读方式打开文件,rw:以读写方式打开文件
//rws:以读写方式打开文件,还要求对文件内容或元数据的每个更新都同步写入底层存储设备
//rwd:以读写方式打开文件,还要求对文件内容的每个更新都同步写入到底层存储设备
RandomAccessFile raf = new RandomAccessFile(new File("G://test//a1.txt"), "rw");
)
{
//RandomAccessFile的文件初始位置,初始是0
System.out.println("文件指针初始位置:"+raf.getFilePointer());
//移动文件指针位置,从移动后的位置开始读取文件内容
raf.seek(32);
byte[] bbuf = new byte[32];
int hasRead = 0;
while((hasRead = raf.read(bbuf))>0) {
System.out.println(new String(bbuf,0,hasRead));
} //指针移动到文件最后
raf.seek(raf.length());
//向文件后追加内容
raf.write("追加内容".getBytes()); } catch (Exception e) {
e.printStackTrace();
} }
}

IO编程之IO流的更多相关文章

  1. python并发编程之IO模型 同步 异步 阻塞 非阻塞

    IO浅谈 首先 我们在谈及IO模型的时候,就必须要引入一个“操作系统”级别的调度者-系统内核(kernel),而阻塞非阻塞是跟进程/线程严密相关的,而进程/线程又是依赖于操作系统存在的,所以自然不能脱 ...

  2. python并发编程之IO阻塞基础知识点

    IO模型 解决IO问题的方式方法 问题是:IO操作阻塞程序执行 解决的也仅仅是网络IO操作   一般数据传输经历的两个阶段,如图: IO阻塞模型分类: 阻塞IO 非阻塞IO 多路复用IO 异步IO(爬 ...

  3. Python并发编程之IO模型

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) IO多路复用 异步IO IO模型比较分析 selectors模块 一.IO模型介绍 Stevens ...

  4. 服务器端网络编程之 IO 模型

    引言  从 T 跳槽到 A 之后,我的编程语言也从 C++ 转为 了 Java.在 T 做的偏服务器端开发,而在 A 更偏向于业务开发.上周在 A 公司组内做了一个<服务器端高性能网络编程> ...

  5. python并发编程之IO模型,

    了解新知识之前需要知道的一些知识 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调 ...

  6. 并发编程之IO模型

    一.阻塞IO(blocking IO) from concurrent.futures import ThreadPoolExecutor import socket server = socket. ...

  7. 网络编程之IO模型

    IO模型的分类 blocking IO:阻塞IO nonblocking IO:非阻塞IO IO multiplexing:IO多路复用 signal driven IO:异步IO 通常情况下IO默认 ...

  8. python----并发编程之IO模型

    一:IO模型介绍  同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个 ...

  9. Python之旅:并发编程之IO模型

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

随机推荐

  1. RTOS诊断和错误检查

    RTOS诊断和错误检查 RTOS diagnostics and error checking 查看RTOS显示系列 错误处理不太可能是任何用于嵌入式系统应用程序的操作系统的主要功能.这是资源限制的必 ...

  2. MySQL面试题汇总

    事务是什么? 一系列操作,要么全部完成,要么一个都不做 事务的ACID特性 原子性:一系列操作要么都执行,要么都不执行 一致性:事务执行前后数据完整性不变,如转账前后总金额不变 隔离性:多个事务并发访 ...

  3. JDBC连接MySQL、Oracle和SQL server的配置

    什么是JDBC 我们可以将JDBC看作是一组用于用JAVA操作数据库的API,通过这个API接口,可以连接到数据库,并且使用结构化查询语言(SQL)完成对数据库的查找,更新等操作. JDBC连接的流程 ...

  4. halcon——缺陷检测常用方法总结(测量拟合)

    引言 机器视觉中缺陷检测分为一下几种: blob分析+特征 模板匹配(定位)+差分:halcon--缺陷检测常用方法总结(模板匹配(定位)+差分) - 唯有自己强大 - 博客园 (cnblogs.co ...

  5. 137. 只出现一次的数字 II

    2021-04-30 LeetCode每日一题 链接:https://leetcode-cn.com/problems/single-number-ii/ 方法1:使用map记录每个数出现的次数,再找 ...

  6. Redis五种基础与三种高级数据结构解析

    记得点赞+关注呦. 前言 在 Redis 最重要最基础就属 它丰富的数据结构了,Redis 之所以能脱颖而出很大原因是他数据结构丰富,可以支持多种场景.并且 Redis 的数据结构实现以及应用场景在面 ...

  7. Android Gradle插件

    目录 什么是Gradle 编写方法 buildSrc 基础概念 Extension 自定义Task Plugin Transformer Gradle用处 好文章 常见问题 Gradle插件练习地址: ...

  8. 「10.29」数列(exgxd)·数对(线段树优化DP)·最小距离(最短路,树上直径思想)

    好久没碰到这么友好乱搞的题了.... A. 数列 考察的是exgcd的相关知识,最后的答案直接O(1)求即可 B. 数对 本来以为是原题,然后仔细看了看发现不是,发现不会只好乱搞骗分了 事实上直接按$ ...

  9. expdp数据泵导出数据汇总

    [oracle@enmo1 ~]$ mkdir datadump[oracle@enmo1 ~]$ cd datadump/[oracle@enmo1 datadump]$ pwd/home/orac ...

  10. 【spring源码系列】之【Bean的生命周期】

    为源码付出的每一分努力都不会白费. 1. Bean的实例化概述 前一篇分析了BeanDefinition的封装过程,最终将beanName与BeanDefinition以一对一映射关系放到beanDe ...