java之IO流(一)

来源:互联网 发布:企业统一认证 知乎 编辑:程序博客网 时间:2024/06/06 00:31

**IO流java中的IO流按照数据类型分为两种:字节流(用得最多)和字符流(多用于处理文档)。
IO流按流向分为:输入流,输出流。**

字节流的抽象基类:InputStream,OutputStream
字符流的抽象基类:Reader,Writer

1.字符流Writer和Reader

1.1在硬盘上创建一个文件并且写入文字数据

    static void createFileAndWrite(){        try {            //FileWriter是Writer的子类。如果文件不存在会在D盘下创建文件。            Writer writer=new FileWriter("D:/test.txt");            //写入字符串数据            writer.write("zhangsan");            //写入之后,数据是在内存中,必须调用flush()方法刷新,将数据从内存写入文件            writer.flush();            //关闭资源,此方法执行之前,会自动调用flush()方法刷新数据,将内存中的数据写入到文件后再关闭。            writer.close();        } catch (IOException e) {            System.err.println(e.toString());        }    }

在D盘创建文件,还可以写成:

Writer writer=new FileWriter("D:\\test2.txt");

因为“\”在java中表示转义字符,所以用”\”来表示文件层次。

Writer writer=new FileWriter("D:/test2.txt",true);

表示在test2.txt文件后面追加数据,而不会覆盖test2.txt以前就存在的数据。

1.2 FileReader读取硬盘文档上的数据。

1.2.1 read()方法(不常用)

FileReader 的read()方法返回的是所读到字符的ASCII码。如果读到了文件的末尾,则会返回-1.所以以-1作为循环条件。

代码:

    static void readFile(){        try {            Reader reader=new FileReader("D:/test2.txt");            int count=0;            while((count=reader.read())!=-1){                //将ASCII码转化为字符                System.out.print((char)count);            }            reder.close();        } catch (IOException e) {            e.printStackTrace();        }    }
1.2.2 read(char[])方法

FileReader的read(char[])是将文件里面的数据读入到char[]缓冲区里面。返回的是每次读取到的个数。如果已经到文件
末尾,则返回-1.read(char[])方法逐位覆盖char缓冲区里面的数据。每执行一次此方法,都会覆盖掉char缓冲区里面原有的数据。

代码:

    static void readFile2(){        try {            Reader reader=new FileReader("D:/test2.txt");            char[]buf=new char[1024];            int num=0;            while((num=reader.read(buf))!=-1){                System.out.print(new String(buf,0,num));            }                reder.close();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }

1.3复制文件(将文件从一个磁盘复制到另一个磁盘)。

思路:
- 创建写对象和读对象。构造方法为文件路径。
- 创建字符数组作为缓冲区。
- 数据读到缓冲区以后,马上写入指定文件,完成文件复制。
- 关闭资源。

代码:

    static void copyFile(){        FileReader fileReader=null;        FileWriter fileWriter=null;        try {            fileReader=new FileReader("D:/code.java");            fileWriter=new FileWriter("E:/code.java");            //定义缓冲区            char[]buf=new char[1024];            int len=0;            while((len=fileReader.read(buf))!=-1){                fileWriter.write(buf, 0, len);//写入到新文件中                System.out.print(new String(buf,0,len));//数据打印到控制台            }        } catch (IOException e) {            throw new RuntimeException("出错了");        }        //关闭资源        finally{            if(fileReader!=null)                try {                    fileReader.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            if(fileWriter!=null)                try {                    fileWriter.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }        }    }

2.字符流缓冲区

字符流缓冲区对应的类有BufferedWriter和BufferedReader。

缓冲区的出现是为了提高流的操作效率出现的。字符流缓冲区和使用数组作为缓冲区原理基本一致。先将数据读或写到缓冲区(内存)中。当缓冲区满了的时候,在硬盘上进行读写操作。避免了频繁读写硬盘,提高了效率。

因此在创建缓冲区之前,必须先要有流对象。

2.1BufferedWriter向硬盘写数据

代码:

    static void bufferTest1() throws IOException{            //创建FileWriter对象            FileWriter fileWriter=new FileWriter("D:/test.txt");            //创建BufferedWriter对象,以FileWriter对象作为构造参数            BufferedWriter bufferedWriter=new BufferedWriter(fileWriter);            //写一个Hello BufferedWriter就换行            for(int i=0;i<6;i++){                bufferedWriter.write("Hello BufferedWriter"+i);                bufferedWriter.newLine();//换行                bufferedWriter.flush();//必须刷新,将数据从内存写到硬盘上            }            bufferedWriter.close();//关闭资源,关闭之前,会刷新一次。    }

2.1 BufferedReader读硬盘数据

BufferedWriter除了拥有FileReader的两个重载的read方法外,还可以读取一行文本。简化了程序,提高了效率。

readLine()方法读取的是每行的有效数据,并不包含每行结尾处的换行符。
代码:

    static void bufferRead1()throws IOException{        //创建FileReader对象        FileReader fileReader=new FileReader("D:/test.txt");        //创建BufferedReader对象,以FileReader对象作为构造参数        BufferedReader bufferedReader=new BufferedReader(fileReader);        //BufferedReader可以读取一行文本,该方法返回String。如果读到末尾,返回null。        String dataString=null;        while((dataString=bufferedReader.readLine())!=null){            System.out.println(dataString);        }        bufferedReader.close();//读完关闭资源    }

2.3 Buffered实现文本文档拷贝

    static void bufferCopy()throws IOException{        //创建Buffered读写对象        BufferedReader bufferedReader=new BufferedReader(new FileReader("D:/code.java"));        BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("E:/code2.java"));        String dataString=null;        while((dataString=bufferedReader.readLine())!=null){            bufferedWriter.write(dataString);            System.out.println(dataString);            bufferedWriter.newLine();//写完一行,就换行,因为readLine只读取有效数据,不包含换行符            bufferedWriter.flush();//写完一行,就刷新一次        }        //关闭资源。        bufferedReader.close();        bufferedWriter.close();    }

3. 装饰类

新建一个类,将需要装饰的类作为该类的构造方法参数。该类中的方法实现调用装饰类中的方法,但进行加强。
例如BufferedReader类中的readLine()方法就是基于FileReader的read()方法来实现的。
装饰类的构造方法参数里面的一定有被装饰类。

class MyBufferedReader extends Reader{    private FileReader fileReader;    public MyBufferedReader(FileReader fileReader){        this.fileReader=fileReader;    }    public void myReadLine(){        //调用FileReader的read()方法实现具体的readLine方法    }    //...还需要覆盖Reader中的抽象方法,此处省略}

4. 其他

**因为BufferedReader和BufferedWriter对缓冲区进行了封装,不需要char数组,因此使用相比
FileReader和FileWriter方便一些。**

5. 字节流

字节流的抽象基类:InputStream,OutputStream

字节流的缓冲区是字节数组

5.1 字节流写文件

代码:

    static void outputStreamTest1 ()throws IOException{    //会创建一个文件        FileOutputStream outputStream=new FileOutputStream("D:/test2.txt");        String string="锄禾日当午" +"\r\n"+"汗滴禾下土";        outputStream.write(string.getBytes());//必须是字节数组        outputStream.close();    }
5.2 字节流读文件

代码:

    static void inputStreamTest1()throws IOException{        FileInputStream inputStream=new FileInputStream("D:/test2.txt");        byte[] bytes=new byte[1024];//创建字节缓冲区        int len=0;        //如果读到末尾,则返回-1        while((len=inputStream.read(bytes))!=-1){            System.out.println(new String(bytes,0,len));            }        inputStream.close();    }

第二种字节流读文件方式(不建议使用)

代码:

    /**     * 因为缓冲区的大小和文件一样,所以不用循环读数据,直接从缓冲区读数据即可。     * @throws IOException     */    static void inputStreamTest2()throws IOException{        FileInputStream inputStream=new FileInputStream("D:/test2.txt");        //inputStream.available()返回的是文件可读的字节数        byte[] bytes=new byte[inputStream.available()];//创建字节缓冲区,大小等于文件按的大小        inputStream.read(bytes);        System.out.println(new String(bytes));          inputStream.close();    }

如果文件太大,那么创建缓冲区的时候会造成虚拟机内存耗尽,不安全。

5.3 字节流实现文件复制

代码:

    /**     * 和使用字符流复制文档文件操作基本一致:     * 1,创建读和写的字节流对象。     * 2,创建字节缓冲区。     * 3,从数据读到缓冲区里面。     * 4,从缓冲区里将数据写入硬盘。     * @throws IOException     */     static void streamCopyPicture()throws IOException{         FileInputStream inputStream=new FileInputStream("D:/view.jpg");         FileOutputStream outputStream=new FileOutputStream("E:/copy.jpg");         byte[] buffer=new byte[1024];         int len=0;         while((len=inputStream.read(buffer))!=-1){             outputStream.write(buffer,0,len);         }         inputStream.close();         outputStream.close();     }
5.4 字节流缓冲区实现文件拷贝

代码:

     /**      * 字节流缓冲区实现文件拷贝      * @throws IOException      */     static void bufferedCopy()throws IOException{         BufferedInputStream inputStream=new BufferedInputStream(new FileInputStream("D:/view.jpg"));         BufferedOutputStream outputStream=new BufferedOutputStream(new FileOutputStream("E:/copy2.jpg"));         int ch=0;         //inputStream.read()读取到的是一个字节的数据         while((ch=inputStream.read())!=-1){             outputStream.write(ch);         }         inputStream.close();         outputStream.close();     }

用法和字符缓冲区的用法基本一致。不过inputStream.read()读取到的是一个字节。

6.转换流

如果需要指定编码方式,那么就需要用到转换流,转换流可以指定编码方式。

6.1 InputStreamReader

从键盘读取数据,如果输入为over,则结束。

 //转换流InputStreamReader     static void keyboardIn()throws IOException{         //inputStream从键盘录入         InputStream inputStream=System.in;         //InputStreamReader是Reader子类,转化流:将字节流转化为字符流         InputStreamReader reader=new InputStreamReader(inputStream);         //创建字符流缓冲区对象,用这个就不用创建字符数组作为缓冲区了         BufferedReader bufferedReader=new BufferedReader(reader);         String string=null;         //每次只读取一行          while((string=bufferedReader.readLine())!=null){              if(string.equals("over")){                  break;              }              System.out.println(string);          }     }

6.2 OutputStreamWriter

OutputStreamWriter是Writer的子类。

以OutputStream作为构造参数。

模拟控制台输出:

     {          //System.out控制台输出返回OutputStream         OutputStream outputStream=System.out;         //转化流,将字节流转化为字符流         OutputStreamWriter outputStreamWriter=new OutputStreamWriter(outputStream);         //使用bufferd缓冲区         BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);         //写入一个字符串         bufferedWriter.write("zhang san");         //写入一个回车换行         bufferedWriter.newLine();         //关闭资源         bufferedWriter.close();     }

7.打印流

//获取系统信息。Properties properties=System.getProperties();properties.list(new PrintStream("D:/test3.txt"));System.out.println(properties);

8. 文件对象File

8.1 文件分隔符

windows和linux下文件分隔符不同,java提供了跨平台的操作来获取文件分隔符。

String string=File.separator;

8.2 常用方法

1,创建文件

boolean createNewFile(); 在指定位置创建文件,如果文件已经存在,则不创建,返回false。
创建成功,返回true。

File file =new File(“file.txt”);

file.createNewFile();//若创建成功,则返回true。若存在则不创建。
创建文件夹:

File mkdir=new File(“test”);

mkdir.mkdir();创建一个test文件夹(文件目录)。此方法只能创建一级目录。

File mkdirs=new File(“test\movies”);
mkdirs.mkdirs()

创建多级文件夹,test文件夹下还有movies文件夹。

2,删除文件

boolean delete();但是如果文件在进行读写操作,删除失败,返回false。
void deleteOnExit();在程序退出时删除指定文件。
3,判断:

boolean canExecute() ; 文件是否能执行。

canRead():是否可读。

canWrite();是否可写。

boolean exists() ;文件是否存在。

boolean isDirectory() :判断当前 抽象路径File是不是文件夹(目录)

boolean isFile() :判断当前 抽象路径File是不是标准文件。

4.获取信息

String getAbsolutePath() :返回此抽象路径名的绝对路径名形式

long length() :返回由此抽象路径名表示的文件的长度。

String getPath() :将此抽象路径名转换为一个路径名字符串。

boolean renameTo(File dest) :重新命名此抽象路径名表示的文件。

8.3 递归列出指定文件下所有的目录和文件

 //列出指定文件下的文件和文件夹,包含子目录中的内容     static void showDir(File file){        System.out.println(file);        //列出该文件下所有的文件夹和文件        File[]files=file.listFiles();        for(int x=0;x<files.length;x++){//遍历            //如果列出的文件是文件夹,那么调用showDir()方法,继续列出其下面的文件和文件夹            if(files[x].isDirectory()){                showDir(files[x]);            }else {                System.out.println(files[x]);            }        }     }
  • 递归必须要有跳出的条件
  • 递归次数不能太多,否则会造成内存溢出。因为每调用一次方法,都会重新开辟一块内存。

- 9. java配置文件与Properties

**Properties是Hashtable的子类,具备map集合的特点,而且存储的键值对都是字符串。
它是集合中和IO技术相结合的集合容器。用来键值对形式的配置文件。**

代码1:

     static void propertiesTest1(){         //创建对象         Properties properties=new Properties();         //设置键值对         properties.setProperty("name", "liang");         properties.setProperty("age", "28");         properties.setProperty("country", "China");         //得到所有字符串类型的键        Set<String>set=properties.stringPropertyNames();        //根据键对Properties进行遍历        for(String string:set){            System.out.println(string+"--"+properties.get(string));        }     }
//输出结果age--28name--liangcountry--China

创建配置文件并用Properties读取和修改:

代码2:

     /**      * Properties和IO流进行关联必须创建相关的IO流对象。      * @throws IOException      */     static void propertiesTest2()throws IOException{         //创建读取的IO流对象,info.txt是配置文件。         FileInputStream fileInputStream=new FileInputStream("D:/info.txt");         Properties properties=new Properties();         //加载流对象,除了InputStream,还可以是Reader。         properties.load(fileInputStream);         //添加一条配置数据         properties.setProperty("hobby", "eating");         //修改配置数据后,必须使用写入流对象将修改后的数据保存到文件中。         FileOutputStream fileOutputStream=new FileOutputStream("D:/info.txt");         //将修改的信息保存到文件中,第二个参数是说明信息。除了可以使用OutputStream,还可以使用Writer。         properties.store(fileOutputStream, "第一次修改");         Set<String>set=properties.stringPropertyNames();            //根据键对Properties进行遍历            for(String string:set){                System.out.println(string+"--"+properties.get(string));            }            //关闭流资源            fileInputStream.close();            fileOutputStream.close();     }

10. 序列流

序列流,可以将多个文件中的内容合并成一个文件

     /**      * 序列流,可以将多个文件中的内容合并成一个文件      * @throws IOException      */     static void sequenceStreamTest() throws IOException{         Vector<FileInputStream>vector=new Vector<>();         //三个文件,创建三个字节输入流对象。         FileInputStream inputStream1=new FileInputStream("D:/1.txt");         FileInputStream inputStream2=new FileInputStream("D:/2.txt");         FileInputStream inputStream3=new FileInputStream("D:/3.txt");         vector.add(inputStream1);         vector.add(inputStream2);         vector.add(inputStream3);         Enumeration<FileInputStream> enumeration=vector.elements();         //构造方法参数是Enumeration对象,所以需要用到Vector。         SequenceInputStream sequenceInputStream=new SequenceInputStream(enumeration);         //创建输出流,将合并好的流进行输出。         FileOutputStream outputStream=new FileOutputStream("D:/4.txt");         //进行读写操作。         byte[] bytes=new byte[1024];         int len=0;         while((len=sequenceInputStream.read(bytes))!=-1){             outputStream.write(bytes,0,len);         }         //关闭资源         sequenceInputStream.close();         outputStream.close();     }
0 0
原创粉丝点击