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这有点拟人的感觉,人直接看懂的是文字 字符流 字节流:读取的是文件中的二进制字节流并不会帮你转换成看的懂得字符 字符流: ...
随机推荐
- Luogu 3626 [APIO2009]会议中心
很优美的解法. 推荐大佬博客 如果没有保证字典序最小这一个要求,这题就是一个水题了,但是要保证字典序最小,然后我就不会了…… 如果一条线段能放入一个区间$[l', r']$并且不影响最优答案,那么对于 ...
- wampserver2.5 在 Win7 64位下的相关配置备忘
发现运行和配置这个版本和之前的Wampserver有些差异,特此记录 1).wampserver2.5-Apache-2.4.9-Mysql-5.6.17-php5.5.12-64b,另外有可能需要安 ...
- JavaScript面向切面编程入门
来源极客网学习视频 关键词Javascript AOP编程 例子1: function test() { alert(2); } //理解,所谓的传入一个"回调",该怎样设计bef ...
- 更新XML的Attribute(属性)
有一个XML文档,一个属性"pk"错了,正确是2.我们怎样把它更改正确?原XML文档如下: <?xml version="1.0" encoding=&q ...
- doges
dogse入门指南 Dogse作为游戏服务端引擎,目前只包含游戏服务端的核心部分,但这也是最核心的部分.它全部使用.net c#开发,充分兼顾了程序性能与代码编写的准确性与易用性,再加上以vs作为开发 ...
- POI2011 Tree Rotations
POI2011 Tree Rotations 给定一个n<=2e5个叶子的二叉树,可以交换每个点的左右子树.要求前序遍历叶子的逆序对最少. 由于对于当前结点x,交换左右子树,对于范围之外的逆序对 ...
- UVA11270 Tiling Dominoes
\(\color{#0066ff}{ 题目描述 }\) 给定一个m×n的矩形网格,用1×2多米诺骨牌完全平铺. 请注意,即使一个平铺的旋转与另一个平铺相匹配,它们仍算作不同的平铺. 下面显示了一个平铺 ...
- [POI2014]KUR-Couriers BZOJ3524 主席树
给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. Input 第一行两 ...
- springboot整合mybatis,redis,代码(三)
一 说明 接着上篇讲述redis缓存配置的用法: 二 正文 首先要使用缓存就必须要开开启缓存,第二步是需要开redis-server 下载redis包之后,点击图中两个都可以开启redis 怎么看是否 ...
- redis分布式锁的使用
一 本身自带的方法进行使用: <dependency> <groupId>redis.clients</groupId> <artifactId>je ...