io基础(字节流、字符流、转换流、缓冲字符流)
首先需要明确的一点是输入流输出流的输入输出是站在内存的角度看的,读取文件,把文件内容写到内存中,是输入流;写文件,把内存中的数据写到文件中,是输出流。
IO操作主要有4个抽象类:
字节输入输出流:InputStream、OutputStream,操作的是字节byte。
字符输入输出流:Reader、Writer,操作的是字符char。
最常用的子类有FileInputStream 、FileOutputStream、InputStreamReader、OutputStreamWriter、FileReader、FileWriter、BufferedReader、BufferedWriter
FileInputStream是InputStream的直接子类,其最常用的构造器是FileInputStream(File file),参数传一个File对象,即获得了此File对象对应的字节输入流,常用的方法是:int read(byte b[]);从字节输入流中读取数据到字节数组中,在读的过程中会阻塞线程,返回值是实际读取到的字节的长度,如果什么都没读到,会返回-1。示例:
public static void main(String[] args) {
File file = new File("D:/tmp.txt");
InputStream input = null;
try {
input = new FileInputStream(file);
//每次读1024个字节
byte[] b = new byte[1024];
int len = -1;
while ((len = input.read(b)) != -1) {
System.out.println(len);
String info = new String(b, 0, len);
System.out.println(info);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
需要注意的是,流资源是很昂贵的资源,用完之后要关闭。通常在finally块中关闭。
FileOutputStream是OutputStream的直接子类,其最常用的构造器有两个,用于得到一个File对象对应的字节输出流:
FileOutputStream(File file);只需传一个File对象
FileOutputStream(File file, boolean append);不仅要传一个File对象,还需要传一个布尔值,如果这个布尔值是true的话,则会在原文件中追加内容,如果是false的话,效果等同于第一个构造器,即会覆盖原文件
字节输出流常用的方法是write(byte[] b);把b字节数组所有的字节写到输出流中。示例:
public static void main(String[] args) {
File file = new File("D:/tmp.txt");
OutputStream output = null;
try {
output = new FileOutputStream(file);
output.write("welcome to u".getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output!= null) {
try {
output.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
值得注意的是,字节输出流write完之后不用调flush方法去手动刷缓存区,实测,只要执行完write()方法之后,文件中就会有内容。当然最终还是得调用close方法关闭流,免得资源浪费。
如果想在文件中输入换行,可以用String separator = System.getProperty("line.separator");拿到换行符,在不同的系统中换行符是不一样的,所以不能写死,必须得通过这种方式得到。得到换行符之后,想换行就简单了,调用字节输出流的write(separator.getBytes())方法就好了。示例:
public static void main(String[] args) {
String separator = System.getProperty("line.separator");
File file = new File("D:/tmp.txt");
OutputStream output = null;
try {
output = new FileOutputStream(file, true);
output.write((separator + "thank u").getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
InputStreamReader是Reader的直接子类,是字节输入流转变成字符输入流的桥梁,也被称为转换流。主要用到的构造器有两个:
InputStreamReader(InputStream in);传入一个InputStream对象,使用当前IDE workspace的编码格式
InputStreamReader(InputStream in, String charsetName);传入一个InputStream对象和一个指定编码集的字符串。建议使用这种方式,尽量让结果与IDE的设置无关,这样代码具有可移植性。
最常用的方法还是 int read(char cbuf[]);不过注意的是,这里操作的是字符数组了,从字符输入流中读取数据到字符数组中,在读的过程中会阻塞线程。
示例:
public static void main(String[] args) {
InputStream input = null;
InputStreamReader inputStreamReader = null;
try {
input = new FileInputStream(new File("/tmp.txt"));
inputStreamReader = new InputStreamReader(input, "GBK");
char[] cbuf = new char[10240];
int len = -1;
while ((len = inputStreamReader.read(cbuf)) != -1) {
System.out.println(len);
String str = new String(cbuf, 0, len);
System.out.println(str);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStreamReader != null) {
try {
inputStreamReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
在简体中文windows系统上创建文本文件,打开,另存为时发现编码是ANSI,ANSI在简体中文windows系统上就是GBK,在繁体中文Windows系统上是Big5。
上例中创建InputStreamReader实例时用了InputStreamReader(InputStream in, String charsetName)构造器,指定读取文件时用GBK解码(数据在计算机中存储的是二进制,按照GBK规则解码成我们能理解的字符)。如果不指定GBK,则会因为我们一般把IDE的workspace的编码设为UTF-8而乱码。(实测)
OutputStreamWriter是Writer的直接子类,是字节输出流转变成字符输出流的桥梁,也称为转换流。常用的构造器也有两个:
OutputStreamWriter(OutputStream out);
OutputStreamWriter(OutputStream out, String charsetName);推荐用这种,在创建时指定编码格式,否则会用IDE workspace的编码格式。
常用的方法是:
write(char cbuf[], int off, int len);用于从文件中读取数据并保存到另一文件的情况
write(String str, int off, int len);用于想把一个字符串保存到一个文件的情况
flush();把数据从缓冲区中刷新到指定文件中。不管是用的write()方法的哪种重载,执行完之后,数据是在缓冲区中(在内存中),需要把缓冲区中的数据手动刷到指定目的地。close()方法内部也调用了flush()方法,如果用close()刷数据的话,刷之后会关闭流,流关闭后再write()就会报错了,所以根据实际需求选择合适的刷新方法。其实,最好不要在最后才刷缓冲区,因为如果数据很大的话,不刷缓冲区会占用很多内存(在内存存储者那些数据),即时不报内存溢出错误也是属于很严重的资源浪费。
示例:
public static void main(String[] args) {
OutputStreamWriter writer = null;
InputStreamReader reader = null;
try {
writer = new OutputStreamWriter(new FileOutputStream(new File("/tmp.txt")), "UTF-8");
reader = new InputStreamReader(new FileInputStream(new File("/1.txt")), "GBK");
char[] cbuf = new char[1024];
int len = -1;
while ((len = reader.read(cbuf)) != -1) {
writer.write(cbuf, 0, len);
writer.flush();
}
writer.write("你好吗?");
writer.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
上例中,1.txt是在windows系统下建的一个文件文件,随便写点内容。上例代码是将1.txt的内容复制到tmp.txt文件中,并在后面追加了一些内容。
FileReader是InputStreamReader的子类,与InputStreamReader只有一点不同,那就是固定了编码为当前IDE workspace的编码集,改不了。不推荐使用。同理,FileWriter也不推荐使用。
public static void main(String[] args) {
FileReader reader = null;
FileWriter writer = null;
try {
reader = new FileReader(new File("/1.txt"));
writer = new FileWriter(new File("/2.txt"));
char[] cbuf = new char[1024];
int len = -1;
while ((len = reader.read(cbuf)) != -1) {
writer.write(cbuf, 0, len);
writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
上例中用了FileReader、FileWriter,复制1.txt的内容到2.txt文件中。1.txt是在简体中文windows系统上创建的一个文本文件,GBK编码,上面代码运行完后,查看2.txt的内容,不会乱码。但是如果把1.txt另存为UTF-8编码的,再运行上面代码,2.txt内容会乱码,只要不改变IDE的workspace的编码,问题就解决不了。所以还是推荐使用InputStreamReader、OutputStreamWriter。
如果使用字节流的话,没有必要使用缓冲流(对应的缓冲流有BufferedInputStream、BufferedOutputStream)。使用字符流时可以使用缓冲字符流BufferedReader、BufferedWriter,其中BufferedReader的地位同InputStreamReader一样,也是Reader的直接子类,BufferedWriter的地位同OutputStreamWriter一样,也是Writer的直接子类。
BufferedReader常用的构造器是BufferedReader(Reader in);创建一个默认大小(8192字符)缓冲区的缓冲字符输入流对象,需要传入一个Reader对象,这个Reader对象通常是一个InputStreamReader实例。
BufferedReader对象常用的方法除了read()的各种重载外,最重要的是多了一个String readLine()方法,用来读取一行,返回值是这一行的数据,如果读到文件尾了,会返回null。其实,如果不逐行读取的话,也没必要用缓冲字符流,用转换流就足够了。
BufferedWriter常用的构造器是BufferedWriter(Writer out);创建一个默认大小(8192字符)缓冲区的缓冲字符输出流对象,需要传入一个Writer对象,这个Writer对象通常是一个InputStreamWriter实例。
BufferedWriter对象常用的方法除了write()的各种重载外,最重要的是多了一个newLine()方法,用于输出一个换行,相当于调用字节输出流对象的write(System.getProperty("line.separator").getBytes())方法或者调用字符输出流对象的write(System.getProperty("line.separator"))方法。
缓冲流用法示例:
public static void main(String[] args) {
BufferedReader reader = null;
BufferedWriter writer = null;
String str = null;
try {
reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("/1.txt")), "GBK"));
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("/2.txt"), "UTF-8"));
while ((str = reader.readLine()) != null) {
writer.write(str);
writer.newLine();
writer.flush();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (writer != null) {
try {
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
上例中,逐行读取文件,并逐行写到新文件,且原文件是GBK编码的,新文件是UTF-8编码的。
io基础(字节流、字符流、转换流、缓冲字符流)的更多相关文章
- 零基础学习java------day17------缓冲字节流,转换字节流,简化流,缓冲字符流,序列化和对象流
1. 缓冲字节流 缓冲区:缓冲区实质上是一个数组.通常它是一个字节数组,但是也可以使用其他种类的数组.但是一个缓冲区不 仅仅 是一个数组.缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程 ...
- day4学python 字符编码转换+元组概念
字符编码转换+元组概念 字符编码转换 #coding:gbk //此处必声明 文件编码(看右下角编码格式) #用来得到python默认编码 import sys print(sys.getdefaul ...
- Java 基础 IO流(转换流,缓冲)
一,前言 在学习字符流(FileReader.FileWriter)的时候,其中说如果需要指定编码和缓冲区大小时,可以在字节流的基础上,构造一个InputStreamReader或者OutputStr ...
- 01 语言基础+高级:1-8 File类与IO流_day10【缓冲流、转换流、序列化流】
day10[缓冲流.转换流.序列化流] 主要内容 缓冲流 转换流 序列化流 打印流 教学目标 能够使用字节缓冲流读取数据到程序 能够使用字节缓冲流写出数据到文件 能够明确字符缓冲流的作用和基本用法 能 ...
- java基础45 IO流技术(输入字符流/缓冲输入字符流)
一.输入字符流 1.1.输入字符流体系 ------| Reader:输入字符流的基类(抽象类) ----------| FileReader:向指定文件读取数据的输入字符流(把硬盘上的数据读取到程 ...
- Java基础知识强化之IO流笔记38:字符流缓冲流之BufferedWriter / BufferedReader使用
1. 字符流缓冲流: 字符流为了高效读写,也提供了对应的字符缓冲流. BufferedWriter:字符缓冲输出流 BufferedReader:字符缓冲输入流 2. BufferedWriter使用 ...
- IO流----转换流、缓冲流
打开一个文本文件,另存为: Ansi就是系统默认编码(就是gbk) 建一个编码是utf-8的txt文件, 例: import java.io.FileWriter; import java.io.IO ...
- IO(字节流、字符流)
第1章 字节流 在前面的学习过程中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据.现在我们就要开始给文件中写数据,或者读取文件中的数据. 1.1 字节输出流OutputStream ...
- (19)IO流之字符流FileReader和FileWriter,缓冲字符流---缓冲输入字符流BufferedReader和缓冲输出字符流BufferedWriter
字符流,读取的文件是字符的时候,有两个基类一个是Reader,一个是Writer这有点拟人的感觉,人直接看懂的是文字 字符流 字节流:读取的是文件中的二进制字节流并不会帮你转换成看的懂得字符 字符流: ...
随机推荐
- Java之命令模式(Command Pattern)
转自:http://www.cnblogs.com/devinzhang/archive/2012/01/06/2315235.html 1.概念 将来自客户端的请求传入一个对象,从而使你可用不同的请 ...
- vs2010 怎样设置文本编辑窗口和解决方案资源管理器同步?
即切换左边的文本编辑窗口,解决方案资源管理器如何定位到相应的文件项上?答案: 工具--选项--项目和解决方案--常规--在解决方案资源管理器中跟踪活动项(前打勾)确定 应该就可以了.
- Linux中的Makefile
在Linux中Makefile扮演一个非常重要的角色,我们可以以Linux为平台在上面编写我们需要的C程序代码, 对于C语言来说,Linux是一个非常好的平台来学习.使用.调试.验证C代码的平台,其强 ...
- Windows系统编程之进程同步试验
试验过程中调用了不少系统函数,并且涉及到一些系统级的概念,在此记录下来做为解决问题的一种方式.也许在以后的编程的过程中是否可以通过调用系统平台上的东西来完成一些任务,这仍不失为一种好的思维方式. 多线 ...
- 2013年第四届蓝桥杯国赛 九宫重排(HashMap+双BFS优化)
九宫重排 时间限制:1.0s 内存限制:256.0MB 问题描述 如下面第一个图的九宫格中,放着 1~8 的数字卡片,还有一个格子空着.与空格子相邻的格子中的卡片可以移动到空格中.经过若干 ...
- 校对双层PDF中的隐藏文本
作者:马健邮箱:stronghorse_mj@hotmail.com发布:2012.06.11 目录一.背景二.能够校对的PDF需要满足的条件三.校对工具的选择四.校对过程五.延伸讨论 事先声明:本文 ...
- 阿里开源混沌工程工具 ChaosBlade
https://github.com/chaosblade-io/chaosblade
- ubuntu - 14.04,安装JDK1.8(JAVA程序需要的开发、运行环境)
一,如何删除低版本的open JDK? 在ubuntn的软件中心中,如果输入"java",我们会看到open JDK,但是最高版本是1.7,也有1.6版本的,如果我们安装上去,可能 ...
- day01.2-计算机网络协议
注:本文摘自林海峰老师的博客,作为个人学习笔记,日后方便阅读,原文详见链接www.cnblogs.com/linhaifeng/articles/5937962.html 一. ISO协议 ...
- AngularJS(五)——filter(过滤器)
前言 过滤器可以用一个管道字符(|)添加到表达式和指令中.比如做ITOO的时候或者其他项目的时候,总是想统一货币日期等显示,以前的做法,不断循环该控件或该标签,然后循环转换.如果利用AngularJS ...