Java基础之IO流(二)
I/O 工作原理
磁盘I/O
tips: DMA:全称叫直接内存存取(Direct Memory Access),是一种允许外围设备(硬件子系统)直接访问系统主内存的机制。基于 DMA 访问方式,系统主内存与硬件设备的数据传输可以省去CPU 的全程调度
特点
- 读写操作基于系统调用实现
- 读写操作经过用户缓冲区,内核缓冲区,应用进程并不能直接操作磁盘
- 应用进程读操作时需阻塞直到读取到数据
网络I/O
特点
- 网络I/O读写操作经过用户缓冲区,Sokcet缓冲区
- 服务端线程在从调用recvfrom开始到它返回有数据报准备好这段时间是阻塞的,recvfrom返回成功后,线程开始处理数据报
字节流
在上一篇中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据。现在我们就要开始给文件中写数据,或者读取文件中的数据
字节输出流OutputStream
OutputStream此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法 输出流中定义都是写write方法
FileOutputStream类
OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件 FileOutputStream类,即文件输出流,是用于将数据写入 File 的输出流
将数据写到文件中
/**
* 将数据写到文件中
*/
public static void test1() throws IOException {
// 创建存储数据的文件
File file = new File("e:\file.txt");
// 创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
// 输出流目的是文件,会自动创建。如果文件存在,则覆盖。
FileOutputStream fos = new FileOutputStream(file);
// 写入数据
byte[] data = "abcde".getBytes();
// 调用父类的write方法
fos.write(data);
// 关闭流资源
fos.close();
}
我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?
给文件中续写数据和换行
/**
* 给文件中续写数据和换行
*/
public static void test2() throws IOException {
File file = new File("e:\file.txt");
// append true 表示可追加,默认是false
FileOutputStream fos = new FileOutputStream(file, true);
String str = "rn" + "Hello";
// 调用父类的write方法
fos.write(str.getBytes());
// 关闭流资源
fos.close();
}
字节输入流InputStream
InputStream此抽象类,是表示字节输入流的所有类的超类,定义了字节输入流的基本共性功能方法
int read():读取一个字节并返回,没有字节返回-1
int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数
FIleInputStream 类
InputStream有很多子类,其中子类FileInputStream可用来读取文件内容 FileInputStream 从文件系统中的某个文件中获得输入字节
在读取文件中的数据时,调用read方法,实现从文件中读取数据 如果返回的是-1,说明流已经读完了
读取文件内容
/**
* 读取文件内容
*/
public static void test3() throws IOException {
File file = new File("e:\file.txt");
// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
// 读取数据。使用 read() 一次读一个字节。
int ch = 0;
// 循环读取内容
while ((ch = fis.read()) != -1) {
System.out.println("ch = " + (char)ch);
}
// 关闭资源
fis.close();
//ch = a
//ch = b
//ch = c
//ch = d
//ch = e
//ch =
//ch =
//
//ch = H
//ch = e
//ch = l
//ch = l
//ch = o
}
读取数据read(byte[])方法 在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符,返回读取到的位置。如果是-1说明读完了
/**
* 读取文件内容
* read(byte[] b)
*/
public static void test4() throws IOException {
File file = new File("e:\file.txt");
// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
FileInputStream fis = new FileInputStream(file);
// 创建一个字节数组,长度可以定义成1024的整数倍。
byte[] buf = new byte[1024];
int len = 0;
// 循环读取内容
while ((len = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0 ,len));
}
// 关闭资源
fis.close();
//abcde
//Hello
}
字节流复制图片
/**
* 字节流复制图片
*/
public static void test5() throws IOException {
// 1. 明确源和目的
File srcFile = new File("e:\1.jpg");
File destFile = new File("e:\1copy.jpg");
// 2. 明确字节流 输入流和源相关联,输出流和目的关联
FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
// 3. 使用输入流的读取方式读取字节,并将字节写入到目的中
// 先定义一个缓冲区
byte[] buf = new byte[1024];
int len = 0;
// 循环读取
while ((len = fis.read(buf)) != -1) {
// 将数组中的指定长度的数据写入到输出流中
fos.write(buf, 0, len);
}
// 4. 关闭资源,先开后关原则
fos.close();
fis.close();
}
字符流
在操作过程中字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理时怎么办呢? 我们读取中文打印再控制台的时候是一个个字节 一个字节是-127 到128的,那如果我们要直接打印中文的话,就需要用到字符流了
字符输入流Reader
我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。API中是否给我们已经提供了读取相应字符的功能流对象,Reader,读取字符流的抽象超类
read():读取单个字符并返回
read(char[]):将数据读取到数组中,并返回读取的个数
FileReader类
用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader
/**
* 读取中文
*/
public static void readText() throws IOException {
FileReader fr = new FileReader("e:\a.txt");
int ch = 0;
while ((ch = fr.read()) != -1) {
// 输出字符对应的编码值
System.out.println(ch);
// 输出字符本身
System.out.println((char)ch);
}
//20170
//今
//22825
//天
//22810
//多
//20113
//云
//65292
//,
//23567
//小
//38632
//雨
}
/**
* 写入中文
*/
public static void writeText() throws IOException {
File file = new File("e:\a.txt");
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
fos.write("今天多云,小雨".getBytes());
fos.close();
}
字符输入流Writer
既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象
FileWriter类
flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用 close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭
写入字符到文件中,先进行流的刷新,再进行流的关闭
/**
* 写入字符到文件中,先进行流的刷新,再进行流的关闭
*/
public static void test7() throws IOException {
// 验收 FileWriter 用于操作文件的便捷类
FileWriter fw = new FileWriter("e:\fw.txt");
// 这些文字都要先编码。都写入到了流的缓冲区中
fw.write("写入字符到文件中,先进行流的刷新,再进行流的关闭");
// 刷新
fw.flush();
// 关闭之前需要刷新
fw.close();
}
- 由javascript中"匿名函数调用写法"引出的一些东东
- javascript中定义私有方法(private method)
- python升级后带来的几个小问题
- 分布式监控系统Zabbix-3.0.3-完整安装记录(1)
- centos6.8下安装部署LNMP-(nginx1.8.0+php5.6.10+mysql5.6.12)
- IE7下当position:fixed遇到text-align:center
- 数组-在Shell脚本中的基本使用介绍
- .Net Core下通过Proxy 模式 使用 WCF
- javascript中function调用时的参数检测常用办法
- squid代理http和https方式上网的操作记录
- kvm虚拟化管理平台WebVirtMgr部署-完整记录(3)
- 域名hiku.com曾百万价格被交易,目前被加拿大大麻公司收购
- Linux系统下的用户密码设定梳理
- Silverlight中的序列化
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- ubuntu环境下安装memcache及启动的方法
- Linux下批量修改服务器用户密码方法步骤
- Linux 常用文本处理命令和vim文本编辑器
- centos7利用yum安装lnmp的教程(linux+nginx+php7.1+mysql5.7)
- linux根据进程号PID查找启动程序的全路径
- linux服务器安装PHP扩展zip,zlib方法
- Lamp环境下设置绑定apache域名的方法分析
- Linux杀不死的进程之CPU使用率700%解决方法
- 解读Linux下ip命令展示的网络连接信息
- Apache ActiveMQ任意文件写入漏洞(CVE-2016-3088)复现
- Linux环境使用g++编译C++方法总结
- linux命令实现音频格式转换和拼接的方法
- Apache 解决80端口占用问题
- Centos7搭建主从DNS服务器的教程
- ubuntu 下JDK环境变量配置方法