IO (read write)

java的控制台输入由System.in完成.

 

Java提供了两种类型的输入输出流:

1)      一种是面向字节的流,数据的处理是以字节为基本单位

2)      一种是面向字符的流,用于字符数据的处理

 

 

按流的方向来分:

——输入流:把外部输入读入当前程序所在的内存

——输出流:把当前程序所在内存的数据输出到外部

 

按流处理数据来分:

——字节流:处理的数据单元是字节(8bit) 适应性广,功能强大

——字符流:处理的数据单元是字符。通常来说,它主要用于处理文本文件,它在处理文本文件时更方便。

 

按流的角色来分

——节点流:和一个IO的物理节点关联,比如磁盘中的某个文件,网络等等

——包装流(处理流/过滤流):以节点为基础,包装之后的得到的流,所有的包装流都是在Filtxxx的过滤流的子类

 


 


 

 

 

文件操作

 

 

创建文件

文件创建函数 file.createNewFile()   创建文件的时候需要抛出异常。


 

 

 

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

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

boolean   exists()                     判断文件或目录是否存在

boolean   createNewFile()        若文件不存在,则创建指定名字的空文件,并返回真,若不存在返回假

boolean   isFile()                       判断对象是否代表有效文件

boolean   isDirectory()     判断对象是否代表有效目录

boolean   equals(File f)    比较两个文件或目录是否相同

string       getName()                    返回文件名或目录名的字符串

string       getPath()                      返回文件或目录路径的字符串

long         length()                       返回文件的字节数,若 File 对象代表目录,则返回 0

long         lastModified()     返回文件或目录最近一次修改的时间

String[]    list()         将目录中所有文件名保存在字符串数组中并返回,若 File 对象不是目录返回 null

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

boolean  mkdir()      创建当前目录的子目录,成功返回真,否则返回假

boolean   renameTo(File newFile)   将文件重命名为指定的文件名

 

File parent = new File("C:"+File.separator+"haha");

parent.mkdir();// 一次只能创建一个目录

 

 

File parent = newFile("C:"+File.separator+"haha"+File.separator+"haha");

parent.mkdirs();// 一次可以创建多个目录

 

 

File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

 

File 的特征:只能访问磁盘上文件和目录。无法访问文件的内容。访问文件的内容需要使用IO

 

 

 

文件的随机读写

RandomAccessFile类用于随机文件的创建和访问,使用这个类可以跳转到文件的任意位置读写数据

 

RnadomAccessFile——随机(任意)访问文件

Random——想访问文件的那个点,就访问文件的哪个点(任意)

特征:

A)     即可读,又可写,还可追加 RandomAccessFile它不会覆盖原有的文件内容

B)      只能访问文件!相当于DataInputStream DataOutputStream

 

RandomAccessFile类是Object类的直接子类

l  Public RandomAccessFile(Stringname, String mode)    指定随机文件流对应的文件名

l  Public RandomAccessFile(File file,String mode)          file指定随机文件流对象所对应的文件名

 

Note mode表示所创建的随机读写文件的操作状态

l  r”表示以只读的方式打开文件

l  rw”表示以读写方式打开文件,使用该模式只用一个对象即可同事实现读写操作

 


 

 

 

RandomAccessFile 类与文件内容有关,但是此类有一个缺点就是说如果要跳转,则需要数据的保存长度一致。

 

 

long length()                      返回文件长度

voidseek(long pos)    移动文件位置指示器,pos 指定从文件开头的偏离字节数

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

int read()                   从文件中读取一个字节,字节的高 24 位为 0,若遇到文件结尾,返回-1

final byte readByte() 从文件中读取带符号的字节值

final charreadChar()           从文件中读取一个 Unicode 字符

final voidwriteChar(inte c)         写入一个字符,两个字节

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

InputStream&& OutputStream

 

FileInputStream          从文件中读取的输入流

PipedInputStream      输入管道

FilterInputStream       过滤输入流

ByteArrayInputStream        从字节数组读取的输入流

SequenceInputStream        两个或多个输入流的联合输入流,按顺序读取

ObjectInputStream    对象的输入流

LineNumberInputStream   为文本文件输入流附加行号

DataInputStream        包含读取 Java 标准数据类型方法的输入流

BufferedInputStream          缓冲输入流

PushbackInputStream         返回一个字节并把此字节放回输入流

 

 

void close()            关闭输入流

void mark()             标记输入流的当前位置

void reset()            将读取位置返回到标记处

int read()                      从输入流中当前位置读入一个字节的二进制数据,以此数据为低位字节,补足16位的整型量(0~255)后返回,若输入流中当前位置没有数据,则返回-1

int read(byte b[])      从输入流中的当前位置连续读入多个字节保存在数组中,并返回所读取的字数

 

int read(byte b[], int off, int len)     从输入流中当前位置连续读len长的字节,从数组第off+1个元素位置处开始存放,并返回所读取的字节数

 

int available()                       返回输入流中可以读取的字节数

long skip(long n)                           略过n个字节

long skip(long n)                           跳过流内的n个字符

booleanmarkSupported()             测试输入数据流是否支持标记

 

 

 

 

 

// 创建一个OuputStream的基类并用FileOutputStream给其赋值

InputStream in=null;

in=new FileInputStream(file);

//声明一个byte数组,用于接受内容

byteb[]= newbyte[1024];

// 从文件中读数据

in.read(b);

System.out.println(newString(b));

// 关闭流FileInputStream

in.close();

 

 

 

 

 

 

 

 

 

 

 

OutputStream类是一个抽象类,JAVA中上述的4种类都是抽象类:抽象类必须通过子类实例化

OutputStream会根据实例化它的子类或对象不同,输出的位置也不同。

 

 

FileOutputStream       写入文件的输出流

PipedOutputStream   输出管道

FilterOutputStream    过滤输出流

ByteArrayOutputStream    写入字节数组的输出流

ObjectOutputStream          对象的输出流

DataOutputStream     包含写Java标准数据类型方法的输出流

BufferedOutputStream      缓冲输出流

PrintStream                       包含print()println()的输出流

 

 

 

 

void close()                                         关闭输出流

void flush()                                         强制清空缓冲区并执行向外设输出数据

void write(int b)                                          将参数b的低位字节写入到输出流

void write(byte b[])                    按顺序将数组b[]中的全部字节写入到输出流

void write(byte b[],int off, int len)      按顺序将数组b[]中第off+1个元素开始的len个数据写入到输出流

 

 

 

import java.io.*;

publicclass JavaStream {

    publicstaticvoidmain(String[] args) throws Exception

    {

       // TODOAuto-generated method stub

       // 首先创建文件

       File file= new File("f:\\demo.txt");

       // 创建一个OuputStream的基类并用FileOutputStream给其赋值

       OutputStream out=null;

       out = new FileOutputStream(file);

       String string="gaoshuo ai chen lin !";

            // 向文件中写数据

       out.write(string.getBytes());

       // 关闭流FileOutputStream

       out.close();

    }

}

 

 

 

 

 

InputSteam&& OutputStream

 

InputStream&& OutputStream主要用来对字节流进行操作

主要的操作方式:

》用File类找到一个文件

》用File类的对象去实例化InputStreamOutputStream的子类的对象

》对文件进行读/写操作

》关闭文件

 

InputStreamOutputStream所操作的都是字节操作,所有的数据都要通过byte数组操作

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Reader&& Writer

harArrayReader         从字符数组读取的输入流

BufferedReader         缓冲输入字符流

PipedReader      输入管道

InputStreamReader   将字节转换到字符的输入流

FilterReader       过滤输入流

StringReader      从字符串读取的输入流

LineNumberReader   为输入数据附加行号

PushbackReader        返回一个字符并把此字节放回输入流

FileReader          从文件读取的输入流

 

void close()        关闭输入流

void mark()         标记输入流的当前位置

booleanmarkSupported()           测试输入流是否支持 mark

int read()                                从输入流中读取一个字符

int read(char[] ch)                   从输入流中读取字符数组

int read(char[] ch, int off, int len)     从输入流中读 len 长的字符到 ch

boolean ready()          测试流是否可以读取

void reset()        重定位输入流

long skip(long n)         跳过流内的 n 个字符

 

    publicstaticvoidmain(String[] args) throws Exception

    {

       // 首先创建文件

       File file=new File("f:\\write.txt");

// 创建一个Reader的基类并用FileReader给其赋值

       Reader r=null;

       r=new FileReader(file);

       //声明一个char数组,用于接受内容

       charb[]=newchar[500];

       // 从文件中读数据

       r.read(b);

       System.out.println("Outputis :"+ newString(b));

       // 关闭流FileReader

       r.close();

    }

 

 

CharArrayWriter        写到字符数组的输出流

BufferedWriter          缓冲输出字符流

PipedWriter       输出管道

OutputStreamWriter          转换字符到字节的输出流

FilterWriter        过滤输出流

StringWriter       输出到字符串的输出流

PrintWriter        包含 print() println()的输出流

FileWriter           输出到文件的输出流

 

 

 

void close()                       关闭输出流

void flush()                        将缓冲区中的数据写到文件中

void writer(int c)                        将单一字符 c 输出到流中

void writer(Stringstr)         将字符串 str 输出到流中

void writer(char[]ch)         将字符数组 ch 输出到流

void writer(char[]ch, int offset, int length)          将一个数组内自 offset 起到 length 长的字符输出到流

 

 

FileWrite类是Write子类OutputStreamWriter类的子类,因此FileWriter类既可以使用Writer类的方法也可以使用OutputStreamWrite类的方法来创建对象。

 

在使用FileWriter类写入文件时,必须先调用FileWriter()构造方法创建FileWrite类的对象,在调用write()方法。

FileWrite构造方法的格式为:

public   FileWriter(String name);

//根据文件名创建一个可写入的输出流对象

publicFileWrite(String name, Boolean a);

//a为真,数据将追加到文件后面

 

 

 

    publicstaticvoidmain(String[] args) throws Exception

    {

       // TODOAuto-generated method stub

       // 首先创建文件

       File file=new File("f:\\write.txt");

       // 创建一个Writer的基类并用FileOutputStream给其赋值

       Writer w=null;

       w=new FileWriter(file);

       String string="ssgaoai chen lin!";

        // 向文件中写数据

       w.write(string);

       // 关闭流FileWriter

       w.close();

      }

 

 

 

 

 

 

Note:

 

Reader&&Writer 用于操作字符流

字符输出时如果不关闭则无法将内容写入到文件:

      根本原因是如果字符流不关闭则内存中的数据不会强制性的输出到文件,即,字符流操作中使用了缓存,在关闭时会强制性的清空缓存,也可以使用flush()方法手工清空缓存。

 

字符流用到了缓存而字节流没有用到缓存。

 

 

ByteArrayInputStream && ByteArrayOutStram&& CharArrayReader && CharArrayWrites

 

 

 

 

PipedOutputStream && PipedInputStream&&PipedReader&& PipedWriter

管道流:主要用于线程间的通信

 

 


 

StreamReader && StreamWriter

 

 

 

 

 

 

 

BufferredInputStream&&BufferedOutputStream&&BufferedRead&&BufferedWrite

缓冲流:

——外部存储器的速度比内存的速度要慢,外部存储器的读写与内存的读写不同步!!通过缓冲就可以解决这种不同步。

——用完流之后,别忘了调用flush(把缓冲中的内容刷入实际的节点)方法

——调用close()也可——系统会在关闭之前自动刷缓冲

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

FilterInputStream&&FilterOutputStream&&FilterRead&&FilterWriter

 

节点流直接与IO节点关联

——IO节点有很多,键盘,网络,文件,磁带…..


过滤流,建立在节点流的基础之上。

过滤流的好处:——消除底层节点之间的差异

——使用过滤流的方法执行IO更加便捷

 

FileOutputStream  ---->PrintStream

FileWrite  ----> PrintStream

 

InputStream --> InputStreamReader --->BuferedReader

如果已经知道要读取的内容是字符内容,就可以按上面的方式转换

 

 

 

 

 

FileInputStream(File file)

FileInputStream(FileDescriptor fdObj)

FileInputStream(String name)

通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径名name指定。

 

 

 

 

DataInputStream && DataOutputStream

 

DataInputStreamDataOutputStream为过滤流(建立在已有IO流的基础之上)

——这两个流增加一些特定的方法来读取特定的数据。

 

 

DataInputStream(InputStream in)

DataOutputStream(OutputStream out)

 

public class DataInputStreamextends FilterInputStreamimplements DataInput

 

 

System.out && System.in

 

System.out把输出送到缺省的显示(通常是显示器)

 

staticPrintStream   out “标准输出流”

PrintStreamOutputStream类的子类.

 

系统输出是将所有信息输出到指定的输出设备上----显示器。

System.out本身是属于PrintStream对象,而PrintStreamOutputStream子类,所以现在实际上可以利用System.outOutputStream类执行实例化操作

 

import java.io.*;

publicclass JavaOut {

    publicstaticvoidmain(String[] args) throws Exception

    {

       // TODOAuto-generated method stub

       OutputStream out=null;

       out= System.out;

       String string ="Thisis word will export by windows!";

       out.write(string.getBytes());

    }

}

 

         system.in 是一个专门用于从键盘输入数据的文件流

                static InputStream   in  “标准输入流”

 

使用System.inInputStream实例化之后,内容确实可以输入了,但是程序存在以下两个问题:

》输入的内容长度受限制

》如果输入的中文超过容量,则可能出现乱码

 

import java.io.*;

publicclass JavaIn {

   publicstaticvoidmain(String[] args) throws Exception

    {

       // TODOAuto-generated method stub

       InputStream in=null;

       in=System.in;

       byteb[]=newbyte[10];  //长度受限

       intlen=in.read(b);

       in.close();

       System.out.println("读入的数据流是:"+new String(b,0,len));

    }

}

 

 

 

 

 

重定向标准输入输出:

——System.in : 标准输入。通常代表键盘

——System.out: 标准输出。通常代表屏幕

System.setOut() ——可以将标准输出重定向另一个输出流。

System.setIn() ——可以将标准输入重定向另一个输入流。

 

Java虚拟机读取其他进程的数据:

Java启动其他进程:

Runtime实例.exec()——该方法的返回值是一个Process对象。

Process——代表一个进程。进程就是应用程序。

 

 

PrintStream/PrintWrite
public class PrintStreamextends FilterOutputStream

PrintStream/PrintWriter实际上是一个打印流, 打印流比普通的OuputStream/Writer 提供了更多了打印数据的方法:

 

PrintStream或者PrintWriter的创建需要使用 OutputStream流来进行创建

PrintWriter(OutputStreamout);   根据现有的OutputStream创建不带自动刷新的PrintWriter

向屏幕写:

import java.io.*;

publicclass JavaOut {

    publicstaticvoid main(String[]args) throws Exception

    {

       // TODOAuto-generated method stub

       PrintWriter writer=new PrintWriter(System.out); 

       String string ="Thisis word will export by windows!";

       writer.print(string);

       writer.println('\n');

       writer.println(100);

       writer.close();

            只有在流关掉以后才能将内容显示在界面上

} }

Note:

   如果未执行writer.close(),那么不会显示输出结果,也就是说PrintWriter类使用缓冲区,当执行close操作时,才将打印的内容显示的输出给相应的对象。

 

 

 

 

 

 

 

 

 

 

向文件中去写:

import java.io.*;

publicclass JavaOut {

    publicstaticvoidmain(String[] args) throws Exception

    {

       // TODOAuto-generated method stub

       File file = new File("f:\\writer.txt");

       PrintWriter writer=new PrintWriter(newFileWriter(file));  

       String string ="Thisis word will export by windows!";

       writer.print(string);

       writer.println('\n');

       writer.println(100);

       writer.close();

    }

}

 

 

BufferedReader类读取文件

 

BufferedReader 类是用来读取缓冲区中的数据。使用时必须创建FileReader类对象,在用该对象为参数创建BufferedReader类的对象。BufferedReader类有两个构造方法,其格式为:

 

public BufferedReader(Reader in);//  创建缓冲区字符输入流

public BufferedReader(Reader in, int size);  // 创建输入流并设置缓冲区的大小

 

 

在输入数据的时候更希望将全部输入的数据一次性读取进来,如果一次性读取,则肯定不会出现乱码。

即输入的数据放入到一个缓存中: BufferReader.

 

import java.io.*;

publicclass JavaIn {

   publicstaticvoidmain(String[] args) throws Exception

    {

       // TODOAuto-generated method stub

       BufferedReader read=null;

       //准备从键盘中读取数据

       read=newBufferedReader(newInputStreamReader(System.in));

         String str=null;

         str=read.readLine();

         System.out.println(str);

      

    }

}

 

 

字节流和字符流之间的转换:

InputStreamReaderOutputStreamWriter,这两个类是字节流和字符流之间转换的类,InputStreamReader可以将一个字节流中的字节解码生成字符。

InputStreamReader:是将输入的内容由字节变为字符

OutputStreamWriter:是将输出的内容由字符转化为字节

OutputStreamWriter将写入的字符编码成字节后写入一个字节流.

 


 

序列化 && ObjectInputStream && ObjectOutputStream

ObjectOutputStream(OutputStream out)

ObjectInputStream(InputStream in)

序列化—— java对象(内存)《————》二进制流  

{ 序列化只是序列化对象(或实例),并非序列化类,所以添加static 修饰的Field是不会被序列化 }

目的: 

A>    有些时候,需要把对象存储到外部存储器中持久保存。

B>    有些时候,需要把对象通过网络传输。

 

可序列化的对象: Java要求可序列化的类实现下面任意两个接口:

——Serializable: 该接口只是一个标记性的接口,实现该接口无需实现任何方法

——Externalizable : 该接口需要实现方法

 

ObjectOutputStream——负责把对象保存到二进制流中

对应的方法:public final void writeObject(Object obj)  throws IOException

ObjectInputStream——负责把二进制流恢复对象

对应的方法:public final Object readObject()throws IOException,

 

 

 

对象引用变量序列化机制:

A>    引用变量所引用类型的对象的所有属性的都应该是可以序列化的

B>    序列化的底层机制:

1>    每序列化一个对象,都会给该对象设置一个编号

2>    如果程序第一次序列化某个对象。系统会真的将该对象序列化成二进制流

3>    如果要序列化的对象是之前已经序列化的。此时仅序列化一个编号

这种序列化机制, 就是为了保存磁盘里的二进制流与内存中的对象是对应的。

 

Transient——修饰符

                 用于修饰成员变量。而且只能修饰实例变量,不能与static同时使用

                 transient用于执行被修饰的Field不会被序列化

static修饰的是类变量——序列化机制负责序列化实例

static修饰的类变量存储在类信息中,并不是存储在对象里。

——因此static修饰的类变量不会被序列化。

 

 

 

transient作用:对于一些敏感信息,比如银行卡的账号,密码,就不应被序列化出来。此时可以使用transient来屏蔽这些信息。但将一些属性完全阻止在序列化之外,有时候也并不完善。

此时可以借助于定制序列化”, 可以对属性进行一些加密。

自定义序列化机制,必须实现如下两个方法:

privatevoid writeObject(java.io.ObjectOutputStream out)

      throws IOException

{…}

privatevoid readObject(java.io.ObjectInputStream in)

      throws IOException, ClassNotFoundException

{…}

版本号:

当类在经常使用的时候,有时候系统无法确定反序列化时的class文件是否还正确,建议显示为可序列化指定一个版本号 /* 即使不指定,系统默认也有一个版本号,但不稳定 */

 

Serialver.exe——专门用于查看本类的版本号

Serialver ——show:显示图形化界面


自定义版本号:

privatestaticfinallongserialVersionUID = 1L;

自定义的版本号的好处是:更加稳定。

只有当我们修改了类的定义的时候,可以由程序员显示的更改该serialVersionUID


 

 

 

 

Java 1.7 && java NIO

传统的java里,只有一个File类,即代表文件,又代表目录

Path ——接口代表一个与平台无关的路径提供大量的文件操作路径

Paths——工具类(Arrays Objects Collections Paths)——工具类中的所有方法都是静态的

Files——操作文件的工具类,提供大量的方法操作文件

 

 

Java IO 小结

 

 


 

 

 

 

面向字符的输入流都是Reader的子类,层次结构如图: