IO流
IO流的分类:
流向:
输入流:读取数据
输出流:写入数据
数据类型:
字节流:
字节输入流 读取数据 InputStream
字节输出流 写入数据 OutputStream
字符流:
字符输入流 读取数据 Reader
字符输出流 写入数据 Writer
需求:往"a.txt"写入一句话,"大数据,yyds"
分析
1、由于是对文本文件进行操作的,最好用字符流来操作,字符流是建立在字符流之上诞生的
2、我们要往文件中写入一句话,要用到输出流,这里用的是字节输出流
所以最终锁定 OutputStream,由于 OutputStream是一个抽象类,不能直接实例化,所以我们要创建一个子类来实例化。
FilreOutputStream构造方法:
FilreOutputStream(File file) 创建文件输出流,以写入由指定的File对象表示的文件
FilreOutputStrea(String name) 创建文件输出流,以指定的名称写入文件
字节输出流的操作步骤:
1、创建字节输出流对象;
2、调用方法,写数据;
3、释放资源
public class FileOutputStreamDemo1 {
public static void main(String[] args) throws Exception{
//创建字节流输出对象
//FileOutputStream(File file) 创建文件输出流以写入由指定的 File对象表示的文件。
// File file = new File("b.txt");
// //如果目标文件不存在,自动创建
// FileOutputStream fos = new FileOutputStream(file);
//FileOutputStream(String name) 创建文件输出流以指定的名称写入文件。
//如果目标文件不存在,自动创建
FileOutputStream fos = new FileOutputStream("c.txt");
// System.out.println(fos);
//调用方法,写数据
fos.write("大数据,yyds".getBytes());
//释放资源
//close()关闭此文件输出流并释放与此流相关联的任何系统资源。
fos.close();
fos.write("继续写入".getBytes());
}
}
字节流写数据的几种方法
public void write(int b)
public void write(byte[] b)
public void write(byte[] b,int off,int len)
public class FileOutputStreamDemo2 {
public static void main(String[] args) throws Exception{
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("d.txt");
//public void write(int b)
//97,底层存储的二进制,97对应的ASCII码的字符是a
fos.write(97);
fos.write(48);
fos.write(65);
//public void write(byte[] b)
byte[] byts = {97,98,99,100,101};
fos.write(byts);
//public void write(byte[] b,int off,int len)
//从位于偏移量 off的指定字节数组写入 len字节到该文件输出流。
fos.write(byts,1,3);
//释放资源
fos.close();
}
}
实现换行操作和追加操作
注意不同的系统换行符不一样:
mac:\r
linux:\n
windows:\r\n
import java.io.FileOutputStream;
public class FileOutputStreamDemo3 {
public static void main(String[] args) throws Exception {
//创建字节输出流对象
// FileOutputStream fos = new FileOutputStream("e.txt");
// fos.write("大数据1,yyds".getBytes());
// fos.write("\r\n".getBytes());
// fos.write("大数据2,yyds".getBytes());
//FileOutputStream(String name, boolean append)
//创建文件输出流以指定的名称写入文件。
//true表示的是可以追加写入数据
FileOutputStream fos = new FileOutputStream("e.txt", true);
fos.write("\r\n今天下雪了\r\n".getBytes());
// fos.write("\r\n".getBytes());
fos.write("但是没有看到积雪".getBytes());
//释放资源
fos.close();
//....
}
}
字节输入流
InputStream(抽象类)
FileInputStream
FileInputStream的构造方法:
FileInputStream(File file)
FileInputStream(String name)
字节输入流的两种方式:
FileInputStream成员方法
1、public int read()
public class FileInputStreamDemo1 {
public static void main(String[] args) throws Exception {
//1、创建字节输入流对象
//FileInputStream(File file)
//读取数据的时候,如果文件不存在,报错
// File file = new File("f.txt"); //f.txt (系统找不到指定的文件。)
// File file = new File("e.txt");
// FileInputStream fis = new FileInputStream(file);
//FileInputStream(String name)
FileInputStream fis = new FileInputStream("e.txt");
//调用read方法读取数据,并输出在控制台上
//public int read(),一次只能读取一个字节,返回的是ASCII码值,强制类型转换
// int read = fis.read();
// System.out.println((char)read);
//
// int read2 = fis.read();
// System.out.println((char)read2);
//如果文件中数据很多的话,还是这样一个字节一个字节的读取,没有做任何改进,即将会很麻烦
//使用循环改进读取
//由于我们不知道什么时候将文件数据读取完毕,所以使用while循环
//控制跳出while循环的条件是什么,数据的下一个字节,如果达到文件的末尾, -1 。
// int read = fis.read();
// while (read != -1) {
// System.out.print((char) read);
// read = fis.read();
// }
//字节输入流读取数据的第一种方式最终版写法:
int i = 0;
while ((i = fis.read()) != -1) {
System.out.print((char) i);
}
//释放资源
fis.close();
}
}
2、public int read(byte b)
import java.io.FileInputStream;
public class FileInputStreamDemo2 {
public static void main(String[] args) throws Exception {
//1、创建字节输入流对象
FileInputStream fis = new FileInputStream("e.txt");
//2、读取数据
//public int read(byte[] b)
//定义一个字节数组
// byte[] bytes = new byte[8];
// //一旦调用这个方法,将实际获取到的字节存储到数组中,返回的是,数组实际读取到的字节数
// int i = fis.read(bytes);
// System.out.println(i);
for(byte b:bytes){
System.out.print((char) b);
}
System.out.println("=============");
String s = new String(bytes);
System.out.println(s);
// String s = new String(bytes, 0, i);
// System.out.println(s);
//用循环改进
//字节流读取数据的第二种方式最终代码
//读入缓冲区的总字节数,如果没有更多的数据,因为文件的结尾已经到达, -1 。
byte[] bytes = new byte[1024];
int length = 0;
while ((length=fis.read(bytes))!=-1){
System.out.println(new String(bytes,0,length));
}
//释放资源
fis.close();
}
}
字符流
字符输出流:Reader
字符输入流:Writer
Writer:
OutputStreamWriter:字符输出流是字节输出流加上编码表得到的一个转换流,后期写数据的时候可以根据自己指定的编码进行输入
public OutputStreamWriter(OutputStream out)
创建一个默认字符编码的OutputStreamWriter。根据默认的编码用字符作为桥梁将字节流的数据转化为字符流。
public OutputStreamWriter(OutputStream out,String charsetName)
根据指定的字符编码将字节流转换为字符流;
字符流=字节流+编码表
public class OutputStreamWriterDemo1 {
public static void main(String[] args) throws Exception {
//1、创建字符输出流对象
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("aaa.txt"));
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("bbb.txt"),"GBK");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("ccc.txt"),"GBK");
osw.write("中国");
//释放资源
osw.close();
}
}
OutputStreamWriter写数据的方法
public void write(int c)
public void write(char[] cbuf)
public void write(char[] cbuf,int off,int len)
public void write(String str)
public void write(String str,int off,int len)
flush()和close()的区别
1、调用flush()后,流对象并没有关闭,还能继续写数据
2、调用close()后,流对象就关闭了,不能通过这个对象继续写数据
public class OutputStreamWriterDemo2 {
public static void main(String[] args) throws Exception {
//1、创建字符输出流对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("ddd.txt"));
//写数据
//public void write(int c) 写一个字符
// osw.write(99);
// osw.write('a');
//现象,我们在把close去掉之后,发现数据没有写入到文件中
//原因
//文件实际上在硬盘存储的是字节,需要手动转换一下进行存储
//void flush()
//刷新流。
// osw.flush();
// osw.write();
//public void write(char[] cbuf) 写一个字符数组
char[] chars = {'a','b','c','d','e'};
// osw.write(chars);
//public void write(char[] cbuf,int off,int len) 写字符数组的一部分
// osw.write(chars,1,3);
//public void write(String str)
// osw.write("明旺和王宇真帅");
//public void write(String str,int off,int len) 写字符串的一部分
osw.write("明旺和王宇真帅",3,2);
//释放资源
osw.close(); //包含了flush()操作
// osw.write();
}
}
Reader
InputStreamReader:字符输入流;
public InputStreamReader(InputStreamReader in)
读取数据,根据默认的编码用字符作为桥梁将字节流数据转换为字符流;
public InputStreamReader(InputStreamReader in,String charsetName)
读取数据,根据指定的编码用字符作为桥梁将字节流的数据转换为字符流;
public int read()
public class InputStreamReaderDemo1 {
public static void main(String[] args) throws Exception {
// InputStreamReader isr = new InputStreamReader(new FileInputStream("bbb.txt"));
InputStreamReader isr = new InputStreamReader(new FileInputStream("ccc.txt"),"GBK");
//一次读取一个字符
int c = 0;
while ((c=isr.read())!=-1){
System.out.print((char) c);
}
//释放资源
isr.close();
}
}
InputStreamReader
读取数据的方法:
public int read(char[] cubf)
public class InputStreamReaderDemo2 {
public static void main(String[] args) throws Exception {
//1、创建字符输入流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("e.txt"));
//一次只读一个字符
//字符读取,如果已经达到流的结尾,则为-1
// int i = 0;
// while ((i=isr.read())!=-1){
// System.out.print((char) i);
// }
//一次读取一个字符数组
//读取的字符数,如果已经达到流的结尾,则为-1
char[] chars = new char[1024];
int length = 0;
while ((length = isr.read(chars)) != -1) {
System.out.print(new String(chars, 0, length));
}
//释放资源
isr.close();
}
}
缓冲区类
字节缓冲输出流
BufferedOutputStream
字节缓冲输入流
BufferedIutputStream
字节缓冲输出流
BufferedOutputStream
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
public class BufferedOuputStreamDemo1 {
public static void main(String[] args) throws Exception {
//BufferedOutputStream(OutputStream out)
//创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
// FileOutputStream fos = new FileOutputStream("g.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("g.txt"));
//一次性写一个字节数组
bos.write("大数据".getBytes());
bos.close();
}
}
字节缓冲输入流
BufferedIutputStream
public class BufferedInputStreamDemo1 {
public static void main(String[] args) throws Exception {
//BufferedInputStream
//BufferedInputStream(InputStream in)
//创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。
// FileInputStream fis = new FileInputStream("g.txt");
// BufferedInputStream bis = new BufferedInputStream(fis);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("g.txt"));
//读取数据
//一次读取一个字节
// int b = 0;
// while ((b=bis.read())!=-1){
// System.out.print((char) b);
// }
System.out.println("======================");
byte[] bytes = new byte[1024];
int length = 0;
while ((length = bis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, length));
}
//释放资源
bis.close();
}
}
字节流一次只读一个字节的时候,如果数据是中文出现了我们看不懂的符号
public class BufferedInputStreamDemo2 {
public static void main(String[] args) throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("g.txt"));
//读取数据
//一次读取一个字节
int b = 0;
while ((b = bis.read()) != -1) {
System.out.print((char) b);
}
//释放资源
bis.close();
}
}
String(byte[] bytes,Charset charset)
构造一个新的String用指定的字节的数组解码charset。解码
byte[] getBytes(Charset charset)
用给定的charset将该String编码为字节序列,将结果储存到新的字节数组中。解码
编码:把看懂的变成看不懂的,类似于加密。
String -- byte[]
解码:把看不懂的变成看懂的,类似于解密。
byte -- String
public class StringDemo {
public static void main(String[] args) throws Exception {
String s = "你好";
//String -- byte[]
// byte[] bytes1 = s.getBytes("GBK");
System.out.println(bytes1);
// printArray(bytes1);
byte[] bytes2 = s.getBytes("Unicode");
printArray(bytes2);
System.out.println();
//byte[] -- String
String s1 = new String(bytes2, "Unicode");
System.out.println(s1);
}
public static void printArray(byte[] bytes){
for (byte b : bytes){
System.out.print(b+",");
}
}
}
字符缓冲流
Bufferedwriter
将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入
可以指定缓冲区的大小,或者可以承受默认缓冲区大小,默认值足够大,可以用于大多数用途
public class BufferedWriterDemo1 {
public static void main(String[] args) throws Exception {
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a2.txt")));
BufferedWriter bw = new BufferedWriter(new FileWriter("a2.txt"));
bw.write("hello");
bw.write("\r\n");
bw.write("world");
bw.write("\r\n");
bw.write("java");
bw.write("\r\n");
bw.write("hadoop");
bw.flush();
//释放资源
bw.close();
}
}
BufferedReader
字符缓冲输入流
从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取
可以指定缓冲区的大小,或者可以使用默认大小,默认值足够大可以有很多用途
BufferedReader(Reader in)
创建使用默认大小的输入缓冲区缓冲字符流。
public class BufferedReaderDEmo1 {
public static void main(String[] args) throws Exception {
// BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
//1、一次读取一个字符
// int ch = 0;
// while ((ch=br.read())!=-1){
// System.out.print((char) ch);
// }
//2、一次读取一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length=br.read(chars))!=-1){
System.out.println(new String(chars,0,length));
}
//释放资源
br.close();
}
}
复制
把当前项目目录下的"a.txt"复制到"b.txt"
输入流:
InputStream--FileInputStram
一次性读取一个字节;
一次性读取一个字节数组;
a.txt
输出流:
OutputStram--FileOutputStream
一次写一个int类型的值;
一次写一个字节;
一次写一个字节数组;
b.txt
public class CopyFileDemo1 {
public static void main(String[] args) throws Exception {
//1、创建字节输入流对象和字节输出流对象
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("f.txt");
//2、读取数据
//a: 一次读取一个字节
// int i = 0;
// while ((i=fis.read())!=-1){
System.out.println();
// fos.write(i);
// }
//b: 一次读取一个字节数组
byte[] bytes = new byte[1024];
int length = 0;
while ((length = fis.read(bytes)) != -1) {
fos.write(bytes, 0, length);
}
//释放资源
fos.close();
fis.close();
}
}
把当前项目目录下的"a.txt"复制到"b.txt"
数据源:
a.txt--读取数据--字符输入流--Reader--InputStramReader
目的地:
b.txt--读取数据--字符输出流--Writer--OutputstreamWriter
public class CopyFileDemo2 {
public static void main(String[] args) throws Exception {
//1、创建字符输入流对象和字符输出流对象
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
//读写数据
//第一种方式
// int ch = 0;
// while ((ch=isr.read())!=-1){
// osw.write(ch);
// osw.flush();
// }
//第二种方式
char[] chars = new char[1024];
int length = 0;
while ((length = isr.read(chars)) != -1) {
osw.write(chars, 0, length);
osw.flush();
}
//释放资源
osw.close();
isr.close();
}
}
由于我们常见的操作都是使用本地默认的编码,我们基本上使用的时候不去指定编码,但是呢,我觉得创建字符转换流对象的时候,名字有点长,所以java提供了子类给我们使用
字符流=字节流+编码表
把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
数据源:
a.txt -- 读取数据 -- 字符输入流 -- Reader -- InputStreamReader -- FileReader
目的地:
b.txt -- 写出数据 -- 字符输出流 -- Writer -- OutputStreamWriter -- FileWriter
public class CopyFileDemo3 {
public static void main(String[] args) throws Exception {
// InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
//FileReader(String fileName)
//创建一个新的 FileReader ,给定要读取的文件的名称。
FileReader fr = new FileReader("a.txt");
//创建字符输出流对象
//FileWriter(String fileName)
//构造一个给定文件名的FileWriter对象。
FileWriter fw = new FileWriter("b.txt");
//一次读写一个字符
// int ch = 0;
// while ((ch=fr.read())!=-1){
// fw.write(ch);
// fw.flush();
// }
//一次读写一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length=fr.read(chars))!=-1){
fw.write(chars,0,length);
fw.flush();
}
//释放资源
fw.close();
fr.close();
}
}
把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
数据源:
a.txt -- 读取数据 -- 字符输入流 -- Reader -- InputStreamReader -- FileReader
目的地:
b.txt -- 写出数据 -- 字符输出流 -- Writer -- OutputStreamWriter -- FileWriter
public class CopyFileDemo4 {
public static void main(String[] args) throws Exception {
//1、创建字符缓冲输入流对象和字符缓冲输出流对象
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("b2.txt"));
//一次读写一个字符数组
char[] chars = new char[1024];
int length = 0;
while ((length= br.read(chars))!=-1){
bw.write(chars,0,length);
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}
IO流的练习
把ArrayList集合中的文件存储到文本文件
public class IOTest1 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//向集合中添加元素
list.add("hello");
list.add("world");
list.add("java");
list.add("bigdata");
BufferedWriter bw = null;
//创建字符缓冲输出流对象
try {
bw = new BufferedWriter(new FileWriter("a4.txt"));
for(String s : list){
bw.write(s);
bw.newLine();
bw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl” 请编写程序读取数据内容,把数据排序后写入ss.txt中。
public class IOTest2 {
public static void main(String[] args) throws Exception{
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("s.txt"));
String s = br.readLine();
br.close();
//将字符串转成字符数组
char[] chars = s.toCharArray();
//Arrays工具类中sort方法排序
Arrays.sort(chars);
//创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("ss.txt"));
bw.write(chars);
bw.flush();
bw.close();
}
}