08 - JavaSE之IO流
IO流
JAVA流式输入输出原理:可以想象成一根管道怼到文件上,另一端是我们程序,然后流的输入输出都是按照程序本身作为第一人称说明的。比如 input,对于我们程序来说就是有数据输入我们程序,output就是我们程序输出数据到文件等。对象不能搞错了,否则就南辕北辙了。
- 通过不同的角度对流的输入输出功能进行分类:
- 按数据流的方向分为:输入流和输出流
- 按处理数据单位不同分为:字节流和字符流(2个字节)
- 按功能不同分为:节点流和处理流
输入流和输出流
JAVA JDK 所提供的所有流类型位于包 java.io 内部,分别继承自下面四个抽象流类型:
字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
节点流和处理流
- 节点流为可以从一个特定的数据源(节点)读写数据(如:文件,内存)。
节点流可以简单的理解为:一根管道直接怼到文件上,进行数据的读写。
- 处理流是连接在已存在的节点流或处理流上的,通过读数据进行处理(过滤等)为程序提供更加强大的读写功能。
处理流可以简单的理解为:套在节点流管道的管子,可以对流过节点流的数据进行处理,过滤等操作。
InputStream 抽象类
- 继承自 InputStream的流都是用于向程序中输入数据,且数据的单位为字节。
- 继承自 InputStream的类有如下等:(加粗为节点流,未加粗为处理流)
FileInputStream
PipedInputStream
FilterInputStream
ByteArrayInputStream
SequenceInputStream
StringBufferInputStream
ObjectInputStream
InputStream的基本方法
int read() throws IOException
int read(byte[] buffer) throws IOException
int read(byte[] buffer, int offset, int length) throws IOException
void close() throws IOException
OutputStream 抽象类
- 继承自 OutputStream的流都是用于从程序中输出数据,且数据的单位为字节。
- 继承自 OutputStream的类有如下等:(加粗为节点流,未加粗为处理流)
FileOutputStream
PipedOutputStream
FilterOutputStream
ByteArrayOutputStream
ObjectOutputStream
OutputStream 基本方法
void write(int b) throws IOException
void write(byte[] b) throws IOException
void write(byte[] b, int off, int len) throws IOException
void close() throws IOException
void flush() throws IOException // 在关闭输出流之前使用,将输出缓冲区的数据写到目的地
Reader
- 继承自 Reader 的流都是用于程序从外部读入数据,且数据的单位是字符(2个字节)。
- 如下为继承自Reader的流。(加粗为节点流,未加粗为处理流)
BufferedReader
CharArrayReader
InputStreamReader
FilterReader
PipedReader
StringReader
- Reader的基本方法 - 略
Writer
- 继承自 Writer的流都是用于程序向外部写入数据,且数据的单位是字符(2个字节)。
- 如下为继承自Writer的流。(加粗为节点流,未加粗为处理流)
BufferedWriter
CharArrayWriter
OutputStreamWriter
FilterWriter
PipedWriter
StringWriter
- Writer的基本方法 - 略
节点流类型
类型 字节流 字符流
File(文件) FileInputStream / FileOutputStream FileReader / FileWriter
Memory Array ByteArrayInputStream / ByteArrayOutputStream CharArrayReader / CharArrayWriter
Memory String -- StringReader / StringWriter
Pipe(管道) PipedInputStream / PipedOutputStream PipedReader / PipedWriter
举例1:FileInputStream
import java.io.*;
public class Test {
public static void main(String[] args) {
int b = 0;
long num = 0;
FileInputStream ln = null;
try {
ln = new FileInputStream("I:/Java/Demo/test.txt");
} catch (FileNotFoundException e) {
System.out.println("文件不存在!");
System.exit(-1);
}
try {
while ((b=ln.read()) != -1) {
System.out.print((char)b);
num++;
}
ln.close();
System.out.println();
System.out.println("共读出:" + num + "个字节。");
} catch (IOException e) {
System.out.println("文件读取失败!");
System.exit(-1);
}
}
}
举例2:FileOutputStream
import java.io.*;
public class Test {
public static void main(String[] args) {
int b = 0;
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("I:/Java/Demo/test.txt");
out = new FileOutputStream("I:/Java/Demo/newtest.txt");
while((b=in.read()) != -1) {
out.write(b);
}
} catch (FileNotFoundException e) {
System.out.println("文件不存在!");
System.exit(-1);
} catch (IOException e) {
System.out.println("文件复制失败!");
System.exit(-2);
}
System.out.println("文件复制成功!");
}
}
处理流类型
处理类型 字节流 字符流
Buffering BufferedInputStream/BufferedOutputStream BufferedReader/BufferedWriter
Filtering FilterInputStream/FilterOutputStream FilterReader/FilterWriter
Converting between bytes and character -- InputStreamReader/OutputStreamWriter
Object Serialization ObjectInputStream/ObjectOutputStream --
Data conversion DataInputStream/DataOutputStream --
Counting LineNumberInputStream LineNumberReader
Peeking ahead PushbackInputStream PushbackReader
Printing PrintStream PrintWriter
- 缓冲流(以Buffered开头)
缓冲流套接在相应的节点流上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。
BufferedReader / BufferedWriter / BufferedInputStream / BufferedOutputStream
缓冲流支持其父类的 mark 和 reset 方法。
BufferedReader 提供了 readLine 方法用于读取一行字符串(以\r或者\n分割)
BufferedWriter 提供了 newLine 用于写入一个行分隔符。
对于输出的缓冲流,写出的数据会先在内存中缓存,使用 flush 方法将会使内存中的数据立刻写出。
举例1:
import java.io.*;
public class Test {
public static void main(String[] args) {
int b = 0;
FileInputStream in = null;
BufferedInputStream bin = null;
try {
in = new FileInputStream("I:/Java/Demo/test.txt");
bin = new BufferedInputStream(in);
bin.mark(100);
for(int i=0; (i<=10)&&(b=bin.read()) != -1; i++) {
System.out.print((char)b);
}
bin.reset();
System.out.println();
for(int i=0; (i<=10)&&(b=bin.read()) != -1; i++) {
System.out.print((char)b);
}
} catch (FileNotFoundException e) {
System.out.println("文件不存在!");
System.exit(-1);
} catch (IOException e) {
e.printStackTrace();
}
}
}
举例2:
import java.io.*;
public class Test {
public static void main(String[] args) {
String s = null;
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("I:/Java/Demo/test.txt"));
BufferedReader br = new BufferedReader(new FileReader("I:/Java/Demo/test.txt"));
for(int i=0; i<100; i++) {
s = Double.toString(Math.random());
bw.write(s);
bw.newLine();
}
bw.flush();
while((s=br.readLine()) != null) {
System.out.println(s);
}
bw.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//0.7365309652822098
//0.577186775602007
//0.11736466966949166
//0.2998096440959087
//0.23859539950503672
//...
- 转换流
- InputStreamReader 和 OutputStreamWriter 用于字节数据到字符数据之间的转换。
- InputStreamReader 需要和 InputStream 套接。
- OutputStreamWriter 需要和 OutputStream 套接。
- 转换流在构造时可以指定其编码结合,例如: InputStream is = new InputStreamReader(System.in, "ISO8859_1")
举例1:
import java.io.*;
public class Test {
public static void main(String[] args) {
try {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("I:/Java/Demo/test.txt"));
osw.write("1234567890");
System.out.println(osw.getEncoding());
osw.flush();
osw.close();
osw = new OutputStreamWriter(new FileOutputStream("I:/Java/Demo/test.txt", true), "ISO8859_1");
osw.write("abcdefghijklmn");
System.out.println(osw.getEncoding());
osw.flush();
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
举例2:
import java.io.*;
public class Test {
public static void main(String[] args) {
try {
String s = null;
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
while((s = br.readLine()) != null) {
if(s.equalsIgnoreCase("exit")) {
break;
}
System.out.println(s);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 数据流
- DataInputStream 和 DataOutputStream 分别继承自 InputStream 和 OutputStream,它属于处理流,需要分别套接在 InputStream 和 OutputStream 类型的节点流上。
- DataInputStream 和 DataOutputStream 提供了可以存取与机器无关的 Java 原始类型数据(如:int,double 等)的方法。
- DataInputStream 和 DataOutputStream 的构造方法为:
DataInputStream (InputStream in)
DataOutputStream (OutputStream out)
数据流的作用?
比如,我们如何存储一个很大的数到文件?我们之前的方法是将其转换成字符串存储,可不可以直接存储呢?数据流可以。它提供了很多方法用于存储基础数据类型的数据,参看 API 文档。
举例1:
import java.io.*;
public class Test {
public static void main(String[] args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 在内存自动生成一个 Byte[] 数组
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeDouble(Math.random());
dos.writeBoolean(true);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
System.out.println(bais.available());
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
dos.close();
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
问题:我们写一个 double,写一个boolean写到哪里了呢?
其实,在我们 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 的时候,就在内存中开辟了一块空间,用来将程序要写入的数据写到这片内存中。
还有,在读数据的时候,由于这片内存的分配是按照队列的方式分配的,所以先写进去的数据要先读出来,如果如上面程序那样,先读boolean的话,就会读取到double 8个字节的第一个字节上,切记!
- Print 流(打印流)
PrintWriter 和 PrintStream 都属于输出流,分别针对与字符和字节。
PrintWriter 和 PrintStream 提供了重载的 print println 方法用于多种数据类型的输出。
PrintWriter 和 PrintStream 的输出操作不会抛出异常,用户通过检测错误状态获取错误信息。
PrintWriter 和 PrintStream 有自动 flush 功能。
PrintWriter(PrintWriter out)
PrintWriter(Writer out, boolean autoFlush)
PrintWriter(OutputStream out)
PrintWriter(OutputStream out, boolean autoFlush)
PrintStream(OutputStream out)
PrintStream(OutputStream out, boolean autoFlush)
举例1:
import java.io.*;
public class Test {
public static void main(String[] args) {
PrintStream ps = null;
try {
FileOutputStream fos = new FileOutputStream("I:\\Java\\Demo\\test.txt");
ps = new PrintStream(fos);
if(null != ps) {
System.setOut(ps);
}
for(int i=0; i<60000; i++) {
System.out.print((char)i + " ");
if(i%50 == 0) {
System.out.println();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
将输出打印语句重定向到 test.txt 文件中。
举例2:
import java.io.*;
public class Test {
public static void main(String[] args) {
String filename = args[0];
if (filename != null) {
list(filename, System.out);
}
}
public static void list(String f, PrintStream fs) {
try {
String s = null;
BufferedReader br = new BufferedReader(new FileReader(f));
while ((s = br.readLine()) != null) {
fs.println(s);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
将 args[0] 所写的文件名对应的文件打印到终端。
举例3:
import java.io.*;
import java.util.*;
public class Test {
public static void main(String[] args) {
String s = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
FileWriter fw = new FileWriter("I:/Java/Demo/log.txt", true);
PrintWriter log = new PrintWriter(fw);
while((s=br.readLine()) != null) {
if(s.equalsIgnoreCase("exit")) {
break;
}
System.out.println(s);
log.println("------");
log.println(s);
log.flush(); // 可以省略
}
log.println("--- " + new Date() + " ---");
log.flush(); // 可以省略
log.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
将从终端输入的内容作为 log 写到 log.txt 文件里面。
- Object 流
Object 流的作用:当我们存储一个元素的时候,(比如在画图软件上画了一个圆)我们的圆有很多属性,原点位置,半径大小,颜色,粗细等,既然每一个属性都需要存储,而且这些属性都在一个 Object 对象里面,那么我们为什么不直接写整个 Object呢?(这叫序列化。)
注意:当你 new 一个 Object 的时候,不单单只有你的属性,还有一些比如 Object的版本号,this,super 等。
举例:
import java.io.*;
public class Test {
public static void main(String[] args) {
TmpClass tm = new TmpClass();
tm.a =10;
tm.d = false;
try {
FileOutputStream fos = new FileOutputStream("I:/Java/Demo/text.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(tm);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("I:/Java/Demo/text.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
TmpClass t = (TmpClass) ois.readObject();
System.out.println(t.a + " " + t.b + " " + t.c + " " + t.d);
} catch (ClassNotFoundException c) {
System.out.println("读取文件失败");
} catch (IOException e) {
e.printStackTrace();
}
}
}
class TmpClass implements Serializable {
int a = 1;
int b = 2;
double c = 3.0;
boolean d = true;
}
- Serializable 接口
- 可以被序列化的,如果想把一个类的对象,写到硬盘或者网络,想把这个对象序列化成一个字节流的话,必须要实现这个接口。
- 这个接口没有任何方法,是一个空接口,是一个标记性接口,它只是给编译器看的,编译器看到后就知道这个类的对象时可以被序列化的,是可以整个写入文件的。
- tansient关键字
使用方法,修饰成员变量。
class TmpClass implements Serializable {
int a = 1;
int b = 2;
tansient double c = 3.0;
boolean d = true;
}
transient 表示透明的意思,就是说在一个类的对象序列化的时候不予考虑,就是将这个类的对象写入文件的时候,不写这个被transient 修饰的成员变量,那么我们再读出来的时候就是默认值(如上,c 读出来的时候是 0.0)
- externalizable 接口
- 可以理解为个性化的 Serializable 接口,externalizable 接口是继承 Serializable 接口得到的,相当于自己控制序列化的过程。(了解就好)
总结
- 本章复习方法:把所有的名字,关键字写到一张纸上,每天看看想想自己,给朕看半个时辰。—— 康熙
08 - JavaSE之IO流的更多相关文章
- 基于JavaSE阶段的IO流详解
1.IO流基本概述 在Java语言中定义了许多针对不同的传输方式,最基本的就是输入输出流(俗称IO流),IO流是属于java.io包下的内容,在JavaSE阶段主要学下图所示的: 其中从图中可知,所有 ...
- JavaSE | IO流
java.io.File类(文件和目录路径名的抽象表示形式) 如果希望在程序中操作文件和目录都可以通过File类来完成,File类能新建.删除.重命名文件和目录. File类是文件或目录的路径,而不是 ...
- JavaSE学习笔记(14)---File类和IO流(字节流和字符流)
JavaSE学习笔记(14)---File类和IO流(字节流和字符流) File类 概述 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 构造方 ...
- JavaSE(一) IO类层次关系和各种IO流的用法总结
今天把IO流的这一知点进行一下总结,因为在之前使用io流的时候,就只知道几个重点常用的IO类,比如FileInputStream,BufferedInputStream(缓冲流)等等,但是不知道它处于 ...
- JavaSE(十二)之IO流的字节流(一)
前面我们学习的了多线程,今天开始要学习IO流了,java中IO流的知识非常重要.但是其实并不难,因为他们都有固定的套路. 一.流的概念 流是个抽象的概念,是对输入输出设备的抽象,Java程序中 ...
- JavaSE学习总结(十七)—— IO流
一.IO流概要 1.1.概念 开发中经常要进行输入输出操作,掌握Java中的IO流显得非常必要. 流(stream)的概念源于UNIX中管道(pipe)的概念.在UNIX中,管道是一条不间断的字节流, ...
- [javaSE] IO流(管道流)
之前我们使用io流,都是需要一个中间数组,管道流可以直接输入流对接输出流,一般和多线程配合使用,当读取流中没数据时会阻塞当前的线程,对其他线程没有影响 定义一个类Read实现Runable接口,实现r ...
- JavaSE复习(四)File类与IO流
File类 构造方法 public File(String pathname) :通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例. public File(String parent ...
- JavaSE 学习笔记之IO流(二十二)
IO流:用于处理设备上数据. 流:可以理解数据的流动,就是一个数据流.IO流最终要以对象来体现,对象都存在IO包中. 流也进行分类: 1:输入流(读)和输出流(写). 2:因为处理的数据不同,分为字节 ...
随机推荐
- Nodejs入门【转载】保留备用
关于 本书致力于教会你如何用Node.js来开发应用,过程中会传授你所有所需的“高级”JavaScript知识.本书绝不是一本“Hello World”的教程. 状态 你正在阅读的已经是本书的最终版. ...
- 为在python中使用dotnet程序安装clr
直接在命令行中录入 pip install pythonnet 会有一个ssl错误提示 ...Could not fetch URL https://pypi.python.org/simple/py ...
- 20171123IdleHandler
在Android中,我们可以处理Message,这个Message我们可以立即执行也可以delay 一定时间执行.Handler线程在执行完所有的Message消息,它会wait,进行阻塞,知道有心的 ...
- gcc和vs在c的一些区别
1.switch中每个标签后面的命令在gcc中需要{}括起来以指明作用域. 2._itoa是非标准的c和c++扩展函数,在linux下可以使用sprintf(string, "%d &q ...
- Java的String类
String类 String是引用数据类型:字符串是String类的对象 String类的构造方法 共有13种重载方式,这里只示例常用的几个 String():创建一个空字符串 String(Stri ...
- Codeforces822 C. Hacker, pack your bags!
C. Hacker, pack your bags! time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- OC语言-block and delegate
参考博客 OC语言BLOCK和协议 iOS Block iOS Block循环引用精讲 iOS之轻松上手block 深入浅出Block的方方面面 Block apple官方参考 1.定义一个block ...
- JMS 消息队列
1.jms broker服务器:Broker:消息队列核心,相当于一个控制中心,负责路由消息.保存订阅和连接.消息确认和控制事务
- poj 2676 如何填满九宫格
Sudoku Time Limit: 2000 MS Memory Limit: 65536 KB 64-bit integer IO format: %I64d , %I64u Java class ...
- poj 2262 Goldbach's Conjecture
素数判定...很简单= =.....只是因为训练题有,所以顺便更~ #include<cstdio> #include<memory.h> #define maxn 50000 ...