`

Java IO流

 
阅读更多

 一 . 流的概念

    流(stream)的概念源于UNIX中的管道(pipe)的概念。流,必有源端和目的端。 

 

二 . 流的分类

1. 根据流的方向,流分为:输入流和输出流。

        输入流:只能从中读取数据,不能向其写出数据。(read  in )

        输出流:只能向其写出数据,不能从中读取数据。(write out)

    注意:输入(读),输出(写) 方向的基本参照物是程序自身。 

  

2. 根据流处理数据的单位,流分为:字节流和字符流。

        字节流:处理数据为字节。

        字符流:处理数据为字符。

 

3. 根据流的功能,流分为:节点流和处理流。

    按流的功能分为:结点流和处理流(过滤流,包装流)。节点流都是直接以物理IO节点作为构造器参数。处理流的构造器参数不是一个物理节点,而是一个已经存在的流,这种流一定是处理流。

        节点流:节点流直接连接到实际数据源(如磁盘文件或内存区域)和实际的输入输出节点连接。

        处理流:将一个已经存在的流进行连接和包装,通过封装后来实现数据读写概念。(相当于对流加一层过滤。)

    例如:过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后再以新的输入流的形式提供给用户,过滤器输出流也类似。


 

    

 

4. 使用流的基本过程

从输入流读数据的过程一般如下: 

open a stream 

while more information 

    read information 

close the stream

 

往输出流写数据的过程一般如下: 

open a stream 

while more information 

    write information 

close the stream

 

 

四 . Java 提供的四种抽象类

基于字节的InputStreamOutputStream:InputStream,OutputStream类仅仅读取和写入单个的字节和字节数组,它们没有读取和写入字符串和数值的方法。

基于字节的ReaderWriter:由于以字节为单位的流处理存储为Unicode码的信息很不方便(Unicode的每个代码单元使用了两个字节),所以有了一个专门的类层次来处理Unicode字符,这些类继承于抽象类Reader和Writer。

  字节流 字符流
输入流 InputStream Reader        
输出流 OutputStream Write      

 

Java的IO流共涉及40多个类,这些类都由四个类派生出来。

 

 

1 . InputStream类和Reader类(读入)

InputStream类和Read类是所有输入流的基类。都是抽象类。本身不能创建实例来执行输入,但它们是所有输入流的模板。

InputStream读取方法:

  • int read() :从输入流中读出一个字节,并返回(0~255)。 若返回-1,则已到输入流的末尾。
  • int read(byte[] buffer) :从输入流中读取数据至buffer数组中,最多读取b.length个字节。 返回实际读取的字节数。说明:字节数组buffer即为缓冲区。
  • int read(byte[] buffer, int off, int len) :从输入流中读取数据至buffer数组中,最多 len 个字节。数据放入buffer数组中时,从数组的offset位置开始存储。返回实际读取的字节数。

Reader读取方法:

  • int read() :从输入流中读取数据的下一个字符。 
  • int read(char [] cbuf) :从输入流中最多读取cbuf.length个字符,并将其存储在字符数组 cbuf 中。 返回实际读取的字符数。说明:字节数组cbuf为缓冲区。
  • int read((char [] cbuf, int off, int len):从输入流中读取最多 len 个字符。并将其存储在字符数组 cbuf 中。数据放入cbuf数组中时,从数组的offset位置开始。返回实际读取的字符数。

InputSream和Reader还支持一下几个方法来移动记录指针:

  • void mark(int readlimit) :在记录指针当前位置记录一个标记。 
  • boolean markSupported() :判断输入流是否支持 mark和 reset 方法,即是否支持标记记录。
  • void reset() :将此流的记录指针重新定位到上一次标记(mark)的位置。
  • long skip(long n) :跳过和丢弃此输入流中数据的 n 个字节/字符。

 

2 . OutputStream类和Writer类(输出)

OutputStream类和Writer类是所有输出流的基类。都是抽象类。

 

OutputStream输出方法:

  • void write(int b) :将指定的字节输出到输出流。b代表字节。
  • void write(byte[] buffer) :将字节数组从的数据输入到指定输出流中。
  • void write(byte[] buffer, int off, int len) :将字节数组从off位置开始,长度为len的字节输出到输出流中。

 

Writer输出方法:

  • void write(int b) :将指定的字符输出到输出流。b代表字符。
  • void write(char[] cbuf) :将字符数组从的数据输入到指定输出流中。
  • void write(char[] cbuf, int off, int len) :将字符数组从off位置开始,长度为len的字符输出到输出流中。
  • void write(String str):将str字符串里包含的字符输出到指定输出流中。
  • void write(String str,int off,int len):将str字符串里从off位置开始。长度为len的字符输出到指定输出流中。

输出流的清空与关闭:

  • void flush() :输出所以缓冲区的数据。
  • void close() :关闭流。
说明:

    使用输出流,一定要关闭输出流。

  •     关闭输出流的作用:释放物理资源。
  •     关闭输出流时,Java自动执行输出流的flush()方法以输出缓冲中区的数据。

 

 

五. 节点流 

1. 节点流类型
类型 字符流 字节流
File

FileReader

FileWriter

FileInputStream

FileOutputStream

Memory Array

CharArrayReader

CharArrayWriter

ByteArrayInputStream

ByteArrayOutputStream

Memory String

StringReader

StringWriter

----
Pipe

PipedReader

PipedWriter

PipedInputStream

PipedOutputStream

Pipe:管道,用于进程间通信。

 

2. 文件的读写

创建文件流的构造方法

字节流

 

FileInputStream FileOutputStream

FileInputStream(File file) 

FileInputStream(FileDescriptor fdObj) 

FileInputStream(String name) 

FileOutputStream(File file) 

FileOutputStream(File file, boolean append) 

FileOutputStream(FileDescriptor fdObj)  

FileOutputStream(String name) 

FileOutputStream(String name, boolean append) 

 

 

字符流

FileReader FileWriter

FileReader(File file)  

FileReader(FileDescriptor fd)  

FileReader(String fileName) 

FileWriter(File file)  

FileWriter(File file, boolean append)  

FileWriter(FileDescriptor fd) 

FileWriter(String fileName)  

FileWriter(String fileName, boolean append)

说明:对于输出流构造方法的参数  boolean append  表示是否在文件之后追加。若没有使用到append参数,则均为覆盖文件。

 

 

例:读文件

import java.io.*;
public class TestFileInputStream {
  public static void main(String[] args) {
    int b = 0;
    FileInputStream in = null;
    try {
      in = new FileInputStream("d:\\share\\java\\io\\TestFileInputStream.java");
    } catch (FileNotFoundException e) {
      System.out.println("找不到指定文件"); 
      System.exit(-1);
    }
    
    try {
      long num = 0;
      while((b=in.read())!=-1){
        System.out.print((char)b); 
        num++;
      }
      in.close();  
      System.out.println();
      System.out.println("共读取了 "+num+" 个字节");
    } catch (IOException e1) {
      System.out.println("文件读取错误"); System.exit(-1);
    }
  }
}

 

例:Reader读取文件

import java.io.*;
public class TestFileReader {
  public static void main(String[] args) {
    FileReader fr = null; 
    int c = 0;
    try {
      fr = new FileReader("d:\\share\\java\\io\\TestFileReader.java");
      int ln = 0;
      while ((c = fr.read()) != -1) {
        System.out.print((char)c);
      }
      fr.close();
    } catch (FileNotFoundException e) {
      System.out.println("找不到指定文件");
    } catch (IOException e) {
      System.out.println("文件读取错误");
    }

  }
}

 

例:复制文件

import java.io.*;
public class FileCopy {
  public static void main(String[] args) {
	  int b = 0;
	  FileReader in = null;
	  FileWriter out = null;
	  try {
	    in = new FileReader("d:/share/java/HelloWorld.java");
	    out = new FileWriter("d:/share/java/io/HW.java");
	    while((b=in.read())!=-1){
	      out.write(b);
	    }
	    out.close();
	    in.close(); 
	    
	  } catch (FileNotFoundException e2) {
	    System.out.println("找不到指定文件"); System.exit(-1);
	  } catch (IOException e1) {
	    System.out.println("文件复制错误"); System.exit(-1);
	  }
	  System.out.println("文件已复制");
  }
}

 

 

 例:Writer写文件

import java.io.*;
public class TestFileWriter {
  public static void main(String[] args) {
    FileWriter fw = null;
    try {
      fw = new FileWriter("d:\\bak\\unicode.dat");
      for(int c=0;c<=50000;c++){
        fw.write(c);
      }
      fw.close();
    } catch (IOException e1) {
    	e1.printStackTrace();
      System.out.println("文件写入错误");
      System.exit(-1);
    }
  }
}

 

例:Reader,Writer复制文件

import java.io.*;
public class TestFileWriter2 {
	public static void main(String[] args) throws Exception {
		FileReader fr = new FileReader("d:/java/io/TestFileWriter2.java");
		FileWriter fw = new FileWriter("d:/java/io/TestFileWriter2.bak");
		int b;
		while((b = fr.read()) != -1) {
		    fw.write(b);
		}
		fr.close();
		fw.close();
	}
}

 

 

六.处理流

 1. 处理流类型

处理类型 字符流 字节流
Buffering

BufferedReader

BufferedWriter

BufferedInputStream

BufferedOutputStream

Filtering

FilterReader

FilterWriter

FilterInputStream

FilterOutputStream

Converting between bytes and character

InputStreamReader

OutputStreamWriter

 
Object Serialization ----

ObjectInputStream

ObjectOutputStream

Data conversion ----

DataInputStream

DataOutputStream

Counting LineNumberReader LineNumberInputStream
Peeking ahead PusbackReader PushcackInputStream
Printing PrintWriter PrintStream

 

 

处理流的使用

    处理流用于对流的再处理或包装。

    创建处理流,即处理流构造函数需要传入一个节点流作参数。这样创建的处理流就包装了该节点流。

    在关闭输入、输出流资源时,只要关闭最上层的处理流。关闭最上层的处理流,系统会自动关闭被包装的节点流。

 

 

1. 缓冲处理流

缓冲流对读写的数据提供了缓冲的功能。缓冲流是最常用的一种流类型。

1. 创建缓冲流的构造方法:

        BufferedInputStream(InputStream in)

        BufferedInputStream(InputStream in, int size)

        BufferedOutputStream(OutputStream out)

        BufferedOutputStream(OutputStream out, int size)

        BufferedReader(Reader in)

        BufferedReader(Reader in, int sz)

        BufferedWriter(Writer out)

        BufferedWriter(Writer out, int sz)

说明:sz为自定义缓冲区的大小。

 

2. 缓冲流的方法说明:

缓冲输入流支持其父类的mark() 和reset()方法。这两个方法使用的较少。

BufferedReader提供了readLine()方法用于读取一行字符串(以\r或\n分隔)。

BufferedWriter提供了newLine()方法用于写入一个行分隔符。

对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法将会使内存中的数据立刻写出。

 

 3.例程

例:BufferedInputStream读取文件示例

import java.io.*;
public class TestBufferStream1 {
  public static void main(String[] args) {
    try {
      FileInputStream fis = new FileInputStream("d:\\share\\java\\HelloWorld.java");
      BufferedInputStream bis = new BufferedInputStream(fis);
      int c = 0;
      System.out.println(bis.read());    //读取一个字节。
      System.out.println(bis.read());    //再读取一个字节。
      bis.mark(100);            //光标定位到100位置。
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){    //读10次字节。
        System.out.print((char)c+" ");
      }
      System.out.println(); 
      bis.reset();            //回到之前标记的100位置。
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){    //再次读取10次字节。
        System.out.print((char)c+" ");
      }
      bis.close();    //关闭流。
    } catch (IOException e) {e.printStackTrace();}
  }
}
 

例:BufferedReader与BufferedWriter  使用示例

import java.io.*;
public class TestBufferStream2 {
  public static void main(String[] args) {
    try {
      BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\share\\java\\dat2.txt"));
      BufferedReader br = new BufferedReader(new FileReader("d:\\share\\java\\dat2.txt"));
      String s = null;
      for(int i=1;i<=100;i++){
        s = String.valueOf(Math.random());  //Math.random()方法表示从0~1的随机数。
        bw.write(s);
        bw.newLine();
      }
      bw.flush();    //清空写缓冲。
      while((s=br.readLine())!=null){        //readLine()方法表示读取一行。
        System.out.println(s);
      }
      bw.close(); 
      br.close();
    } catch (IOException e) { e.printStackTrace();}
  }
}
 

 

 2. 转换处理流

 转换流:用于将字节流和字符流相互转换。(常用,重要)

InputStreamReader和OutputStreamWriter:用于将字节流转换成字符流。

说明:

      InputStreamReader继承于Reader。

      OutputStreamWriter继承于Writer。

 

例程

例:InputStreamReader,将InputStream包装为Reader。

import java.io.*;
public class TestTransForm1 {
  public static void main(String args[]) {
    InputStreamReader isr = new InputStreamReader(System.in);//System.in即从控制台接受输入的流。
    BufferedReader br = new BufferedReader(isr);    //将isr再包装为bufferedReader。
    String s = null;
    try {
      s = br.readLine();
      while(s!=null){
        if(s.equalsIgnoreCase("exit")) break;
        System.out.println(s.toUpperCase());
        s = br.readLine();
      }
      br.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
} //阻塞
 说明:System.in是一种阻塞式的流。没有输入,则程序停滞。

 

例:OutputStreamWriter,将OutputStream包装为Writer。

import java.io.*;
public class TestTransForm2 {
  public static void main(String[] args) {
    try {
      OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:\\bak\\char.txt"));
      osw.write("mircosoftibmsunapplehp");    //可以写入字符串。默认以当前系统编码,并写入FileOutStream。中文操组系统的默认编码及GBK。
      System.out.println(osw.getEncoding());    //osw.getEncoding() 表示取得字符编码。
      osw.close();
      osw = new OutputStreamWriter(new FileOutputStream("d:\\bak\\char.txt", true),"ISO8859_1"); //FileOutputStream的参数true,表示在原文件后面添加。
      osw.write("mircosoftibmsunapplehp");    //写入字符串,以ISO8859_1编码(latin-1),并写入FileOutStream。
      System.out.println(osw.getEncoding());
      osw.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

 3. 数据处理流

DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,属于处理流。

DataInputStream和DataOutputStream可以存取与机器无关的Java原始类型数据(如:int,double等)的方法。

 

创建数据流的构造方法:

  • DataInputStream(InputStream in) 
  • DataOutputStream(OutputStream out) 

 

常用方法:

DataInputStream方法 DataOutputStream方法

int read(byte[] b) 

int read(byte[] b, int off, int len)  

void readFully(byte[] b) 

void readFully(byte[] b, int off, int len) 

int skipBytes(int n) 

 boolean readBoolean() 

byte readByte() 

char readChar() 

double readDouble() 

float readFloat() 

int readInt() 

long readLong() 

short readShort() 

int readUnsignedByte() 

int readUnsignedShort() 

String readUTF() 

static String readUTF(DataInput in) 

 

void write(byte[] b, int off, int len) 

void write(int b) 

 void flush()  

int size() 

void writeBoolean(boolean v) 

void writeByte(int v)  

void writeBytes(String s) 

void writeChar(int v)  

void writeChars(String s)  

void writeDouble(double v) 

void writeFloat(float v)  

void writeInt(int v) 

void writeLong(long v) 

void writeShort(int v) 

void writeUTF(String str)

 说明:

1. UTF表示utf8。

 

 

例程:

例:使用DataOutputStream包装ByteArrayOutputStream,使用DataInputStream包装ByteInputStream;将不同数据类型写入内存,再从内存中读取出来。

import java.io.*;
public class TestDataStream {
  public static void main(String[] args) {
    try{
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      DataOutputStream dos = new DataOutputStream(baos);  //DataOutputStream包装ByteArrayOutputStream 。
      dos.writeDouble(Math.random());
      dos.writeBoolean(true);
      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());    //字节数组装入ByteArrayInputStream,再由ByteArrayInputStream包装。      System.out.println(bais.available());    //打印:9
      DataInputStream dis = new DataInputStream(bais);
      System.out.println(dis.readDouble());  //先写先读
      System.out.println(dis.readBoolean());
      dos.close();  dis.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
 说明:

1. ByteArrayOutputStream的toByteArray()方法:将流中的数据以byte数组读取出来。

2. ByteArrayOutputStream的available()方法:返回流字节个数。

3. 先写先读。即先进先出。队列。

 

 

4. 打印处理流

    PrintWriter和PrintStream都属于输出流,分别针对字符和字节。

    PrintWriter和PrintStream提供了重载的print、println方法 ,用于多种数据类型的输出。(这使得输出非常方便。)

    PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息。

    PrintWriter和PrintStream有自动flush功能。

    System.out即一个PrintStream。

 

打印流的构造方法

PrintStream PrintWriter

PrintStream(File file) 

PrintStream(File file, String csn) 

PrintStream(OutputStream out) 

PrintStream(OutputStream out, boolean autoFlush) 

PrintStream(OutputStream out, boolean autoFlush, String encoding) 

PrintStream(String fileName) 

PrintStream(String fileName, String csn) 

PrintWriter(File file) 

PrintWriter(File file, String csn) 

PrintWriter(OutputStream out) 

PrintWriter(OutputStream out, boolean autoFlush) 

PrintWriter(String fileName) 

PrintWriter(String fileName, String csn) 

PrintWriter(Writer out) 

PrintWriter(Writer out, boolean autoFlush) 

 

例程

例:PrintStream包装FileOutputStream

import java.io.*;
public class TestPrintStream1 { 
  public static void main(String[] args) {
    PrintStream ps = null;
    try {
      FileOutputStream fos = new FileOutputStream("d:\\bak\\log.dat");
      ps = new PrintStream(fos);
    } catch (IOException e) {
      e.printStackTrace();
    }
    if(ps != null){
      System.setOut(ps);
    }
    int ln = 0;
    for(char c = 0; c <= 60000; c++){
      System.out.print(c+ " ");
      if(ln++ >=100){ System.out.println(); ln = 0;}
    }
  }
}

说明:
1.System.setOut() 该方法用于设置系统输出位置。

 

 

例:读取文件,并将内容显示在控制台中。

import java.io.*;
public class TestPrintStream2 {
  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 {
      BufferedReader br = new BufferedReader(new FileReader(f));
      String s = null; 
      while((s=br.readLine())!=null){
        fs.println(s);            
      }
      br.close();
    } catch (IOException e) {
      fs.println("无法读取文件");
    }
  }
}
 

例:接受System.in的输入内容。将输入内容添加到文件,并记录日期。

import java.util.*; 
import java.io.*;
public class TestPrintStream3 {
  public static void main(String[] args) {
    String s = null;
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    try {
      FileWriter fw = new FileWriter("d:\\bak\\logfile.log", true); //Log4J
      PrintWriter log = new PrintWriter(fw);
      while ((s = br.readLine())!=null) {
        if(s.equalsIgnoreCase("exit")) {
	  break;
	}
        System.out.println(s.toUpperCase());
        log.println("-----");
        log.println(s.toUpperCase()); 
        log.flush();
      }
      log.println("==="+new Date()+"==="); 
      log.flush();
      log.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

 

 

 

5. Object处理流

    将object直接转换为字节,然后使用流传输字节。可以将对象写入硬盘或网络。

    对象要被序列化。即对象的类需要实现Serializable接口。实现Serializable接口不需要实现任何方法。这类接口成为标记性接口。被Serializable接口标记的类可以被序列化。

    ObjectInputStream类与ObjectOutputStream类:用于object的传输。

例程

例:将对象写入文件,再从文件中读取对象。

import java.io.*;
public class TestObjectIO {
	public static void main(String args[]) throws Exception {
		T t = new T();
		t.k = 8;
		FileOutputStream fos = new FileOutputStream("d:/share/java/io/testobjectio.dat");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		oos.writeObject(t);
		oos.flush();
		oos.close();
		
		FileInputStream fis = new FileInputStream("d:/share/java/io/testobjectio.dat");
		ObjectInputStream ois = new ObjectInputStream(fis);
		T tReaded = (T)ois.readObject();
		System.out.println(tReaded.i + " " + tReaded.j + " " + tReaded.d + " " + tReaded.k);
		
	}
}

class T implements Serializable
{
	int i = 10;
	int j = 9;
	double d = 2.3;
	transient int k = 15;  //transient关键字,表示透明的。表示不需要序列化该成员变量。
}

 

补充:Externalizable接口

Serialization接口用于标记对象可以序列化,但是序列化的方法是JVM控制的。

通过实现Externallizable接口可以有程序员控制序列化的过程。Externallizable接口继承自Serialization接口。

 

实现Externalizable接口需要实习以下两个方法:

  • void readExternal(ObjectInput in)  :定义从ObjectInput中读取的过程。
  • void writeExternal(ObjectOutput out) :定义向ObjectOutput写入的过程。

 

 

流相关的设计模式 

    装饰器模式:处理流都是对其他流的包装。

 

 

 

流关闭的问题

    按照学习时就留下的观念,流必须关闭,而且关闭顺序非常重要:先打开后关闭,后打开先关闭。用包装的观念来看:先关闭外层,再关闭内层。

    通过实际分析:只需要关闭最外层的流。当使用处理流的时候,在关闭输入/输出资源时。只需要关闭上层流即可。因为当关闭上层流的时候系统会默认去关闭被处理的节点流。

 

 

 

输入输出体系

说明: 

    上图中的各个流都是位于java.io包下的流。还有一些其他流用于访问音频文件,加密/解密,压缩/解压缩等流。

    如AudioInputStream,CipherInputStream,DeflaterInputStream,ZipInputStream.

 

 

继承于InputStream,OutputStream的类

输入字节流

1) ByteArrayInputStream:把内存中的一个缓冲区作为InputStream使用 

2) StringBufferInputStream:把一个String对象作为InputStream   ---已过时。 此类未能正确地将字符转换为字节。从 JDK 1.1 开始,从字符串创建流的首选方法是通过 StringReader 类进行创建。 

3) FileInputStream:把一个文件作为InputStream,实现对文件的读取操作 

4) PipedInputStream:实现了pipe的概念,主要在线程中使用 

5) SequenceInputStream:把多个InputStream合并为一个InputStream 

输入字节流

1) ByteArrayOutputStream:把信息存入内存中的一个缓冲区中 

2) FileOutputStream:把信息存入文件中 

3) PipedOutputStream:实现了pipe的概念,主要在线程中使用 

4) SequenceOutputStream:把多个OutStream合并为一个OutStream

 

 

继承于Reader,Writer的类

输入字符流

  • 1) CharArrayReader:与ByteArrayInputStream对应 
  • 2) StringReader:与StringBufferInputStream对应 
  • 3) FileReader:与FileInputStream对应 
  • 4) PipedReader:与PipedInputStream对应 

输出字符流

  • 1) CharArrayWrite:与ByteArrayOutputStream对应 
  • 2) StringWrite:无与之对应的以字节为导向的stream 
  • 3) FileWrite:与FileOutputStream对应 
  • 4) PipedWrite:与PipedOutputStream对应

 

 

推回输入流:PushbackInputStream 和 PushbackReader

 

    PushbackInputStream和PushbackReader都有如下方法:

  • void unread(byte[]/char[] buf) :将一个字节/字符数组内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。
  • void unread(byte[]/char[] buf,int off, int len) :将字节/字符数组里从off开始,长度为len的字节/字符的内容推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。
  • void unread(int b):将一个字节/字符推回到推回缓冲区里,从而允许重复读取刚刚读取的内容。

    推回输入流都带有一个推回缓冲区,当程序调用unread()方法时,系统将会把指定数组的内容推回到该缓冲区。当推回输入流每次调用read方法时总是先从推回缓冲区读取,只有当完全读取了队徽缓冲区的内容后,且还没有装满read所需的数组时才会从原输入流中读取。

 

 

重定向标准输入/输出:System.in 和 System.out

    Java标准输入/输出通过System.in和System.out来代表,默认情况下它们代表键盘和显示器,

    System类的三个对象:

  • static PrintStream err :“标准”错误输出流。 
  • static InputStream in :“标准”输入流。 
  • static PrintStream out :“标准”输出流。

当程序通过System.in来输入时,实际上是从键盘读取输入;当程序通过System.out来输出时,程序总是输出到屏幕。 

 

System类里提供三个重定向标准输入输出的方法:

  • static void setErr(PrintStream err) :重新分配“标准”错误输出流。 
  • static void setIn(InputStream in) :重新分配“标准”输入流。 
  • static void setOut(PrintStream out) :重新分配“标准”输出流。

 

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

    Runtime对象的exec方法可以运行平台上的其他教程。该方法产生Process对象,Process对象代表由Java程序启动的子进程,Process类提供以下三个方法,用于让程序和其子进程进行通信。

  • InputStream getErrorStream() 获取子进程的错误流。 
  • InputStream getInputStream() 获取子进程的输入流。 
  • OutputStream getOutputStream() 获取子进程的输出流。

    注意:子进程读取程序数据,就是让程序把数据输出到子进程中(将像把数据输出打文件中一样,只是现在子进程节点代替了文件节点),所以应该使用输出流。

 

 

RandomAccessFile

RandomAccessFile可以自由访问文件的任意位置。

RandomAccessFile允许自由定位文件记录指针。

RandomAccessFile可以不从开始地方开始输出,所以RandomAccessFile可以向已存在的文件后追加内容。因此,如果程序需要向已存在的文件后追加内容,则应该使用RandomAccessFile。

 

RandomAccessFile构造方法

  • RandomAccessFile(File file, String mode) 
  • RandomAccessFile(String name, String mode) 

创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。

    mode参数有如下四个值:

  • “r”:以只读方式打开指定文件。如果RandomAccessFile执行写入方法会抛出IOException。
  • “rw”:以读取、写入方式打开指定文件。如果文件尚不存在,则尝试创建该文件。
  • “rws”:以读取、写入方式打开指定文件.相对于”rw”模式,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备.
  • “rwd”:以读取、写入方式打开指定文件。相对于”rw”模式,还要求对文件内容的每个更新都同步写入到底层存储。

RandomAccessFile对象包含了一个记录指针,用以表示当前读写处的位置,当程序新创建一个RandomAccessFile对象时候,该对象的文件记录指针位于文件头(也就是0处),当读/写了n个字节后,文件记录指针将会向后移动n个字节. RandomAccessFile可以自由移动该记录指针,即可以向前移动,也可以向后移动.

RandomAccessFile用一下方法操作记录指针:

  • long getFilePointer() :返回文件记录指针的当前位置。
  • void seek(long pos) :将文件记录指针定位到pos位置。

    RandomAccessFile使用readXxx()和witerXxx()读写文件:

int read() 从此文件中读取一个数据字节。 

  • int read(byte[] b) 将最多 b.length 个数据字节从此文件读入 byte 数组。 
  • int read(byte[] b, int off, int len) 将最多 len 个数据字节从此文件读入 byte 数组。

以下readXxx()方法将从文件中读取一个Xxx的数据:

  • boolean readBoolean()  byte readByte()  char readChar()  double readDouble()
  • float readFloat()  int readInt()  long readLong()  short readShort()
  • int readUnsignedByte() 从此文件读取一个无符号的八位数。 
  • int readUnsignedShort() 从此文件读取一个无符号的 16 位数。 
  • String readUTF() 从此文件读取一个字符串。
  • void readFully(byte[] b)   将 b.length 个字节从此文件读入 byte 数组,并从当前文件指针开始。 
  • void readFully(byte[] b, int off, int len) 将正好 len 个字节从此文件读入 byte 数组,并从当前文件指针开始。 
  • String readLine() 从此文件读取文本的下一行。 
  • void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。 
  • void write(byte[] b, int off, int len) 将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。 
  • void write(int b)  向此文件写入指定的字节。

 

    以下writeXxx ()方法将在文件中写入一个Xxx的数据.

  • void writeBoolean(boolean v) 按单字节值将 boolean 写入该文件。 
  • void writeByte(int v)   按单字节值将 byte 写入该文件。 
  • void writeBytes(String s) 按字节序列将该字符串写入该文件。 
  • void writeChar(int v) 按双字节值将 char 写入该文件,先写高字节。 
  • void writeChars(String s) 按字符序列将一个字符串写入该文件。 
  • void writeDouble(double v) 使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long,然后按八字节数量将该 long 值写入该文件,先定高字节。 
  • void writeFloat(float v) 使用 Float 类中的 floatToIntBits 方法将浮点参数转换为一个 int,然后按四字节数量将该 int 值写入该文件,先写高字节。 
  • void writeInt(int v) 按四个字节将 int 写入该文件,先写高字节。 
  • void writeLong(long v) 按八个字节将 long 写入该文件,先写高字节。 
  • void writeShort(int v) 按两个字节将 short 写入该文件,先写高字节。 
  • void writeUTF(String str) :使用 modified UTF-8 编码以与机器无关的方式将一个字符串写入该文件。
 
 
  • 大小: 11.2 KB
  • 大小: 51.9 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics