黑马程序员------IO流使用

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

Properties:属于map集合,不用指定泛型,内部只能存放字符串类型
方法:
p.put();放入字符串
p.loag(输入流)
p.store(输出流,注释)
p.clear();”清空集合”
p.containsKey(key);”是否包含某个key”
p.containsValue(value);”是否包含某个value”
p.entrySet();”返回Set集合,包含所有键值对信息”
p.keySet();”返回Set集合,包含所有键”
p.get(key);”根据key获取value”
p.getProperty(key);”根据key返回键,返回值是string类型”
p.getProperty(key, defaultValue);”根据key返回键,返回值是string类型,没有值的时候使用默认值”
p.isEmpty();”集合是否为空”
p.size();”集合长度”

    public static void propertiesDemo() {
        Properties p = new Properties();
        p.put("zhangsan", "10");
        p.put("zhangsan1", "101");
        p.put("zhangsan2", "102");
        p.put("zhangsan3", "103");
        "//把Properties 内的数据以列表形式输出"
        p.list(new PrintStream(System.out));

        "/**
         * 模拟load()和store()
         * load():读取的文件内部必须是键值对的形式,
         * a = b
         */"
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        String line = null;
        try {
            while ((line = br.readLine()) != null) {
                if ("over".equals(line))
                    break;
                    "//对字符串根据 = 分割"
                String[] s = line.split("=");
                bw.write(s[0] + " : " + s[1]);
                bw.flush();
                "//换一行"
                bw.newLine();
            }
            br.close();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        "/**
         * 使用load和stroe来加载文件和输出文件
         */"
        try {
            "//读取文件"
            p.load(new FileInputStream("d://c.txt"));
            "//把p对象中的内容写入到文件中"
            p.store(new OutputStreamWriter(new FileOutputStream("c://cc.txt"), "utf-8"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

RandomAccessFile 随机文件读写
(即可以读,也可以写,创建对象时声明权限即可,r:读,w:写)
raf.setLength(newLength);设置一个文件的大小(设置后文件大小立即为设置的大小,凡是内部没有数据)
raf.length();获取文件大小
raf.read();读取文件
raf.write();写文件:可以读写基本数据类型
raf.readLine();读取一行
raf.seek(int);从哪里开始读取或写入
raf.skipBytes(n);跳过多少字节
可以多个RandomAccessFile 对象同时对一个文件进行读写操作(多线程下载)

    public static void demo3() {
        try {
            "通过url获取网络资源对象"
            URL url = new URL("http://127.0.0.1:8080/demo.avi");
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setReadTimeout(3000);
            conn.connect();
            InputStream in = conn.getInputStream();
            "获取网络文件大小"
            long length = conn.getContentLength();
            "创建本地文件,并设置大小"
            File file = new File("c://demo//t.avi");
            if (file.exists()) {
                file.delete();
                file.createNewFile();
            } else {
                file.createNewFile();
            }
            RandomAccessFile raf = new RandomAccessFile(file, "rw");
            "设置文件大小,只有RandomAccessFile才有这个方法"
            raf.setLength(length);
            raf.close();
            conn.disconnect();
            "开启三个线程,并传入开始和结束位置"
            method(0, length / 3);
            method(length / 3, length / 3 * 2);
            method(length / 3 * 2, length);

        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

    public static void method(final long start, final long end) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                File file = new File("c://demo//t.avi");
                if (!file.exists()) {
                    throw new RuntimeException("找不到文件");
                }
                try {
                    "三个线程共三个RandomAccessFile对象,
                    他们同时操作一个文件"
                    RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                    "设置URL"
                    URL url = new URL("http://127.0.0.1:8080/demo.avi");
                    "获取httpUrlConnextion对象"
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    "连接方法"
                    conn.setRequestMethod("GET");
                    "读取超时时间"
                    conn.setReadTimeout(3000);
                    "设置提交属性"
                    conn.setRequestProperty("Range", "bytes=" + start + "-" + end);
                    conn.connect();
                    System.out.println("开始下载:" + Thread.currentThread());
                    System.out.println("开始下载:" + start + "  :  " + end);
                    InputStream in = conn.getInputStream();
                    byte[] by = new byte[1024];
                    "设置从文件哪个位置开始写入数据"
                    raf.seek(start);
                    while ((len = in.read(by)) != -1) {
                        "写入数据"
                        raf.write(by, 0, len);
                    }
                    System.out.println("关闭:" + Thread.currentThread());
                    raf.close();
                } catch (Exception e) {
                    e.printStackTrace();
                } 
            }
        }).start();
    }

PrintStream
只有输出流,没有输入流
可以操作字节流和字符流,一般经常使用字符流
一般使用在打印日志信息中,方便

    public static void demo2() {
        try {
            File f = new File("c://demo//b.txt");
            int[] i = new int[1];
            i[3] = 4;
        } catch (Exception e) {
            try {
                "获取时间"
                Date date = new Date();
                "当参数是输出流的时候,可以指定自动刷新,指定自动刷新后只有println(),printf(),formar()方法有用,若参数是file,不能设置自动刷新
                print()不会自动刷新"
                "FileOutputStream 若文件已经存在采用追加模式,我不是覆盖"
                PrintStream ps = new PrintStream(new FileOutputStream("c://demo//d.txt"true),
                        true);
                "打印的是字节流"
                ps.write(date.toString().getBytes());
                "打印时间,打印的是字符流"
                ps.println(date);
                "把异常信息打印到ps对象中"
                e.printStackTrace(ps);
            } catch (FileNotFoundException e1) {
                throw new RuntimeException("日志文件创建失败!");
            }

        }
    }

LinenumberReader:
没有LinenumberWriter
使用lnr.getLineNumber()获取行号,默认从0开始
使用lnr.setLineNumber(10);这是行号的起始位置
LinenumberReader自带缓存,有readLine()方法

    public static void lineNum() {
        LineNumberReader lnr = null;
        BufferedWriter bw = null;

        try {
            lnr = new LineNumberReader(new FileReader("d://demo.txt"));
            bw = new BufferedWriter(new FileWriter("c://demo.txt"));
            String line = null;
            "设置行号从10开始"
            lnr.setLineNumber(10);
            while ((line = lnr.readLine()) != null) {
                bw.write(lnr.getLineNumber() + " : " + line);
                "// 最好使用自带的方法换行,这样可以跨平台"
                bw.newLine();
                bw.flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            "关闭资源"
            try {
                if (lnr != null)
                    lnr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (bw != null)
                    bw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

流的切割和合并
序列流:
对流进行合并,只有InputStream,不能使用字符流(Reader,Writer)
输入流是一个有序集合,当读取到第一个流的末尾处,会继续读第二个流的开始,直到结束

    public static void sequenceInputStream() {
        "/**
         * 文件的切割
         * 实际上就是在输出时候指定输出的大小
         * 例:定义的缓冲区大小是多大,那么分割的就是多大
         */"
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            "// 获取文件输入流"
            fis = new FileInputStream("d://love.mp3");
            int num = 0;
            int count = 0;"// 文件名的计数"
            "// 缓存大小是1m"
            byte[] by = new byte[1024 * 1024];
            while ((num = fis.read(by)) != -1) {
                count++;
                "/**
                 * 在内部进行创建输出流,当第一个数组存满后
                 * 创建输出流进行存储,然后立刻关闭
                 * 当再次循环的时候重新创建输出流,重新放新的数据
                 */"
                fos = new FileOutputStream("c://" + count + "1.part");
                fos.write(by, 0, num);
                fos.flush();
                fos.close();
            }
            fis.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        "// 声明集合,内部存放输入流,若是输入流数量小于两个不用创建集合,直接使用构造方法传递就可以"
        ArrayList<FileInputStream> list = new ArrayList<FileInputStream>();
        try {

            "// 添加输入流"
            list.add(new FileInputStream("c://11.part"));
            list.add(new FileInputStream("c://21.part"));
            list.add(new FileInputStream("c://31.part"));
            "// 获取每一个输入流,由于被Enumeration使用,他是匿名内部类,要使用final修饰"
            final Iterator<FileInputStream> it = list.iterator();
            "/**
             * SequenceInputStream中只能接收Enumeration集合,不能使用Iterator
             * 使用Enumeration集合是vector,但是已经被ArrayList代替
             * 所以重写Enumeration的方法
             */"
            Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {

                @Override
                public boolean hasMoreElements() {
                    return it.hasNext();"// 是否有下一个"
                }

                @Override
                public FileInputStream nextElement() {
                    return it.next();"// 获取下一个对象"
                }
            };
            FileOutputStream fos2 = new FileOutputStream("c://lov1.mp3");
            SequenceInputStream sis = new SequenceInputStream(en);
            "/**
             * 最后进行输出
             */"
            int num = 0;
            byte[] by = new byte[1024];
            while ((num = sis.read(by)) != -1) {
                fos2.write(by, 0, num);
            }
            sis.close();
            fos2.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

对象的持久化存储:
ObjectOutputStream,ObjectInputStream
将一个对象进行持久化存储,存储的对象必须实现Serializable接口,打上标记
实现Serializable的类默认会生成一个UId:
public static final long serialVersionUID = 10;
它会根据这个值进行判断是不是原来的对象,默认是根据类中的成员进行计算,也可以手工指定
当对象进行持久化存储后,这时候修改了类中的一些值,例如添加了一个成员等
这时候再读取对象文件的时候会报错:java.io.InvalidClassException
静态不能被序列化
非静态不想被序列化使用关键字:transient

    public static void serializable() {
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("d://demo2.txt"));
            ois = new ObjectInputStream(new FileInputStream("d://demo2.txt"));
            "// 写入一个对象"
            oos.writeObject(new Persion("lisi", 31));
            oos.writeObject(new Persion("lisi1", 31));
            oos.writeObject(new Persion("lisi2", 32));
            oos.close();
            "// 读取一个对象,并进行强转"
            Persion p = (Persion) ois.readObject();
            Persion p1 = (Persion) ois.readObject();
            Persion p2 = (Persion) ois.readObject();
            System.out.println(p.getName() + "  " + p.getAge());
            System.out.println(p1.getName() + "  " + p1.getAge());
            System.out.println(p2.getName() + "  " + p2.getAge());

        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
import java.io.Serializable;

public class Persion implements Serializable {
    private static final long serialVersionUID = 1;
    private String name;
    private int age;
    public Persion(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
}

管道流:
PipedInputStream PipedOutputStream
一般应用在多线程中,一个线程负责输入,而另一个线程负责输出
当一段连接线程提前结束的时候:会报错

    public static void guanDaoDemo() {
        "创建一个输入管道流,这里使用了匿名内部类,局部变量要声明为final"
        final PipedInputStream pis = new PipedInputStream();
        "创建一个输出管道流"
        final PipedOutputStream pos = new PipedOutputStream();
        try {
            "两个流进行连接"
            pis.connect(pos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        "输出管道流"
        new Thread(new Runnable() {

            @Override
            public void run() {
                int num = 0;
                System.out.println("正在读取数据...");
                try {
                    while ((num = pis.read()) != -1) {
                        System.out.println(num);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        "输入管道流"
        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    System.out.println("正在写入数据...");
                    Thread.sleep(3000);
                    pos.write("--------".getBytes());
                    System.out.println("写入完成...");
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

存储基本数据类型
DataInputStream,DateOutputStream
注意:
写入顺序和读取顺序必须相同(第一个写入的是int类型,则读取的时候第一个必须是int类型,如果是long类型,则会多读取数据,造成数据错误)
gbk编码表:一个中文占2个字节
utf -8:一个中文占3个字节
utf-8改:一个中文占4个字节
当存储的数据大于256时,最好是用writeInt(),他是直接存储32位,而write()只是存储8位,
会造成损失精度
writeUTF(“你好”);当写入时使用了这个方法,取出时一定要使用readUTF();取出

public static void dataDemo() {
        try {
            DataInputStream dis = new DataInputStream(new FileInputStream("d://demo3.txt"));
            DataOutputStream dos = new DataOutputStream(new FileOutputStream("d://demo3.txt"));
            dos.writeInt(78);"// 写入32位"
            dos.write(455);"// 写入8位,会造成精度损失"
            dos.writeBoolean(true);
            dos.writeUTF("你好");
            dos.close();

            int a = dis.readInt();
            int b = dis.read();
            boolean c = dis.readBoolean();
            String s = dis.readUTF();
            System.out.println(a + " " + b + " " + c + " " + s);
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

字节数组操作数据,字符数组,字符串:
ByteArrayInputStream ByteArrayOutputStream
实例:把文件的中内容读取到内存中
不需要关闭,因为没有调用底层资源,关闭也没用
bos.size()获取输出长度
这个是直接输出到内存中

    public static void arrayDemo() {
        BufferedReader br;
        try {
            "读取一个文件"
            br = new BufferedReader(new FileReader("d://demo.txt"));
            "定义输出文件"
            FileOutputStream fos = new FileOutputStream("d://demo4.txt");
            StringBuilder sb = new StringBuilder();
            String line = null;
            "把文件读取的内容添加到StringBuilder中"
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            System.out.println(sb.toString());
            "// 读取字节数据"
            ByteArrayInputStream bis = new ByteArrayInputStream(sb.toString().getBytes());
            "ByteArrayOutputStream 是把数据写入到内存中"
            ByteArrayOutputStream bos = new ByteArrayOutputStream();"// 长度自动增加"
            int by = 0;
            while ((by = bis.read()) != -1) {
                "// 输出,这里是输出到内存中"
                bos.write(by);
            }
            "// 输出到outputstream,必须要先执行完上面while循环,把数据写入内存后,才能执行writeTo()"
            bos.writeTo(fos);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值