IO流(二)(其他常用流)

IO流(二)(其他常用流)

(一)数据输入输出流

数据输入流: DataInputStream
数据输出流: DataOutputStream

特点 可以写基本数据类型,可以读取基本数据类型

特有方法

write(基本类型)可以写基本类型

read()读写顺序一致

(二)内存操作流

A:内存操作流的概述
	a:操作字节数组
		ByteArrayOutputStream
		ByteArrayInputStream
		此流关闭无效,所以无需关闭
	b:操作字符数组
		CharArrayWrite
		CharArrayReader
	c:操作字符串
		StringWriter
		StringReader	

ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read` 方法要提供的下一个字节。

关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException

不关联任何文件,中对内存中的数据进行读写

(用StringBuffer当缓冲区)

文件合并1

public class Demo13 {
    public static void main(String[] args) throws IOException {
        FileInputStream inputStream = new FileInputStream("G:\\20190724-字符流-上午1\\20190724-杂七杂八流-下午\\许巍 - 曾经的你.mp3");
        FileInputStream inputStream1 = new FileInputStream("G:\\20190724-字符流-上午1\\20190724-杂七杂八流-下午\\许巍 - 蓝莲花.mp3");
        FileOutputStream out = new FileOutputStream("E:\\音乐\\歌曲大合唱.mp3");

​    ArrayList<FileInputStream> list = new ArrayList<>();
​    list.add(inputStream);
​    list.add(inputStream1);
​    int len=0;
​    byte[] bytes = new byte[1024*8];
​    for (FileInputStream stream : list) {
​        while ((len=stream.read(bytes))!=-1){
​            out.write(bytes,0,len);
​            out.flush();
​        }

​        stream.close();
​    }
​    out.close();
}

}

方法2

public class 把多个文件合成一个文件 {
    public static void main(String[] args) throws IOException {
        FileInputStream in1 = new FileInputStream("许巍 - 曾经的你.mp3");
        FileInputStream in2 = new FileInputStream("许巍 - 蓝莲花.mp3");
        FileOutputStream out = new FileOutputStream("歌曲大联唱.mp3");

​    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
​    //创建一个集合
​    ArrayList<FileInputStream> list = new ArrayList<>();
​    list.add(in1);
​    list.add(in2);
​    int len=0;
​    byte[] bytes = new byte[1024 * 8];
​    for (FileInputStream in : list) {
​        while ((len=in.read(bytes))!=-1){
​            byteOut.write(bytes,0,len);
​            byteOut.flush();
​        }
​        in.close();
​    }

​    //取出两首歌的字节数据
​    byte[] allBytes = byteOut.toByteArray();
​    System.out.println(allBytes.length);
​    //将两首歌的字节数据,写到硬盘上

​    ByteArrayInputStream byteIn = new ByteArrayInputStream(allBytes);
​    int len2 = 0;
​    byte[] bytes2 = new byte[1024 * 8];

​    while ((len2 = byteIn.read(bytes)) != -1) {
​        out.write(bytes, 0, len2);
​        out.flush();
​    }

​    out.close();

}
}


(三)打印流

PrintStream

  •   打印流的特点
      a: 打印流只能操作目的地,不能操作数据源(不能进行读取数据)
      
      - b: 可以操作任意数据类型的数据 调用print() 方法可以写任意数据类型
      
      - c: 如果我们启用自动刷新,那么在调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
        /**
          		通过以下构造创建对象 能够启动自动刷新  然后调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
      /**
        		通过以下构造创建对象 能够启动自动刷新  然后调用println、printf 或 format 方法中的一个方法的时候,会完成自动刷新
        	 * public PrintWriter(OutputStream out,  boolean autoFlush)	 启动 自动刷新
        	 * public PrintWriter(Writer out,  boolean autoFlush)		启动自动刷新
        	 */
      
      - d: 这个流可以直接对文件进行操作(可以直接操作文件的流: 就是构造方法的参数可以传递文件或者文件路径)
          		
          		
    

    字节打印流(文件和屏幕)

​ 字符打印流(只能关联文件)

键盘录入的第二种方法
public class 键盘录入的第二种方式 {
    public static void main(String[] args) throws IOException {
        //Scanner scanner = new Scanner(System.in);
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true){
            System.out.println("请输入数据");
            String s = reader.readLine();
            //自定义一个结束标记
            if("886".equals(s)){
                break;
            }
            System.out.println(s);
        }

}

}

PrintWriter实现自动刷新和换行

A:案例演示:PrintWriter实现自动刷新和换行
	PrintWriter pw = new PrintWriter(new FileWriter("printWriter2.txt") , true) ;
	pw.println(true) ;
	pw.println(100) ;
	pw.println("中国") ;

(四)随机访问流

A:随机访问流概述
	RandomAccessFile概述 最大特点 能读能写  注:你咋么写,就咋么读取 顺序不能乱
	RandomAccessFile类不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能。
	支持对随机访问文件的读取和写入。

	 RandomAccessFile的父类是Object , 这个流对象可以用来读取数据也可以用来写数据.可以操作任意数据类型的数据.
我们可以通过getFilePointer方法获取文件指针,并且可以通过seek方法设置文件指针

文件复制多份

public class Demo4 {
    public static void main(String[] args)  {
        Scanner scanner = new Scanner(System.in);
        System.out.println("你想要复制几份");
        int i = scanner.nextInt();
        try {
            RandomAccessFile f1 = new RandomAccessFile(new File("G:\\20190724-字符流-上午1\\20190724-杂七杂八流-下午\\许巍 - 曾经的你.mp3"),"rw");
            for ( i = 0; i < 3; i++) {
                f1.seek(0);
                RandomAccessFile f2 = new RandomAccessFile(new File("G:\\20190724-字符流-上午1\\20190724-杂七杂八流-下午\\曾经的你"+ i+".mp3"), "rw");
                int len = 0;
                    byte[] bytes = new byte[1024*1024];
                    while ((len = f1.read(bytes)) != -1) {
                        f2.write(bytes, 0, len);
                }
            }
            f1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    }

(五)序列化流

A:序列化流的概述
	所谓的序列化:就是把对象通过流的方式存储到文件中.注意:此对象 要重写Serializable 接口才能被序列化
	反序列化:就是把文件中存储的对象以流的方式还原成对象
	序列化流:	ObjectOutputStream
	反序列化流:	ObjectInputStream
	 

​```
 像这样一个接口中如果没有方法,那么这样的接口我们将其称之为标记接口(用来给类打标记的,相当于猪肉身上盖个章)
​```

 一个对象可以被序列化的前提是这个对象对应的类必须实现Serializable接口
如何解决序列化时候的黄色警告线问题
我们的一个类可以被序列化的前提是需要这个类实现Serializable接口,就需要给这个类添加一个标记.

在完成序列化以后,序列化文件中还存在一个标记,然后在进行反序列化的时候,
会验证这个标记和序列化前的标记是否一致,如果一致就正常进行反序列化,如果

不一致就报错了. 而现在我们把这个类做了修改,将相当于更改了标记,而导致这两个标记不一致,就报错了.



解决问题: 只要让这个两个标记一致,就不会报错了吧 

怎么让这两个标记一致呢? 	不用担心,很简单,难道你们没有看见黄色警告线吗? alt+enter, 生成出来
private static final long serialVersionUID = -7602640005373026150L;


如何让对象的成员变量不被序列化

使用transient关键字声明不需要序列化的成员变量

private transient int age ;// 可以阻止成员变量的序列化使用transient

(六)Properties

A:Properties的概述
	Properties 类表示了一个持久的属性集。
	Properties 可保存在流中或从流中加载。
	属性列表中每个键及其对应值都是一个字符串。
	Properties父类是Hashtable
	- 属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型
Properties的特殊功能使用
A:Properties的特殊功能
	public Object setProperty(String key,String value)
	public String getProperty(String key)
	public Set<String> stringPropertyNames()
Properties的load()和store()功能
  • A:Properties的load()和store()功能
    	 Properties和IO流进行配合使用:
    	 - public void load(Reader reader): 读取键值对数据把数据存储到Properties中
    
    - public void store(Writer writer, String comments)把Properties集合中的键值对数据写入到文件中, comments注释
    

    A:案例演示
    需求:我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”

    案例

    分析:

    • a: 把文本文件中的数据加载到Properties集合中
    • b: 判断这个集合中是否有"lisi"这个键
    • 如果有直接修改其值为100
    • c: 把集合中的数据再次存储到文本文件中
public class Demo{
    public static void main(String[] args) throws IOException {
 
        Properties properties = new Properties();
        properties.load(new FileInputStream("user.propreties"));
        if(properties.containsKey("lisi")){
            //如果这个键存在,把值改为100
            properties.setProperty("lisi","100");//键相同,值覆盖
        }
        //改完之后再写回源文件
        properties.store(new FileWriter("user.propreties"),null);
    }
}

(七)SequenceInputStream

SequenceInputStream 
	表示其他输入流的逻辑串联。
	它从输入流的有序集合开始,
	并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,
	依次类推,直到到达包含的最后一个输入流的文件末尾为止
	a:构造方法
	SequenceInputStream(InputStream s1, InputStream s2) 
	通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),
	以提供从此 SequenceInputStream 读取的字节。
	b:构造方法
	SequenceInputStream(Enumeration<? extends InputStream> e) 
	 通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数

案例:将一个music.mp3文件,拆分成多个小文件,再将多个小文件,合并成一个mp3文件

public class Demo2 {
    public static void main(String[] args) throws IOException {
       
       heBing();
    }
    private static void heBing() throws IOException {
        File file = new File("E:\\music");
        File[] files = file.listFiles();
        Vector<FileInputStream> vector = new Vector<>();
        for (File f : files) {
            FileInputStream in = new FileInputStream(f);
            vector.add(in);
        }
        Enumeration<FileInputStream> elements = vector.elements();
        SequenceInputStream sequenceInputStream = new SequenceInputStream(elements);
        FileOutputStream out = new FileOutputStream(new File(file, "合并.mp3"));
        int len = 0;
        byte[] bytes = new byte[1024 * 1024];
        while ((len=sequenceInputStream.read(bytes))!=-1){
             out.write(bytes,0,len);
             out.flush();
        }
        out.close();
        sequenceInputStream.close();
        //合并完之后,把小文件删掉
        File file1 = new File("E:\\music");
        File[] files1 = file.listFiles();
        for (File ff : files1) {
            if(ff.length()<=1024*1024){
                ff.delete();
            }
        }
    }
    private static void chaiFen() throws IOException {
        FileInputStream in = new FileInputStream("歌曲串烧.mp3");
        //我们封装一个文件夹,放我们拆分的文件
        File file = new File("E:\\music");
        if(!file.exists()){
            file.mkdirs();
        }
        //拆分
        int len=0;
        byte[] bytes=new byte[1024*1024];
        int index=0;
        while ((len=in.read(bytes))!=-1){
            index++;
            FileOutputStream out = new FileOutputStream(new File(file, index + ".mp3"));
            out.write(bytes,0,len);
            out.close();
        }

        in.close();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值