java之IO流(一)

**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--28
name--liang
country--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();

     }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值