一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能它读。
java.io包中的流对应两种流,一种流直接从指定的位置(如磁盘文件或内存区域)读或写,这种流称为结点流(node stream),其它的流则称为过滤器(filters)。过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后以新的输入流形式提供给用户,过滤器输出流的原理也类似。
Java中的流,可以从不同的角度进行分类。
按照数据据流的方向不同可以分为:输入流和输出流。
按照处理数据单位不同可以分为:字节流和字符流。
按照实现功能不同可以分为:节点流和处理流。
输出流:
输入流:
因此输入和输出都是从程序的角度来说的。
字节流:一次读入或读出是8位二进制。
字符流:一次读入或读出是16位二进制。
字节流和字符流的原理是相同的,只不过处理的单位不同而已。后缀为Stream是字节流,而后缀为Reader,Writer是字符流。
节点流:直接与数据源相连,读入或读出。
直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。
处理流:与节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。
Jdk提供的流继承了四大类:InputStream(字节输入流),OutputStream(字节输出流),Reader(字符输入流),Writer(字符输出流)。
以下是java中io中常用的流。
字节输入流:
字节输出流:
字符输入流:
字符输出流:
简单介绍其上图:
对文件进行操作:
FileInputStream(字节输入流)
FileOutputStream(字节输出流)
FileReader(字符输入流)
FileWriter(字符输出流)
对管道进行操作:PipedInputStream(字节输入流),PipedOutStream(字节输出流),PipedReader(字符输入流),PipedWriter(字符输出流)
PipedInputStream的一个实例要和PipedOutputStream的一个实例共同使用,共同完成管道的读取写入操作。主要用于线程操作。
字节/字符数组:ByteArrayInputStream,ByteArrayOutputStream,CharArrayReader,CharArrayWriter是在内存中开辟了一个字节或字符数组。
Buffered缓冲流::BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter,是带缓冲区的处理流,缓冲区的主要目的是:避免每次和硬盘打交道,提高数据访问的效率。
转化流:InputStreamReader/OutputStreamWriter,把字节转化成字符。
数据流:DataInputStream,DataOutputStream。
package io; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class Demo13 { public static void main(String[] args) throws IOException { BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bw.txt")); bufferedWriter.write("hello"); bufferedWriter.newLine(); bufferedWriter.write("world"); // 刷新流 bufferedWriter.flush(); // 关闭资源 bufferedWriter.close(); } }
因为平时若是我们输出一个8个字节的long类型或4个字节的float类型,那怎么办呢?可以一个字节一个字节输出,也可以把转换成字符串输出,但是这样转换费时间,若是直接输出该多好啊,因此这个数据流就解决了我们输出数据类型的困难。数据流可以直接输出float类型或long类型,提高了数据读写的效率。
打印流:printStream,printWriter,一般是打印到控制台,可以进行控制打印的地方。
对象流:ObjectInputStream,ObjectOutputStream,把封装的对象直接输出,而不是一个个在转换成字符串再输出。
序列化流:SequenceInputStream。
对象序列化:把对象直接转换成二进制,写入介质中。
使用对象流需要实现Serializable接口,否则会报错。而若用transient关键字修饰成员变量,不写入该成员变量,若是引用类型的成员变量为null,值类型的成员变量为0. 三、流的概念和作用
-
Java的常用输入、输出流
java.io包中的stream类根据它们操作对象的类型是字符还是字节可分为两大类: 字符流和字节流。-
Java的字节流
InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。-
Java的字符流
Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。结合开始所说的输入/输出流 ,出现了个一小框架。字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer学习Java IO,不得不提到的就是JavaIO流。
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。
IO流的分类
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流
字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。字节流和字符流的区别:
(1)读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
(2)处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
(3)字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的;而字符流在操作的时候下后是会用到缓冲区的,是通过缓冲区来操作文件,我们将在下面验证这一点。
结论:优先选用字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。
-
一次读取一个字节数组,相当于构造一个缓冲区,有没有比一次读取一个字节数组还要高效的流? 字节缓冲流
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
// 复制操作:将e盘下的abc.mp4复制到当前项目下,输出copy.mp4
// 封装源文件
FileInputStream fis = new FileInputStream("e://abc.mp4");
// 封装目的地文件
FileOutputStream fos = new FileOutputStream("copy.mp4");
// 读写操作:一次读取字节数组
byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
// 边读边写
fos.write(bys, 0, len);
}
// 释放资源
fis.close();
fos.close();
}
}
计算机如何存储中文的?当前平台默认编码集 :GBK 一个中文两个字节
第一个字节:一定是负数
第二个字节:一般是负数,也可能是正数。
代码示例
package io;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Demo2 {
public static void main(String[] args) throws UnsupportedEncodingException {
// TODO Auto-generated method stub
String string = "我爱你中国";
// 转成字节数组
byte[] bs = string.getBytes("gbk");
System.out.println(bs);
// 转成字符串的形式
System.out.println(Arrays.toString(bs));
}
}
字节缓冲输入流public BufferedInputStream(InputStream in):默认缓冲区大小,构造缓冲输入流对象
public BufferedInputStream(InputStream in,int size):指定缓冲区大小,构造缓冲输入流对象
public int read()
public int read(byte[] b,int off,int len)
在使用缓冲输入流的时候,
两种方式读取(一次读取一个字节/一次读取一个字节数组),只能用一种方式,否则,会出现错误!
代码示例
package io;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.sql.Time;
public class Demo3 {
private static BufferedInputStream bufferedInputStream;
public static void main(String[] args) throws Exception {
bufferedInputStream = new BufferedInputStream(new FileInputStream("demo\\c.txt"));
// 一次读取一个字节
// int by=0;
// while ((by=bufferedInputStream.read())!=-1) {
// System.out.print((char)by);
//
// }
long oldTime = System.currentTimeMillis();
byte[] bs = new byte[1024];
int len = 0;
// 一次读取一个字节数组
while ((len = bufferedInputStream.read(bs)) != -1) {
System.out.println(new String(bs, 0, len));
// String(byte[] bytes, int offset, int length)
}
bufferedInputStream.close();
long newTime = System.currentTimeMillis();
long time = newTime - oldTime;
System.out.println(time);
}
}
字节缓冲输出流:构造方式:
(第一种开发中) public BufferedOutputStream(OutputStream out):采用的默认的缓冲区大小(足够大了) ,来构造一个字节缓冲输出流对象
public BufferedOutputStream(OutputStream out,int size):指定size缓冲区大小构造缓冲输出流对象
IllegalArgumentException - 如果 size <= 0
写数据的方式:
一次写一个字节
write(int by)
一次写一个字节数组
write(byte[] b, int off, int len)
方法:
void flush() ;刷新缓冲区中的流
面试题:
字节缓冲输出流它的构造方法为什么不能直接传递路径/文件?
缓冲输入流/缓冲输出流,它只是在底层提供一个缓冲区数组,
底层实现文件的复制/读取/写入这些操作都依赖于基本流对象来操作(InputStream/OutputStream/FileInputStream/FileOutputstream)
代码示例
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws Exception {
// 构造一个字节缓冲输出流对象
// public BufferedOutputStream(OutputStream out)
/*
* OutputStream out = new FileOutputStream("out.txt") ; BufferedOutputStream bos
* = new BufferedOutputStream(out) ;
*/
// 符合Java的一种设计模式:装饰者设计模式(过滤器:Filter)
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("bos.txt"));
// 写数据
bos.write("hello".getBytes());
// 释放资源
bos.close();
}
}
存储文件IO流:永久存储(耗时)
数据库:永久存储
基本的字节流
文件字节输入流/文件字节输出流
高效的字节流(缓冲流)
操作一个视频文件,来测试速度问题
基本的字节流一次读取一个字节 ://耗时:85772毫秒
基本的字节流一次读取一个字节数组 :共耗时:216毫秒
高效的字节流一次读取一个字节 :共耗时:682毫秒
高效的字节流一次读取一个字节数组:共耗时:49毫秒
代码示例
package io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Demo5 {
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
// method1("f:\\a.jpg","copy1.jpg");//共耗时:891毫秒
// method2("f:\\a.jpg","copy2.jpg");//共耗时:15毫秒
// method3("f:\\a.jpg","copy3.jpg");//共耗时:31毫秒
method4("f:\\a.jpg", "copy4.jpg");// 共耗时:0毫秒
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
}
// 基本字节流一次读取一个字节
private static void method1(String src, String dest) throws Exception {
FileInputStream fileInputStream = new FileInputStream(src);
FileOutputStream fileOutputStream = new FileOutputStream(dest);
int by = 0;
while ((by = fileInputStream.read()) != -1) {
fileOutputStream.write(by);
}
fileInputStream.close();
fileOutputStream.close();
}
// 基本字节流一次读取一个字节数组
private static void method2(String src, String dest) throws Exception {
FileInputStream fileInputStream = new FileInputStream(src);
FileOutputStream fileOutputStream = new FileOutputStream(dest);
byte[] bs = new byte[1024];
int len = 0;
while ((len = fileInputStream.read(bs)) != -1) {
fileOutputStream.write(bs, 0, len);
}
fileInputStream.close();
fileOutputStream.close();
}
// 高效字节流一次读取一个字节
private static void method3(String src, String dest) throws Exception {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(dest));
int by = 0;
while ((by = bufferedInputStream.read()) != -1) {
bufferedOutputStream.write(by);
}
bufferedInputStream.close();
bufferedOutputStream.close();
}
// 高效字节流一次读取一个字节数组
private static void method4(String src, String dest) throws Exception {
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(dest));
byte[] bs = new byte[1024];
int len = 0;
while ((len = bufferedInputStream.read(bs)) != -1) {
bufferedOutputStream.write(bs, 0, len);
}
bufferedInputStream.close();
bufferedOutputStream.close();
}
}
使用字节流一次读取一个字节的方式,会造成中文乱码--->Java提供了一个字符流(专门用来解决中文乱码问题)
代码示例
public class FileInputStreamDemo {
public static void main(String[] args) throws Exception {
// 封装文件
// 一次读取一个字节的方式
FileInputStream fis = new FileInputStream("a.txt");
// 读数据
int by = 0;
while ((by = fis.read()) != -1) {
System.out.print((char) by);
}
// 释放资源
fis.close();
}
}
编码和解码:前后的编码格式要一致!
编码:
简单理解:将能看懂的东西--->看不懂的东西
解码:
看不懂的东西---能看懂的东西
举例: 谍战片
今天老地方见...
编码:
今---->字节---->二进制数据
解码:二进制数据-->十进制数据--->字节---->字符串
今
编码: 将字符串变成一个字节数组
public byte[] getBytes() :平台默认编码集(默认的是Gbk)
public byte[] getBytes(Charset charset) ;"指定编码格式
解码:将字节数组--->字符串
public String(byte[] bytes) :使用平台默认编码集(gbk)
public String(byte[] bytes,Charset charset):用指定的编码格式来解码
代码示例
public class StringDemo {
public static void main(String[] args) throws Exception {
// 定义一个字符串
String str = "你好";
// 编码和解码:前后必须一致
// 编码
// byte[] bys = str.getBytes() ;
byte[] bys = str.getBytes("utf-8");// -28, -67, -96, -27, -91, -67]
System.out.println(Arrays.toString(bys));// [-60, -29, -70, -61]
System.out.println("------------------");
// 解码
// public String(byte[] bytes) :使用平台默认编码集(gbk)
// String s = new String(bys) ;
// String s = new String(bys, "GUK") ;//一个中文对应三个字节
String s = new String(bys, "utf-8");// 一个中文对应三个字节
System.out.println(s);
}
}
需求:将a.txt文件中的内容进行复制,复制到当前项目下(b.txt)文本文件:优先采用字符流
源文件:a.txt---->Reader---->InputStreamReader---->FileReader
目的的文件:b.txt--->Writer-->OutputStreamWriter---->FileWriter
代码示例
package io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Demo8 {
public static void main(String[] args) throws Exception {
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("src\\io\\demo7.java"));
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("aa.txt"));
// 一次读取一个字符数组
/*
* char [] cs=new char[1024]; int len=0; while
* ((len=inputStreamReader.read(cs))!=-1){ outputStreamWriter.write(cs, 0, len);
* } inputStreamReader.close(); outputStreamWriter.close();
*/
// 一次读取一个字符
/*
* int ch=0; while ((ch=inputStreamReader.read())!=-1) {
* outputStreamWriter.write((char)ch); } inputStreamReader.close();
* outputStreamWriter.close();
*/
// 方式2:使用便捷类进行操作
FileReader fileReader = new FileReader("src//io//Demo8.java");
FileWriter fileWriter = new FileWriter("bb.java");
// 一次读取一个字符数组
char[] cs = new char[1024];
int len = 0;
while ((len = fileReader.read(cs)) != -1) {
fileWriter.write(cs, 0, len);
}
fileReader.close();
fileWriter.close();
}
}
字符转换输入流:InputStreamReaderInputStreamReader(InputStream in) :构造一个字符转换输入流,默认编码
public InputStreamReader(InputStream in,Charset cs) 构造一个字符转换输入流,指定编码
字符转换输入流=字节流+编码格式
代码示例
public class ReaderDemo {
public static void main(String[] args) throws Exception {
// 需求:要读取当前项目下的osw.txt,将内容输出在控制台上
// InputStreamReader isr =
// new InputStreamReader(
// new FileInputStream("osw.txt", "utf-8") ;
InputStreamReader isr = new InputStreamReader(new FileInputStream("osw.txt"), "gbk");
// 读数据
// 一次读取一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = isr.read(chs)) != -1) {
System.out.println(new String(chs, 0, len));
}
// 关闭资源
isr.close();
}
}
字符输出流写数据的功能:public void write(int c):写单个字符
public void write(char[] cbuf):写字符数组
public abstract void write(char[] cbuf, int off, int len):写字符数组的一部分
public void write(String str):写字符串
public void write(String str,int off, int len):写字符串的某一部分
flush和close方法的区别?
close:关闭该流,关闭该流对象以及与它相关联的资源文件,关闭之后,不能再对流对象进行操作了,否则会有异常
flush:刷新该流,防止一些文件(图片文件/音频文件)缺失,或者没有加载到流对象中,刷新了该流,还是可以对流对象进行操作
字符缓冲输入流/字符缓冲输出流
杂七杂八的流(properties:属性集合类/合并流/序列化Serializable/内存操作流)
NIO
代码示例
package io;
import java.io.FileWriter;
public class Demo10 {
public static void main(String[] args) throws Exception {
// 创建字符输出流对象
FileWriter fileWriter = new FileWriter("cc.txt");
// 写一个字符
fileWriter.write('a');
fileWriter.write(97);
// 刷新流
fileWriter.flush();
fileWriter.write(98);
fileWriter.flush();
char[] cs = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' };
// 写一个字符数组
fileWriter.write(cs);
// 写一个字符数组
fileWriter.write(cs, 0, 5);
fileWriter.flush();
// 写字符串
fileWriter.write("我爱高圆圆!!!");
fileWriter.flush();
// 写字符串的一部分
fileWriter.write("我爱高圆圆", 0, 4);
fileWriter.flush();
fileWriter.close();// 关闭流之前一定要刷新流
}
}
先使用字符缓冲输出流写数据,再使用字符缓冲输入流读数据,显示控制台上字符缓冲输出流:
特有功能:public void newLine():写入行分隔符
字符缓冲输入流:
特有功能:public String readLine():一次读取一行
代码示例
package io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class Demo11 {
public static void main(String[] args) throws Exception {
write();
BufferedReader bufferedReader = new BufferedReader(new FileReader("hhh.java"));
/*
* String string=bufferedReader.readLine(); System.out.println(string);
* string=bufferedReader.readLine(); System.out.println(string);
* string=bufferedReader.readLine(); System.out.println(string);
*/
// 代码在重复,改进版
String line = null;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
private static void write() throws Exception {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("hhh.java"));
// 写数据
for (int x = 0; x < 10; x++) {
bufferedWriter.write("hello" + x);
bufferedWriter.newLine();
bufferedWriter.flush();
}
bufferedWriter.close();
}
}
BufferedReader:字符缓冲输入流构造方法
public BufferedReader(Reader in)默认缓冲区大小构造字符缓冲输入流对象。
public BufferedReader(Reader in, int size)制定缓冲区大小构造字符缓冲输入流。
需求:读取当前项目下的bw.txt这个文件
package io;
import java.io.BufferedReader;
import java.io.FileReader;
public class Demo12 {
public static void main(String[] args) throws Exception {
// 创建字符缓冲输入流对象
BufferedReader bufferedReader = new BufferedReader(new FileReader("src\\io\\Demo11.java"));
char[] ch = new char[1024];
int len = 0;
while ((len = bufferedReader.read(ch)) != -1) {
System.out.println(new String(ch, 0, len));
}
bufferedReader.close();
}
}
在字符流中提供了一个更高效的流-->字符缓冲流字符缓冲输入流
字符缓冲输出流
BufferedWrier:文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入构造方法
BufferedWriter(Writer out) :默认缓冲区大小构造字符缓冲输出流对象
BufferedWriter(Writer out,int size):指定缓冲区大小构造字符缓冲输出流对象
代码示例
package io;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Demo13 {
public static void main(String[] args) throws IOException {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bw.txt"));
bufferedWriter.write("hello");
bufferedWriter.newLine();
bufferedWriter.write("world");
// 刷新流
bufferedWriter.flush();
// 关闭资源
bufferedWriter.close();
}
}
使用字符缓冲流进行复制操作 分别使用两种方式
1)一次读取一个字符数组
2)一次读取一行
代码示例
package io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class Demo14 {
public static void main(String[] args) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new FileReader("src\\io\\Demo12.java"));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("copy.java"));
// 一次读取一个字符数组
/*
* char[] cs=new char[1024]; int len =0; while
* ((len=bufferedReader.read(cs))!=-1) { bufferedWriter.write(cs, 0, len);
* bufferedWriter.flush(); } bufferedReader.close(); bufferedWriter.close();
*/
// 一次读取一行
String line = null;
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
bufferedReader.close();
bufferedWriter.close();
}
}
需求:把ArrayList集合中的字符串数据存储到文本文件ArrayList集合存储的元素为String类型,可以存储一些字符串
使用增强for遍历ArrayList
使用BufferedWriter(文本文件)
源文件:ArrayList<String>
目的地:BufferedWriter输出文本文件,给文件中写入字符
代码示例
package io;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
public class Demo15 {
public static void main(String[] args) throws Exception {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("hello");
arrayList.add("world");
arrayList.add("javaweb");
// 创建一个字符缓冲输出流
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("arrayList.java"));
// 使用增强for进行遍历
for (String string : arrayList) {
bufferedWriter.write(string);
bufferedWriter.newLine();
bufferedWriter.flush();
}
bufferedWriter.close();
}
}
复制文本文件(5种方式分别完成)文本文件:字符流
基本字符流一次读取一个字符
一次读取一个字符数组
字符缓冲流一次读取一个字符
一次读取一个字符数组
一次读取一行
代码示例
package io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class Demo16 {
public static void main(String[] args) throws Exception {
// method1("src//io/Demo15.java","copy.java");
method2("src//io/Demo15.java", "copy1.java");
}
private static void method1(String src, String dest) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new FileReader(src));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(dest));
// 一次读取一个字符数组
char[] cs = new char[1024];
int len = 0;
while ((len = bufferedReader.read(cs)) != -1) {
bufferedWriter.write(cs, 0, len);
bufferedWriter.newLine();
bufferedWriter.flush();
}
bufferedReader.close();
bufferedWriter.close();
}
private static void method2(String src, String dest) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new FileReader(src));
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(dest));
// 一次读取一行
String line = null;
while ((line = bufferedReader.readLine()) != null) {
// 一次写入一行
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
bufferedReader.close();
bufferedWriter.close();
}
}
需求:有一个文本文本,需要将文本文件中的内容放到ArrayList集合中,遍历集合获取元素 源文件:b.txt----->读取---->BuffferedReader
目的地:ArrayList<String>
代码示例
package io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
public class Demo17 {
public static void main(String[] args) throws Exception {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("hhh.java"));
BufferedReader bufferedReader = new BufferedReader(new FileReader("hhh.java"));
ArrayList<String> arrayList = new ArrayList<String>();
// 创建文件
for (int i = 0; i < 100; i++) {
bufferedWriter.write("hello java world!!! " + i);
bufferedWriter.newLine();
bufferedWriter.flush();
}
// 读取文件
String line = null;
while ((line = bufferedReader.readLine()) != null) {
// 将文件中的内容读取出来存储在arrayList数组中
arrayList.add(line);
}
for (String string : arrayList) {
System.out.println(string);
}
bufferedReader.close();
bufferedWriter.close();
}
}
需求:我有一个文本文件中存储了几个名称,请大家写一个程序实现随机获取一个人的名字。 1)封装一个文本文件:使用字符缓冲输入流读文件
2)创建一个ArrayList<String>
3)使用字符缓冲输入流readLine(),一次读取一行,就将该行数据添加到集合中
4)创建Random类对象
5)Random类对象.nextInt(集合对象.size()) ;
6)通过角标get(int index ):获取内容
代码示例
package io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class Demo18 {
private static Scanner in;
public static void main(String[] args) throws Exception {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("hhh.txt"));
BufferedReader bufferedReader = new BufferedReader(new FileReader("hhh.txt"));
ArrayList<String> arrayList = new ArrayList<String>();
// 创建文件
System.out.println("请输入人名");
in = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
String name = in.nextLine();
bufferedWriter.write(name);
bufferedWriter.newLine();
bufferedWriter.flush();
}
// 一次读取一行
String line = null;
while ((line = bufferedReader.readLine()) != null) {
arrayList.add(line);
}
bufferedReader.close();
bufferedWriter.close();
// 创建Random类对象
Random random = new Random();
// 获取随机数
int index = random.nextInt(arrayList.size());
// 通过角标查找对应元素
String name = arrayList.get(index);
System.out.println("幸运的人是:" + name);
}
}
内存操作流:适用于临时存储文件.内存操作输入流:byteArrayInputStream
ByteArrayInputStream(byte[] buf)
内存操作输出流: byteArrayOutputStream
构造方法:ByteArrayOutputStream()
内存操作流:一个程序结束后,那么流对象就会从内存中消失
代码示例
package io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class Demo19 {
public static void main(String[] args) throws Exception {
// 创建内存操作输出流对象
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
for (int i = 0; i < 10; i++)
byteArrayOutputStream.write(("helloworld" + i + " ").getBytes());
// 此流不需要关闭
byte[] buf = byteArrayOutputStream.toByteArray();
// 创建内存操作输入流对象
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buf);
// 一次读取一个字节
int by = 0;
while ((by = byteArrayInputStream.read()) != -1) {
System.out.print((char) by);
}
}
}
打印流 PrintWriter
源文件:StringDemo.java --->BufferedReader
目的文件:Copy.java ----->PrintWriter代码示例
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装文件
BufferedReader br = new BufferedReader(new FileReader("StringDemo.java"));
PrintWriter pw = new PrintWriter(new FileWriter("Copy.java", true));
// 一次读取一行
String line = null;
while ((line = br.readLine()) != null) {
// 向打印输出内容
pw.println(line);
}
// 释放资源
pw.close();
br.close();
}
}
数据流:针对基本类型的数据进行读写操作
数据输入流:DataInputStream
数据输出流:DataOutputStream
代码示例
package org.westos.io;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Demo {
public static void main(String[] args) throws Exception {
write();
read();
}
private static void write() throws Exception {
DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream("dos.txt"));
dataOutputStream.writeInt(10);
dataOutputStream.writeShort(100);
dataOutputStream.writeByte(120);
dataOutputStream.writeDouble(12.34);
dataOutputStream.writeFloat(12.56F);
dataOutputStream.writeBoolean(true);
dataOutputStream.writeChar('a');
dataOutputStream.close();
}
private static void read() throws Exception {
DataInputStream dataInputStream = new DataInputStream(new FileInputStream("dos.txt"));
int i = dataInputStream.readInt();
short s = dataInputStream.readShort();
byte b = dataInputStream.readByte();
double d = dataInputStream.readDouble();
float f = dataInputStream.readFloat();
boolean flag = dataInputStream.readBoolean();
char c = dataInputStream.readChar();
dataInputStream.close();
System.out.println(i);
System.out.println(s);
System.out.println(b);
System.out.println(d);
System.out.println(f);
System.out.println(flag);
System.out.println(c);
}
}
打印流
字符打印流(针对文本进行操作:PrintWriter)
字节打印流(printStream 和标准输出流有关系 System.out;)
PrintWriter:属于输出流
1)只能写数据(只能针对目的地文件进行操作),不能读数据(不能针对源文件进行操作)
2)可以针对文本文件直接进行操作
如果一个类的构造方法里面有File对象或者String类型数据,这个类可以对文本文件直接操作
FileInputStream
FileOutputStream
FileWriter
FileReader..
PrintWriter
3)自动刷新功能::PrintWriter(OutputStream out/Writer out,boolean autoflush);第二个参数如果是true 表示启动自动刷新功能
4)打印的方法:print(XXX x)/println(XXX xx)
package org.westos.io;
import java.io.FileWriter;
import java.io.PrintWriter;
public class Demo2 {
public static void main(String[] args) throws Exception {
PrintWriter printWriter = new PrintWriter(new FileWriter("pw.java"));
printWriter.println("hello");// 自动换行并且向pw.java文件打印内容
printWriter.println("java");
printWriter.println("world");
printWriter.flush();
printWriter.close();
}
}
输出一个文本文件,启动PrintWriter的自动刷新功能
package org.westos.io;
import java.io.FileWriter;
import java.io.PrintWriter;
public class Demo3 {
public static void main(String[] args) throws Exception {
PrintWriter printWriter = new PrintWriter(new FileWriter("pw2.java"), true);
printWriter.println("hello");
printWriter.println("world");
printWriter.println("javaEE");
printWriter.close();
}
}
SequenceInputStream 表示其他输入流的逻辑串联(合并流)构造方法
public SequenceInputStream(InputStream s1, InputStream s2)
复制文件
a.txt----->b.txt
c.txt----->d.txt
现在的需求:
a.txt+b.txt--->c.txt
StringDemo.java+SystemInDemo.java---->Copy.java
代码示例
package io;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
public class Demo3 {
public static void main(String[] args) throws Exception {
InputStream in1 = new FileInputStream("src\\io\\Demo.java");
InputStream in2 = new FileInputStream("src\\io\\Demo3.java");
// 创建合并流对象
SequenceInputStream sis = new SequenceInputStream(in1, in2);
// 创建一个字节缓冲输入流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));
// 原来怎么读写,现在依然这样读写
byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
// 关闭资源
sis.close();
bos.close();
}
}
sequenceInputStream另一种构造方式
public SequenceInputStream(Enumeration e)
将多个输入流对象进行合并
a.txt+b.txt+c.txt--->d.txt
代码示例
public class SequenceInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// StringDemo.java+SystemInDemo.java+PrintWriterDemo.java--->Copy.java文件中
// 定义一个集合Vector
Vector<InputStream> v = new Vector<InputStream>();
// 使用InputStream封装文件
InputStream s1 = new FileInputStream("StringDemo.java");
InputStream s2 = new FileInputStream("SystemInDemo.java");
InputStream s3 = new FileInputStream("PrintWriterDemo.java");
// 将流对象添加到集合中
v.add(s1);
v.add(s2);
v.add(s3);
// 特有功能
Enumeration<InputStream> en = v.elements();
// 创建合并输入流对象
SequenceInputStream sis = new SequenceInputStream(en);
// 创建字节缓冲输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));
// 一次读取一个字节数组
byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
// 关闭资源
bos.close();
sis.close();
}
}
sequenceInputStream另一种构造方式public SequenceInputStream(Enumeration e)
将多个输入流对象进行合并
a.txt+b.txt+c.txt--->d.txt
代码示例
public class SequenceInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// StringDemo.java+SystemInDemo.java+PrintWriterDemo.java--->Copy.java文件中
// 定义一个集合Vector
Vector<InputStream> v = new Vector<InputStream>();
// 使用InputStream封装文件
InputStream s1 = new FileInputStream("StringDemo.java");
InputStream s2 = new FileInputStream("SystemInDemo.java");
InputStream s3 = new FileInputStream("PrintWriterDemo.java");
// 将流对象添加到集合中
v.add(s1);
v.add(s2);
v.add(s3);
// 特有功能
Enumeration<InputStream> en = v.elements();
// 创建合并输入流对象
SequenceInputStream sis = new SequenceInputStream(en);
// 创建字节缓冲输出流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));
// 一次读取一个字节数组
byte[] bys = new byte[1024];
int len = 0;
while ((len = sis.read(bys)) != -1) {
bos.write(bys, 0, len);
bos.flush();
}
// 关闭资源
bos.close();
sis.close();
}
}
标准的输入输出流InputStream in = System.in
PrintStream out = System.out ;
jdk5以后,Java--->Scanner(InputStream in)
键盘录入
1)Scanner
2)BufferedReader里面包装字符转换输入流,包装System.in
代码示例
package io;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Demo5 {
public static void main(String[] args) throws Exception {
InputStream inputStream = System.in;
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
// BufferedReader bufferedReader=new BufferedReader(new
// InputStreamReader(System.in));
System.out.println("请输入一个字符串:");
String line = bufferedReader.readLine();
System.out.println("你输入的字符串为:" + line);
System.out.println("请输入一个整数:");
String integer = bufferedReader.readLine();
// 强制类型转换
int num = Integer.parseInt(integer);
System.out.println("你输入的整数为:" + num);
}
}
标准输出流* PrintStream ps = System.out ;
*使用BufferedWriter 去包装System.out
package io;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
public class Demo6 {
public static void main(String[] args) throws Exception {
/*
* System.out.println("我爱高圆圆");
* System.out.println("--------------------------------");
*/
PrintStream printStream = System.out;
printStream.println("我爱高圆圆");
System.out.println("---------------------------------");
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
bufferedWriter.write("hello");
bufferedWriter.newLine();
bufferedWriter.write("java");
;
bufferedWriter.newLine();
bufferedWriter.write("world");
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
}
}
序列化流 ObjectInputStream
ObjectOutputStream
java.io.NotSerializableException :当前类未实现序列化功能的异常
Serializable:接口 没有构造方法,没有字段,也没有方法
接口---->标记接口
自定义类要实现序列化功能,必须实现Serializable接口
类实现了serializable也意味着他是标记类
假设之前针对Peroson操作序列的时候,产生一个标记 Preson.class--->固定ID 100
name -100
age -100
已经序列化完毕了,然后又修改了Person类里面的一些东西,加入了toString()
Person.class---固定id -- 200
org.westos_01.Person; local class incompatible:
stream classdesc serialVersionUID = -428218385429329797,
local class serialVersionUID = -5865763454468005049
因为手动修改了这些类的属性/成员变量,将序列化版本Id改变了
InvalidClassException:一般情况:该类的序列版本号与从流中读取的类描述符的版本号不匹配
实际开发中,不想多次对当前这些序列化,如果这样做,非常麻烦?
如何解决呢?
让当前实现序列化功能的这个类产生一个固定ID,注意看程序有黄色警告线,直接就点它固定Id
比如:当前的这个类中有很多属性(性别,地址,学号...),某些属性不想被序列化,如何解决这样一个问题
代码示例
package io2;
import java.io.Serializable;
public class Person implements Serializable {
private String name;
transient int age;
// private int age;
public Person() {
super();
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
package io2;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class Demo {
private static ObjectOutputStream objectOutputStream;
private static ObjectInputStream objectInputStream;
public static void main(String[] args) throws Exception, Exception {
write();
read();
}
// 反序列化流对象 ObjectInputStream
private static void read() throws Exception, IOException {
objectInputStream = new ObjectInputStream(new FileInputStream("oos.txt"));
Object object = objectInputStream.readObject();
objectInputStream.close();
System.out.println(object);
}
// 序列化流对象 ObjectOutputStream
private static void write() throws Exception, IOException {
objectOutputStream = new ObjectOutputStream(new FileOutputStream("oos.txt"));
// Person person=new Person("高圆圆",37);
Person person2 = new Person("赵又廷", 39);
// objectOutputStream.writeObject(person);
objectOutputStream.writeObject(person2);
}
}
Properties:表示了一个持久的属性集(简称:属性集合类) extends Hashtable<K,V> Map集合的可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
public Properties():无参构造
代码示例
public class PropertiesDemo {
public static void main(String[] args) {
// 它继承Hashtable
// 创建一个属性集合类对象
// Properties<String,String> prop = new Properties<String,String>() ;
Properties prop = new Properties();
System.out.println(prop);
System.out.println("---------------------");
// 给属性集合类中的属性列表添加元素
prop.put("高圆圆", "赵又廷");
prop.put("文章", "马伊琍");
prop.put("黄晓明", "baby");
System.out.println(prop);
// 遍历属性集合类
Set<Object> keySet = prop.keySet();
for (Object key : keySet) {
Object value = prop.get(key);
System.out.println(key + "=" + value);
}
}
}
属性集合类的特有功能:public Object setProperty(String key, String value) :给属性列表中添加键和值,并且强制都使用String
public Set<String> stringPropertyNames():遍历的功能
public String getProperty(String key)用指定的键在此属性列表中搜索属性
代码示例
public class PropertiesDemo2 {
public static void main(String[] args) {
// 创建属性集合类对象
Properties prop = new Properties();
// 添加元素
prop.setProperty("张三", "20");
prop.setProperty("李四", "22");
prop.setProperty("王五", "18");
// 遍历
// 获取所有的键的集合
Set<String> keyset = prop.stringPropertyNames();
for (String key : keyset) {
// 通过键找值
String value = prop.getProperty(key);
System.out.println(key + "----" + value);
}
}
}
可以保存在流中或从流中加载,只能使用属性集合类public void store(Writer writer,String comments):把集合中的数据保存到文本文件中(属性集合)
public void load(Reader reader):将文本文件中的数据加载到属性集合中
举例:
打游戏:游戏进度的保存和游戏加载
代码示例
package io2;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Properties;
public class Demo4 {
public static void main(String[] args) throws Exception {
myStore();
myLoad();
}
private static void myLoad() throws Exception {
Properties properties = new Properties();
FileReader fileReader = new FileReader("name.txt");
// 将文本文件中的数据加载到属性集合中
properties.load(fileReader);
fileReader.close();
System.out.println(properties);
}
private static void myStore() throws Exception {
// 创建一个属性集合类对象
Properties properties = new Properties();
properties.setProperty("张三", "20");
properties.setProperty("文章", "29");
properties.setProperty("成龙", "55");
FileWriter fileWriter = new FileWriter("name.txt");
// 将属性集合中的数据存储到文本文件中
properties.store(fileWriter, "name's content");
fileWriter.close();
}
}
通过属性集合查找文本文件中的数据,如果存在则进行修改
代码示例
package io2;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Properties;
import java.util.Set;
public class Demo5 {
public static void main(String[] args) throws Exception {
Properties properties = new Properties();
FileReader fileReader = new FileReader("demo\\name.txt");
properties.load(fileReader);
System.out.println(properties);
fileReader.close();
// 遍历属性集合
Set<String> keySet = properties.stringPropertyNames();
for (String key : keySet) {
if ("文章".equals(key)) {
properties.setProperty(key, "666");
}
}
System.out.println(properties);
FileWriter fileWriter = new FileWriter("demo\\name.txt");
properties.store(fileWriter, "name's content");
}
}