文章目录
- 小结:
字节流
字节输入流 InputStream
int read()
int read(byte[] bys)
字节输出流 OutputStream
void write(int i)
void write(byte[] bys,int i,int j)
子类
FileOutputStream
FileInputStream
字节缓冲流
BufferedInputStream
BufferedOutputStream
字符流:
字符输入流 Reader
int read()
int read(char[] bys)
字符输出流 Writer
void write(int i)
void write(char[] bys,int i,int j)
转换流—字符流
InputStreamReader(InputStream)
OutputStreamWriter(OutputStream)
子类:
FileReader
FileWriter
void write(String s)
字符缓冲流:
BufferedReader:
String readLine()
BufferedWriter:
void newLine()
1 io流
1.1 io流用来处理设备之间的数据传输。
- 主要用来实现文件的上传和下载
- java中对数据的操作是通过流的方式进行的
- java用来操作流的对象都在io包中。
- 后面我们还会讲到nio可以理解 new io
1.2 io流的分类
-
按照流向分:
输入流:读取数据
输出流:写入数据 -
按照数据类型分:
字节流:
字节输入流
字节输出流
字符流:
字符输入流
字符输出流 -
什么时候用什么流?
用普通记事本打开能看懂就用字符流,看不懂用字节流,什么都不懂直接用字节流。
1.3 io流中常用的基类
-
字节流的基类:
InputStream 字节输入流 读数据
OutputStream 字节输出流 写数据 -
字符流的基类:
Reader 字符输入流 读数据
Writer 字符输出流 写数据 -
注意:这四个基类的子类名称都是以基类的名字作为后缀的。
比如:FileInputStream FileOutputStream
FileReader FileWriter
…
1.4 练习
我要在a.txt文件中写入 hello,meimei.
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 我要在a.txt文件中写入 hello,meimei.
* 分析:
* 我们操作的是字符,用字符流来做更方便一些。
* 但是字符流是在字节流之后才有的。
* 所以我们先讲用字节流做。
*
* 我现在是要写入,所以应该使用字节输出流----OutputStream
* 但是它是一个抽象类,不能实例话。应该找一个具体的子类。
* 我们发现它有很多子类,应该用哪个?
* 想我们现在要干什么?要给 文件 中写入。
* 文件是 File
* 所以就找到了对应的子类:FileOutputStream
* 文件输出流是用于将数据写入到输出流指定的File
*
* 构造方法:
* FileOutputStream(File file)
创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(String name)
创建文件输出流以指定的名称写入文件。
*
字节输出流写数据的步骤:
* 创建字节输出流对象
* 调用方法写数据
* 释放资源
* */
public class Demo13 {
public static void main(String[] args) throws IOException {
String s = "hello,meimei.";
FileOutputStream fos = new FileOutputStream("a.txt");
//void write(byte[] b) 写一个字节数组的数据
fos.write(s.getBytes());
fos.close();
}
}
2 OutputStream 文件输出流
2.1 概述
- 文件输出流是用于将数据写入到输出流File
- 抽象类 所以用具体子类FileOutputStream
2.2 构造方法
FileOutputStream(File file)
创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(File file, boolean append)
创建文件输出流以写入由指定的 File对象表示的文件。
FileOutputStream(String name)
创建文件输出流以指定的名称写入文件。
FileOutputStream(String name, boolean append)
创建文件输出流以指定的名称写入文件。
2.3 成员方法(写数据)
void write(byte[] b)
将 b.length个字节从指定的字节数组写入此文件输出流。
void write(byte[] b, int off, int len)
将 len字节从位于偏移量 off的指定字节数组写入此文件输出流。
void write(int b)
将指定的字节写入此文件输出流。
package com.momo.demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* FileOutputStream 的写数据方法
* */
public class Demo14 {
public static void main(String[] args) throws IOException {
File f = new File("a.txt");
FileOutputStream fos = new FileOutputStream(f);
//FileOutputStream fos = new FileOutputStream("a.txt");
//fos.write(97);
byte[] bys = {97,98,99,100};
//fos.write("hellogege".getBytes());
//fos.write(bys);
fos.write(bys,1,2);
fos.close();
}
}
2.4 字节输出流写数据的相关问题
-
创建字节输出流对象的时候都做了哪些事情?
FileOutputStream fos = new FileOutputStream(“b.txt”);
如果文件不存在,调用系统功能创建该文件
创建fos对像
把fos对象和文件关联起来(把fos对象指向那个文件) -
为什么一定要close释放资源呢?
资源有限,需要合理利用。
让对象变成垃圾,垃圾回收器就可以回收它。
释放跟该文件相关的系统资源。
-
如何追加写入数据?
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 追加写入:
* 使用带2个参数的构造方法,第二个参数传 true即可
* */
public class Demo15 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("b.txt",true);
fos.write("ccc".getBytes());
fos.close();
}
}
-如何实现换行写入?
写入换行符即可
注意:一般来说不同的操作系统对于换行符的写法是不一样的。
也就是说我们现在这个代码拿到其他操作系统上运行的时候有可能就会出问题。
不用担心,后面有解决方案。
linux: \n
mac: \r
windows: \r\n
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 追加写入:
* 使用带2个参数的构造方法,第二个参数传 true
*
* 换行写入?
* 写入换行符接口
* */
public class Demo15 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("b.txt",true);
//fos.write("ccc".getBytes());
for(int i=0;i<10;i++){
fos.write("我爱你".getBytes());
//fos.write("\r\n".getBytes());
}
fos.write("\r\n".getBytes());
// fos.write("\r".getBytes());
// fos.write("\n".getBytes());
fos.close();
}
}
2.5 字节流写数据加入异常处理
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 分开处理
* */
public class Demo16 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("b.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fos.write("abc".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 一起处理
* */
public class Demo17 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("b.txt");
fos.write("aaaa".getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 改进版
* */
public class Demo18 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("b.txt");
fos.write("aaaa".getBytes());
} catch (
FileNotFoundException e) {
e.printStackTrace();
} catch (
IOException e) {
e.printStackTrace();
} finally {
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3 字节流读取数据
3.1 InputStream
- 抽象类
- FileInputStream
用于读取诸如图像数据的原始字节流。
3.2 构造方法
FileInputStream(File file)
通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。
FileInputStream(String name)
通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
3.3 成员方法(读数据的方法)
int read()
从该输入流读取一个字节的数据。
int read(byte[] b)
从该输入流读取最多 b.length个字节的数据为字节数组。
int read(byte[] b, int off, int len)
从该输入流读取最多 len字节的数据为字节数组。
package com.momo.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 字节输入流读取数据
* 步骤:
* 创建字节输入流对象
* 调用方法读取数据,展示到控制台上
* 释放资源
* */
public class Demo19 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
//读一个字节
/* int i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
i = fis.read();
System.out.println(i);
System.out.println((char)i);
我们发现当读取到文件末尾的时候返回的是-1
*/
/* int i = fis.read();
while (i!=-1){
System.out.println((char)i);
i = fis.read();
}*/
//改进版
/* int i = 0;
while ((i=fis.read())!=-1){
System.out.println((char)i);
}*/
//读取一个字节数组:返回的是实际读取的字节个数,到达文件末尾的时候返回-1
// byte[] bys = new byte[5];
/* int i = fis.read(bys);
System.out.println(i);
System.out.println(new String(bys,0,i));
i = fis.read(bys);
System.out.println(i);
System.out.println(new String(bys,0,i));
i = fis.read(bys);
System.out.println(i);
System.out.println(new String(bys,0,i));*/
/* int i = 0;
while ((i=fis.read(bys))!=-1){
System.out.println(new String(bys,0,i));
}*/
//读取字节数组中的一部分
byte[] bys = new byte[5];
int i = fis.read(bys, 0, 3);
System.out.println(i);
System.out.println(new String(bys,0,i));
fis.close();
}
}
package com.momo.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 字节流读取中文会出现一些问题:乱码了。看不懂
* */
public class Demo21 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("b.txt");
/* int i = 0;
while ((i=fis.read())!=-1){
// System.out.println(i);
System.out.println((char)i);
}*/
/* byte[] bys = new byte[5];
int i = 0;
while ((i=fis.read(bys))!=-1){
//System.out.println(i);
System.out.println(new String(bys,0,i));
}*/
}
}
3.4 练习:复制文本文件
把a.txt中的内容复制到b.txt中
package com.momo.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 把a.txt中的内容复制到b.txt中
* 分析:
* 数据源:数据从哪里来 a.txt 读取 输入流 FileInputStream
* 目的地:数据到那里去 b.txt 写入 输出流 FileOutputStream
*
* 刚才读取中文的时候,读一个字节,然后转换输出乱码了。
* 这次我还是读取一个字节,然后写一个字节,为什么没有乱吗?
* 主要是因为,我们刚才每读取一个字节就把该字节转换成字符串,然后输出。
* 这次虽然我依然是读取一个字节,但是我没有转换,而是读一个写一个。
* 最后写完之后系统会自动转换。
* */
public class Demo20 {
public static void main(String[] args) throws IOException {
//封装数据源和目的地
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("b.txt");
//调用方法读写即可
int i = 0;
while ((i = fis.read())!=-1){
fos.write(i);
}
//释放资源
fis.close();
fos.close();
}
}
package com.momo.demo;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/*
* 计算机他是如何识别的?它怎么知道什么时候该转成中文?
* 在计算机中存储中文的时候在UTF-8编码下一般占用3个字节:
* 在GBK编码下一般占用2个字节:
* 第一个字节都是负数
* 第二个字节一般也是负数。即使出现正数,没有影响。
* 第三个字节一般也是负数。即使出现正数,没有影响。
* */
public class Demo22 {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "abcd";
byte[] bys = s.getBytes();
System.out.println(Arrays.toString(bys));
//[97, 98, 99, 100]
System.out.println("------------");
String ss = "我爱龙哥";
byte[] bytes = ss.getBytes();
System.out.println(Arrays.toString(bytes));
//[-26, -120, -111, -25, -120, -79, -23, -66, -103, -27, -109, -91]
System.out.println("-------------------");
//String(byte[] bytes, String charsetName)
/* String s1 = new String(ss.getBytes(),"GBK");
System.out.println(s1);*/
/* byte[] bytes1 = ss.getBytes("UTF-8");
System.out.println(Arrays.toString(bytes1));*/
byte[] bytes1 = ss.getBytes("GBK");
System.out.println(Arrays.toString(bytes1));
//[-50, -46, -80, -82, -63, -6, -72, -25]
}
}
- 用一次读写一个字节
package com.momo.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 复制文件一次读写一个字节数组
* */
public class Demo23 {
public static void main(String[] args) throws IOException {
//封装数据源和目的地
FileInputStream fis = new FileInputStream("log.txt");
FileOutputStream fos = new FileOutputStream("a.txt");
//调用方法
//byte[] bys = new byte[5];
//数组长度一般给1024或者1024的倍数
byte[] bys = new byte[1024];
int i = 0;
while ((i=fis.read(bys))!=-1){
fos.write(bys,0,i);
// System.out.println(new String(bys,0,i));
}
fis.close();
fos.close();
}
}
-练习:复制普通的文件
-练习:复制图片,音乐
3.5 字节流一次读写一个字节和一次读写一个字节数组的区别
- 一次读写一个字节数组,效率更高,速度更快一些。
- 比如: 一次拿一件和一次拿多件的区别
100件货物,一次拿一件,要来回100次
一次拿10件,来回10次
package com.momo.demo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 一次读写一个字节,和一次读写一个字节数组对比
* */
public class Demo24 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\张小龙\\Desktop\\1.mp3");
FileOutputStream fos = new FileOutputStream("123.mp3");
//一次一个字节
/* int i = 0;
while ((i = fis.read())!=-1){
fos.write(i);
}*/
//一次读写一个字节数组
byte[] bys = new byte[1024];
int i = 0;
while ((i = fis.read(bys))!=-1){
fos.write(bys,0,i);
}
fis.close();
fos.close();
}
}
4 字节缓冲流
4.1 上面写的代码,一次读写一个字节数组的速度明显比一次读写一个字节快很多。
主要是因为,我们加入了一个数组这样的缓冲区效果。
java本身在设计的时候也考虑到了这样的设计思想(装饰模式)
所以java为了提高效率,给我们也提供了自带缓冲区的字节缓冲流。
这个流也被称为高效流(缓冲流)
-
字节缓冲输入流
BufferedInputStream -
字节缓冲输出流
BufferedOutputStream -
构造方法都可以指定缓冲区的大小,但是一般我们不指定。因为默认的够用了。
-
为什么构造方法中要的不是一个文件或者路径?要的是基本的字节流?
因为缓冲流仅仅是为了提供缓冲区,为了提高效率设计的。
但是真正的读写操作还是在基本的流对象中。所以它要的是基本的流对象。
5 BufferedOutputStream
5.1 该类实现缓冲输出流
5.2 构造方法:
BufferedOutputStream(OutputStream out)
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
BufferedOutputStream(OutputStream out, int size)
创建一个新的缓冲输出流,以便以指定的缓冲区大小将数据写入指定的底层输出流。
5.3 成员方法(写数据)
void write(byte[] b, int off, int len)
从指定的字节数组写入 len个字节,从偏移 off开始到缓冲的输出流。
void write(int b)
将指定的字节写入缓冲的输出流。
package com.momo.demo;
import java.io.*;
/*
* 字节缓冲输出流写数据
* */
public class Demo25 {
public static void main(String[] args) throws IOException {
/* OutputStream os = new FileOutputStream("a.txt");
BufferedOutputStream bos = new BufferedOutputStream(os);*/
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("a.txt"));
// bos.write(97);
// bos.write("hello".getBytes());
bos.write("hellomeinv".getBytes(),1,3);
bos.close();
}
}
6 BufferedInputStream
6.1 概述
- 字节缓冲输入流
6.2,构造方法:
BufferedInputStream(InputStream in)
创建一个 BufferedInputStream并保存其参数,输入流 in ,供以后使用。
BufferedInputStream(InputStream in, int size)
创建 BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。
6.3,成员方法(读数据的方法)
int read()
见 read法 InputStream的一般合同。
int read(byte[] b, int off, int len)
从给定的偏移开始,将字节输入流中的字节读入指定的字节数组。
package com.momo.demo;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
* 字节缓冲输入流读数据
* */
public class Demo26 {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
/* int i=0;
while ((i=bis.read())!=-1){
System.out.println((char)i);
}*/
int j = 0;
byte[] bys = new byte[1024];
while ((j=bis.read(bys))!=-1){
System.out.println(new String(bys,0,j));
}
bis.close();
}
}
- 练习:使用字节缓冲流复制文件(普通,图片,音频)
package com.momo.demo;
import java.io.*;
/*
* 分别用四种方式复制 音乐 进行对比
* 基本字节流一次读写一个字节 共花费:67354毫秒
* 基本字节流一次读写一个字节数组 共花费:113毫秒
* 高校字节流一次读写一个字节 共花费:290毫秒
* 高效字节流一次读写一个字节数组 共花费:39毫秒
* */
public class Demo27 {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
//copy1("123.mp3","456.mp3");
// copy2("123.mp3","456.mp3");
//copy3("123.mp3","456.mp3");
copy4("123.mp3","456.mp3");
long end = System.currentTimeMillis();
System.out.println("共花费:"+(end-start)+"毫秒");
}
public static void copy4(String src,String desc) throws IOException {
FileInputStream fis = new FileInputStream(src);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(desc);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int i = 0;
byte[] bys = new byte[1024];
while ((i=bis.read(bys))!=-1){
bos.write(bys,0,i);
}
/* fis.close();
fos.close();
bis.close();
bos.close();*/
}
public static void copy3(String src,String desc) throws IOException {
FileInputStream fis = new FileInputStream(src);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(desc);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int i = 0;
while ((i=bis.read())!=-1){
bos.write(i);
}
/* fis.close();
fos.close();
bis.close();
bos.close();*/
}
public static void copy2(String src,String desc) throws IOException {
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc);
int i = 0;
byte[] bys = new byte[1024];
while ((i=fis.read(bys))!=-1){
fos.write(bys,0,i);
}
fis.close();
fos.close();
}
public static void copy1(String src,String desc) throws IOException {
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(desc);
int i = 0;
while ((i=fis.read())!=-1){
fos.write(i);
}
fis.close();
fos.close();
}
}
7 字符流的基类
Reader
Writer
7.1 字符流
- 由于使用字节流操作中文的时候不是很方便,容易出问题。所以java就给我们提供了字符流。字符流是通过字节流转换而来的。而我们的中文在不同的编码方式下占用的字节数是不一样的。
所以我们先给大家讲转换流。 - 字符流 = 字节流+编码表。
7.2 编码表
-
由字符以及它对应的数值组成的一张表
-
计算机只能识别二进制数据
-
为了方便使用计算机,让计算机可以识别各个国家的文字,各个国家就把他们的文字都用数字来表示,并且是一一对应的,最后就形成了一张表。
7.3 常用的编码表
- ASCII
- ISO-8859-1:8位表示一个数据
- GBK
- GB2312
- BIG5:中国台湾,香港使用的繁体编码表
- UTF-8: 最多用3个字节来表示一个字符
一个能够用就用一个
一个不够用2个
二个不够用三个 - Unicode:国际标准码,融合了多种文字
所有的文字都用2个字节来表示。java用的就是这个
7.4 字符串的编码和解码
-
编码:把我们能看懂的变成计算机能看懂的。 String—byte[]
byte[] getBytes(String charsetName) -
解码:把计算机看的懂的变成我们看的懂的。 byte[]----String
String(byte[] bytes, String charsetName) -
编码和解码的时候一定要使用同一种编码方式。否则就会乱码。
package com.momo.demo;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/*
* 编码
* 解码
* */
public class Demo4 {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "进攻";
//byte[] bytes = s.getBytes();//[-24, -65, -101, -26, -108, -69]
//byte[] bytes = s.getBytes("utf-8");
//[-24, -65, -101, -26, -108, -69]
byte[] bytes = s.getBytes("gbk");//[-67, -8, -71, -91]
// System.out.println(Arrays.toString(bytes));
//String ss = new String(bytes);
//String ss = new String(bytes,"gbk");
String ss = new String(bytes,"utf-8");
System.out.println(ss);
}
}
8 转换流
8.1 OutputStreamWriter 字符输出流
OutputStreamWriter是从字符流到字节流的桥梁:向其写入的字符编码成使用指定的字节charset 。
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。
- 构造方法:
OutputStreamWriter(OutputStream out)
创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName)
创建一个使用命名字符集的OutputStreamWriter。 - 写数据方法
void write(char[] cbuf)
写入一个字符数组。
void write(char[] cbuf, int off, int len)
写入字符数组的一部分。
void write(int c)
写一个字符
void write(String str)
写一个字符串
void write(String str, int off, int len)
写一个字符串的一部分。
8.2 InputStreamReader 字符输入流
- InputStreamReader是从字节流到字符流的桥:它读取字节,并使用指定的charset将其解码为字符 。
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集。 - 构造方法
InputStreamReader(InputStream in)
创建一个使用默认字符集的InputStreamReader。
InputStreamReader(InputStream in, String charsetName)
创建一个使用命名字符集的InputStreamReader。
-读数据的方法
int read()
读一个字符
int read(char[] cbuf)
将字符读入数组。
abstract int read(char[] cbuf, int off, int len)
将字符读入数组的一部分。
package com.momo.demo;
import java.io.*;
/*
* 转换流
* */
public class Demo5 {
public static void main(String[] args) throws IOException {
//输出流写数据
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"));//默认的
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"),"utf8");
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),"gbk");
// osw.write(97);
//osw.write("我爱你".toCharArray());
//osw.write("abcdefg".toCharArray(),1,2);
//osw.write("哈哈哈哈哈");
// osw.write("小龙");
osw.write("abcd");
//osw.write("abdfdfad",2,3);
osw.close();
System.out.println("------------");
//输入流读数据
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
//InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"gbk");
/* int i = 0;
while ((i=isr.read())!=-1){
System.out.println((char)i);
}*/
int i = 0;
char[] chs = new char[1024];
while ((i=isr.read(chs))!=-1){
System.out.println(new String(chs,0,i));
}
isr.close();
}
}
8.3 转换流写数据的flush方法和close方法的区别?
- flush刷新之后对象可以继续使用
- close之后对象就不能使用了
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/*
* 这次没有调用close方法,数据没有写进去?
* close方法关闭流对象的方法,但是关闭之前会刷新缓冲区。把数据写入文件中。
* 没有关闭的的话数据其实还在缓冲区中。
* 我们可以使用flush方法来刷新缓冲区。数据就可以写入
*
* 区别:
* flush刷新之后对象可以继续使用
* close之后对象就不能使用了
* */
public class Demo6 {
public static void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"));
//为什么数据没有写进去?
/*
* 字符=2个字节
* 文件中数据存储的基本单位是字节。
* */
osw.write('b');
// osw.close();
/*
* 如果不想close还想把数据写入,我们可以使用一个方法用来刷新缓冲区
* flush方法
* */
osw.flush();
osw.write('d');
osw.close();
// IOException: Stream closed
// osw.write('r');
// osw.close();
}
}
- 练习:使用转换流复制文本文件
package com.momo.demo;
import java.io.*;
/*
* 转换流复制文件
* */
public class Demo7 {
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\keda\\day29\\src\\com\\momo\\demo\\Demo4.java"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("log.txt"));
//一次一个字符
/* int i =0;
while ((i=isr.read())!=-1){
osw.write(i);
//osw.flush();
}*/
//一次读写一个字符数组
int i =0;
char[] chs = new char[1024];
while ((i=isr.read(chs))!=-1){
osw.write(chs,0,i);
//osw.flush();
}
isr.close();
osw.close();
}
}
9 转换流的简化写法
9.1 写法
转换流的名字比较长,而且我们常见的操作都是按照本地默认编码方式来实现的。
所以为了简化书写,java针对转换流提供了对应的子类。
-
InputStreamReader = FileInputStream+编码表
-
FileReader = InputStreamReader+默认编码表
-
OutputStreamWriter = FileOutputStream+编码表
-
FileWriter = OutputStreamWriter+默认编码表
9.2 FileWriter
- 方便写入字符文件。 该类的构造函数有默认字符编码和默认字节缓冲区大小。
- 构造方法:
FileWriter(File file)
给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append)
给一个File对象构造一个FileWriter对象。
FileWriter(String fileName)
构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append)
构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。 - 写数据的方法都是父类中的
9.3 FileReader
-方便读入字符文件。 该类的构造函数有默认字符编码和默认字节缓冲区大小。
-构造方法:
FileReader(File file)
创建一个新的 FileReader ,给出 File读取。
FileReader(String fileName)
创建一个新的 FileReader ,给定要读取的文件的名称。
- 读数据的方法也都是父类中的。
package com.momo.demo;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 使用转换流的子类直接复制文件
* */
public class Demo8 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("log.txt");
FileWriter fw = new FileWriter("d.txt");
//一次读写一个字符
/* int i = 0;
while ((i=fr.read())!=-1){
fw.write(i);
}*/
//一次读写一个字符数组
int i = 0;
char[] chs = new char[1024];
while ((i=fr.read(chs))!=-1){
fw.write(chs,0,i);
}
fr.close();
fw.close();
}
}
-练习:自己练习使用字符流的简化写法复制文件
10 字符缓冲流
- 字节流为了提高效率提供了对应的缓冲流,同样字符流为了提高效率也提供了对应的缓冲流
10.1 BufferedReader 字符缓冲输入流 读数据
-
从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取。
-
可以指定缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途。
-
构造方法:
BufferedReader(Reader in)
创建使用默认大小的输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz)
创建使用指定大小的输入缓冲区的缓冲字符输入流。 -
特有功能:
String readLine() 读一行文字。
10.2 BufferedWriter 字符缓冲输出流 写数据
-
将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入。
-
可以指定缓冲区大小,或者可以接受默认大小。 默认值足够大,可用于大多数用途。
-
构造方法:
BufferedWriter(Writer out)
创建使用默认大小的输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz)
创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。 -
特有功能:
void newLine() 写一行行分隔符。
package com.momo.demo;
import java.io.*;
/*
* 字符缓冲流写入数据
* */
public class Demo9 {
public static void main(String[] args) throws IOException {
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
bw.write(97);
bw.write("abc".toCharArray());
bw.write("abcdef".toCharArray(),1,3);
bw.write("adsfdsf");
bw.write("adsfdsfasdf",2,2);
bw.flush();
bw.close();
}
}
package com.momo.demo;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*
*字符缓冲流读数据
* */
public class Demo10 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("log.txt"));
/* int i = 0;
while ((i=br.read())!=-1){
System.out.print((char)i);
}*/
char[] chs = new char[1024];
int i = 0;
while ((i=br.read(chs))!=-1){
System.out.println(new String(chs,0,i));
}
br.close();
}
}
- 练习:使用字符缓冲流复制文件
package com.momo.demo;
import java.io.*;
/*
* 字符缓冲流的特有功能
* BufferedReader
* String readLine() 一次可以读一行文字。
* 注意:不一样的地方是当读取到末尾的时候返回的是 null 不是-1
* BufferedWriter
* void newLine() 根据当前系统来决定换行符
* */
public class Demo11 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
/*String line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);
line = br.readLine();
System.out.println(line);*/
/* String line = null;
while ((line = br.readLine())!=null){
System.out.println(line);
}
br.close();*/
System.out.println("----------------");
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));
for(int i=0;i<5;i++){
bw.write("aaa"+i);
//bw.write("\r\n");
bw.newLine();
bw.flush();
}
bw.close();
}
}
-
练习:使用字符缓冲流特有功能复制文件
-
字节流复制数据:4种
-
字符流复制数据:5种
10.3 io流的练习
- 复制文本文件
- 复制图片,音乐
- 有一个集合,集合中保存了一些字符串数据。读取集合中的字符串,存储到文本文件中。
- 把文本文件中的每一行数据读取存到集合中
- 把指定文件夹中的内容复制到另一个文件夹中。 a文件夹中有: a.txt b.txt c.mp3 复制到b文件夹中。
- 复制多级文件夹
- 键盘输入几个学生信息,按照总分高低存储文本文件
- 练习:假如a.txt中有一个字符串“sdkljfaslfkjavavaabdc”
要求读取文件中的字符串然后排序后写道b.txt中。 - 注册登录 io 流版
把用户的注册信息保存到文件中,将来直接从文件中读取信息,判断用户是否登录成功。
10.4 操作基本数据类型的流
DataInputStream
DataOutputStream
10.5 操作字节数组的流
ByteArrayInputStream
ByteArrayOutputStream
10.6 操作字符数组的流
CharArrayReader
CharArrayWriter
10.7 操作字符串的流
StringReader
StringWriter
10.8 打印流
10.9 序列化流
11 序列化
11.1 概述
- 序列化:把内存中的对象变成字节数组,保存到文件中。
ObjectOutputStream
构造方法:ObjectOutputStream(OutputStream out)
创建一个写入指定的OutputStream的ObjectOutputStream。 - 反序列化:读取文件中的对象字节数组,在变成内存中的对象。
ObjectInputStream
构造方法:
ObjectInputStream(InputStream in)
创建从指定的InputStream读取的ObjectInputStream。
package com.momo.domain;
import java.io.Serializable;
public class Stu implements Serializable {
private String name;
private transient int age;
//private double salary;
public Stu() {
}
public Stu(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
package com.momo.demo;
import com.momo.domain.Stu;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
/*
* 序列化
* 注意:一个对象要想进行序列化,必须:
* 该类必须实现Serializable,是一个标记性接口。
* 如果我们将来希望有一些属性不要被序列化,该属性
* 必须标注出来。使用关键字:transient
* */
public class Demo12 {
public static void main(String[] args) throws IOException {
Stu s = new Stu("默默",18);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("stu.txt"));
oos.writeObject(s);
oos.close();
}
}
package com.momo.demo;
import com.momo.domain.Stu;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
/*
* 反序列化
* */
public class Demo13 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("stu.txt"));
Object o = ois.readObject();
Stu s = (Stu)o;
System.out.println(s);
System.out.println(s.getName()+"---"+s.getAge());
}
}
- 练习:序列化集合