Java程序设计学习笔记(三)—— IO
时间:2016-3-24 11:02
——IO流(Input/Output)
IO流用来处理设备之间的数据传输。
Java对数据的操作是通过流的方式。
Java对于操作流的对象都在IO包中。
流按操作数据分为两种:字节流与字符流。
字符流为了处理文本数据,可以在内部融合编码表,编码表可以自己指定,处理文字时不会出现乱码。
图片等文件使用字节流。
首个中国编码表——GB2312
后来进行了一次扩容——GBK
再后来为了方便使用,将世界上各个国家的编码表融合——Unicode,在Unicode编码表中无论什么字符,都用两个字节来表示。
后期Unicode进行了优化,产生了UTF-8,在UTF-8中,能用一个字符就用一个字符,减少空间浪费。
字符流的由来:
不同编码表之间的字符会产生乱码,为了避免此现象的发生,Java在流技术上,就基于字节流产生了字符流,字符流可以在字
符流内部指定编码表,从而解决不同编码表之间的乱码问题。
通用字节流,字符流是基于字节流的。
流按流向分为:输入流和输出流。
——字符流
FileReader、FIleWriter、BufferedReader、BufferedWriter
1、IO流常用基类(这四个类都是抽象类)
字节流的抽象基类:
InputStream,OutputStream
字符流的抽象基类:
Reader,Writer
注:由这四各类派生出来的子类名称都是以其父类名作为自类名的后缀。
如:InputStream的子类FileInputStream
如:Reader的子类FileReader
后缀名是父类名,前缀名是该流对象的功能。
2、Writer类
是抽象类,构造方法是protected,也就是只能在子类中使用。
Writer类的共性方法:
Writer append(char c)
abstract void close()
关闭流,并刷新流。
当流关闭后,不能再使用write方法。
abstract void flush()
刷新流
void write(int c)
写入单个字符。
write()方法仅仅是将数据写入到内存当中,也就是写入到流中,想要将数据写入文件,需要刷新流。flush()方法刷新流。
void write(char[] cbuf)
写入字符数组。
void write(String str)
写入字符串。
void write(String str,int off,int len)
写入字符串的某一部分。
str--字符串 off--相对初始写入字符的偏移量(从哪开始) len--要写入的字符数。
既然IO流是用于操作数据的,数据的最常见体现形式是:文件,那么就以操作文件为主来演示。
需求:
在硬盘上,创建一个文件并写入一些文字数据。
找到一个专门用于操作文件的Writer子类对象:FileWriter,前缀名是功能,后缀名是父类名。
(可以发现,Writer实现的子类特点:前缀名是功能,后缀名是父类名)
3、FileWriter
构造方法:
FileWriter(String fileName)
根据给定的文件名构造一个FileWriter流对象。
FileWriter(String fileName, boolean append)
根据给定的文件名以及指示是否附加写入数据的boolean值来构造一个FileWriter流对象。
append:一个boolean值,如果为true,则将数据写入文件末尾处,而不是写入文件开始处。
也就是实现了文件的续写,不再从文件开头写数据了。
如果文件不存在,先创建文件再续写,如果文件存在,直接续写。
在Windows操作系统中,换行符是:\r\n
在Linux操作系统中,换行符是:\n
继承自Writer的方法:
abstract void close()
关闭流,并且刷新流。
abstract void flush()
刷新该流的缓冲。
void write(int c)
写入单个字符。
void write(String str)
写入字符串。
void write(String str,int off,int len)
写入字符串的某一部分。
void wrie(cha[] cbuf)
写入字符数组。
abstract void write(char[ ] cbuf,int off,int len)
写入字符数组的某一部分。
4、IO异常处理
凡是能和设备产生关系的操作都会发生异常。
FileWriter fw = null; //需要将fw定义在try外部,否则finally无法访问。
5、FileReader
用来读取字符文件的便捷类,此类的构造方法有默认的字符编码和默认字节缓冲区。
默认编码可以通过getProperties()方法获取当前系统的编码。,该编码表是可变化的。
将文本读入流中。
构造方法:
该类的对象一被创建就必须明确要操作的文件,所以该类没有无参构造方法。
FileReader(String fileName)
在给定从中读取数据的文件名的情况下创建一个新的FileReader流对象。
并且该文件会被创建到指定目录下,如果该目录下已有同名文件,将覆盖原文件。
FileWriter(File file)
指定文件。
继承自Reader的方法:
abstract void close()
关闭流并释放与之关联的所有资源。
并不刷新流。
int read()
读取单个字符,返回的是int型的ASCII码值。
read方法一次读取一个字符,而且会自动往下读。
如果读到文件的末尾,会返回-1。
//一次读取一个字符
public static void main(String[] args)throws IOException
int read(char [ ] buff)
将字符读入数组,返回的是int型的字符个数。
没有直接读字符串的方法。
通常字符数组的长度定义为1024或者是1024的整数倍。
代码示例:
//使用字符数组读取字符
public static void main(String[] args)throws IOException
//另一个String方法来输出字符数组:String(char[].offset,len)
//功能是将指定长度的字符数组转换为字符串。
//使用循环读取字符
publicstatic void main(String[] args) throws IOException
{
FileReaderfr = new FileReader("Demo.txt");
char[]ch = new char[3];
int num;
while((num= fr.read(ch)) != -1)
{
System.out.println("num= " + num + ".." + new String(ch,0,num));
}
fr.close();
}
abstract int read(char[ ],int off,int len)
从数组指定位置开始读入字符,从off处开始读取字符,要读取的最多字符数为len。
while((num = fr.read(buf)) != -1)
7、字符流的缓冲区
缓冲区的出现提高了对数据的读写效率。
对应类
BufferedWriter
BufferedReader
缓冲区要结合流才可以使用,因为缓冲区的为了提高流的操作效率。
在流的基础上对流的功能进行了增强。
8、BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
读取流缓冲区在对象建立时需要有被缓冲的对象,也就是在缓冲区构造方法中传入FIleReader的对象。
构造方法:
BufferedReader(Read in)
创建一个默认大小输入缓冲区的缓冲字符输入流。
in是一个流对象。
继承自Reader的方法:
void close()
关闭该流并释放与之关联的所有资源。
int read()
读取单个字符。
int read(char[ ],int off,int len)
从指定位置开始读入,并且指定长度。
特有方法:
String readLine()
读取一个文本行。遇到'\n'或者'\r'就认为某行终止。
读完一行会自动跳到下一行。
包含该行内容的字符串,不包含任何行终止符,如果达到流的末尾,则返回null。
因为不会读取到换行符,所以在读取过程中一般配合newLine使用。
readLine底层其实就是read方法。
9、BufferedWriter
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。(意思就是全部存完一次写入)
该类的构造方法必须有参数,因为有流才有缓冲区。
所以在创建缓冲区之前,必须有流对象。一般开发都会加入缓冲区技术,对性能和效率进行增强。
构造方法:
BufferedWriter(Writer out)
创建一个使用默认大小输出缓冲区的缓冲字符输出流。
out是一个Writer流对象。
继承自Writer的方法:
void close()
关闭此流并刷新。
void flush()
刷新该流的缓冲。
void write(char [ ],int off,int len)
写入字符数组的某一部分。
void write(int c)
写入单个字符。
void write(String s,int off,int len)
写入字符串的某一部分。
特有方法:
void newLine()
写入一个行分隔符,换行。
因为在Windows中换行符是“\r\n”,而Linux中换行符为“\n”,会出现兼容性问题,所以newLine的出现提高了Java的跨平台性。
/**
11、LineNumberReader
跟踪行号的缓冲字符输入流。
该类继承自BufferedReader,所以可以直接调用BufferedReader的方法。
此类定义了方法setLineNumber(int)和getLineNumber(),用于设置行号和获取行号,默认情况下,行号从0开始。
setLineNumber(int):设置起始行号。
getLineNumber() :获取当前行号。
12、输入输出举例
包含了FileReader,FileWriter,BufferedReader,BufferedWriter的用法。
13、装饰设计模式
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能,那么自定义的该类可以
成为装饰类。
例如
BufferedReader中的读取一行:readLine();
装饰类通常会通过构造方法接受被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
装饰模式比继承要灵活,避免了集成体系的臃肿,而且降低了类与类之间关系。
装饰类因为增强已有对象,具备的功能和已有的功能是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都属于同一
个体系中。
/**
——字节流
1、FileOutputStream
如果想要操作图片数据,就需要用到字节流。
字符串转成字节数组的方法:
byte[] String.getBytes()
字符串转成字符数组的方法:
String[] toCharArrays()
int available()
返回剩余字符数。
可以通过available()的返回值来确定数组大小,但是虚拟机启动时默认是64MB,所以需要注意数组大小。
2、字节流缓冲区
BufferedInputStream 和 BufferedOutputStream
10、IOStream
字符流需要刷新数据,而字节流不需要刷新,因为字符流中有一个字符数组,临时存储字符数据,刷新后才将数组内容写入。
字节流如果不使用缓冲区,就不需要刷新操作。
12、用BufferedI/OStream复制一个图片
InputStreamReader,专门用于操作字节流的字符流对象。
可以将字节流转换成字符流。
在构造时需要接收一个字节流对象。
InputStreamReader(InputStream in)
方法继承自Reader。
/*
通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。
也就是readLine()方法。
那么能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?
readLine方法是字符流缓冲区Buff而恶毒Reader类中的方法。
那么能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢?
*/
16、总结规律
流操作的基本规律:
最痛苦的就是对象有很多,不知道该用哪一个。
选择对象可以通过三个步骤来完成:
1、明确源和目的
源:输入流
InputStream
Reader
目的:输出流
OutputStream
Writer
2、操作的数据是否是纯文本
如果是,就选择字符流。
如果不是,就选择字节流。
3、当体系明确后,再明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘,键盘。
目的设备:内存,硬盘,控制台。
复制文件:将一个文本文件中的数据存储到另一个文件中。
源:因为是源,所以使用读取流:InputStream和Reader
是不是操作文本文件?
是!就可以选择字符流Reader。
明确设备:硬盘中的文件。
Reader体系中可以操作文件的对象是FileReader。
是否需要提高效率?
是!使用BufferedReader缓冲区。
FileReader fr = new FileReader("a.txt");
BufferedReader bufr = new BufferedReader(fr);
目的:因为是目的,所以使用输出流:OutputStream和Writer
是否纯文本?
是!使用字符流Writer
设备:硬盘中的一个文件。
Writer体系中可以操作文件的对象是FIleWriter。
是否需要提高效率?
是!使用BufferedWriter缓冲区。
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
17、指定编码表
想要把录入的数据按照指定的编码表(utf-8),将数据存储到文件中。
目的:OutputStream和Writer
是否存储为文本文件?
是!使用Writer
设备:硬盘中的一个文件
使用Writer体系中可以操作文件的FIleWriter
但是FIleWriter是使用默认的编码表GBK,存储时需要加入指定的编码表utf-8,而指定的编码表只有转换流可以指定。
所以要使用的对象是OutputStreamWriter,并且该转换流对象要接收一个字节输出流对象(FileOutputStream),还可以接收指定
的编码表。
OutputStreamWriter osw = new OutputStreamWritrr(new FileOutputStream("a.txt"),"utf-8");
是否需要提高效率?需要。
BufferedWriter bufw = new BufferedWriter(osw);
所以,转换流什么时候使用?
通常涉及到字符编码转换时,需要用到转换流。
18、改变标准输入输出设备
System中的setIn和setOut方法,可以改变输入输出设备。
如果setIn方法参数是一个文本文件,setOut方法参数也是一个文本文件,就会复制文件。
Java程序设计学习笔记(三)—— IO的更多相关文章
- 20145213《Java程序设计学习笔记》第六周学习总结
20145213<Java程序设计学习笔记>第六周学习总结 说在前面的话 上篇博客中娄老师指出我因为数据结构基础薄弱,才导致对第九章内容浅尝遏止地认知.在这里我还要自我批评一下,其实我事后 ...
- JAVA WEB学习笔记(三):简单的基于Tomcat的Web页面
注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...
- Java程序设计学习笔记(一)
时间:2015-6-2 23:04 程序员,程序猿,程序媛,码农 ------------------------------------------------------- --Java的应用 ...
- Java设计模式学习笔记(三) 工厂方法模式
前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...
- java jvm学习笔记三(class文件检验器)
欢迎装载请说明出处:http://blog.csdn.net/yfqnihao 前面的学习我们知道了class文件被类装载器所装载,但是在装载class文件之前或之后,class文件实际上还需要被校验 ...
- Java基础学习笔记三 Java基础语法
Scanner类 Scanner类属于引用数据类型,先了解下引用数据类型. 引用数据类型的使用 与定义基本数据类型变量不同,引用数据类型的变量定义及赋值有一个相对固定的步骤或格式. 数据类型 变量名 ...
- Java程序设计学习笔记(六) — 网络编程
时间:2016-5-8 02:03 --网络编程 网络传输实际上就是进行数据传输. 一.传输的步骤: 1.对对方IP地址进行定位. 2.将数据打包发送到 ...
- 《Thinking in Java》学习笔记(三)
1>Java中的常量 使用final和static来修饰的变量称为常量,常量用大写字母表示,字母间用下划线连接. Java中定义常量有以下几种方式: interface ConstantInte ...
- Java程序设计学习笔记(二)
--正则表达式 正则表达式 ^ 匹配的开始 $ 匹配的结束 [] 表示匹配任意一个字符 [asdasd] ...
随机推荐
- 《PHP 实现 Base64 编码/解码》笔记
前言 早在去年 11 月底就已经看过<PHP 实现 Base64 编码/解码>这篇文章了,由于当时所掌握的位运算知识过于薄弱,所以就算是看过几遍也是囫囵吞枣一般,不出几日便忘记了其滋味. ...
- CentOS7下 PHP怎么安装redis扩展
当前系统是centos7,当初使用yum install php 命令进行的默认安装,不过版本是5.4的. 安装过程参考:简单快速安装Apache+PHP+MySql服务环境(一) 后来为了适应其他框 ...
- P4169-CDQ分治/K-D tree(三维偏序)-天使玩偶
P4169-CDQ分治/K-D tree(三维偏序)-天使玩偶 这是一篇两种做法都有的题解 题外话 我写吐了-- 本着不看题解的原则,没写(不会)K-D tree,就写了个cdq分治的做法.下面是我的 ...
- ElasticSearch简介和快速实战
ElasticSearch简介和快速实战 ElasticSearch与Lucene Lucene可以被认为是迄今为止最先进.性能最好的.功能最全的搜索引擎库(框架) 但是想要使用Lucene,必须使用 ...
- 在 CentOS 7.5 64位上使用 yum 安装 MySQL 8.0
前段时间在 CentOS 7.5 64位上安装 MySQL 8.0.查了些资料,在这里记录一下详细的安装和设置步骤. 一.安装 使用yum安装MySQL之前需要先下载对应的.rpm文件,下载方法: 去 ...
- Python实用案例,Python脚本,Python实现帮你选择双色球号码
往期回顾 Python实现自动监测Github项目并打开网页 Python实现文件自动归类 前言: 今天我们就利用python脚本实现帮你选择双色球号码.直接开整~ 开发工具: python版本: 3 ...
- java时间工具类型,格式化时间,最近7天 月初 月末 季度 月度 时间格式化 等等
package com.tz.util; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util. ...
- tp3 联表查询
联表查询D("column") ->field("{$DbPrefix}column.pid,{$DbPrefix}news.*") ->where ...
- anyRTC 重磅推出在线实时 K 歌解决方案
在线音乐领域一直是各大资本巨头投资的热点,从抢占版权到现在的"云上之争", 主流平台的战火从版权资源转向创新领域扩延.而如今,在线K歌正在成为抢占"云音乐"市场 ...
- 自学linux——2.认识目录及常用指(命)令
认识目录及常用指(命)令 1.备份: 快照(还原精灵):短期备份 频繁备份 可关可开.可能会影响系统的操作. 备份时:虚拟机--快照 还原时:虚拟机--快照--快照管理器--相应位置--转到 克隆 ...