欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

day_25I/O输入输出

程序员文章站 2022-06-10 22:54:20
...

 

目的:

 

在变量、数组和对象中存储数据是暂时的,程序结束后它们就会丢失。

 

为了能够永久地保存程序创建的数据,需要将其保存在磁盘文件中,这样以后就可以在其他程序中使用它们。

Java的I/O技术可以将数据保存到文本文件、二进制文件甚至是ZIP压缩文件中,以达到永久性保存数据的要求。

掌握I/O处理技术能够提高对数据的处理能力。

 

了解Java中的流概念

了解Java中输入/输出流的分类

掌握文件输入/输出的使用方法

掌握ZIP压缩输入/输出流的应用

 

12.1流概述

 

  流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。

 

I/O提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。

 

虽然I/O流经常与磁盘文件存取有关,但是程序的源和目的也可以是键盘、鼠标、内存或显示器窗口等。

 

12.2 输入/输出流

 

java.io包

输入流类:

       抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;

输出流类:

       抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。

 

12.2.1输入流

java.lang.Object

java.io.InputStream

 

 

Java中的字符是Unicode编码,是双字节的。

InputStream是用来处理字节的,在处理字符文本时不是很方便。

Java为字符文本的输入提供了专门一套单独的类Reader,但是Reader类

并不是InputStream类的替换者,只是在处理字符串时简化了编程。

 

 

Reader类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。

 

 

12.2.2输出流

OutputStream类是字节输入流的抽象类,此抽象类表示输出字节流的所有类的超类。

OutputStream类中的所有方法均返回void,在遇到错误时会引发IOException异常。

 

Writer 类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。

 

 

12.2.3 案例

显示指定类型的文件

 

 

 

12.3 File类

 

File类是io包中唯一代表磁盘文件本身的对象。

可以通过调用File类中的方法,实现创建、删除、重命名文件等。

 

File类的对象主要用来获取文件本身的一些信息,如文件所在的目录、文件的长度、文件读写权限等。

 

数据流可以将数据写入到文件中,而文件也是数据流最常用的数据媒体。

 

12.3.1文件的创建于删除

 

构造方法

1.File(String pathname) 

          通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

 

语法格式:

new File(String pathname)

 

pathname: 是指路径名称(包含文件名)

 

File file = new File("d:/1.txt");

 

2.File(String parent, String child) 

          根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。

 

该构造方法根据定义的父路径和子路径字符串(包含文件名)创建一个新的File对象。

new File(String parent,String child)  

parent:父路径字符串 

child:   子路径字符串

 

 

3.File(File parent, String child) 

          根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。

 

该构造方法根据parent抽象路径名和child路径名字符串创建一个新File实例。

 

new File(File f,String child)

f:父路径对象

child:子路径字符串

 

注意:

       对于windows平台,包含盘符的路径名前缀由驱动器号和一个“:”组成。

如果是绝对路径名,还可能后跟"\\"。

 

12.3.1.1代码案例

package day25;

 

import java.io.File;

import java.io.IOException;

 

public class FileTest {

public static void main(String[] args) {

 

/*File(File?parent, String?child) 

*根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例

*在项目中创建FileTest类,在主方法中判断文件夹是否存在..txt文件,

*如果文件存在将其删除,不存在则创建该文件 */

File file = new File("E:/zhuhw_study","test.txt");

if(file.exists()) {

file.delete();

System.out.print("文件已被删除");

}else{

try {

file.createNewFile();

System.out.print("文件已被创建");

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

}

}

}

 

运行结果:

文件已被创建

 

12.3.2获取文件信息

 

 

代码案例:

package day25;

 

import java.io.File;

import java.io.IOException;

 

public class FileTest {

public static void main(String[] args) {

 

/*获取文件夹下的..txt文件的文件名、文件长度、并判断该文件是否是隐藏文件。*/

   File f2 = new File("E:/zhuhw_study","test2.txt");

   System.out.println("文件的文件名:  "+f2.getName());

   System.out.println("文件的长度: "+f2.length());

   System.out.println("文件是否是隐藏文件: "+f2.isHidden());

}

}

运行结果:

文件的文件名:  test2.txt

文件的长度: 0

文件是否是隐藏文件: false

 

12.4文件输出/输出流

 

12.4.1基本概念

如果将数据永久保存,可使用文件输入/输出流与指定的文件建立连接,将需要的数据永久保存到文件中。

java.lang.Object

 java.io.InputStream

    java.io.FileInputStream

 

java.lang.Object

   java.io.OutputStream

     java.io.FileOutputStream

 

都是用来操作磁盘文件的。

 

12.4.1代码案例

 

使用FileOutputStream类向文件work写入信息,然后通过FileInputStream类将work文件中的数据读取到控制台上。

 

 package day25;

 

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

 

public class FileTest {

public static void main(String[] args){

/*使用FileOutputStream类向文件word写入信息,

然后通过FileInputStream类将文件中的数据读取到控制台上。*/

File file = new File("G:/asiainfo","test_zhuhw");

try {

FileOutputStream fio = new FileOutputStream(file);

byte b[] = "你好呀,我是瓦询...".getBytes();

fio.write(b);

fio.close();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

try {

FileInputStream fii = new FileInputStream(file);

byte byt[] = new byte[1024];

/*

* 从此输入流中将 byte.length 个字节的数据读入一个 byte 数组中。

* public int read(byte[] b)

* b - 存储读取数据的缓冲区。

* 返回:读入缓冲区的字节总数,如果因为已经到达流末尾

* 而没有更多的数据,则返回 -1 */

int len = fii.read(byt);

/*public String(byte[] bytes,

             int offset,

             int length)

通过使用平台的默认字符集解码指定的 byte 子数组,

构造一个新的 String。新 String 的长度是字符集的函数,

因此可能不等于该子数组的长度。

参数:

bytes - 要解码为字符的 byte

offset - 要解码的第一个 byte 的索引

length - 要解码的 byte 数 

           */

String s = new String(byt,0,len);

System.out.print("文件中的信息是: "+s);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

 

}

}

运行结果:

文件中的信息是: 你好呀,我是瓦询...

 

 

一个被打开的流有可能会用尽系统资源,这取决于平台的和实现。

如果没有将打开的流关闭,当另一个程序试图打开另一个流时,这些资源可能会得不到。

 

 

 

12.4.2 FileReader 和 FileWriter

 

另一个资料看到的,好理解

掌握流的基本概念

掌握Java中各种常用输出输入流的基本用法

能够熟练地编写应用程序解决文件的读写问题

 

8.1流的基本概念

“流”可以被理解为管道。

管道:两个端口,一端与数据源(当输入数据时)或数据宿(当输出数据时)相连,另一端与程序相连。

在两端口,“管道”在读写数据时能够应付数据源和数据宿的多样性,消化掉因数据源/宿的多样性带来的数据读/写的复杂性;

而在与程序相连的端口,“管道”提供了输入输出的统一操作接口。

 

对管道的统一而简单的操作,这样就大大降低了输入输出的复杂性。

 

有了流,程序和外界的数据交换都可通过流实现。

 

分类:

       根据流中的数据传输的方向,将流分为输入流和输出流。

      根据“管道”里流动的数据类型,将分为字符流(Character Streams)和字节流(Byte Streams)

 

提示:

       在java的底层操作中,所有的输入输出都是以字节形式进行的。

 

8.2 字节流

java中的字节流是以字节(byte)为基本处理单位,用于对二进制数据进行读写操作。

对应输入字节流会和输出字节流的两个顶层的抽象类,分别是InputStream和OutputStream。

 

 

8.3字符流

java的字符流是以16位的Unicode码表示的字符为基本处理单位。

对应输入字符流和输出字符流的两个顶层的抽象类,分别是Reader和Writer。

 

 

8.4 File类

文件是许多程序的基本数据源和数据宿,是保存永久数据和共享信息的媒体。

在Java中,目录页被当作文件,可以用list方法列出目录中的文件名。

 

 

8.5 System.in 和System.out对象

 

可以在程序中直接使用而不用重新定义自己的流对象,因为它们都是静态成员。

 

8.6 FileInputStream类和FileOutputStream类

 

通常所使用的文件中,有很多文件是二进制文件,它们以字节作为数据处理的单位。

 

8.7FileReader类和FileWriter类

因为大多数程序涉及文件读写,,所以FileReader类是一个经常用到的类,可以在一个指定文件上实例化一个文件输入流,

利用流提供的方法从文件中读取一个字符或者一组数组。

最重要的方法是read。

 

由FileWriter类可以实例化一个文件输出流,并提供向文件中写入一个字符或者一组数据的方法。

 

8.8过滤流

 

连接:

https://www.ibm.com/developerworks/cn/java/j-lo-javaio/

 

 

 

 

星期日, 十一月 29, 2015 15:46:12

 

 

5、带缓存的输入输出流

 

5.1 缓存可以说S是I/O的一种性能优化。

缓存流为I/O流增加了内存缓存区。

 

5.1 BufferedInputStream与BufferedOutputStream类

 

BufferedInputStream类可以对任何的InputStream类进行带缓存区的包装以达到性能优化。

 

文件--->InputStream-->BufferedInputStream--->程序(目的地)

 

注意:

        BufferedOutputStream有一个flush()方法用来将缓存区的数据强制输出完--->刷新。

flush()方法只对使用缓存区的OutputStream类的子类有效。

当调用close()方法时,系统在关闭流之前,也会将缓存区中信息刷新到磁盘文件中。

 

5.2 BufferedReader与BufferedWriter类

 

BufferedReader与BufferedWriter类 分别继承Reader类与Writer类。

这两个类同样具有内部缓存机制,并可以以行为单位进行输出。

 

字符数据(程序)-->BufferedWriter-->OuterputStreamWriter-->OutputStream-->文件

 

注意:

        在使用BufferedWriter类的writer()方法时,数据并没有立刻被写入至输出流中,而是首先进入缓存区中。

如果想立刻将缓存区中的数据写入输出流中,一定要调用flush()方法。

 

5.3案例

 

向指定的磁盘中写入数据,并通过BufferedReader类将文件中的信息分行显示。

 

package day29;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

 

public class BufferTest {

public static void main(String[] args) {

/*向指定的磁盘中写入数据,

并通过BufferedReader类将文件中的信息分行显示。*/

 

String content[] = {"好久不见","最近好吗","瓦询..."};//定义字符串数组

File file = new File("G:/word.txt");//创建文件对象

try {

FileWriter fw = new FileWriter(file); //创建FileWriter对象

BufferedWriter bufw = new BufferedWriter(fw);//创建BufferedWriter类对象

for(int k = 0;k < content.length; k++) {     

bufw.write(content[k]);     //将字符串数组中数组中元素写入到磁盘文件中

bufw.newLine(); //将数组中的单个元素以单行的形式写入文件

}

bufw.close();        //将BufferedWriter流关闭

fw.close();          //将FileWriter流关闭

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

try {

FileReader fr = new FileReader(file);//创建FileReader类对象

BufferedReader bufr = new BufferedReader(fr);//创建BufferedReader类对象

String s = null;                      //创建字符串对象

int i = 0;

while((s = bufr.readLine() )!= null){//如果文件的文本行数不为null,则进入循环

i++;

System.out.println("第"+i+"行  : "+s); //输出文件数据

}

bufr.close();                 //将BufferedReader流关闭

fr.close();                   //将FileReader流关闭

 

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

}

}

 

运行结果:

第1行  : 好久不见

第2行  : 最近好吗

第3行  : 瓦询...

 

6、数据输入输出流

 

   6.1 数据输入输出流(DataInputStream类与DataOutputStream类)允许应用程序以与机器无关的方式

从底层输入流中读取基本Java数据类型。= 当读取一个数据时,不必再关心这个数值应当是什么字节。

 

   6.2 代码案例

 分别通过DataOutputStream类的writeUTF()、writeChars()、writeBytes()方法向指定的磁盘文件中输入数据,

并通过DataInputStream类的readUTF()方法将写入的数据输出到控制台上。

 

package day29;

 

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.OutputStream;

 

public class DataStreamTest {

public static void main(String[] args) {

/*分别通过DataOutputStream类的

* writeUTF()、writeChars()、writeBytes()方法向指定的磁盘文件中输入数据,

* 并通过DataInputStream类的readUTF()方法将写入的数据输出到控制台上。*/

 

try {

/*FileOutputStream(File file) 

* 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。*/

FileOutputStream fs = new FileOutputStream("G:/word.txt");

/*DataOutputStream(OutputStream out) 

*创建一个新的数据输出流,将数据写入指定基础输出流。*/

DataOutputStream ds = new DataOutputStream(fs);

ds.writeUTF("使用writeUTF()方法写入数据");  //写入磁盘数据

ds.writeChars("使用writeChars()方法写入数据");

ds.writeBytes("使用writeBytes()方法写入数据");

ds.close();

 

/*DataInputStream(InputStream in) 

* 使用指定的底层 InputStream 创建一个 DataInputStream。*/

FileInputStream fis = new FileInputStream("G:/word.txt");

DataInputStream dis = new DataInputStream(fis);

System.out.print(dis.readUTF());  //将文件数据输出

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

}

}

 

运行结果:

使用writeUTF()方法写入数据

 

 

 

 

 

7、ZIP压缩输入输出流

 

可以节省存储空间。java.util.zip包中的ZipOutputStream类与ZipInputSream类来实现文件的压缩/解缩。

 

如果要将文件内容写到zip文件内,必须先写入对应于该文件的“目录进入点”,

并且把要写入文件内容的位置移到此进入点所指的位置,然后再写入文件内容。

 

如果要从zip压缩管理文件内读取某个文件,要先找到对应文件的"目录进入点"(从他可知该文件在zip文件内的位置),

才能读取这个文件内容。

 

7.1压缩文件

利用ZipOutputStream类对象,可将文件压缩为“.zip”文件。

构造函数:

      ZipOutputStream(OutputStream out);

 

7.2代码案例

 

本例在zip()方法中实现使用ZipOutputStream类对文件进行压缩,在主方法中调用该方法。

 

package day29;

 

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.util.zip.ZipEntry;

import java.util.zip.ZipOutputStream;

 

public class ZipTest {

/*本例在zip()方法中实现使用ZipOutputStream类对文件进行压缩,在主方法中调用该方法。*/

public static void main(String[] args) {

ZipTest book = new ZipTest();  //创建本例对象

try {

book.zip("G:/hello.zip", new File("G:/hello")); //调用方法,参数为压缩后文件与要压缩文件

System.out.println("压缩完成");//输出信息

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

private void zip(String zipFileName,File inputFile) throws Exception{

FileOutputStream fos = new FileOutputStream(zipFileName);

ZipOutputStream out  = new ZipOutputStream(fos);//创建ZipOutputStream类对象

zip(out,inputFile,"");//调用方法

System.out.println("压缩中...");

out.close();//将流关闭

}

 

private void zip(ZipOutputStream out,File f,String base) throws Exception{//方法重载

if(f.isDirectory()) { //测试此抽象路径名表示的文件是否是一个目录

File[] f1 = f.listFiles(); //获取路径数组

out.putNextEntry(new ZipEntry(base+"/"));//写入此目录的entry

base = base.length() == 0?"":base+"/";//判断参数是否为空

for(int i =0;i<f1.length;i++){//循环遍历数组中文件

zip(out,f1[i],base+f1[i]);

}

}else{

out.putNextEntry(new ZipEntry(base));//创建新的进入点

FileInputStream in = new FileInputStream(f);//创建FileInput对象

int b;

System.out.println(base);

while((b = in.read())!=-1) {//如果没到达流的尾部

out.write(b);  //将字节写入当前zip条目

}

in.close(); //关闭流

}

}

}

 

运行结果:

G:\hello\hello1.txt

G:\hello\hello2.txt

压缩中...

压缩完成

 

7.3 解压缩zip文件

ZipInputStream类可读取zip压缩格式的文件,包括对已压缩和未压缩条目的支持(entry).

 

7.4代码案例

创建类,通过ZipInputStream类将上例生成的压缩文件解压到指定文件夹中。

 

package day29;

 

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.util.zip.ZipEntry;

import java.util.zip.ZipInputStream;

 

public class Decompressing {

public static void main(String[] args){

ZipInputStream zin;//创建ZipInputStream对象

try {

zin = new ZipInputStream(new FileInputStream("G:/hello.zip"));

                             //实例化对象,指明要进行解压的文件

ZipEntry entry = zin.getNextEntry();//获取下一个ZipEntry

while(((entry = zin.getNextEntry())!=null)&&!entry.isDirectory()) {

             //如果entry不为空,并不在同一目录下

File file = new File(entry.getName());//获取文件目录

if(!file.exists()) { //如果该文件不存在

file.createNewFile();//创建该文件

 

}

zin.closeEntry();//关闭当前entry

System.out.println(entry.getName()+"解压成功");

}

zin.close();  //关闭流

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

 

}

}

 

运行结果:

G:\hello\hello1.txt解压成功

G:\hello\hello2.txt解压成功

 

本例是通过此ZipEntry的getName()方法,得知此文件名称(含path),借此来决定压缩之后的目录和文件名。

使用ZipInputStream类来解压文件,必须先使用getNextEntry()来获取其内的第一个ZipEntry。

 

星期日, 十一月 29, 2015 18:45:35

相关标签: java I/O