第二十二天 IO-高效流(缓冲流)&转换流【悟空教程】

第二十二天 IO-高效流(缓冲流)&转换流【悟空教程】

第22天 IO

第1章 高效流

1.1 高效流 (缓冲流)

在我们学习字节流与字符流的时候,大家都进行过读取文件中数据的操作,读取数据量大的文件时,读取的速度会很慢,很影响我们程序的效率,那么,我想提高速度,怎么办?

Java中提高了一套缓冲流,它的存在,可提高IO流的读写速度

缓冲流,根据流的分类分类字节缓冲流与字符缓冲流。如下:

高效字节流:BufferedInputStream/BufferedOutputStream 字节缓冲流

高效字符流:BufferedReader/BufferedWriter 字符缓冲流

高效流使用普通流对象作为构造方法参数。将普通流包装,提供高效的装饰。

关闭流时只需要关闭高效流即可。

1.2 字节缓冲流

字节缓冲流根据流的方向,共有2个

  • 写入数据到流中,字节缓冲输出流 BufferedOutputStream
  • 读取流中的数据,字节缓冲输入流 BufferedInputStream

它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度

1.2.1 字节缓冲输出流BufferedOutputStream

通过字节缓冲流,进行文件的读写操作 写数据到文件的操作

  • 构造方法

public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

public class BufferedOutputStreamDemo01 {

public static void main(String[] args) throws IOException {

//写数据到文件的方法

write();

}

/*

* 写数据到文件的方法

* 1,创建流

* 2,写数据

* 3,关闭流

*/

private static void write() throws IOException {

//创建基本的字节输出流

FileOutputStream fileOut = new FileOutputStream("abc.txt");

//使用高效的流,把基本的流进行封装,实现速度的提升

BufferedOutputStream out = new BufferedOutputStream(fileOut);

//2,写数据

out.write("hello".getBytes());

//3,关闭流

out.close();

}

}

1.2.2 字节缓冲输入流 BufferedInputStream

刚刚我们学习了输出流实现了向文件中写数据的操作,那么,现在我们完成读取文件中数据的操作

  • 构造方法

public BufferedInputStream(InputStream in)

/*

* 从文件中读取数据

* 1,创建缓冲流对象

* 2,读数据,打印

* 3,关闭

*/

private static void read() throws IOException {

//1,创建缓冲流对象

FileInputStream fileIn = new FileInputStream("abc.txt");

//把基本的流包装成高效的流

BufferedInputStream in = new BufferedInputStream(fileIn);

//2,读数据

int ch = -1;

while ( (ch = in.read()) != -1 ) {

//打印

System.out.print((char)ch);

}

//3,关闭

in.close();

}

1.3 普通流与缓冲流效率比较

package cn.javahelp_01;

import java.io.BufferedInputStream;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

/*

* 缓冲流与普通流 读取文件效率对比

*

*/

public class Demo {

public static void main(String[] args) throws IOException {

//普通字节流 fun();

//缓冲流 fun2();

fun3(); //普通数组

// 缓冲流数组 fun4();

}

private static void fun4() throws FileNotFoundException, IOException {

//创建 缓冲流对象

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("hi.jpg"));

long start = System.currentTimeMillis();

byte[] b = new byte[8*1024];

int len;

while ((len = bis.read(b))!=-1) {

}

bis.close();

long end = System.currentTimeMillis();

System.out.println("BufferedInputStream 使用数组 读取文件的时间:" + (end - start) + "毫秒"); //

}

private static void fun3() throws FileNotFoundException, IOException {

FileInputStream fis = new FileInputStream("hi.jpg");

long start = System.currentTimeMillis();

byte[] b = new byte[ 8 *1024];

int len;

while ((len = fis.read(b)) != -1) {

}

fis.close();

long end = System.currentTimeMillis();

System.out.println("FileInputStream 使用数组 读取文件的时间:" + (end - start) + "毫秒"); //

}

private static void fun2() throws FileNotFoundException, IOException {

// 创建缓冲流 对象

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("hi.jpg"));

long start = System.currentTimeMillis();

int b;

while ((b = bis.read()) != -1) {

// System.out.print((char)b);

}

System.out.println();

bis.close(); // 关闭资源的时候 ,只需要关闭 缓冲流即可.

long end = System.currentTimeMillis();

System.out.println("BufferedInputStream 读取文件的时间:" + (end - start) + "毫秒"); // 225毫秒

}

private static void fun() throws FileNotFoundException, IOException {

// 使用 FileInputStream 读取 文件 . 打印在控制台.

FileInputStream fis = new FileInputStream("hi.jpg");

long start = System.currentTimeMillis();

int b;

while ((b = fis.read()) != -1) {

// System.out.print((char)b);

}

System.out.println();

fis.close();

long end = System.currentTimeMillis();

System.out.println("FileInputStream 读取文件的时间:" + (end - start) + "毫秒"); // 38995

// 毫秒

}

}

1.4 缓冲流高效原理:

看源码:内置数组,8*1024缓冲

1.5 字符缓冲流BufferedWriter和BufferedReader

1.5.1 基本用法

  • BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
  • BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

public class Demo01BufferedStream {

public static void main(String[] args) throws IOException {

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

bw.write("hello");

//bw.flush();

bw.close();

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader("bw.txt "));

/*

//一次读写一个字符

int ch;

while((ch=br.read())!=-1){

System.out.print((char)ch);

}

*/

//一次读写一个字符数组

char[] chs = new char[1024];

int len;

while((len=br.read(chs))!=-1) {

System.out.print(new String(chs,0,len));

}

//释放资源

br.close();

}

}

1.5.1.1 缓冲流复制文本文件的两种方式

public class Demo02CopyFile {

public static void main(String[] args) throws IOException {

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader("Demo01FileWriter.java"));

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));

//读写数据

/*

//一次读写一个字符

int ch;

while((ch=br.read())!=-1) {

bw.write(ch);

}

*/

//一次读写一个字符数组

char[] chs = new char[1024];

int len;

while((len=br.read(chs))!=-1) {

bw.write(chs,0,len);

}

//释放资源

bw.close();

br.close();

}

}

1.5.2 特殊方法:

高效字符流在普通IO方法的基础上,添加了readLine方法与newLine方法

  • BufferedWriter
    • void newLine():写一个换行符,这个换行符由系统决定
  • BufferedReader
    • String readLine():一次读取一行数据,但是不读取换行符

注意:

一切带缓冲的流在写出数据时,均需要刷新缓冲区调用flush方法,否则数据并没有真正写出到文件,而仍然停留在缓冲区。

在复制一行时,每次读取到的是这行的内容,虽然是以回车换行判断一行,但不包含最终的回车换行。可以使用”\r\n”来代表windows中的回车换行,但是却不通用,因为不同的操作系统,它的回车换行字符不一样。所以用newLine方法换行。

1.5.2.1 字符高效输出流 BufferedWriter (换行)

将文本写入字符输出流,高效各个字符,从而提供单个字符、数组和字符串的高效写入。

  • 方法:

void newLine() 根据当前的系统,写入一个换行符 newLine方法可以跨凭台使用

/*

* BufferedWriter 字符高效输出流

* 方法

* public void newLine()写入一个行分隔符

*

* 需求: 通过高效输出流写入数据到文件

* 分析:

* 1,创建流对象

* 2,写数据

* 3,关闭流

*

*/

public class BufferedWriterDemo {

public static void main(String[] args) throws IOException {

//创建流

//基本字符输出流

FileWriter fileOut = new FileWriter("file.txt");

//把基本的流进行包装

BufferedWriter out = new BufferedWriter(fileOut);

//2,写数据

for (int i=0; i<5; i++) {

out.write("hello");

out.newLine();

}

//3,关闭流

out.close();

}

}

1.5.2.2 字符高效输入流 BufferedReader(读取一行)

从字符输入流中读取文本,高效各个字符,从而实现字符、数组和行的高效读取。

  • 方法

public String readLine() 读取一个文本行,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

/*

* BufferedReader 字符高效输入流

*

* 方法:

* String readLine()

* 需求:从文件中读取数据,并显示数据

*/

public class BufferedReaderDemo {

public static void main(String[] args) throws IOException {

//1,创建流

BufferedReader in = new BufferedReader(new FileReader("file.txt"));

//2,读数据

//一次一个字符

//一次一个字符数组

//一次读取文本中一行的字符串内容

String line = null;

while( (line = in.readLine()) != null ){

System.out.println(line);

}

//3,关闭流

in.close();

}

}

1.5.2.3 缓冲流特殊功能复制文本文件

/*

* 采用高效的字符高效流,完成文本文件的赋值

*

* 数据源: file.txt

* 目的地: copyFile.txt

*

* 分析:

* 1,指定数据源, 是数据源中读数据,采用输入流

* 2,指定目的地,是把数据写入目的地,采用输出流

* 3,读数据

* 4,写数据

* 5,关闭流

*/

public class CopyTextFile {

public static void main(String[] args) throws IOException {

//1,指定数据源, 是数据源中读数据,采用输入流

BufferedReader in = new BufferedReader(new FileReader("file.txt"));

//2,指定目的地,是把数据写入目的地,采用输出流

BufferedWriter out = new BufferedWriter(new FileWriter("copyFile.txt"));

//3,读数据

String line = null;

while ( (line = in.readLine()) != null ) {

//4,写数据

out.write(line);

//写入换行符号

out.newLine();

}

//5,关闭流

out.close();

in.close();

}

}

1.6 包装思想

在高效流的源码中,我们发现普通流通过构造方法传入到高效流对象中,即高效流对象中包含了一个普通流对象。所以普通流中的方法高效流都存在,而高效流在普通流的基础上又添加了新的更为强大的方法,且添加了缓冲区效率也更高。

这相当于将普通流进行了包装,让原有类的功能变得更为强大。

在后边学习中,我们会遇到一些类似的包装类,其构造方法参数不是对应资源而是对应的普通流对象。

第2章 转换流

2.1 System.in与System.out

我们常见的System.in与System.out就是典型的字节流,可以直接与控制台进行数据传输。

如:OutputStream os = System.out;

方法阻塞:

当调用这个方法时,程序会进行等待,当方法调用结束后,阻塞结束。

Scanner并不是键盘录入,是文本扫描,可以根据绑定IO资源的不同,扫表不同的文本资源,如果给予文件,则扫描文件,如果给予System.in则扫描键盘录入数据

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.UnsupportedEncodingException;

/*

* 转换流 是 字符流的子类

*

* 字符流 = 字节流 + 编码表 . 保证了编码表 和 文件的编码 一致 ,能够读取数据成功.

* 编码表和 文件的编码不一致, 乱码.

* InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的 InputStreamReader。

*/

public class Demo {

public static void main(String[] args) throws IOException {

//创建 InputStreamReader 对象

InputStreamReader isr = new InputStreamReader(new FileInputStream("bj.txt"), "utf8") ;

char ch = (char)isr.read();

System.out.println(ch);

}

}

2.2 InputStreamReader与OutputStreamWriter

操作字节流对于程序来说过于繁琐,程序员更偏爱操作字符。所以,当面对一些字节流的操作时,我们可以将其转换为字符流再进行操作,这样便非常方便了。

Reader:

InputStreamReader可以完成字节输入流转换为字符输入流

Writer:

OutputStreamWriter可以完成字节输出流转换为字符输出流。

由上边可以知道,转换流是字符流的一种,创建对象时传入对应字节流对象即可完成转换动作。

转换流同样使用了包装的思想,其构造方法接收的同样为IO流对象,并非某个文件资源。关闭转换流的同时即关闭了对应的字节流。

2.3 OutputStreamWriter类

查阅OutputStreamWriter的API介绍,OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。

  • 代码演示:

public static void writeCN() throws Exception {

//创建与文件关联的字节输出流对象

FileOutputStream fos = new FileOutputStream("c:\\cn8.txt");

//创建可以把字符转成字节的转换流对象,并指定编码

OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");

//调用转换流,把文字写出去,其实是写到转换流的高效区中

osw.write("你好");//写入高效区。

osw.close();

}

OutputStreamWriter流对象,它到底如何把字符转成字节输出的呢?

其实在OutputStreamWriter流中维护自己的高效区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter高效区中。然后再调用刷新功能,或者关闭流,或者高效区存满后会把高效区中的字节数据使用字节流写到指定的文件中。

2.4 InputStreamReader类

查阅InputStreamReader的API介绍,InputStreamReader 是字节流通向字符流的桥梁:它使用指定的字符编码表读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

  • 代码演示

public class InputStreamReaderDemo {

public static void main(String[] args) throws IOException {

//演示字节转字符流的转换流

readCN();

}

public static void readCN() throws IOException{

//创建读取文件的字节流对象

InputStream in = new FileInputStream("c:\\cn8.txt");

//创建转换流对象

//InputStreamReader isr = new InputStreamReader(in);这样创建对象,会用本地默认码表读取,将会发生错误解码的错误

InputStreamReader isr = new InputStreamReader(in,"utf-8");

//使用转换流去读字节流中的字节

int ch = 0;

while((ch = isr.read())!=-1){

System.out.println((char)ch);

}

//关闭流

isr.close();

}

}

注意:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象。

2.5 转换流和子类区别

发现有如下继承关系:

Writer 字符输出流

|- OutputStreamWriter 转换流(字符流—>字节流)(属于字符输出流, 可以指定字符编码表,用来写入数据到文件)

|--FileWriter 操作文件中字符输出流,采用默认的字符编码表

Reader 字符输入流

|- InputStreamReader: 转换流(字节流à字符流)(属于字符输入流,可以指定字符编码表,用来从文件中读数据)

|--FileReader操作文件中字符输入流,采用默认的字符编码表

父类和子类的功能有什么区别呢?

OutputStreamWriter和InputStreamReader是字符和字节的桥梁:也可以称之为字符转换流。字符转换流原理:字节流+编码表。

FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));//默认字符集。

InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");//指定GBK字符集。

FileReader fr = new FileReader("a.txt");

这三句代码的功能是一样的,其中第三句最为便捷。

注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?

条件:

1、操作的是文件。2、使用默认编码。

总结:

字节--->编码表--->字符 : 看不懂的--->看的懂的。 需要读。输入流。 InputStreamReader

字符--->编码表--->字节 : 看的懂的--->看不懂的。 需要写。输出流。 OutputStreamWriter

2.6 编码表

2.6.1 编码表概念

在转换流或者字符串的构造方法当中,我们发现有一个参数始终没有使用,即字符串型的编码集名称。

如果没有指定该名称,则默认为”GBK”,GBK就是编码表的一种。

编码表即字符与存储数据的对应关系表,每一个字符都对应一个数字。

所以,有如下公式:

字符 = 字节 + 编码表

2.6.2 常用编码表

GBK:中文环境默认码表,中文码表(2个字节对应一个汉字)

GB2312:与GBK基本相同

UTF-8:万国码,JavaEE项目中的通用编码表,包含各国文字编码(一般3个字节对应一个汉字)

ISO8859-1:拉丁码表,不包含中文,是西方较通用的码表

BIG-5:繁体字码表

2.6.3 编码表使用

乱码:当字符与字节转换过程中使用了不同的码表,会造成乱码的情况。

在字符串中:

当我们将字符串转为对应的数字字节时,需要指定码表,则存储了为该字符该码表对应的数字字节,如果使用了其他码表重写翻译回字符串,则拼写的新字符串会乱码。

在IO中:

与字符串编码表使用类似,当以某个码表写出字节数据时,又使用另外码表展示,会出现乱码。

第3章 IO练习

3.1 IO常见习题操作

3.1.1 使用try/catch完成简单的IO代码。

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.PrintStream;

/*

* try ... catch 处理 IO流 文本复制代码 . 全选Ctrl+shift+z

*/

public class Demo {

public static void main(String[] args) throws IOException {

// 创建流对象

FileInputStream fis = null;

FileOutputStream fos = null;

try {

fis = new FileInputStream("bj4.txt");

fos = new FileOutputStream("bj3.txt");

// 操作数据

int b;

while ((b = fis.read()) != -1) {

fos.write(b);

}

} catch (IOException e) {

System.out.println("IO异常");

e.printStackTrace();

//打印异常到日志

e.printStackTrace(new PrintStream("Exception.log"));

} finally {

// 关闭资源

fos.close();

fis.close();

}

}

}

3.1.2 文本反转

bj.txt

那时酒醉意昏沉,东倒西歪乱撒泼。

逞雄撞入广寒宫,风流仙子来相接。

见她容貌挟人魂,旧日凡心难得灭。

全无上下失尊卑,扯住嫦娥要陪歇。

再三再四不依从,东躲西藏心不悦。

色胆如天叫似雷,险些震倒天关阙。

纠察灵官奏玉皇,那日吾当命运拙。

广寒围困不通风,进退无门难得脱。

却被诸神拿住我,酒在心头还不怯。

押赴灵霄见玉皇,依律问成该处决。

bjj.txt

押赴灵霄见玉皇,依律问成该处决。

却被诸神拿住我,酒在心头还不怯。

广寒围困不通风,进退无门难得脱。

纠察灵官奏玉皇,那日吾当命运拙。

色胆如天叫似雷,险些震倒天关阙。

再三再四不依从,东躲西藏心不悦。

全无上下失尊卑,扯住嫦娥要陪歇。

见她容貌挟人魂,旧日凡心难得灭。

逞雄撞入广寒宫,风流仙子来相接。

那时酒醉意昏沉,东倒西歪乱撒泼。

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileInputStream;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.LinkedList;

/*

* 将一个bj.txt文本文档上的文本反转,

* 第一行和倒数第一行交换

* 第二行和倒数第二行交换

*

* 1. 读取文件.读一行. readLine. BufferedReader

* 2. 读取内容, 添加到集合中.

* ArrayList 有序. 反向遍历

* LinkedList. 1-10 addFirst , 正向遍历.

* map. 1 "----" , 2,"-----" 10."---" .

* 3. 写出文件

*

*

*/

public class Test {

public static void main(String[] args) throws IOException {

//创建流对象

BufferedReader br = new BufferedReader

(new InputStreamReader(new FileInputStream("bj.txt"), "utf8"));

//创建 集合

LinkedList<String > linkedList = new LinkedList<>();

String line = null;

while (( line = br.readLine())!= null) {

linkedList.addFirst(line); // 10 - 9 .. 1

}

br.close();

// 创建 输出流对象

BufferedWriter bw = new BufferedWriter(new FileWriter("bjj.txt"));

// 遍历集合

for (int i = 0; i < linkedList.size(); i++) {

String string = linkedList.get(i);

bw.write(string);

bw.newLine();

}

// 关闭资源

bw.close();

System.out.println("转换完毕");

}

}

3.1.3 用户数据初始化_用户登录

User.txt

<姓名:老王,密码:laowang>

<姓名:八戒,密码:babajiejie>

<姓名:奎木狼,密码:kuimulang>

public class User {

String name ; // 姓名

String psw ; // 密码

public User() {

super();

// TODO Auto-generated constructor stub

}

public User(String name, String psw) {

super();

this.name = name;

this.psw = psw;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getPsw() {

return psw;

}

public void setPsw(String psw) {

this.psw = psw;

}

@Override

public String toString() {

return " 用户 名=" + name + ", 密码=" + psw;

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + ((name == null) ? 0 : name.hashCode());

result = prime * result + ((psw == null) ? 0 : psw.hashCode());

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj)

return true;

if (obj == null)

return false;

if (getClass() != obj.getClass())

return false;

User other = (User) obj;

if (name == null) {

if (other.name != null)

return false;

} else if (!name.equals(other.name))

return false;

if (psw == null) {

if (other.psw != null)

return false;

} else if (!psw.equals(other.psw))

return false;

return true;

}

}

import java.io.BufferedReader;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.util.ArrayList;

/*

* 从文本中,读取用户信息,创建用户对象,保存到集合.

*

*/

public class Test2 {

public static void main(String[] args) throws IOException {

// 创建 输入流 读取 文件 .

BufferedReader br = new BufferedReader(new FileReader("User.txt"));

//创建集合

ArrayList<User> userList = new ArrayList<>();

String userData = null ;

while (( userData = br.readLine() )!= null) {

// 解析数据, 把字符串 数据 封装 一个User 对象.

System.out.println(userData);

User user = new User();

// 干掉 < >

String substring = userData.substring(1, userData.length() -1 ); // 姓名:老王,密码:laowang

// " ," split

String[] split = substring.split(","); // split 姓名:老王 | 密码:laowang

for (String string : split) {

System.out.println(string);

String[] split2 = string.split(":");

if (split2[0].equals("姓名")) {

String name = split2[1] ; // 姓名

System.out.println("=== " + name );

user.setName(name);

}else {

String psw = split2[1]; // 密码

System.out.println("=====" + psw);

user.setPsw(psw);

}

}

// 把对象保存集合 . ArrayList

userList.add(user);

}

// 关闭资源

br.close();

System.out.println(userList);

}

}

文件复制(分别使用字节/字符/高效/转换),可以完成自由灵活地文件复制。

单级文件夹复制,即文件夹中不包含文件夹时,将a文件夹内所有内容复制到b文件夹中

较难习题:

多级文件夹复制:将a文件夹下的所有内容(包括a文件夹全部复制到b文件夹中)(了解)

IO结合字符串:将字符内容读取后,再进行筛选判断工作

IO结合集合:将内容读取后,使用集合持有在内存中进行其他操作

第4章 本日自习作业:

4.1 知识点相关题

4.1.1 转换流OutputStreamWriter和InputStreamReader

题目:

1) 定义类Test1,定义main()方法,按以下要求编写代码:

  • 构造一个“字节输出流”FileOutputStream,指向项目目录下的文件demo01.txt
  • 使用这个字节输出流,构造一个OutputStreamWriter,并且指定编码为:UTF-8.
  • 通过转换流输出以下内容:

孙红雷

葛优

黄渤

黄晓明

  • 关闭输出转换流。
  • 运行程序,查看文件内容;(使用不同的文本编辑器:记事本,Eclipse,notpat++等)

2) 定义类Test2,定义main()方法,按以下要求编写代码:

  • 构造一个“字节输入流”FileInputStream,指向项目目录下的文件demo01.txt
  • 使用这个字节输入流,构造一个InputStreamReader,并且指定编码为:UTF-8.
  • 循环一次读取一个字符,并打印。
  • 关闭输出转换流。
  • 运行程序,打印内容。

3) 将Test2中读取的编码改为:GBK,再次运行Test2,会看到乱码,请问为什么?

4.1.2 掌握使用缓冲流复制文件的方式

定义类Test3,定义main()方法,按以下要求编写代码:

  • 构建一个字符缓冲输入流,指向srcPath.txt文件
  • 构建一个字符缓冲输出流,指向destPath.txt文件
  • 使用一次读一个字符的方式和一次读一个缓冲数组的方式分别测试,复制此文件夹中的内容
  • 关闭流
  • 运行代码,查看目的文件

4.1.3 知识点:字节缓冲流:BufferedOutputStream和BufferedInputStream

题目:

1) 定义类Test3,定义main()方法,按以下要求编写代码:

  • 构造一个缓冲输入流,指向某个文件;
  • 构造一个缓冲输出流,指向某个位置上的一个新文件。
  • 使用一次复制一个字节的方式,复制文件;
  • 关闭流;
  • 运行程序,查看新文件;
  • 将复制方式改为:一次复制一个字节数组;

2) 定义类Test4,定义main()方法,按以下要求编写代码:

  • 定义方法:method1(),实现:基本字节流一次复制一个字节的方式复制文件;
  • 定义方法:method2(),实现:基本字节流一次复制一个字节数组的方式复制文件;
  • 定义方法:method3(),实现:缓冲字节流一次复制一个字节的方式复制文件;
  • 定义方法:method4(),实现:缓冲字节流一次复制一个字节数组的方式复制文件;

4.1.4 使用try/catch完成简单的IO操作

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.PrintStream;

/*

* try ... catch 处理 IO流 文本复制代码 .

*/

public class Demo {

public static void main(String[] args) throws IOException {

// 创建流对象

FileInputStream fis = null;

FileOutputStream fos = null;

try {

fis = new FileInputStream("bj4.txt");

fos = new FileOutputStream("bj3.txt");

// 操作数据

int b;

while ((b = fis.read()) != -1) {

fos.write(b);

}

} catch (IOException e) {

System.out.println("IO异常");

e.printStackTrace();

e.printStackTrace(new PrintStream("Exception.log"));

} finally {

// 关闭资源

fos.close();

fis.close();

}

}

}

4.1.5 使用高效流完成文件复制

4.1.6 使用转换流包装两个文件对象,完成文件复制

4.1.7 向一个文件中输出汉字,通过不同的编码演示乱码

4.1.8 完成以下练习

4.1.9 单级文件夹复制(可使用多种IO类型)

4.1.10 从一个文件中读取所有内容(该文件中全部为中文),并查找”的”这个字出现了几次

4.1.11 一个集合中存储多个Person对象(name,age),将多个对象内容写到文本中

4.1.12 读取一个文本文件,将内容打印到控制台(不能使用System.out.println)

4.1.13 附加:多级文件夹复制(了解)

4.1.14 理清所有IO类的关系(建议:可以画图)

4.2 代码题

4.2.1 复制文本文件(5种方式)

public class Demo01CopyFileTest {

public static void main(String[] args) throws IOException {

String srcFileName = "Demo01FileWriter.java";

String destFileName = "Copy.java";

method1(srcFileName,destFileName);

method2(srcFileName,destFileName);

method3(srcFileName,destFileName);

method4(srcFileName,destFileName);

method5(srcFileName,destFileName);

}

//基本流一次读写一个字符

public static void method1(String srcFileName,String destFileName) throws IOException {

//创建输入流对象

FileReader fr = new FileReader(srcFileName);

//创建输出流对象

FileWriter fw = new FileWriter(destFileName);

//一次读写一个字符

int ch;

while((ch=fr.read())!=-1) {

fw.write(ch);

}

//释放资源

fw.close();

fr.close();

}

//基本流一次读写一个字符数组

public static void method2(String srcFileName,String destFileName) throws IOException {

//创建输入流对象

FileReader fr = new FileReader(srcFileName);

//创建输出流对象

FileWriter fw = new FileWriter(destFileName);

//一次读写一个字符数组

char[] chs = new char[1024];

int len;

while((len=fr.read(chs))!=-1) {

fw.write(chs,0,len);

}

//释放资源

fw.close();

fr.close();

}

//缓冲流一次读写一个字符

public static void method3(String srcFileName,String destFileName) throws IOException {

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader(srcFileName));

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter(destFileName));

//一次读写一个字符

int ch;

while((ch=br.read())!=-1) {

bw.write(ch);

}

//释放资源

bw.close();

br.close();

}

//缓冲流一次读写一个字符数组

public static void method4(String srcFileName,String destFileName) throws IOException {

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader(srcFileName));

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter(destFileName));

//一次读写一个字符数组

char[] chs = new char[1024];

int len;

while((len=br.read(chs))!=-1) {

bw.write(chs,0,len);

}

//释放资源

bw.close();

br.close();

}

//缓冲流一次读写一个字符串

public static void method5(String srcFileName,String destFileName) throws IOException {

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader(srcFileName));

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter(destFileName));

//一次读写一个字符串

String line;

while((line=br.readLine())!=null){

bw.write(line);

bw.newLine();

bw.flush();

}

//释放资源

bw.close();

br.close();

}

}

4.2.2 把ArrayList集合中的字符串数据存储到文本文件

  • 每一个字符串元素作为文件中的一行数据

public class Demo02ArrayListToFileTest {

public static void main(String[] args) throws IOException {

//创建集合对象

ArrayList<String> list = new ArrayList<String>();

//往集合中添加字符串元素

list.add("hello");

list.add("world");

list.add("java");

//创建输出缓冲流对象

BufferedWriter bw = new BufferedWriter(new FileWriter("array.txt"));

//遍历集合,得到每一个字符串元素,然后把该字符串元素作为数据写到文本文件

for(int i=0; i<list.size(); i++) {

String s = list.get(i);

bw.write(s);

bw.newLine();

bw.flush();

}

//释放资源

bw.close();

}

}

4.2.3 从文本文件中读取数据到ArrayList集合中,并遍历集合

  • 每一行数据作为一个字符串元素

public class Demo03FileToArrayListTest {

public static void main(String[] args) throws IOException {

//创建输入缓冲流对象

BufferedReader br = new BufferedReader(new FileReader("array.txt"));

//创建集合对象

ArrayList<String> list = new ArrayList<String>();

//读取数据,每次读取一行数据,把该行数据作为一个元素存储到集合中

String line;

while((line=br.readLine())!=null) {

list.add(line);

}

//释放资源

br.close();

//遍历集合

for(int i=0; i<list.size(); i++) {

String s = list.get(i);

System.out.println(s);

}

}

}

4.2.4 转换流操作文本

要求:

转换流读取文本文件,源文件abc.txt是UTF-8编码

将文本中的所有字符以字符数组形式读出,将字符数组存储到字符串缓存区中,

将字符串缓冲区中的字符串一次性写出到文件 abc22.txt,同样也是UTF-8编码

答案:

public static void main(String[] args) throws IOException{

InputStreamReader isr = new InputStreamReader(new FileInputStream("c:\\abc.txt"),"utf-8");

int len = 0 ;

StringBuilder builder = new StringBuilder();

char[] buf = new char[1024];

while((len = isr.read(buf))!=-1){

builder.append(new String(buf,0,len));

}



OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("c:\\abc22.txt"), "utf-8");

osw.write(builder.toString());

osw.flush();

isr.close();

osw.close();

    }

4.2.5 缓冲流BufferedInputStream,BufferedOutputStream复制文本文件

要求:

按照读写文本一行的形式赋值

数据源文件为copy.txt 复制后的数据目的文件为copy_copy.txt

答案:

public class CopyTextFile {

    public static void main(String[] args) throws IOException{

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("c:\\copy.txt"));

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("d:\\copy_copy.txt"));

//读数据

byte[] buffer = new byte[1024];

int len  = 0;

while( (len=bis.read(buffer)) != -1){

//写数据到目的地

bos.write(buffer, 0, len);

}

  bis.close();

  bos.close();

    }

}

原文发布于微信公众号 - Java帮帮(javahelp)

原文发表时间:2018-06-09

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏pangguoming

JSP 中EL表达式用法详解

EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便。接下来介绍EL主要的语法结构: ${sessionScope...

43750
来自专栏微信公众号:Java团长

Java IO流学习总结

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直...

19920
来自专栏个人随笔

Java IO流

package cn.bdqn.demo; import java.io.File; import java.io.FileInputStream; impo...

28460
来自专栏日常分享

JSP/Servlet Web 学习笔记 DaySix —— EL表达式

1)EL从scope中得到参数时可以自动转换类型,因此对于类型转换的限制更加宽松。

9730
来自专栏菩提树下的杨过

java学习:使用dom4j读写xml文件

dom4j是一个优秀的开源项目,专用于xml文件的读写,而且支持强大的xpath. 下面的代码演示了对xml文件demo.xml的读写 demo.xml内容: ...

27660
来自专栏醒者呆

编程语言的基础——搞定JavaIO

关键字:IO基础,JUnit生命周期,字节流,字符流,字符编码,对象流,序列化,反序列化 Java I/O 流是一组有顺序的,有起点和终点的字节集合。是对设...

40650
来自专栏cloudskyme

java在指定目录下执行dos命令或者bat文件

直接看源程序吧 public static void main(String[] args) throws IOException { File dir =...

55450
来自专栏desperate633

Java中的异常处理2堆栈追踪finally自动尝试关闭资源语法

想要知道异常的根源,以及多重方法调用下异常的传播,可以利用异常对象自动收集的堆栈的追踪来取得相关信息,例如,调用调用异常对象的printStacktrace()...

8520
来自专栏一个会写诗的程序员的博客

《Kotlin 程序设计》第十三章 使用Kotlin开发JavaScript代码

我们知道,JavaScript是动态类型的语言,这意味着它不会在编译期检查类型。而相对来说,Kotlin和Java都是静态类型的。

12820
来自专栏一个会写诗的程序员的博客

《Kotin 编程思想·实战》

1.2 程序执行的三种方式 1.2.1 编译执行 1.2.2 解释执行 1.2.3 虚拟机执行

9010

扫码关注云+社区

领取腾讯云代金券