JAVASE-26: IO流之其他的一些字符流、字节流

1. 数据输入输出流

DataOutputStream写-DataInputStream读

怎么写的就怎么读,能够读写基本数据类型(ctrl+q可以查看传入什么参数)

特有方法:

DataOutputStream 写
writeInt(); writeDouble(); writeBoolean(); writeUTF();

DataInputStream 读
readInt(); readDouble(); readBoolean(); readUTF();

public static void main(String[] args) throws IOException {
    DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));
    int i = in.readInt();
    System.out.println(i);
    double v = in.readDouble();
    System.out.println(v);
    boolean b = in.readBoolean();
    System.out.println(b);
    String s = in.readUTF();
    System.out.println(s);

    writeData();
}

private static void writeData() throws IOException {
    DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
    out.writeInt(100);
    out.writeDouble(3.14);
    out.writeBoolean(true);
    out.writeUTF("你好世界");
    out.close();
}

2. 内存操作流

不直接关联任何文件,只在内存中进行读写

2.1. 操作字节数组

ByteArrayOutputStream写-ByteArrayInputStream读 (常用)

ByteArrayOutputStream 写

他在内存中维护了一个字节数组作为缓冲区,随着数据的不断写入,缓冲区会自动不断扩充,要取出缓冲区数据,可以使用toByteArray()、toString()。此类实现了一个输出流,其中的数据被写入一个 byte 数组。

toByteArray() 返回的是它所维护的字节数组

toString() 返回字符串类型

ByteArrayOutputStream out = new ByteArrayOutputStream();
out.write("爱生活".getBytes());
out.write("爱java".getBytes());
out.write("好好学习".getBytes());
out.write("天天向上".getBytes());
out.write("天天向上".getBytes());

byte[] bytes = out.toByteArray();
String s = new String(bytes);
System.out.println(s);

String s1 = out.toString();
System.out.println(s1);

out.close();

ByteArrayInputStream(byte[] buf) 读

使用buf作为其缓冲区数组,传入一个有数据的字节数组

然后它会把这个字节数组里的数据,读入创建的新字节数组

ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
byte[] bytes1 = new byte[1024];
int len = bis.read(bytes1);

String s2 = new String(bytes1, 0, len);
System.out.println(s2);
2.2 操作字符数组 CharArrayWriter-CharArrayReader

维护了一个字符数组作为缓冲区

取 .valueof()

CharArrayWriter charArrayWriter = new CharArrayWriter();
charArrayWriter.write("一行字符串");
charArrayWriter.write(new char[]{'a','b','c'});

char[] chars = charArrayWriter.toCharArray();
System.out.println(String.valueOf(chars));

System.out.println(charArrayWriter.toString());
2.3 操作字符串 StringWriter-StringReader

取 .toString()

StringWriter stringWriter = new StringWriter();
stringWriter.write("abc");
stringWriter.write("abc");
stringWriter.write("abc");
stringWriter.write("abc");

System.out.println(stringWriter.toString());

练习:要两首mp3合并成一首歌

public static void main(String[] args) throws IOException {
    FileInputStream in1 = new FileInputStream("许巍 - 蓝莲花.mp3");
    FileInputStream in2 = new FileInputStream("许巍 - 曾经的你.mp3");
    FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\许巍合.mp3");
    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) {
            out.write(bytes,0,len);
        }
        in.close();
    }
    System.out.println("合并完毕");
}

3. 打印流

只能写出数据 不能读取数据

字节打印流 PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式

PrintStream(File file)
创建具有指定文件且不带自动行刷新的新打印流。
PrintStream(OutputStream out, boolean autoFlush)
创建新的打印流。

PrintStream stream = new PrintStream("a.txt");
stream.write("你好".getBytes());
stream.println("我很好");
stream.flush();
stream.println("我很好");
stream.println("我很好");

PrintStream out = System.out;
out.write("hhhe".getBytes());
System.out.println("abc"); // hhheabc
System.out.write("ab".getBytes()); // ab

字符打印流 PrintWriter 字符流要刷新才能过去

public static void main(String[] args) throws FileNotFoundException {
    PrintWriter writer = new PrintWriter("b.txt");
    writer.write("abc");
    writer.println("abc");
    writer.println("abc");
    writer.flush();
    writer.close();
}

PrintWriter(OutputStream out, boolean autoFlush)
通过现有的 OutputStream 创建新的 PrintWriter

PrintWriter printWriter = new PrintWriter(new FileOutputStream("c.txt"), true);
/*
printWriter.write("abc");
printWriter.write("\r\n");
printWriter.write("abc");
printWriter.write("\r\n");
*/
printWriter.println("abc");
printWriter.println("abc");
printWriter.println("abc");
// printWriter.flush();
printWriter.close();

练习:打印流复制文本文件

public static void main(String[] args) throws IOException {
    PrintWriter printWriter = new PrintWriter(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\a.java"),true);
    BufferedReader in = new BufferedReader(new FileReader("MyTest1.java"));
    while (true){
        String s = in.readLine();
        if(s!=null){
            printWriter.println(s);
        }else{
            break;
        }
    }
    in.close();
    printWriter.close();
}

4. 随机访问流

RandomAccessFile 能读也能写。random 形容词 随机的 随意的 胡乱的、access 动词 存取 访问 使用

此类不属于流,是Object的子类。但它融合了InputStream和OutputStream的功能。

.writeInt();

.writeDouble();

.writeUTF();

… …

.getFilePointer(); 获取指针

.seek(某个位置); 定位文件指针位置

public static void main(String[] args) throws IOException {
    RandomAccessFile in = new RandomAccessFile("e.txt", "rw");
    int i = in.readInt();
    long filePointer = in.getFilePointer();
    System.out.println("指针位置:"+filePointer);// 指针位置:4
    double v = in.readDouble();
    filePointer = in.getFilePointer();
    System.out.println("指针位置:"+filePointer);// 指针位置:12
    boolean b = in.readBoolean();
    filePointer = in.getFilePointer();
    System.out.println("指针位置:" + filePointer);// 指针位置:13
    String s = in.readUTF();
    filePointer = in.getFilePointer();
    System.out.println("指针位置:" + filePointer);// 指针位置:21

    // 定位文件指针的位置
    in.seek(13);
    s = in.readUTF();
    System.out.println(i);// 200
    System.out.println(v);// 32.2
    System.out.println(b);// false
    System.out.println(s);// 你好
    System.out.println(s);// 你好
}

private static void writeData() throws IOException {
    RandomAccessFile out = new RandomAccessFile("e.txt", "rw");
    out.writeInt(200);
    out.writeDouble(32.2);
    out.writeBoolean(false);
    out.writeUTF("你好");
}

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

练习:利用RandomAccessFile模拟下载文件

public static void main(String[] args) throws IOException {
    RandomAccessFile in=null;
    RandomAccessFile out=null;
    try {
        in = new RandomAccessFile("许巍 - 蓝莲花.mp3", "rw");
        out = new RandomAccessFile("C:\\Users\\ShenMouMou\\Desktop\\许巍 - 蓝莲花.mp3", "rw");
        // 点了继续下载:1.先 判断之前的那个文件,在不在,如果不在
		File file = new File("C:\\Users\\ShenMouMou\\Desktop\\许巍 - 蓝莲花.mp3");
        if (!file.exists()) {
        	in.seek(0);
        	out.seek(0);
        }else{
        	BufferedReader reader = new BufferedReader(new FileReader("config.txt"));
            String s = reader.readLine();
            long l = Long.parseLong(s);
            in.seek(l+1);
            out.seek(l+1);
        }
        
        int len=0;
        byte[] bytes = new byte[2];
        int i=0;
        while ((len=in.read(bytes))!=-1){
            out.write(bytes,0,len);
        }
        in.close();
        out.close();
        
    } catch (Exception e) {
        e.printStackTrace();
        long pointer = in.getFilePointer();
        PrintWriter printWriter = new PrintWriter("config.txt");
        printWriter.println(pointer);
        printWriter.flush();
        printWriter.close();
    }
}

5. 序列化流 反序列化流

序列化—针对对象,把对象通过流的方式存储到文件中,此对象 要重写Serializable 接口(serializable 形容词 可序列化 可串行化的)才能被序列化

new ObjectOutputStream(new FileOutputStream());

.writeObject();

必须给类实现一个接口:Serializable 序列化接口

如果想要一个类的对象 能被序列化 要求该类要实现Serializable 序列化接口,

如果不想序列化某个参数 可以加上transient 排除某些属性 不要被序列化

private transient int age ;// 可以阻止成员变量的序列化使用transient(transient 形容词 瞬态 瞬时的)

反序列化 就是把文件中存储的对象以流的方式还原成对象

new ObjectInputStream(new FileInputStream());

.readObject();

public static void main(String[] args) throws IOException, ClassNotFoundException {
     readData();
}

private static void readData() throws IOException, ClassNotFoundException {
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.txt"));
    Student s = (Student) in.readObject();
    System.out.println(s.getName()+"=="+s.getAge());
}

private static void writeData() throws IOException {
    Student s1 = new Student("张三", 23);
    // NotSerializableException
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.txt"));
    out.writeObject(s1);
    out.close();
}
public class Student implements Serializable {

    private static final long serialVersionUID = -7476321121279308524L;
    private String name;
    // transient 可以排除某些属性,不要被序列化。
    // private transient int age;
    private int age;

6. 属性集合

Properties 类表示了一个持久的属性集。properties–名词 性能 道具 内容 属性 特性 property的复数形式
Properties 可保存在流中或从流中加载。
属性列表中每个键及其对应值都是一个字符串。
Properties父类是Hashtable

属于双列集合,这个集合中的键和值都是字符串 Properties不能指定泛型

Properties的键值都是定好的,默认为String

new Properties();

操作一些配置文件

读取配置文件,配置文件有要求,一般配置文件的后缀名 .properties

配置文件中键值 ,以=分割

public static void main(String[] args) throws IOException {
    // 读取配置文件中的数据
    HashMap<String, String> hm = new HashMap<>();
    BufferedReader reader = new BufferedReader(new FileReader("user.properties"));
    while (true){
        String line = reader.readLine();
        if(line!=null){
            String[] s = line.split("=");
            hm.put(s[0],s[1]);
        }else{
            break;
        }
    }
    System.out.println(hm);
}

Properties的特殊功能

存数据 .setProperty()

取数据 .getProperty()

public static void main(String[] args) {
    // Properties 他的键和值的数据类型,已经默认为String
    Properties properties = new Properties();
    /*
    properties.put("username","zhangsan");
    Object username = properties.get("username");
    */
    properties.setProperty("username", "zhangsan");
    String username = properties.getProperty("username2");
    // String username = properties.getProperty("username2","aaa");

    System.out.println(username);// null
    System.out.println(properties);// {username=zhangsan}
}

Properties和IO流进行配合使用:

public void load(Reader reader): 读取键值对数据把数据存储到Properties中

public void store(Writer writer, String comments)把Properties集合中的键值对数据写入到文件中, comments注释

.store(new FileOutputStream(""))

.load(new FileInputStream(""))


7. 顺序流

sequence 名词 顺序 序列

合并文件,SequenceInputStream

表示其他输入流的逻辑串联。
它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

a:构造方法
SequenceInputStream(InputStream s1, InputStream s2)
通过记住这两个参数来初始化新创建的 SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取 s2),以提供从此 SequenceInputStream 读取的字节。

public static void main(String[] args) throws IOException {
        // 将a.txt和b.txt两个文本文件的内容合并到c.txt
        FileInputStream in1 = new FileInputStream("a.txt");
        FileInputStream in2 = new FileInputStream("b.txt");
        FileInputStream in3 = new FileInputStream("b.txt");
        SequenceInputStream allIn = new SequenceInputStream(in1, in2);
        SequenceInputStream allIn2 = new SequenceInputStream(allIn, in3);
        FileOutputStream out = new FileOutputStream("ff.txt");
        int len=0;
        byte[] bytes = new byte[1024];
        while ((len=allIn.read(bytes))!=-1){
            out.write(bytes,0,len);
            out.flush();
        }
        allIn.close();
        out.close();
    }

b:构造方法
SequenceInputStream(Enumeration<? extends InputStream> e)
通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。

new Vector

Vector.elements();

public static void main(String[] args) throws IOException {

    FileInputStream in1 = new FileInputStream("a.txt");
    FileInputStream in2 = new FileInputStream("b.txt");
    FileInputStream in3 = new FileInputStream("b.txt");
    Vector<FileInputStream> vector = new Vector<>();
    vector.add(in1);
    vector.add(in2);
    vector.add(in3);
    // Enumeration
    Enumeration<FileInputStream> elements = vector.elements();

    SequenceInputStream allIn = new SequenceInputStream(elements);
    FileOutputStream out = new FileOutputStream("ff.txt");

    int len = 0;
    byte[] bytes = new byte[1024];
    while ((len = allIn.read(bytes)) != -1) {
        out.write(bytes, 0, len);
        out.flush();
    }
    allIn.close();
    out.close();

}

8. scanner

scanner 名词 扫描仪 扫描机

Scanner(File source)
构造一个新的 Scanner,它生成的值是从指定文件扫描的。

Scanner(InputStream source)
构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。

public static void main(String[] args) throws FileNotFoundException {
    

    Scanner scanner = new Scanner(new File("MyTest1.java"));
    while (scanner.hasNextLine()){
        String s = scanner.nextLine();
        System.out.println(s);
    }

    Scanner scanner1 = new Scanner(new FileInputStream("MyTest1.java"));
}

键盘录入的 第二种方式

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();
        System.out.println(s);
        if("886".equals(s)){
            break;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值