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;
}
}
}