IO流

本博主要理论,具体实现比较少。

IO

IO是什么:

IO流用来处理设备之间的数据传输。

Java程序中,对于数据的输入/输出操作以“流(Stream)”的方式进行。

流的分类:

按操作数据单位不同分为:字节流(8bit),字符流(16bit

按数据流的流向不同分为:输入流,输出流。

按流的角色不同分类:节点流,处理流。

 

JavaIO流共涉及40多个类,都是由规则的,都是从上面图片中四个基类派生而来。

这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

IO应用场景:

输入input:读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存中)。

输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

 

 

Java.io.File类的使用:

文件流:FileInputStream/FileOutputStream/FileWriter

缓冲流:BufferedInputStream/BufferedOutputStream/BufferedReader/BufferedWriter

具体对应如下图(非常重要,本人用IO流基本看此图):

 

File类的方法:

 

File基本操作:

File dir1 = new File("D:/IOTest/dir1");

if (!dir1.exists()) {     // 如果D:/IOTest/dir1不存在,就创建为目录

dir1.mkdir(); }

// 创建以dir1为父目录,名为"dir2"File对象

File dir2 = new File(dir1, "dir2");

if (!dir2.exists()) { // 如果还不存在,就创建为目录

dir2.mkdirs(); }

File dir4 = new File(dir1, "dir3/dir4");

if (!dir4.exists()) {

dir4.mkdirs();

}

// 创建以dir2为父目录,名为"test.txt"File对象

File file = new File(dir2, "test.txt");

if (!file.exists()) { // 如果还不存在,就创建为文件

file.createNewFile();

}

文件流:

读取文件:

1、建立一个流对象,将已存在的一个文件加载进流

FileReader fr=new FileReader(“Test.txt”);

2、创建一个临时存放数据的数组

Char[] ch=new char[1024];

3、调用流对象的读取方法将流中的数据读入到数组中

fr.read(ch);

FileReader fr = null;

try{

fr = new FileReader("c:\\test.txt");

char[] buf = new char[1024];

int len= 0;

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

System.out.println(new String(buf ,0,len));}

}catch (IOException e){

System.out.println("read-Exception :"+e.toString());}

finally{

if(fr!=null){

try{

fr.close();

}catch (IOException e){

System.out.println("close-Exception :"+e.toString());

} } }

 

写入文件:

1、创建流对象,建立数据存放文件

FileWriter fw=new FileWriter(“Test.txt”);

2、调用流对象的写入方法,将数据写入流

Fw.write(“test”);

3、关闭流资源,并将流中的数据清空到文件中。

Fw.close();

FileWriter fw = null;

try{

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

fw.write("text");

}

catch (IOException e){

System.out.println(e.toString());

}

finally{

If(fw!=null)

try{

 fw.close();

}

catch (IOException e){

System.out.println(e.toString());} }

 

注意:

1、定义文件路径时,注意:可以使用/”或“\\

2、在写入一个文件时,如果目录下有同名文件将被覆盖

3、在读取文件时,必须保证该文件已存在,否则异常

缓冲流:

1、为了提高数据读写速度,java提供了缓冲功能的流,使用缓冲流时,会创建一个内部缓冲区数组。

2、根据数据操作把缓冲流分为分为:

BufferedInputStreamBufferedOutputStream

BufferedReaderBufferedWriter

3、缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了新的方法。

4、对于输出的缓冲流,写出的数据会现在内存中缓存,使用flush()将会使内存中的数据立刻写出。

BufferedReader br = null;

BufferedWriter bw = null;

try {

//step1:创建缓冲流对象:它是过滤流,是对节点流的包装

br = new  BufferedReader(new FileReader("d:\\IOTest\\source.txt"));

bw = new BufferedWriter(new FileWriter("d:\\IOTest\\destBF.txt"));

String str = null;

while ((str = br.readLine()) != null) { //一次读取字符文本文件的一行字符

bw.write(str); //一次写入一行字符串

bw.newLine();  //写入行分隔符

} bw.flush();  //step2:刷新缓冲区

} catch (IOException e) {

e.printStackTrace();

}

finally {

// step3: 关闭IO流对象

try {

if (bw != null) {

bw.close();  //关闭过滤流时,会自动关闭它所包装的底层节点流

}

} catch (IOException e) {

e.printStackTrace();

}

try {

if (br != null) {

br.close();

}  } catch (IOException e) {

e.printStackTrace();

}

}

转换流:

1、转换流提供了在字节流和字符流之间的转换

2、JavaAPI提供了两个转换流:

2.1InputStreamReader

用于将字节流中读取到的字节按照指定字符集解码成字符,需要和InputStream“套接”

public InputStreamReader(InputStream in)

public InputSreamReader(InputStream in,String charsetName)

2.2OutputStreamWriter

用于将要写入到字节流中的字符按指定字符集编码成字节。需要和OutputStream“套接”构造方法

public OutputStreamWriter(OutputStream out)

public OutputSreamWriter(OutputStream out,String charsetName)

3、字节流中的数据都是字符时,转换成字符流操作更高效

 

public void testMyInput() throws Exception{

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

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

 

    InputStreamReader isr = new InputStreamReader(fis,"GBK");

    OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");

 

    BufferedReader br = new BufferedReader(isr);

    BufferedWriter bw = new BufferedWriter(osw);

 

    String str = null;

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

        bw.write(str);

        bw.newLine();

        bw.flush();

}    bw.close();  br.close();}

标准输入输出流:

1System.inSystem.out分别代表了系统标准的输入和输出设备

2、默认输入设备是键盘,输出设备是显示器

3System.in的类型是InputStream

4System.out的类型是PrintStream,其是OutputStream的子类FilterOutputStream 的子类

5、通过System类的setInsetOut方法对默认设备进行改变。

public static void setIn(InputStream in)

public static void setOut(PrintStream out)

打印流:

在整个IO包中,打印流是输出信息最方便的类。

1、PrintStream(字节打印流)PrintWriter(字符打印流)

提供了一系列重载的printprintln方法,用于多种数据类型的输出

PrintStreamPrintWriter的输出不会抛出异常

PrintStreamPrintWriter有自动flush功能

System.out返回的是PrintStream的实例

FileOutputStream fos = null;

try {

fos = new FileOutputStream(new File("D:\\IO\\text.txt"));

} catch (FileNotFoundException e) {

e.printStackTrace();

}//创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)

PrintStream ps = new PrintStream(fos,true);

if (ps != null) { // 把标准输出流(控制台输出)改成文件

System.setOut(ps);}

for (int i = 0; i <= 255; i++) {  //输出ASCII字符

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

if (i % 50 == 0) {   //50个数据一行

System.out.println(); // 换行

}  }

ps.close();

数据流:

1、为了方便地操作Java语言的基本数据类型的数据,可以使用数据流。

2、数据流有两个类:(用于读取和写出基本数据类型的数据)

DataInputStream DataOutputStream

分别“套接”在 InputStream OutputStream 节点流上

3、DataInputStream中的方法

boolean readBoolean() byte readByte()

     char readChar() float readFloat()

     double readDouble() short readShort()

     long readLong() int readInt()

     String readUTF()                                 void readFully(byte[] b)

 

例子:

DataOutputStream dos = null;

try { //创建连接到指定文件的数据输出流对象

dos = new DataOutputStream(new FileOutputStream(

"d:\\IOTest\\destData.dat"));

dos.writeUTF("ab中国");  //UTF字符串

dos.writeBoolean(false);  //写入布尔值

dos.writeLong(1234567890L);  //写入长整数

System.out.println("写文件成功!");

} catch (IOException e) {

e.printStackTrace();

} finally { //关闭流对象

try {

if (dos != null) {

// 关闭过滤流时,会自动关闭它包装的底层节点流

dos.close();

}

} catch (IOException e) {

e.printStackTrace();

} }

对象流:

1ObjectInputStreamOjbectOutputSteam

用于存储和读取对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

2、序列化(Serialize):用ObjectOutputStream类将一个Java对象写入IO流中

3、反序列化(Deserialize):用ObjectInputStream类从IO流中恢复该Java对象

4ObjectOutputStreamObjectInputStream不能序列化statictransient修饰的成员变量

对象的序列化:

1、对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象

2、序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原

3、序列化是 RMIRemote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础

如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:

Serializable

Externalizable

4、凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:

private static final long serialVersionUID;

serialVersionUID用来表明类的不同版本间的兼容性

如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的源代码作了修改,serialVersionUID 可能发生变化。故建议,显示声明

5、显示定义serialVersionUID的用途

希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID

不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID

 

posted @ 2019-01-05 22:04  空杯+空船  阅读(169)  评论(0编辑  收藏  举报