JAVA : I/O系统

来源:互联网 发布:php array slice 编辑:程序博客网 时间:2024/05/16 11:20

*

java.io

java的核心库java.io提供了全面的IO接口。包括:文件读写、标准设备输出等。Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。

通过数据流、序列化和文件系统提供系统输入和输出。


流是一个很形象的概念,当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。


java.io常用类

JDK所提供的所有流类位于java.io包中,都分别继承自以下四种抽象流类。
InputStream:继承自InputStream的流都是用于向程序中输入数据的,且数据单位都是字节(8位)。
OutputStream:继承自OutputStream的流都是程序用于向外输出数据的,且数据单位都是字节(8位)。
Reader:继承自Reader的流都是用于向程序中输入数据的,且数据单位都是字符(16位)。
Writer:继承自Writer的流都是程序用于向外输出数据的,且数据单位都是字符(16位)。


Java流输入输出原理

Java把这些不同来源和目标的数据都统一抽象为数据流。Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象。
在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流。


File类

在Java中,可以用File类来表示一个文件,文件可以是所有文件,包括文件夹.(可以理解为linux中的文件概念,一切皆文件,File)

目录列表器

public class Demo {    public static FilenameFilter filter (final String regex) {//传入的参数必须是final的,这样它才能够使用来自该类范围之外的对象        return new FilenameFilter() {            @Override            public boolean accept(File dir, String name) {                return name.equals("迅雷下载");//匿名内部类的实现方式            }        };    }    public static void main(String[] args) {        File file = new File("d:\\");        if (file.isDirectory()) {            System.out.println(file.getPath());//查看路径            String[] files = file.list(new MyFileNmeFilter());//也可以不指定过滤器            for (String s : files) {                System.out.println(s);//查看目录内所有文件            }        }    }}class MyFileNmeFilter implements FilenameFilter {//当然也可以用匿名内部类来实现    @Override    public boolean accept(File dir, String name) {        return name.equals("迅雷下载");//可用正则表达式过滤    }}

一个简单的查看当前目录文件的递归

当查看C D 等位置的时候,可能会报空指针。这段代码会查看当前目录下的所有文件。

public class Demo {    public static void fun(File file) {        if (file.isDirectory()) {            File[] files = file.listFiles();            for (File f : files) {                fun(f);            }        } else {            System.out.println(file);        }    }    public static void main(String[] args) {        String str = ".";//查看当前目录        File f = new File(str);        fun(f);    }}

输入和输出


流概念

首先要讲一下”流”这个概念;编程语言的I/O库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或有能力接收数据的接收端对象。”流”屏蔽了实际的I/O设备处理数据的细节。然后之所以下面这些IO类叫做经典的输入输出流,是因为后面还会接触到Java的NIO。

什么是IO

Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法。

Java.io是大多数面向数据流的输入/输出类的主要软件包。此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO。

流IO的好处是简单易用,缺点是效率较低。块IO效率很高,但编程比较复杂。

Java IO模型 :
Java的IO模型设计非常优秀,它使用Decorator模式,按功能划分Stream,您可以动态装配这些Stream,以便获得您需要的功能。例如,您需要一个具有缓冲的文件输入流,则应当组合使用FileInputStream和BufferedInputStream。
首先来讲我们需要从几个方面来对Java的IO进行一个分类,以便有一个直观的认识:
1. 输入流和输出流
输入流是指只能从中读数据,而不能向里面写数据:包括InputStream和Reader两个基本接口
输出流是指只能向里面写数据而不能向其中读数据:包括OutputStream和Writer两个基本接口

  1. 字节流和字符流
    字节流和字符流的唯一不同就在于他们的操作的数据单元不同而已,字节流操作的数据单元是字节,而字符流操作的数据单元是字符。所有从Writer,Reader派生来的类都是字符流的类。而所有从InputStream和OutputStream派生出来的类都是字节流的类。

  2. 节点流和处理流
    所谓的节点流指的是:可以向/从一个特定的IO设备(如磁盘,网络,数组,字符串)读/写的流;节点流也被成为低级流。
    所谓的处理流指的是:对一个已存在的流进行连接或封装,然后通过封装以后的流来实现数据的读写功能。处理流也叫做高级流。
    Java中的IO使用了装饰器的设计模式,就是体现在节点流和处理流的包装关系上。使用处理流的好处在于我们可以忽略掉底层数据源的不同,而使用统一的方式进行读写。
    这里写图片描述

因为节点流是所有输入输出的基础,所以有必要拿出来单独细看一下。
(1) . InputStream 对应的节点流(按对应的数据源分) ,作用是用来表示那些从不同数据源产生输入的类。
1. 字节数组:ByteArrayInputStream。以字节数组作为读取对象,允许将内存的缓冲区当作InputStream使用。
2. String对象:StringBufferInputSteam。将String转换成InputStream,过期了
3. 文件:FileInputStream。用于从文件中读取信息。
4. ”管道”: PipedInputStream,产生用于写入相关PipedOutputStream的数据,实现管道化“概念”。
5. FilterInputStream 抽象类,作为“装饰器”的接口,其中,装饰器为其他的InputStream 类提供有用功能。

(2).OutputSteamd对应的结点流 ,该类别的类决定了输出所要去往的目标。
1. ByteArrayOutputStream。在内存中创建缓冲区,所有送往”流”的数据都要放置在此缓冲区。
2. FileOutputStream 用于将信息写入到文件
3. PipedOutputStream 将信息写入到管道
4. FilterOutputStream 抽象类,作为“装饰器”的接口,其中,装饰器为其他的OutputSteamd类提供有用功能。

(3).Reader对应的节点流
1. FileReader:以文件作为读取对象
2. StringReader:以字符串作为读取对象
3. CharArrayReader:以字符数组作为读取对象
4. PipeReader:以管道作为读取对象

(4).Writer对应的节点流
1. FileReader:以文件作为输出对象
2. StringWriter:以字符串作为输出对象
3. CharArrayReader:以字符数组作为输出对象
4. PipedWriter:以管道作为输出对象

InputStream可以通过InputStreamReader转换成Reader的,而OutPutstream可以通过OutputStreamWriter转换成Writer。


代码举例

. I/O流 包装,作用于读文件

public class Demo {    public static void main(String[] args) throws Exception {        File file = new File("./test.txt");//指定输入文件        if(file.exists()){            System.out.println("file exists,begin read file...");            try {                FileInputStream fis = new FileInputStream(file);//文件流作为输入                InputStreamReader isr = new InputStreamReader(fis,"UTF-8");//转换为字符输入流                BufferedReader br = new BufferedReader(isr);//转换为缓冲流,提高速度,这是非常常见的方式                String line;                while((line = br.readLine()) != null){                    System.out.println(line);                }                br.close();                isr.close();                fis.close();                System.out.println("read file end...");            } catch (final Exception e) {                e.printStackTrace();            }        }    }}

. 读取 >> 写入

public class Demo {    private static final String file = "./test.txt";//读取的文件    public static void main(String[] args) throws Exception {        int LineNum = 1;        BufferedReader br = new BufferedReader(new FileReader(file));        PrintWriter pw = new PrintWriter("/writertest.txt");//要被写入的文件        //PrintWriter中提供了一个快捷的构造器方式,可以使得我们不用进行复杂的包装        String s ;        while ((s = br.readLine()) != null) {            pw.println(LineNum++ +": "+s);        }        pw.close();        br.close();    }}

. DataOutputStream
如果我们使用DataOutputStream写入数据,那么java就可以保证我们使用DataInputStream准确的读取数据,无论读和写的平台多么不同,

public class Demo {    private static final String file = "./test.txt";//读取的文件    public static void main(String[] args) throws Exception {        //使用DataOutputStream向文件写入数据        DataOutputStream out =new DataOutputStream(new BufferedOutputStream(new FileOutputStream("./dataFile.txt")));        ///当我们使用DataOutputStream写字符串并让DataInputStream能够恢复        //它的唯一可靠做法就是使用UTF-8编码,这里是使用writeUTF()和readUTF()实现的        out.writeUTF("That was a message");//此处可写入不同的数据类型        out.close();        DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("./dataFile.txt")));        System.out.println(dis.readUTF());        dis.close();    }}

. 使用DataInputStream逐个读取字节

public class Demo {    private static final String file = "./test.txt";//读取的文件    public static void main(String[] args) throws Exception {        DataInputStream dis = new DataInputStream(new ByteArrayInputStream("kkkkkkkkk".getBytes()));        while(dis.available()!=0){            System.out.print((char)dis.readByte());        }    }}

. 管道流PipedInputStream和PipedOutputStream
管道流内部在实现时还有大量的对同步数据的处理 ,管道输出流和管道输入流执行时不能互相阻塞,所以一般要开启独立线程分别执行 ,顺便复习了多线程操作

public class Demo {    public static void main(String[] args) throws Exception {        PipedInputStream pis = new PipedInputStream();        PipedOutputStream pos = new PipedOutputStream();        pis.connect(pos);//输入流与输出流连接        ReadThread readThread = new ReadThread(pis);        WriteThread writeThread = new WriteThread(pos);        new Thread(readThread).start();        new Thread(writeThread).start();    }}class ReadThread implements Runnable {    private PipedInputStream pis;    ReadThread(PipedInputStream pis) {        this.pis = pis;    }    @Override    public void run() {//由于必须要覆盖run方法,所以这里不能抛,只能try        try {            sop("R:读取前没有数据,阻塞中...等待数据传过来再输出到控制台...");            byte[] buf = new byte[1024];            int len = pis.read(buf);  //read阻塞            sop("R:读取数据成功,阻塞解除...");            String s = new String(buf, 0, len);            sop(s);    //将读取的数据流用字符串以字符串打印出来            pis.close();        } catch (Exception e) {            throw new RuntimeException("R:管道读取流失败!");        }    }    private static void sop(Object obj) //打印    {        System.out.println(obj);    }}class WriteThread implements Runnable {    private PipedOutputStream pos;    WriteThread(PipedOutputStream pos) {        this.pos = pos;    }    @Override    public void run() {//由于必须要覆盖run方法,所以这里不能抛,只能try        try {            sop("W:开始将数据写入:但等个5秒让我们观察...");            Thread.sleep(5000);  //释放cpu执行权5秒            pos.write("W: writePiped 数据...".getBytes());  //管道输出流            pos.close();        } catch (Exception e) {            throw new RuntimeException("W:WriteThread写入失败...");        }    }    private static void sop(Object obj) //打印    {        System.out.println(obj);    }}//output//R:读取前没有数据,阻塞中...等待数据传过来再输出到控制台...//W:开始将数据写入:但等个5秒让我们观察...//R:读取数据成功,阻塞解除...//W: writePiped 数据...

Reader和Writer

InputStreamReader可以把InputStream抓换成Reader;InputStreamWriter可以把InputStream转换成Writer


自我独立的类:RandomccessFile

RandomAccessFile是用来访问那些保存数据记录的文件的,你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。但是该类仅限于操作文件。

RandomAccessFile不属于InputStream和OutputStream类系的。实际上,除了实现DataInput和DataOutput接口之外(DataInputStream和DataOutputStream也实现了这两个接口),它和这两个类系毫不相干,甚至不使用InputStream和OutputStream类中已经存在的任何功能;它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是从零开始写的。这可能是因为RandomAccessFile能在文件里面前后移动,所以它的行为与其它的I/O类有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。

基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream结合起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )、skipBytes()跳过多少字节数。此外,它的构造函数还要一个表示以只读方式(“r”),还是以读写方式(“rw”)打开文件的参数 (和C的fopen( )一模一样)。它不支持只写文件。

只有RandomAccessFile才有seek搜寻方法,而这个方法也只适用于文件。BufferedInputStream有一个mark( )方法,你可以用它来设定标记(把结果保存在一个内部变量里),然后再调用reset( )返回这个位置,但是它的功能太弱了,而且也不怎么实用。

RandomAccessFile的绝大多数功能,但不是全部,已经被JDK 1.4的nio的”内存映射文件(memory-mapped files)”给取代了,你该考虑一下是不是用”内存映射文件”来代替RandomAccessFile了。


public static void main(String[] args) throws IOException {          RandomAccessFile rf = new RandomAccessFile("rtest.dat", "rw");          for (int i = 0; i < 10; i++) {              //写入基本类型double数据              rf.writeDouble(i * 1.414);          }          rf.close();          rf = new RandomAccessFile("rtest.dat", "rw");          //直接将文件指针移到第5个double数据后面          rf.seek(5 * 8);  //寻址        //覆盖第6个double数据          rf.writeDouble(47.0001);          rf.close();          rf = new RandomAccessFile("rtest.dat", "r");          for (int i = 0; i < 10; i++) {              System.out.println("Value " + i + ": " + rf.readDouble());          }          rf.close();      }  

RandomAccessFile类的应用

public class RandomAccessFileDemo {   public static void main(String[] args) throws Exception {    RandomAccessFile file = new RandomAccessFile("file", "rw");    // 以下向file文件中写数据    file.writeInt(20);// 占4个字节    file.writeDouble(8.236598);// 占8个字节    file.writeUTF("这是一个UTF字符串");// 这个长度写在当前文件指针的前两个字节处,可用readShort()读取    file.writeBoolean(true);// 占1个字节    file.writeShort(395);// 占2个字节    file.writeLong(2325451l);// 占8个字节    file.writeUTF("又是一个UTF字符串");    file.writeFloat(35.5f);// 占4个字节    file.writeChar('a');// 占2个字节    file.seek(0);// 把文件指针位置设置到文件起始处    // 以下从file文件中读数据,要注意文件指针的位置    System.out.println("——————从file文件指定位置读数据——————");    System.out.println(file.readInt());    System.out.println(file.readDouble());    System.out.println(file.readUTF());    file.skipBytes(3);// 将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。    System.out.println(file.readLong());    file.skipBytes(file.readShort()); // 跳过文件中“又是一个UTF字符串”所占字节,注意readShort()方法会移动文件指针,所以不用加2。    System.out.println(file.readFloat());    //以下演示文件复制操作    System.out.println("——————文件复制(从file到fileCopy)——————");    file.seek(0);    RandomAccessFile fileCopy=new RandomAccessFile("fileCopy","rw");    int len=(int)file.length();//取得文件长度(字节数)    byte[] b=new byte[len];    file.readFully(b);    fileCopy.write(b);    System.out.println("复制完成!");   }  }  

利用RandomAccessFile实现文件的多线程下载

即多线程下载一个文件时,将文件分成几块,每块用不同的线程进行下载。下面是一个利用多线程在写文件时的例子,其中预先分配文件所需要的空间,然后在所分配的空间中进行分块,然后写入:

public static void main(String[] args) throws Exception {          // 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件          RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw");          raf.setLength(1024*1024); // 预分配 1M 的文件空间          raf.close();          // 所要写入的文件内容          String s1 = "第一个字符串";          String s2 = "第二个字符串";          String s3 = "第三个字符串";          String s4 = "第四个字符串";          String s5 = "第五个字符串";          // 利用多线程同时写入一个文件          new FileWriteThread(1024*1,s1.getBytes()).start(); // 从文件的1024字节之后开始写入数据          new FileWriteThread(1024*2,s2.getBytes()).start(); // 从文件的2048字节之后开始写入数据          new FileWriteThread(1024*3,s3.getBytes()).start(); // 从文件的3072字节之后开始写入数据          new FileWriteThread(1024*4,s4.getBytes()).start(); // 从文件的4096字节之后开始写入数据          new FileWriteThread(1024*5,s5.getBytes()).start(); // 从文件的5120字节之后开始写入数据      }      // 利用线程在文件的指定位置写入指定数据      static class FileWriteThread extends Thread{          private int skip;          private byte[] content;          public FileWriteThread(int skip,byte[] content){              this.skip = skip;              this.content = content;          }          public void run(){              RandomAccessFile raf = null;              try {                  raf = new RandomAccessFile("D://abc.txt", "rw");                  raf.seek(skip);                  raf.write(content);              } catch (FileNotFoundException e) {                  e.printStackTrace();              } catch (IOException e) {                  // TODO Auto-generated catch block                  e.printStackTrace();              } finally {                  try {                      raf.close();                  } catch (Exception e) {                  }              }          }      }  

I/O流对 典型使用方式

尽管可以通过不同的方式组合I/O流泪,但可能也就只用到其中的几种组合。下面的例子可以作为典型的I/O流用法的基本参考,这些示例中异常处理简化为简单的抛出。

缓冲输入文件

如果想要打开一个文件用于字符输入,可以使用以String或File对象作为文件名的FileInputReader,为了提高速度,对那个文件进行缓冲,可将产生的引用传给一个BufferedReader构造器。当readLine()返回null时,就达到了文件的末尾。

public class BufferedInputFile {      public static String read(String filename) throws IOException {          BufferedReader in = new BufferedReader(new FileReader(filename));          String s;          StringBuilder sb = new StringBuilder();          while ((s = in.readLine()) != null) {              sb.append(s+"\n");          }          in.close();          return sb.toString();      }      public static void main(String[] args) throws IOException {          System.out.print(read("BufferedInputFile.java"));      }  }  //字符串sb用来累积文件的全部内容(包括必须添加的换行符,因为readLine()已将它们删除),最后调用close()关闭文件。

从内存输入

public static void main(String[] args) throws IOException {          StringReader in = new StringReader(read("MemoryInput.java"));          int c;          while ((c = in.read()) != -1)              System.out.print((char) c);      }      public static String read(String filename) throws IOException {          BufferedReader in = new BufferedReader(new FileReader(filename));          String s;          StringBuilder sb = new StringBuilder();          while ((s = in.readLine()) != null) {              sb.append(s + "\n");          }          in.close();          return sb.toString();      }      //read()是以int形式返回一下字节,因此必须类型转换为char才能正确打印

格式化的内存输入

要读取格式化数据,可以使用DataInputStream,它是一个面向字节的I/O类,因此必须使用InputStream类而不是Reader类。当然,可以用InputStream以字节形式读取任何数据(例如一个文件),不过这里使用的是字符串。

public static String read(String filename) throws IOException {        BufferedReader in = new BufferedReader(new FileReader(filename));        String s;        StringBuilder sb = new StringBuilder();        while ((s = in.readLine()) != null) {            sb.append(s + "\n");        }        in.close();        return sb.toString();    }    public static void main(String[] args) throws IOException {        try {            DataInputStream in = new DataInputStream(new ByteArrayInputStream(read("writertest.txt").getBytes()));            while (true) {                System.out.print((char) in.readByte());            }        } catch (EOFException e) {            System.err.println("End of stream");        }    }

如果从DataInputStream用readByte()一次一个字节地读取字符,那么任何字节的值都是合法的结果,因此返回值不能用来检测输入是否结束。相反可以使用available()方法查看还有多少个可供存取的字符。下面的例子演示了怎样一次一个字节地读取文件:

public static String read(String filename) throws IOException {        BufferedReader in = new BufferedReader(new FileReader(filename));        String s;        StringBuilder sb = new StringBuilder();        while ((s = in.readLine()) != null) {            sb.append(s + "\n");        }        in.close();        return sb.toString();    }    public static void main(String[] args) throws IOException {        try {            DataInputStream in = new DataInputStream(new ByteArrayInputStream(read("writertest.txt").getBytes()));            while (in.available() != 0) {//这里判断是重要的地方                System.out.print((char) in.readByte());            }        } catch (EOFException e) {            System.err.println("End of stream");        }    }
  • 注意,available()的工作方式会随着所读取的媒介的类型的不同而有所不同;字面意思就是“在没有阻塞的情况下所能读取的字节数”。对应文件,这意味着整个文件,但是对于不同类型的流,可能就不是这样的,因此要谨慎使用。

基本的文件输出

FileWriter对象可以向文件写入数据。首先,创建一个与指定文件连接的FileWriter,实际上通常会用BufferedWriter将其包装起来用以缓冲输出,本例中为了提供格式化机制,它被装饰成PrintWriter。按照这种方式创建的数据文件可作为普通文本文件读取。

public static String read(String filename) throws IOException {          BufferedReader in = new BufferedReader(new FileReader(filename));          String s;          StringBuilder sb = new StringBuilder();          while ((s = in.readLine()) != null) {              sb.append(s + "\n");          }          in.close();          return sb.toString();      }      static String file = "BasicFileOutput.out";      public static void main(String[] args) throws IOException {          BufferedReader in = new BufferedReader(new StringReader(read("BasicFileOutput.java")));          PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));          int lineCount = 1;          String s;          while ((s = in.readLine()) != null) {              out.println(lineCount++ + ": "+s);          }          out.close();          System.out.println(read(file));      }  

Java SE5在PrintWriter中添加了一个辅助构造器,使得不必每次希望创建文本文件并向其中写入时,都去执行所有的装饰工作,如下例所示:

public static String read(String filename) throws IOException {          BufferedReader in = new BufferedReader(new FileReader(filename));          String s;          StringBuilder sb = new StringBuilder();          while ((s = in.readLine()) != null) {              sb.append(s + "\n");          }          in.close();          return sb.toString();      }      static String file = "FileOutputShortcut.out";      public static void main(String[] args) throws IOException {          BufferedReader in = new BufferedReader(new StringReader(read("FileOutputShortcut.java")));          // Here's the shortcut:          PrintWriter out = new PrintWriter(file);          int lineCount = 1;          String s;          while ((s = in.readLine()) != null)              out.println(lineCount++ + ": " + s);          out.close();          // Show the stored file:          System.out.println(BufferedInputFile.read(file));      }  

存储和恢复数据

PrintWriter可以对数据进行格式化,以便人们阅读。但是为了输出可供另一个“流”恢复的数据,需要用DataOutputStream写入数据,并用DataInputStream恢复数据。注意DataOutputStream和DataInputStream是面向字节的,因此要使用InputStream和OutputStream。

public static void main(String[] args) throws IOException {          DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("Data.txt")));          out.writeDouble(3.1415926);          out.writeUTF("That was pi");          out.writeDouble(1.41413);          out.writeUTF("Square root of 2");          out.close();          DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("Data.txt")));          System.out.println(in.readDouble());          System.out.println(in.readUTF());          System.out.println(in.readDouble());          System.out.println(in.readUTF());      }  

文件读写实用工具

public class TextFile extends ArrayList<String> {      /**      * Read a file as a single string        * @param fileName      * @return      * @throws IOException       */      public static String read(String fileName) throws IOException {          StringBuilder sb = new StringBuilder();          BufferedReader in = new BufferedReader(new FileReader(new File(fileName).getAbsoluteFile()));          try {              String s;              while ((s = in.readLine()) != null) {                  sb.append(s);                  sb.append("\n");              }          } finally {              in.close();          }          return sb.toString();      }      /**      * Write a single file       * @param fileName      * @param text      * @throws IOException      */      public static void write(String fileName,String text) throws IOException {          PrintWriter out = new PrintWriter(new File(fileName).getAbsoluteFile());          try{              out.print(text);          } finally{              out.close();          }      }      /**      * Read a file ,split by any regular expression      * @param fileName      * @param splitter      * @throws IOException      */      public TextFile(String fileName,String splitter) throws IOException{          super(Arrays.asList(read(fileName).split(splitter)));          if (get(0).equals("")) {              remove(0);          }      }      public TextFile(String fileName) throws IOException{          this(fileName, "\n");      }      public void write(String fileName) throws IOException {          PrintWriter out = new PrintWriter(new File(fileName).getAbsoluteFile());          try{              for (String item:this) {                  out.println(item);              }          } finally{              out.close();          }      }      /**      *       * @param args      * @throws IOException       */      public static void main(String[] args) throws IOException {          String fileName = "TextFile.java";          String file = read(fileName);          write("test.txt", file);          TextFile text = new TextFile("test.txt");          text.write("test2.txt");          TreeSet<String> words = new TreeSet<String>(new TextFile(fileName, "\\W+"));          System.out.println(words.headSet("a"));          //下面代码可以统计文档里各个字母出现的次数          TextFile text2 = new TextFile(fileName,"\\W+");          Map<Character, Integer> charsStat = new HashMap<Character, Integer>();          for (String word:text2) {              for (int i = 0; i < word.length(); i++) {                  Character ch = word.charAt(i);                  Integer freq = charsStat.get(ch);                  charsStat.put(ch, freq == null ? 1:freq+1);              }          }          List<Character> keys = Arrays.asList(charsStat.keySet().toArray(new Character[0]));          Collections.sort(keys);          for (Character key:keys) {              System.out.println(key +" =>"+charsStat.get(key));          }      }  }  

读取二进制文件

public class BinaryFile {    public static byte[] read(File bFile) throws IOException{      BufferedInputStream bf = new BufferedInputStream(        new FileInputStream(bFile));      try {        byte[] data = new byte[bf.available()];        bf.read(data);        return data;      } finally {        bf.close();      }    }    public static byte[]    read(String bFile) throws IOException {      return read(new File(bFile).getAbsoluteFile());    }  }  

标准I/O

在Java的类库java.lang中我们经常用到System类的System.in,,System.out这种控制台输入输出,这就是所谓的标准流。

标准I/0的使用

System.in的使用

如果单纯的直接对System.in操作来接受控制台的输入,我们能做到的太少,因此我们要接受控制台的输入我们需要对它进行包装,其中一种包装方式就是用其他的方式进行包装

        BufferedReader buf=new BufferedReader(new InputStreamReader(System.in));          String s=buf.readLine();          System.out.println(s);          //或者使用Scanner        Scanner in=new Scanner(System.in);          int tt=in.nextInt();          System.out.println(tt); 

System.out和System.err的使用

控制台输出字体颜色格式不一样


重定向

标准I/O默认的是控制台输入输出,那么我们可以将他们修改,这就是重定向,对于重定向System有3种方法,分别是setIn(InputStream),setOut(PintStream),setErr(PrintStream)。我们可以将他们重定向到文件里,这就实现了我们常见的日志系统

        InputStream in = new BufferedInputStream(new FileInputStream(new File(                    "c:/in.txt")));            System.setIn(in);            PrintStream out = new PrintStream(new FileOutputStream(new File(                    "c:/out.log")));            System.setOut(out);            PrintStream err = new PrintStream(new FileOutputStream(new File(                    "c:/err.log")));            System.setErr(err);    

进程控制

你经常会需要在java内部执行其它操作系统程序,并且要控制这此程序的输入和输出,java类库提供了执行这些操作的类 , 为了捕获程序执行时产生的标准输出流,你需要调用getInputStream(),这是因为。是我们可以从中读取信息的流。

            BufferedReader br=new BufferedReader(                      new InputStreamReader(                              process.getInputStream()  //捕获输入流                            ));              String s;              while((s=br.readLine())!=null)                  System.out.println(s);              //捕获错误流              BufferedReader b2=new BufferedReader(                      new InputStreamReader(                              process.getErrorStream()                              ));              while((s=b2.readLine())!=null)              {                  System.err.println("sssssssss:"+s);              }  

参考:
1. java 编程思想第四版
2. http://blog.csdn.net/akon_vm/article/details/7429245
3. http://blog.csdn.net/zhoupenglei/article/details/46312491

0 0