Java的IO总结

非流式文件类--File类

  从定义看,File类是Object的直接子类,同时它继承了Comparable接口可以进行数组的排序。

File类的操作包括文件的创建、删除、重命名、得到路径、创建时间等,以下是文件操作常用的函数。

 

 

File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。 

File类共提供了三个不同的构造函数,以不同的参数形式灵活地接收文件和目录名信息。

构造函数:
1)File (String   pathname)   
     例:File  f1=new File("FileTest1.txt"); //创建文件对象f1,f1所指的文件是在当前目录下创建的FileTest1.txt
2)File (String  parent  ,  String child)
     例:File f2=new  File(“D:\\dir1","FileTest2.txt") ;//  注意:D:\\dir1目录事先必须存在,否则异常
3)File (File    parent  , String child)
     例:File  f4=new File("\\dir3");
          File  f5=new File(f4,"FileTest5.txt");  //在如果 \\dir3目录不存在使用f4.mkdir()先创建

        一个对应于某磁盘文件或目录的File对象一经创建, 就可以通过调用它的方法来获得文件或目录的属性。    
       1)public boolean exists( ) 判断文件或目录是否存在
       2)public boolean isFile( ) 判断是文件还是目录 
       3)public boolean isDirectory( ) 判断是文件还是目录
       4)public String getName( ) 返回文件名或目录名
       5)public String getPath( ) 返回文件或目录的路径。
       6)public long length( ) 获取文件的长度 
       7)public String[ ] list ( ) 将目录中所有文件名保存在字符串数组中返回。 
       File类中还定义了一些对文件或目录进行管理、操作的方法,常用的方法有:
       1) public boolean renameTo( File newFile );    重命名文件
       2) public void delete( );   删除文件
       3)  public boolean mkdir( ); 创建目录

流简单概念介绍

在Java程序中,对于数据的输入/输出操作以"流" (stream) 方式进行;
J2SDK提供了各种各样的"流"类,用以获取不同种类的数据;程序中通过标准的方法输入或输出数据。
Java的流类型一般位于java.io包中


流的方向:
输入流:数据源到程序(InputStream、Reader读进来)
输出流:程序到目的地(OutPutStream、Writer写出去)


处理数据单元:
字节流:按照字节读取数据(InputStream、OutputStream)
字符流:按照字符读取数据(Reader、Writer)


功能不同:
节点流:可以直接从数据源或目的地读写数据。
处理流(包装流):不直接连接到数据源或目的地,是其他流进行封装。目的主要是简化操作和提高性能.


节点流和处理流的关系:
节点流处于io操作的第一线,所有操作必须通过他们进行;
处理流可以对其他流进行处理(提高效率或操作灵活性).

字节流基类

1).InputStream

InputStream:字节输入流基类,抽象类是表示字节输入流的所有类的超类。

 常用方法:

    // 从输入流中读取数据的下一个字节
    abstract int read()
    // 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中
    int read(byte[] b)
    // 将输入流中最多 len 个数据字节读入 byte 数组
    int read(byte[] b, int off, int len)


    // 跳过和丢弃此输入流中数据的 n个字节
    long skip(long n)

    // 关闭此输入流并释放与该流关联的所有系统资源
    void close()

2).OutputStream

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

 常用方法:
    // 将 b.length 个字节从指定的 byte 数组写入此输出流
    void write(byte[] b)
    // 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流
    void write(byte[] b, int off, int len)
    // 将指定的字节写入此输出流
    abstract void write(int b)

    // 关闭此输出流并释放与此流有关的所有系统资源
    void close()

    // 刷新此输出流并强制写出所有缓冲的输出字节
    void flush()

字节流FileInputStream和FileOuputStream

介绍

1).FileInputStream

FileInputStream:字节文件输入流,从文件系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节流。

 构造方法:
    // 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定
    FileInputStream(File file)
    // 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径name指定
    FileInputStream(String name)

 常用方法:覆盖和重写了父类的的常用方法。

2).FileOutputStream

FileOutputStream:字节文件输出流是用于将数据写入到File,从程序中写入到其他位置。

 构造方法:
    // 创建一个向指定File对象表示的文件中写入数据的文件输出流
    FileOutputStream(File file)
    // 创建一个向指定File对象表示的文件中写入数据的文件输出流
    FileOutputStream(File file, boolean append)
    // 创建一个向具有指定名称的文件中写入数据的输出文件流
    FileOutputStream(String name)
    // 创建一个向具有指定name的文件中写入数据的输出文件流
    FileOutputStream(String name, boolean append)

 常用方法:覆盖和重写了父类的的常用方法。

文件复制

(熟悉操作):

/**
* 功能:文件复制
* 技能:FileInputStream和FileOuputStream
*
* 总结
* 如何创建流
*  InputStream is = new FileInputStream(new File("e:/readme.txt"));
*  OutputStream os = new FileOutputStream(new File("e:\\readme2.txt"));
*
*
* 流使用完毕一定要关闭
*
* 如何使用流
*   n = is.read();
*   os.write(n);
*        
* 缺点:
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //创建一个输入流和输出流
//                File file = new File("e:/readme.txt");
//                InputStream is = new FileInputStream(file);
               InputStream is = new FileInputStream(new File("e:/readme.txt"));
//                File file2 = new File("e:\readme2.txt");
//                OutputStream os = new FileOutputStream(file2);
               OutputStream os = new FileOutputStream(new File("e:\\readme2.txt"));
               
               //使用输入流和输出流完成文件复制
               int n;//中转站,比较小(水杯)
               
               //读一个字节
               n = is.read();//从输入流读取一个字节的内容赋给n
               while(n != -1){//没有到达末尾
                       //写一个字节
                       os.write(n);
                       //输出一个字节
                       //System.out.print((char)n);
                       
                       //读一个字节
                       n = is.read();
               }        
               
               //关闭输入流和输出流
               is.close();
               os.close();

       }

}

正式标准实现:(一次1024)

/**
* 功能:文件复制
* 技能:FileInputStream和FileOuputStream
*
* 总结
* 如何创建流
*  InputStream is = new FileInputStream(new File("e:/readme.txt"));
*  OutputStream os = new FileOutputStream(new File("e:\\readme2.txt"));
*
*
* 流使用完毕一定要关闭
*
* 如何使用流
*   n = is.read();
*         os.write(n);
*        
* 缺点:中转站太小
*
* @author Administrator
*
*/
public class TestCopy2 {

       public static void main(String[] args) throws IOException {
               //创建输入流和输出流
               InputStream fis = new FileInputStream("e:/JDK_API_1_6_zh_CN.CHM");
               OutputStream fos = new FileOutputStream("e:/JDK_API_1_6_zh_CN2.CHM");
               //使用输入流和输出流
               byte [] buf = new byte[1024];
               //读一次
               int len = fis.read(buf);//将源文件的内容写入到buf中,返回真实读取的字节数
               while(len != -1){
                       //写一次
                       //fos.write(buf);//写1024
                       fos.write(buf, 0, len);
                       //读一次
                       len = fis.read(buf);
               }
               
               
               //关闭输入流和输出流
               fis.close();
               fos.close();
       }

}

 

字符流Reader和Writer

字符流基类

1).Reader

Reader:读取字符流的抽象类.

  常用方法:
    // 读取单个字符
    int read()
    // 将字符读入数组
    int read(char[] cbuf)
    // 将字符读入数组的某一部分
    abstract int read(char[] cbuf, int off, int len)
    // 跳过字符
    long skip(long n)

    // 关闭该流并释放与之关联的所有资源
    abstract void close()

2).Writer

Writer:写入字符流的抽象类.

 常用方法:
    // 写入字符数组
     void write(char[] cbuf)
    // 写入字符数组的某一部分
    abstract void write(char[] cbuf, int off, int len)
    // 写入单个字符
    void write(int c)
    // 写入字符串
    void write(String str)
    // 写入字符串的某一部分
    void write(String str, int off, int len)

    // 将指定字符添加到此 writer
    Writer append(char c)
    // 将指定字符序列添加到此 writer
    Writer append(CharSequence csq)
    // 将指定字符序列的子序列添加到此 writer.Appendable
    Writer append(CharSequence csq, int start, int end)

    // 关闭此流,但要先刷新它
    abstract void close()
    // 刷新该流的缓冲
    abstract void flush()

文件复制:

熟悉操作     

/**
*
* 1.字节流可以读写任何文件(文本文件、二进制文件(音频视频图片 chm))
*         字符流只可以读写文本文件(word不是文本文件)
*   但是字符串处理非英文字符文本文件非常方便
*  
* 2.其实只有字节流,没有字符流
*         字符流底层使用的还是字节流
*                Java在字节流基础上提供了字符流,给编程带来便利
*
* 3.字符流如何是英文字符还是中文字符
*                英文占一个字节,最高位是0   0111 0011
*                中文占两个字节,最高位是1   1011 1011 1001 1101
*
* 4.缺陷:没有进行异常处理
*
*
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //创建输入流和输出流
               Reader fr = new FileReader(new File("e:/readme.txt"));
               Writer fw = new FileWriter(new File("e:\\readme2.txt"));//默认是false 覆盖
               //Writer fw = new FileWriter(new File("e:\\readme2.txt"), true);
               //使用输入流和输出流
//                //读一个字符
//                int ch = fr.read();        //中转站是一个字符
//                while(ch !=-1){
//                        //写一个字符
//                        fw.write(ch);
//                        //输出
//                        System.out.println((char)ch);
//                        //读一个字符
//                        ch = fr.read();        
//                }        
               
               char cbuf [] = new char[1024];
               //读一次
               int len = fr.read(cbuf);//将读取的内容放入cbuf数组,返回的是真正读取的字符个数
               while(len != -1){
                       //写一次
                       //fw.write(cbuf);
                       fw.write(cbuf, 0, len);
                       //读一次
                       len = fr.read(cbuf);                        
               }                
               //关闭输入流和输出流
               fr.close();
               fw.close();
       }

}

加上缺陷处理完整版:

/**
*
* 1.字节流可以读写任何文件(文本文件、二进制文件(音频视频图片 chm))
*         字符流只可以读写文本文件(word不是文本文件)
*   但是字符串处理非英文字符文本文件非常方便
*  
* 2.其实只有字节流,没有字符流
*         字符流底层使用的还是字节流
*                Java在字节流基础上提供了字符流,给编程带来便利
*
* 3.字符流如何是英文字符还是中文字符
*                英文占一个字节,最高位是0   0111 0011
*                中文占两个字节,最高位是1   1011 1011 1001 1101
*
* 4.缺陷:没有进行异常处理
*
*
* @author Administrator
*
*/
public class TestCopy2 {

       public static void main(String[] args){
               
               Reader fr = null;
               Writer fw = null;
               try {
                       //创建输入流和输出流
                       fr = new FileReader(new File("e:/readme.txt"));
                       fw = new FileWriter(new File("e:\\readme2.txt"));//默认是false 覆盖

                       
                       char cbuf [] = new char[1024];
                       //读一次
                       int len = fr.read(cbuf);//将读取的内容放入cbuf数组,返回的是真正读取的字符个数
                       while(len != -1){
                               //写一次
                               //fw.write(cbuf);
                               fw.write(cbuf, 0, len);
                               //读一次
                               len = fr.read(cbuf);                        
                       }
               } catch (FileNotFoundException e) {
                       e.printStackTrace();
               } catch (IOException e) {
                       e.printStackTrace();
               }finally{
                       //关闭输入流和输出流
                       try {
                               if(fr != null){
                                       fr.close();
                               }                                
                       } catch (IOException e) {
                               e.printStackTrace();
                       }
                       
                       try {
                               if(fw != null){
                                       fw.close();
                               }                                
                       } catch (IOException e) {
                               e.printStackTrace();
                       }
                       
               }
       }

}

缓冲字节流BufferedInputStream和BufferedOuputStream

介绍

BufferedInputStream

字节缓冲输入流,提高了读取效率。

     构造方法:
     // 创建一个 BufferedInputStream并保存其参数,即输入流in,以便将来使用。
     BufferedInputStream(InputStream in)
     // 创建具有指定缓冲区大小的 BufferedInputStream并保存其参数,即输入流in以便将来使用
     BufferedInputStream(InputStream in, int size)

.BufferedOutputStream

字节缓冲输出流,提高了写出效率。

     构造方法:
     // 创建一个新的缓冲输出流,以将数据写入指定的底层输出流
     BufferedOutputStream(OutputStream out)
     // 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
     BufferedOutputStream(OutputStream out, int size)

     常用方法:
     // 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流
     void write(byte[] b, int off, int len)
     // 将指定的字节写入此缓冲的输出流
     void write(int b)
     // 刷新此缓冲的输出流
     void flush()

文件复制

/**
* 功能:文件复制
* 技能:BufferedInputStream和BufferedOuputStream
*
*
* 1.节点流和处理流
*        节点流   FileInputStream  FileOutputStream
*   处理流  BufferedInputStream  BufferedOutputStream
*  
* 2.处理流的好处
*        好处1:提供了性能
*
*
* 3.如何创建处理流
*                BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM")));
               BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM")));
               

* 4.关闭流:只要关闭高层流即可,底层流可以不关闭
*        关闭高层流的会关闭底层流
*
*
* 5.何时将输出缓冲区的内容更新到文件中(刷新 flush)
*
*        1.缓冲区满了,自动刷新
*  2.关闭输出流时,会先刷新再关闭
*  3.不满的时候也可以手动刷新  
*     bos.flush();
*
*
*   public void close() throws IOException {
       try {
         flush();//刷新缓冲区
       } catch (IOException ignored) {
       }
       out.close(); //关闭底层流
   }
*
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //创建一个输入流和输出流
//                InputStream is = new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM"));
//                OutputStream os = new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM"));
//                BufferedInputStream bis = new BufferedInputStream(is);//默认输入缓冲区大小8192
//                BufferedOutputStream bos = new BufferedOutputStream(os);//默认输出缓冲区大小8192
               
               BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("e:/JDK_API_1_6_zh_CN.CHM")));
               BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("e:\\JDK_API_1_6_zh_CN2.CHM")));
               
               //使用输入流和输出流完成文件复制
               int n;//中转站,比较小(水杯)
               
               //读一个字节
               n = bis.read();//从输入流读取一个字节的内容赋给n
               while(n != -1){//没有到达末尾
                       //写一个字节
                       bos.write(n);
                                               
                       //读一个字节
                       n = bis.read();
               }        
               
               
               //关闭输入流和输出流
               bis.close();
               bos.close();

       }

}

缓冲字符流BufferedReader和BufferedWriter

 

1).BufferedReader

BufferedReader:字符缓冲流,从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。

 构造方法:
    // 创建一个使用默认大小输入缓冲区的缓冲字符输入流
    BufferedReader(Reader in)
    // 创建一个使用指定大小输入缓冲区的缓冲字符输入流
    BufferedReader(Reader in, int sz)
 特有方法:
    // 读取一个文本行
    String readLine()

2).BufferedWriter

BufferedWriter:字符缓冲流,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

 构造方法:
    // 创建一个使用默认大小输出缓冲区的缓冲字符输出流
    BufferedWriter(Writer out)
    // 创建一个使用给定大小输出缓冲区的新缓冲字符输出流
    BufferedWriter(Writer out, int sz)
 特有方法:
    // 写入一个行分隔符
    void newLine() 

 

文件复制

/**
* 按行读取文件并复制
*
* 只要文本文件才有行的概念  字符流
* 提高速度:缓冲流
* BufferedReader和BufferedWriter
*
*
*
* 1.处理流的好处
*        1.提高性能
*  2.简化操作
*  
* 2.readLine的实现原理
*        底层还是按照字符一个个读取, 由于采用了缓冲区,性能是提高
*  基本思路:
        *  StringBuilder  builder = new StringBuilder("");
        *   ch = br.read();
        *  while(读取的这个字符是换行符的时候){
        *          builder.append(ch);
        *          ch = br.read();
        *  }
        *  return builder.toString();
*
* 3.bw.newLine(); 不同的操作系统,换行符不同
*        (1)在微软的MS-DOS和Windows中,使用"回车CR('\r')"和"换行LF('\n')"两个字符作为换行符;
            Windows系统里面,每行结尾是 回车+换行(CR+LF),即"\r\n";
       (2)Unix系统里,每行结尾只有 换行CR,即"\n";
       (3)Mac系统里,每行结尾是 回车CR 即'\r'。
*  
*  *
* @author Administrator
*
*/
public class TestCopy2 {

       public static void main(String[] args) throws IOException {
               //创建输入流和输出流
//                Reader fr = new FileReader(new File("e:/java基础题目以及答案1.txt"));
//                BufferedReader br = new BufferedReader(fr);
//                Writer fw = new FileWriter(new File("e:/java基础题目以及答案2.txt"));
//                BufferedWriter bw = new BufferedWriter(fw);
               BufferedReader br = new BufferedReader(new FileReader(new File("e:/java基础题目以及答案1.txt")));
               BufferedWriter bw = new BufferedWriter(new FileWriter(new File("e:/java基础题目以及答案2.txt")));
               
               //使用输入流和输出流
               //读一行
               String str = br.readLine();
               while(str != null){
                       //写一行
                       bw.write(str);
                       bw.newLine();//换一行
                       //读一行
                       str = br.readLine();
               }                
               
               //关闭输入流和输出流                
               br.close();
               bw.close();

       }

}

字符转换流

何时使用转换流?

1.    当字节和字符之间有转换动作时;

2.    流操作的数据需要编码或解码时。

 

1).InputStreamReader

InputStreamReader:字节流转字符流,它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

 构造方法:
    // 创建一个使用默认字符集的 InputStreamReader
    InputStreamReader(InputStream in)
    // 创建使用给定字符集的 InputStreamReader
    InputStreamReader(InputStream in, Charset cs)
    // 创建使用给定字符集解码器的 InputStreamReader
    InputStreamReader(InputStream in, CharsetDecoder dec)
    // 创建使用指定字符集的 InputStreamReader
    InputStreamReader(InputStream in, String charsetName)
 特有方法:
    //返回此流使用的字符编码的名称 
    String getEncoding() 
/**
*
*
* 功能:将从键盘输入的一行行数据复制到另外一个文件中
*
* 1.转换流
*   InputStreamReader  将InputStream转换成Reader
*   OutputStreamWriter 将OutputStream转换成Writer
*   ReaderInputStream  这个真没有
*   WriterOutputStream  这个也没有
*  
*  
* 2.InputStreamReader到底是个InputStream还是一个Reader
*   Reader reader = new InputStreamReader(is);
*        
*        public class InputStreamReader extends Reader
*
* 3.转换流使用了一个设计模式:适配器(转换器)模式
*  
*   手机耳机口(大口)------------(大头)转换头(小口)------ 耳机(小头)
*
*   Reader(readLine()) ------------   (Reader)转换流InputStreamReader(InputStream)  ---------  InputStream(System.in)
*  

*
*
*
* @author Administrator
*
*/
public class TestCopy1 {

       public static void main(String[] args) throws IOException {
               //创建输入流和输出流
               //Reader reader = new FileReader(new File("e:/java基础题目以及答案1.txt"));
//                InputStream is = System.in;
//                Reader reader = new InputStreamReader(is);
//                BufferedReader br = new BufferedReader(reader);
               Scanner input = new Scanner(System.in);
               BufferedWriter bw = new BufferedWriter(new FileWriter(new File("e:/java.txt")));
               
               //使用输入流和输出流
               //读一行
       //        String str = br.readLine();
               String str = input.next();
               while(!"bye".equals(str)){ //"null"
                       //写一行
                       bw.write(str);
                       bw.newLine();//换一行
                       //读一行
                       //str = br.readLine();
                       str = input.next();
               }                
               
               //关闭输入流和输出流                
               //br.close();
               input.close();
               bw.close();

       }

}

 

2).OutputStreamWriter

OutputStreamWriter:字节流转字符流。

 构造方法:
    // 创建使用默认字符编码的 OutputStreamWriter
    OutputStreamWriter(OutputStream out)
    // 创建使用给定字符集的 OutputStreamWriter
    OutputStreamWriter(OutputStream out, Charset cs)
    // 创建使用给定字符集编码器的 OutputStreamWriter
    OutputStreamWriter(OutputStream out, CharsetEncoder enc)
    // 创建使用指定字符集的 OutputStreamWriter
    OutputStreamWriter(OutputStream out, String charsetName)
 特有方法:
    //返回此流使用的字符编码的名称 
    String getEncoding() 

(3).FileReader、FileWriter

 FileReader:InputStreamReader类的直接子类,用来读取字符文件的便捷类,使用默认字符编码。
 FileWriter:OutputStreamWriter类的直接子类,用来写入字符文件的便捷类,使用默认字符编码。

 性能测试和调优

之前说带缓冲区会快很多,到底是不是这样呢?

我们复制一个MP4文件来测试一下

不带缓冲的用例两秒,这对于一个IO操作来说显然太长了。

我们用带缓冲区的试一下:

可以看到,读取次数一样,时间少了很多。

但是,读取次数还是太多了,我们可以通过扩大byte数组的方式来减少读写次数。

很明显,速度进一步加快。

但是请注意:也不是数组越大越好,视情况而定。

我们确定了数组大小之后,我们还可以设置缓冲区的大小进一步优化时间。

因为我们是从缓冲区读数据,缓冲区从硬盘读数据,形成这个体系可以加快我们的速度。

实际中可以多次调整尝试,确定最优的方案

System类对IO的支持

 针对一些频繁的设备交互,Java语言系统预定了3个可以直接使用的流对象,分别是:

·        System.in(标准输入),通常代表键盘输入。

·        System.out(标准输出):通常写往显示器。

·        System.err(标准错误输出):通常写往显示器。

PrintStream

/**
*
* System.out 是PrintStream类的一个实例
*                public final static PrintStream out = null;
*                                                    Student  stu  = null;
*
* PrintStream 输出流  字节流  处理流
*                打印流只有输出流,没有输入流
*
*
* PrintStream类的方法println() 这个方法功能简直太强大了!!!
*        可以直接讲各种数据类型(基本数据类型、引用数据类型)直接写入到文件中,并且换行。太方便了,太强大了!!
*  不管什么类型,写入到文件中全部变成字符串
*  缺点1: 123#3.14#true#bjsxt  需要使用特殊的字符来区分各个内容,防止混淆
*  缺点2: 123#3.14#true======="123"  "3.14"  "true"  读出来之后都是字符串,还需要将字符串转换成真实类型
*  
*  DataInputStream和DataOutputStream
*
* @author Administrator
*
*/
public class TestPrintStream {

       public static void main(String[] args) throws FileNotFoundException {
               
               //PrintStream ps = System.out;
               PrintStream ps = new PrintStream(new FileOutputStream(new File("e:/bjsxt.txt")));
               ps.println(123);
               ps.println('A');
               ps.println(3.14);
               ps.println(true);
               ps.println("bjsxt");
               ps.println(new Date().toString());
               
               OutputStream os =new FileOutputStream(new File("e:/bjsxt.txt"));
               
               
//                os.write(一个字节);
//                String datestr = new Date().toString();;
//                byte [] buf = datestr.getBytes();
//                os.write(buf);
//                BufferedWriter bw;
//                bw.newLine();

               ps.close();
       }
       
       public void method1(){
               PrintStream ps = System.out;
               ps.println(123);
               ps.println('A');
               ps.println(3.14);
               ps.println(true);
               ps.println("111");
               ps.println(new Date().toString());
               
//                System.out.println(123);
//                System.out.println('A');
//                System.out.println(3.14);
//                System.out.println(true);
//                System.out.println("111");
//                System.out.println(new Date().toString());
       }

}

PrintWriter

/**
*
* 装饰模式
*
*   this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName))),
            false);
*
*  减少了子类的数量,是继承的一种替代方案
*
* @author Administrator
*
*/
public class TestPrintWriter {

       public static void main(String[] args) throws IOException {
               PrintWriter pw1 = new PrintWriter(new FileWriter("e:/bjsxt.txt"));
               
               PrintWriter pw2 = new PrintWriter(new FileOutputStream("e:/bjsxt.txt"));
               
               PrintWriter pw3 = new PrintWriter(new File("e:/bjsxt.txt"));
               
               PrintWriter pw = new PrintWriter("e:/bjsxt.txt");
               pw.println(123);
               pw.println('A');
               pw.println(3.14);
               pw.println(true);
               pw.println("1111t");
               pw.println(new Date().toString());

               
               pw.close();
       }

}

ACM IO 快速读写

输出

第一种使用传统的System.out.println()方式输出。

public class Main {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for(int i=0;i<100000;i++)
            System.out.println(i);
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
    }
}


time=3443ms
显然在ACM中会超时

第二种使用PrintWriter输出:

public class Main {
    public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        for(int i=0;i<100000;i++)
            out.println(i);
        out.flush();
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
        out.close();
    }
}


结果:
time=328ms

虽然每次输出的结果会有大致几十毫秒的偏差,但总体上来看,PrintWriter输出要比用System.out.println()输出快上10倍左右。这个结果就比较让人满意了。

输入

Scanner类读取文件(in.txt,里面有从一到一百万的的整数)

public class Main {
    public static void main(String[] args) throws IOException{
        Scanner sc = new Scanner(new FileInputStream("in.txt"));
        long start = System.currentTimeMillis();
        for(int i=1;i<=1000000;i++)
            sc.nextInt();
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
    }
}


运行结果:

time=2930ms   
大概3秒,实际上如果ACM中真有一百万的数据,若用Scanner读取,还没开始计算,就已经超时了。

用StreamTokenizer读取

public class Main {
    public static StreamTokenizer in;
    static {
        try{
            in = new StreamTokenizer(new BufferedReader(new InputStreamReader(new FileInputStream("in.txt"))));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }
    public static void main(String[] args) throws IOException{
        long start = System.currentTimeMillis();
        for(int i=1;i<=1000000;i++)
            nextInt();    //这里仅读取,不输出
        long end = System.currentTimeMillis();
        System.out.println("time="+(end-start)+"ms");
    }
}

运行结果:

time=397ms
要注意的是,用StreamTokenizer读取字符串时,只能读取纯字母字符串,如果包含数字或者其他字符会返回null。这是用StreamTokenizer读取的缺点。但是用它读取数字时没有问题的。

总结一下:
如果数据量比较小,用Scanner是比较方便的
如果数据量很大的话,那么用StreamTokenizer 是一个很好的选择

最后是模板:

import java.io.*;

public class Main {
    public static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in),32768));
    public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

    public static double nextDouble() throws IOException{ in.nextToken(); return in.nval; }
    public static float nextFloat() throws IOException{ in.nextToken(); return (float)in.nval; }
    public static int nextInt() throws IOException{ in.nextToken(); return (int)in.nval; }
    public static String next() throws IOException{ in.nextToken(); return in.sval;}

    public static void main(String[] args) throws IOException{
//        获取输入
        while(in.nextToken()!=StreamTokenizer.TT_EOF){
            break;
        }
        int x = (int)in.nextToken();  //第一个数据应当通过nextToken()获取
        
        int y = nextInt();
        float f = nextFloat();
        double d = nextDouble();
        String str = next();

//        输出
        out.println("abc");
        out.flush();
        out.close();
    }
}

至此,Java的IO总结完啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章