您的位置:首页 > 编程语言 > Java开发

Java笔记(五) 输入输出

2016-06-10 14:21 471 查看
1.输入输出流

(1)I/O流的概念

Java中没有标准的输入输出语句,在Java中将信息的输入与输出过程抽象为输入输出流,Java所有的输入和输出操作都要通过I/O包中的一些流类方法来实现。

读写数据的方法大体上是一样的:(读:1打开一个流、2.读信息、3.关闭流)(写:1.打开一个流、2.写信息、3.关闭流)

(2)预定义的I/O流类概述

常见包:java.io

输入输出流分类:(1.输入流或输出流<-从流的方向划分2.节点流或处理流<-从流的分工3.面向字符流或面向字节流<-从流的内容)

按面向字符流和面向字节流分类:Object:(面向字节的流:InputStream、OutputStream;面向字符的流:Reader、Writer)

a.面向字符的流–Reader和Writer类

针对字符数据的特点进行优化过的,字符流的源或目标通常是文本文件。

Java中的字符使用的都是16-bit的Unicode编码(将全世界所有的符号进行统一编码)。

Reader和Writer是java.io包中所有字符流的抽象基类。

Reader和Writer的子类又可分为两大类:一类用来从数据源读入数据或往目的地写入数据(称为节点流)有阴影的;另一类对数据执行某种处理(称为处理流)无阴影的。

Reader | ->BufferedReader->LineNumberReader

| ->CharArrayReader

| ->InputStreamReader->FileReader

| ->FilterReader->PushbackReader

| ->PipedReader

| ->StringReader

Writer   | ->BufferedWriter
| ->CharArrayWriter
| ->OutputStreamReader->FileWriter
| ->FilterWriter
| ->PipedWriter
| ->StringWriter
| ->FilterWriter


绝大多数程序使用Reader和Writer这两个抽象类的一系列子类来读入和写出文本信息,例如:FileReader/FileWriter就是用来读/写文本文件的。

b.字节流–InputStream和OutputStream类

InputStream和OutputStream是用来处理8位字节流的抽象基类,程序使用这两个类的子类来读写8位的字节信息,这种流通常被用来读写诸如图片,声音之类的二进制数据,事实上,绝大多数数据是被存储为二进制文件的。

这些子类中有两个特殊的类ObjectInputStream和ObjectOutputStream,他们可用来读/写对象。还有两个特殊的类PipedInputStream和PipedOutputStream主要用来完成线程之间的通信。

类似于处理字符流的类,InputStream和OutputStream的子类也分为两部分,节点流(有阴影)和处理流(无阴影)。

InputStream | ->FileInputStream

| ->PipedInputStream

| ->FilterInputStream->(LineNumberInputStream、DataInputStream、BufferedInputStream、PushbackInputStream)

| ->ByteArrayInputStream

| ->SequenceInputStream

| ->StringBufferInputStream

| ->ObjectInputStream

OutputStream        |  ->FileOutputStream
|  ->PipedOutputStream
|  ->FilterOutputStream->(DataOutputStream、BufferedOutputStream、PrintStream)
|  ->ByteArrayOutputStream
|  ->ObjectOutputStream


c.标准输入输出

Java中标准输入输出流:(标准输入:System.in;标准输出:System.out;标准错误输出:System.err)

System.in是InputStream类型的,代表标准输入流,这个流是已经打开了的,默认状态对应于键盘输入。

System.out和System.error是PrintStream类型的,代表标准输出流和标准错误信息输出流,默认状态对应于屏幕输出。

标准的输入输出设备也可以通过这个类的重导向函数进行从新指定:

(setIn(InputStream)//指定新的标准输入流;setOut(PrintStream)//指定新的标准输出流;setErr(PrintStream)//指定新的标准错误输出流)

System.in是原始的InputStream,要经过包装才能从键盘读取信息。

BufferedReader in=new BufferedReader(new (System.in)); String s=in.readLine();

InputStreamReader和BufferedReader都属于“处理流”。

d.处理流

处理流不直接与数据源或目标相连,而是与另外的流配合,对数据进行某种处理,例如:BufferedReader对另一个流产生的数据进行缓冲。

e.I/O异常

多数I/O方法在遇到错误时会抛出异常,因此调用这些方法,必须在函数头声明抛出IOException异常,或者在try块中执行I/O,然后捕获IOException异常。

I/O流类有一个共同点,一旦被创建,就会自动打开,通过调用其close方法。可以显示关闭任何一个流。如果这个流对象不再被引用,Java的垃圾回收机制也会隐式的关闭它。

2.文件读写

(1)写文本文件

FileWriter类

Writer->OutputStreamWriter->FileWriter

new FileWriter(String s); //每次创建将产生一个新的s文件

new FileWriter(String s,boolean append); //如果append是true,可以实现在已有文件内容之后续写而不是完全替代

一个Writer类可以实现内部格式到外部磁盘文件格式的转换,当一个涉及文件操作的程序结束时,都应该执行close()方法。

当写入的文本很少时,使用FileWriter类就可以了,如果需要写入的内容很多,就应当使用java.io包里的缓冲器流类BufferedWriter,这两个类都用于输出字符流,包含的方法几乎完全一样,但BufferedWriter多提供了一个newLine()方法用于换行,用”\n”换行兼容性不如newLine();

(2)读文本文件

FileReader类

Reader->InputStreamReader->FileReader

缓冲器类:BufferedReader,具有readLine()函数,可以一行一行的读取输入流中的内容。

FileReader流对象被创建后,文件就被打开了,如果不存在,则会抛出一个IOException。

检测是否到文件结尾:(1.用readLine()方法,如果不再有数据,则返回null;2.利用Reader类的read()方法返回一个int型整数,如果读到文件末尾,则返回-1)

(3)写二进制文件

OutputStream及其子类

OutputStream->FilterOutputStream->BufferedOutputStream

(4)读二进制文件

FileInputStream、DataInputStream、BufferedInputStream等

InputStream->FileInputStream

InputStream->FilterInputStream->(DataInputStream、BufferedInputStream)

EOFException是IOException的子类,只有文件结束的异常才会被捕捉到。

DataInputStream函数使用参见API文档

System.out属于PrintStream类,其write(int)方法继承自OutputStream,因此也是写出其int类型参数的底8位字节。

(5)File类

File类是IO包中唯一表示磁盘文件信息的对象,他定义了一些与平台无关的方法来操作文件。

在Java中,目录也被当作File使用,只是多了一些目录特有的功能。

File类常用的API:

构造函数:(public File(String name); public File(String pathToName,String Name); public File(File directory,String name); public File(URI rui);)

public static final String pathSeparator //获取适合本机的分隔符

boolean canRead() //如果文件可读,则返回真,否则返回假

boolean canWrite() //如果文件可写,则返回真,否则返回假

boolean exists() //如果File构造函数所制定的名称是指定路径中文件或目录,则返回真,否则返回假。

boolean creatNewFile() //如果文件不存在,则创建这个名称的空文件,并返回真,如果文件存在,则返回假

boolean isFile() //如果File构造函数参数所指定的名称是一个文件,则返回真,否则返回假。

boolean isDirectory() //如果File构造函数参数所指定的名称是一个目录,则返回真,否则返回假。

boolean isAbsolute() //如果File构造函数参数所指定的名称是一个文件或目录的绝对路径,则返回真,否则返回假。

boolean delete() //删除文件或目录,如果是目录,必须是空目录才能删除成功,删除成功返回真,否则返回假。

String getAbsolutePath() //返回一个包含文件或目录的绝对路径的字符串

String getName() //返回一个包含文件名或目录名的字符串

String getPath() //返回一个包含文件或目录路径的字符串

String getParent() //返回一个包含文件或目录的父路径的字符串,则可在其中找到文件或目录的目录。

long length() //返回文件的字节长度。如果File对象代表目录,则返回0.

long lastModified() //返回文件或目录最近一次修改的时间,该时间的表示与平台相关,返回值只用于与该方法返回的其他值进行比较。

String[] list() //返回一个代表目录中内容的字符串数组,如File对象不是目录,则返回null.

(6)处理压缩文件

java.util.zip包中提供了一些类,可以压缩格式对流进行读写,他们都继承自字节流类OutputStream和InputStream。

其中GZIPOutputStream和ZipOutputStream可分别把数据压缩成GZIP格式和Zip格式;GZIPInputStream和ZipInputStream可以分别把压缩成GZIP格式或Zip的数据解压缩恢复原状,所有类使用的压缩算法都是相同的。

为了提高压缩效率,可以将缓冲流BufferedInputStream或BufferedOutputStream包装在压缩输入输出流当中。

从InputStream类的对象读取一个字节用的是read()方法,返回的是一个int型数字,每个字节都被转化为[0,255]之间的一个整形,如果读到了文件末尾,则返回-1,向OuputStream类型的对象写一个字节用的是write(int)方法,但int是32位的,所以只写int的底8位。

压缩类的使用很简单,只需要将别的输入输出流,包装在GZIPInputStream、ZipInputStream和GZIPOutputStream、ZipOutputStream中。

需注意的是,GZIPOutputStream和GZIPInputStream的构造函数都只能接受字节流类的对象,本身也是字节流。Reader类的InputStreamReader可以将读入的字节流转化为字符流。可以说,InputStreamReader和OutputStreamWriter构建了字节流与字符流之间的桥梁,InputStreamReader能够将InputStream转换为Reader,OutputStreamWriter则能将Writer转换为OutputStream。ZipOutputStream和ZipInputStream类的使用方法还有一些不同。Zip文件是一个压缩文件,里面含有多个文件,所以有多个入口,在压缩文件中,每一个文件用一个ZipEntity对象来表示,该对象的getName()方法返回文件的最初名称。

(7)对象序列化

Java是一种面向对象的语言,因而对象的永久存储是非常重要的。

java.io包中提供了专门用于对象信息存储和读取的输入输出流类ObjectInputStream和ObjectOutputStream,但这两个类不会保存和读取对象中的transient和static类型的变量,这使得我们可以选择性地存储必要的信息,所有的对象并不是都自动能被序列化的,要是实现对象的序列化,这个对象所属的类必须实现Serializable接口。

关键字:transient

transient说明一个属性是临时的,不会被序列化。

transient adj.短暂的

(8)随机文件读写

java.io包提供了RandomAccessFile类用于随机文件的创建和访问。使用这个类,可以跳转到文件的任意位置读写数据。

随机文件的应用程序必须指定文件的格式,最简单的是要求文件中的所有记录均保持相同的固定长度。

RandomAccessFile类有个位置指示器,指向当前读写处的位置,刚打开文件时,文件指示器指向文件的开头处。可以用seek,skipBytes等方法移动文件指示器到新的位置,随后的读写操作将从新的位置开始。RandomAccessFile在等长记录格式文件的随机读取时有很大的优势,但该类操作仅限于操作文件,不能访问其他I/O设备,如网络,内存映像等。

RandomAccessFile类的常用API:

public RandomAccessFile(File f,String mode); //指定关联的文件及处理方法

public void setLength(long newLength); //设置文件长度,即字节数

public long length(); //返回文件的长度,即字节数。

public void seek(long pos); //移动文件位置指示器,pos指定文件开头的偏离字节数。可以超过文件总字节数,但只有写操作后,才能扩展文件大小。

public int skipBytes(int n); //跳过n个字节,返回数为实际跳过的字节数。

public int read(); //从文件读取一字节,字节的高24位为0。如遇到结尾,则返回-1.

public final double readDouble(); //读取8个字节。

public final void writeChar(int v); //写入一个字符,两个字节,高位先写入。

public final void writeInt(int v); //写入四个字节的int型数字。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: