黑马程序员——Java编程语言学习总结 – IO流

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

IO流

Java 的流式输入/输出建立在四个抽象类的基础上:InputStream, OutputStream,Reader和 Writer。它们用来创建具体流式子类。尽管程序通过具体子类执行输入/输出操作,但顶层的类定义了所有流类的基本通用功能。InputStream和 OutputStream 设计成字节流类。Reader 和 Writer 为字符流设计。字节流类和字符流类形成分离的层次结构。一般说来,处理字符或字符串时应使用字符流类,处理字节或二进制对象时应用字节流类。
一般在操作文件流时,不管是字节流还是字符流都可以按照以下的方式进行:
A、 使用 File 类找到一个文件
B、 通过 File 类的对象去实例化字节流或字符流的子类
C、 进行字节(字符)的读、写操作
D、 关闭文件流

注意:一般我们在探讨IO流的时候,如果没有明确说明按哪种分类来说,默认情况下是按照数据类型来分的。

 

 

一、字节流

需求:我要往一个文本文件中输入一句话:"hello,io"

分析:

A:这个操作最好是采用字符流来做,但是呢,字符流是在字节流之后才出现的,所以,今天我先讲解字节流如何操作。

B:由于我是要往文件中写一句话,所以我们要采用字节输出流。

 

通过上面的分析后我们知道要使用:OutputStream

但是通过查看API,我们发现该流对象是一个抽象类,不能实例化。

所以,我们要找一个具体的子类。

而我们要找的子类是什么名字的呢?这个时候,很简单,我们回想一下,我们是不是要往文件中写东西。

文件是哪个单词:File

然后用的是字节输出流,联起来就是:FileOutputStream

注意:每种基类的子类都是以父类名作为后缀名。

XxxOutputStream

XxxInputStream

XxxReader

XxxWriter

 

1,字节输出流FileOutputStream

FileOutputStream构造方法:

FileOutputStream(File file)

FileOutputStream(String name)

 

操作步骤:

A:创建字节输出流对象

B:调用write()方法

C:释放资源

 

public void write(int b):写一个字节

public void write(byte[] b):写一个字节数组

public void write(byte[] b,intoff,int len):写一个字节数组的一部分

如何实现数据的换行

为什么现在没有换行呢?因为你值写了字节数据,并没有写入换行符号。

如何实现呢?写入换行符号即可呗。

刚才我们看到了有写文本文件打开是可以的,通过windows自带的那个不行,为什么呢?

因为不同的系统针对不同的换行符号识别是不一样的?

windows:\r\n

linux:\n

Mac:\r

而一些常见的个高级记事本,是可以识别任意换行符号的。

 

如何实现数据的追加写入

用构造方法带第二个参数是true的情况即可

 

2,字节输入流FileInputStream

字节输入流操作步骤:

A:创建字节输入流对象

B:调用read()方法读取数据,并把数据显示在控制台

C:释放资源

 

读取数据的方式:

A:int read():一次读取一个字节

B:int read(byte[] b):一次读取一个字节数组,返回值其实是实际读取的字节个数。

 

 

 

 

3,转换流

InputStreamReader:从字节流 -- 转换流 -- 字符缓冲流

字节流:InputStreamis = System.in;

转换流:InputStreamReaderisr = new InputStreamReader(is);

缓冲流:BufferedReaderbr = new BufferedReader(isr);

其实上面三句代码我们一般会如下写:

BufferedReaderbr = new BufferedReader(new InputStreamReader(System.in));

 

OutputStreamWriter:从字符流  -- 转换流 -- 字节流

缓冲流:BufferedWriterbw = new BufferedWriter(osw);

转换流:OutputStreamWriterosw = new OutputStreamWriter(os);

字节流:OutputStreamos = System.out;

三句话合并:

BufferedWriterbw = new BufferedWriter(new OutputStreamWriter(System.out));

 

4,使用字节流复制图片的4种方式

分析:

复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。

通过该原理,我们知道我们应该采用字节流。

数据源:

c:\\a.jpg -- FileInputStream --BufferedInputStream

目的地:

d:\\b.jpg -- FileOutputStream --BufferedOutputStream

 

public class CopyImageDemo {

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

使用字符串作为路径

String srcString = "c:\\a.jpg";

String destString = "d:\\b.jpg";

使用File对象做为参数

File srcFile = newFile("c:\\a.jpg");

File destFile = newFile("d:\\b.jpg");

 

method1(srcFile,destFile);

method2(srcFile,destFile);

method3(srcFile,destFile);

method4(srcFile,destFile);

}

 

//方式1:字节缓冲流一次读写一个字节数组

private static void method4(File srcFile, FiledestFile) throws IOException {

BufferedInputStream bis = newBufferedInputStream(new FileInputStream(

srcFile));

BufferedOutputStream bos = newBufferedOutputStream(

new FileOutputStream(destFile));

 

byte[] bys = new byte[1024];

int len = 0;

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

bos.write(bys, 0, len);

}

 

bos.close();

bis.close();

}

 

//方式2:字节缓冲流一次读写一个字节

private static void method3(File srcFile, FiledestFile) throws IOException {

BufferedInputStream bis = newBufferedInputStream(new FileInputStream(

srcFile));

BufferedOutputStream bos = newBufferedOutputStream(

new FileOutputStream(destFile));

 

int by = 0;

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

bos.write(by);

}

 

bos.close();

bis.close();

}

 

//方式3:基本字节流一次读写一个字节数组

private static void method2(File srcFile, FiledestFile) throws IOException {

FileInputStream fis = newFileInputStream(srcFile);

FileOutputStream fos = newFileOutputStream(destFile);

 

byte[] bys = new byte[1024];

int len = 0;

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

fos.write(bys, 0, len);

}

 

fos.close();

fis.close();

}

 

//方式4:基本字节流一次读写一个字节

private static void method1(File srcFile, FiledestFile) throws IOException {

FileInputStream fis = newFileInputStream(srcFile);

FileOutputStream fos = newFileOutputStream(destFile);

 

int by = 0;

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

fos.write(by);

}

 

fos.close();

fis.close();

}

}

 

二、字符流

尽管字节流提供了处理任何类型输入/输出操作的足够的功能,但它们不能直接操
作 Unicode 字符。既然 Java 的一个主要目标是支持“一次编写,处处运行”,包含直
接的字符输入/输出的支持是必要的。本节将讨论几个字符输入/输出类。如前所述,
字符流层次结构的顶层是 Reader 和 Writer 抽象类。

1,字符流的写入FileWriter

FileWriter是抽象类Writer的子类,用于向指定文件写入字符流。

 

       构造方法

FileWriter(File file)

         根据给定的 File 对象构造一个FileWriter 对象。

FileWriter(File file,boolean append)

         根据给定的 File 对象构造一个FileWriter 对象。

FileWriter(FileDescriptor fd)

         构造与某个文件描述符相关联的FileWriter 对象。

FileWriter(String fileName)

         根据给定的文件名构造一个FileWriter 对象。

FileWriter(String fileName,boolean append)

         根据给定的文件名以及指示是否附加写入数据的boolean 值来构造FileWriter 对象。

 

                    Filefile = new File("pw.txt");

                    FileWriterfw = new FileWriter(file);

                   

                    FileWriterfw = new FileWriter(new File("pw.txt"));

                   

                    FileWriterfw = new FileWriter("pw.txt");

             B:步骤

                    创建文件对象,指定写入的文件目录

                    调用write方法写入数据

                    关闭资源

 

                    FileWriterfw = new FileWriter("fw.txt");

                    fw.write("haha");

                    fw.flush();.一定要记得刷

                    fw.close();

特点

wrtie完后,一定要刷,flush 里面的fileName如果没有,会自已创建。

fw.write(ch,0,i);为了防止写出空格,因为reader(ch)是每次读取的是一个数组,返回是当时写入的字符数目int 所以在writer时,要给定长度。

这个可以写一次,刷一次,也可写多次刷一次,关健看每次写入的大小,如果大的话,就刷多几次

避免过份耗内存,最后一定要close(),关闭以释放资源

 

 

2,字符流的读取FileReader

FileReader是io包下抽象类Reader的一个子类, 用于从文件中读取字符

 

构造方法

FileReader(File file)  在给定从中读取数据的 File 的情况下创建一个新FileReader。

 

FileReader(FileDescriptor fd)  在给定从中读取数据的FileDescriptor 的情况下创建一个新FileReader。

 

FileReader(String fileName)  在给定从中读取数据的文件名的情况下创建一个新FileReader。

 

特点:

不管读还是写,都要关闭流!

读取的时候有两种方式:一种是一个字符一个字符读,这个时候返回的是ASCII,所以要强转;二是字符数组的方式读,也就是一次一个char数组。

那么我们定义数组长度就显得尤为重要了,不然容易乱码,所以一般定义为char[1024].也就是1KB

 

 

 

3,  字符写入缓冲流BufferedWrite

是FileWriter的子类,是可以高效写入字符文件的便捷类此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。

 

特点

有自带的缓冲区,写入速度快 会抛异常

 

4,       字符读取缓冲流BufferedReader

是FileReader的子类,叫字符缓冲流,对文件里的字符读出并缓存至自有缓冲区,还可以一行一行读取。用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。

特点

一次可读入一行,效率比一次读一个字符数组高,因为有自带的缓冲区.

其是用FileReader来构造,不是文件名称

为什么readLine()要加newLine?

因为readLine()是以分割符为基点

 

 

 

5, 字符流复制文本文件的5种方式

分析:

复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。

通过该原理,我们知道我们应该采用字符流更方便一些。

数据源:

c:\\a.txt -- FileReader -- BufferdReader

目的地:

d:\\b.txt -- FileWriter -- BufferedWriter

package cn.itcast_01;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

 

public class CopyFileDemo {

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

String srcString = "c:\\a.txt";

String destString = "d:\\b.txt";

method1(srcString,destString);

method2(srcString,destString);

method3(srcString,destString);

method4(srcString,destString);

method5(srcString,destString);

}

 

//方式1:字符缓冲流一次读写一个字符串

private static void method5(StringsrcString, String destString)

throws IOException {

BufferedReader br = new BufferedReader(newFileReader(srcString));

BufferedWriter bw = new BufferedWriter(newFileWriter(destString));

 

String line = null;

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

bw.write(line);

bw.newLine();

bw.flush();

}

 

bw.close();

br.close();

}

 

//方式2:字符缓冲流一次读写一个字符数组

private static void method4(StringsrcString, String destString)

throws IOException {

BufferedReader br = new BufferedReader(newFileReader(srcString));

BufferedWriter bw = new BufferedWriter(newFileWriter(destString));

 

char[] chs = new char[1024];

int len = 0;

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

bw.write(chs, 0, len);

}

 

bw.close();

br.close();

}

 

//方式3:字符缓冲流一次读写一个字符

private static void method3(StringsrcString, String destString)

throws IOException {

BufferedReader br = new BufferedReader(newFileReader(srcString));

BufferedWriter bw = new BufferedWriter(newFileWriter(destString));

 

int ch = 0;

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

bw.write(ch);

}

 

bw.close();

br.close();

}

 

//方式4:基本字符流一次读写一个字符数组

private static void method2(StringsrcString, String destString)

throws IOException {

FileReader fr = new FileReader(srcString);

FileWriter fw = new FileWriter(destString);

 

char[] chs = new char[1024];

int len = 0;

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

fw.write(chs, 0, len);

}

 

fw.close();

fr.close();

}

 

//方式5:基本字符流一次读写一个字符

private static void method1(StringsrcString, String destString)

throws IOException {

FileReader fr = new FileReader(srcString);

FileWriter fw = new FileWriter(destString);

 

int ch = 0;

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

fw.write(ch);

}

 

fw.close();

fr.close();

}

}

三、其他IO流

1,数据流

可以读写基本数据类型的数据

数据输入流:DataInputStream

DataInputStream(InputStream in)

数据输出流:DataOutputStream

 

 

2,内存操作流

用于处理临时存储信息的,程序结束,数据就从内存中消失。

字节数组:

ByteArrayInputStream

ByteArrayOutputStream

字符数组:

CharArrayReader

CharArrayWriter

字符串:

StringReader

StringWriter

 

3,打印流

字节流打印流   PrintStream

字符打印流       PrintWriter

 

打印流的特点:

A:只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。

B:可以操作任意类型的数据。

C:如果启动了自动刷新,能够自动刷新。

D:该流是可以直接操作文本文件的。

哪些流对象是可以直接操作文本文件的呢?

FileInputStream

FileOutputStream

FileReader

FileWriter

PrintStream

PrintWriter

 

 

 

4,标准输入输出流

System.in 标准输入流。是从键盘获取数据的

 

键盘录入数据:

A:main方法的args接收参数。

java HelloWorld hello world java

B:Scanner(JDK5以后的)

Scanner sc = new Scanner(System.in);

String s = sc.nextLine();

int x = sc.nextInt()

C:通过字符缓冲流包装标准输入流实现

BufferedReader br = new BufferedReader(newInputStreamReader(System.in));

 

 

标准输入输出流

System类中的两个成员变量:

public static final InputStream in “标准”输入流。

public static final PrintStream out “标准”输出流。

 

InputStream is = System.in;

PrintStream ps = System.out;

 

 

5,随机访问流:

RandomAccessFile类不属于流,是Object类的子类。

但它融合了InputStream和OutputStream的功能。

支持对文件的随机访问读取和写入。

 

public RandomAccessFile(String name,Stringmode):第一个参数是文件路径,第二个参数是操作文件的模式。

模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据

 

 

6,序列化流

把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据(ObjectOutputStream)

反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象(ObjectInputStream)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值