1. 字节流和字符流概要:
字节流:可以参考之前写的(普通字节流)
字符流:普通字符流;
便捷字符流:也属于字符流的一种,简单易记,缺点是不能指定编码表;
高效流:能够快速的读写数据;
2.数据输入输出流: 可以直接读写基本数据类型的流,示例代码如下;
//这是写数据,向文本文件写完记得关闭流,释放资源;
DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.txt"));
dos.writeInt(200);
dos.writeBoolean(false);
dos.writeDouble(3.14);
dos.writeUTF("你好");
dos.close();
//这是读数据,通过输入流实现,怎么写数据就怎么读数据,顺序不能乱;
DataInputStream dis = new DataInputStream(new FileInputStream("a.txt"));
int i = dis.readInt();
boolean b = dis.readBoolean();
double v = dis.readDouble();
String s = dis.readUTF();
System.out.println(i);
System.out.println(b);
System.out.println(v);
System.out.println(s);
dis.close();
3. 内存操作流:只操作内存中的数据,不操作文件,起中介作用;
又可以分为三种:
- 操作字节数组;
- 操作字符数组;
- 操作字符串;
//1. 内存操作流输出流,将数据写入其维护的字节数组缓冲区;
ByteArrayOutputStream bos = new ByteArrayOutputStream(200);
bos.write("你好".getBytes());
bos.write("世界".getBytes());
bos.write("hello".getBytes());
bos.write("world".getBytes());
//toByteArray() 取出ByteArrayOutputStream他所维护的字节数组
byte[] bytes = bos.toByteArray();
//把ByteArrayOutputStream字节数组缓冲区,转成字符串
String string = bos.toString();
System.out.println(string);
//创建内存操作流输入流,关联写入的字节数组缓冲区,进而读取字节数组缓冲区的数据;
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
int len=0;
byte[] bytes1 = new byte[1024];
//将缓冲区的数据通过内存操作流读出来,同时用普通输出流写入指定文件;
FileOutputStream out= new FileOutputStream("b.txt");
while ((len=bis.read(bytes1))!=-1){
out.write(bytes1,0,len);
}
bos.close();
bis.close();
out.close();
//2. 内存操作流之操作字符数组;
CharArrayWriter charArrayWriter = new CharArrayWriter(200);
charArrayWriter.write("abc");
charArrayWriter.write("abd");
charArrayWriter.write("abc3r");
//将维护的字符串转换成字符数组;
char[] chars = charArrayWriter.toCharArray();
String s = String.valueOf(chars);
String s1 = new String(chars);
System.out.println(s);
System.out.println(s1);
//也可将写入的数据直接转换成字符串
String string = charArrayWriter.toString();
System.out.println(string);
//3. 操作字符串
StringWriter stringWriter = new StringWriter();
stringWriter.write("aaaaa");
stringWriter.write("aaaaa");
stringWriter.write("aaaaa");
stringWriter.write("aaaaa");
stringWriter.write("aaaaa");
stringWriter.write("aaaaa");
//也可将写入的数据直接转换成字符串
String string = stringWriter.toString();
System.out.println(string);
3. 打印流:PrintStream,字节打印流& PrintWriter,字符打印流;
//1. 字节打印流:向f.txt文本文件中写入数据;
PrintStream printStream = new PrintStream(new File("f.txt"));
printStream.println(200);
printStream.println(600);
printStream.println("abc");
printStream.write("abc".getBytes());
printStream.close();
//** 标准输出流:向控制台打印,即向显示器打印;
PrintStream out = System.out;
out.println(200);//打印并换行;
out.print(200);//打印不换行
out.print(200);
out.print(200);
out.print(200);
out.close();
//字符打印流:参数2表示自动刷新是否开启;
PrintWriter printWriter = new PrintWriter(new FileOutputStream("f.txt"),true);
printWriter.println("abc");
printWriter.println("abc");
printWriter.println("abc");
//**注意:如果开启自动刷新,就必须使用println、printf 或 format中的一个方法,才能刷新;
//**另外,字符流没有自动刷新的情况下,必须手动刷新;
//printer.flush();
printer.close();
4. Scanner键盘扫描输入流:
nextLine();//录入数据方法;
下面为简单实例:复制文件到指定文件
//构造一个新的 Scanner,它生成的值是从指定的输入流扫描的。
//Scanner扫描录入可以关联从字节输入流传入的文件
Scanner scanner = new Scanner(new FileInputStream("MyTest.java"));
PrintWriter writer = new PrintWriter(new FileOutputStream("MyTest234.java"), true);
//Scanner边扫描关联文件数据,边录入数据
while (scanner.hasNextLine()){
String s = scanner.nextLine();//录入数据
// System.out.println(s);
writer.println(s);
System.out.println(s);//打印到显示器控制台
}
//释放资源
scanner.close();
writer.close();
//**高效的流也可以关联键盘录入:
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
while (true) {
System.out.println("请输入内容");
String s = bufferedReader.readLine();//读取键盘录入的数据;
//自己定义一个结束标记
if ("886".equals(s)) {//若键盘录入为指定内容,结束录入;
break;
}
System.out.println(s);//打印键盘录入的数据
}
5. 随机访问流:RandomAccessFile
此流最大的特点是可读可写,创建流对象时,可以在参数二声明“rw”,即可;
此流有文件指针,可以定位到指定位置,继续读取文件数据;
//向文本文件中写入不同类型的数据
RandomAccessFile rw = new RandomAccessFile(new File("hi.txt"), "rw");
rw.writeInt(100); //4
rw.writeBoolean(true);
rw.writeDouble(3.14);
rw.writeUTF("你好");
rw.close();
将一个mp3文件,拆分成多个小文件,再将多个小文件,合并成一个mp3文件
比如 :大海.mp3 大小是 3.8M 切成多份小的mp3 每份文件1M 切割4份,当然最后一份是 0.8M,然后将4分小的mp3文件再合并回成一首歌。
package org.westos.demo1102;
import java.io.*;
import java.util.ArrayList;
public class Test3 {
public static void main(String[] args) throws IOException {
//封装要拆分的源文件
File file1 = new File("许巍 - 曾经的你.mp3");
//封装要写入的文件夹;
File file2 = new File("C:\\Users\\Administrator\\Desktop\\test");
ChaiFen(file1,file2);
HeCheng(file2);
}
private static void ChaiFen(File file1,File file2) throws IOException {
long filePointer=0;
//计算文件相对大小,可以判断需要循环几次才可将文件分别读完
long length = file1.length();
System.out.println((length/(1024*1024))+"MB");
for (int i = 1; i <=length+1 ; i++) {
RandomAccessFile readfile = new RandomAccessFile(file1,"rw");
File file = new File(file2+"\\"+i+"许巍 - 曾经的你.mp3");
RandomAccessFile writefile = new RandomAccessFile(file, "rw");
int len=0;
byte[] bytes=new byte[0];
bytes = new byte[1024*1024];
//每次重新写出文件数据时,必须将文件指针录入到读取文件的位置;
//并且将写的指针置0,才能写出1024KB数据;
readfile.seek(filePointer);
writefile.seek(0);
len=readfile.read(bytes);
writefile.write(bytes,0,len);
if ((len=readfile.read())==-1) {
break;
}
//录入读取到的文件指针;
filePointer = readfile.getFilePointer();
System.out.println(filePointer);
writefile.close();
readfile.close();
}
}
private static void HeCheng(File file) throws IOException {
File[] files = file.listFiles();
ArrayList<File> list = new ArrayList<>();
for (File f : files) {
if (f.isFile()&&f.getName().endsWith(".mp3")){
File filemusic = new File(file + "\\" + f.getName());
list.add(filemusic);
}
}
File[] files1 = file.listFiles();
FileOutputStream out = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\test\\music.mp3");
for (File f : files) {
int len=0;
byte[] bytes=new byte[0];
bytes = new byte[1024*1024];
FileInputStream in = new FileInputStream(f);
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
out.flush();
}
in.close();
}
out.close();
System.out.println(list);
}
}
6. 序列化流和反序列流:将一个对象保存到文件中或将对象读取回来;
public static void main(String[] args) throws IOException, ClassNotFoundException {
File file = new File("data.txt");
WriteObj(file);
ReadObj(file);
}
private static void ReadObj(File file) throws IOException, ClassNotFoundException {
//将文本文件关联序列化输入流读取
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(file));
//依次读取学生对象,并输出
Object obj = objIn.readObject();
Student student = (Student) obj;
String name = student.getName();
int age = student.getAge();
System.out.println(name + "====" + age);
obj = objIn.readObject();
student = (Student) obj;
name = student.getName();
age = student.getAge();
System.out.println(name + "====" + age);
obj = objIn.readObject();
student = (Student) obj;
name = student.getName();
age = student.getAge();
System.out.println(name + "====" + age);
}
private static void WriteObj(File file) throws IOException {
Student student = new Student();
student.setName("张三");
student.setAge(23);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(24);
Student student3 = new Student();
student3.setName("王五");
student3.setAge(25);
//NotSerializableException
//将文本文件关联序列化输出流;
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(file));
//将学生对象写入文本文件中;
objOut.writeObject(student);
objOut.writeObject(student2);
objOut.writeObject(student3);
objOut.close();
}
//学生类:一个类对象,要想序列化成功,该类要实现 Serializable 这个标记接口
public class Student implements Serializable {
//这个类,实现了Serializable接口最好再生成一个serialVersionUID
public static final long serialVersionUID = 8490232753105806755L;
private String name;
//transient 排除这个字段不要序列化
//private transient int age;
private int 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;
}
}
7. 属性集合Properties:
无法指定泛型,键值都是字符串类型,继承自Hashtable集合
//用特有的方法,来存键值,键值的数据类型,已经规定为字符串类型
map.setProperty("张三", "25");
map.setProperty("王五", "26");
//通过键找值,如果没找到返回null
String value = map.getProperty("李四");
System.out.println(value);
//如果这个键没有找到对应的值,则返回默认值;参数2:就是默认值
String value2= map.getProperty("文章","姚笛");
System.out.println(value2);
//举例更改键对应的值:
public static void main(String[] args) throws IOException {
//一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。
//请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”
Properties map = new Properties();
//向文件中写入数据
SetProperties(map);
//修改键值对中,指定键的值
ChangeProperties(map);
}
private static void ChangeProperties(Properties map) throws IOException {
map.load(new FileInputStream("datanew.properties"));
String property = map.getProperty("lisi");
//获得"lisi"键对应的值后,判断值只要非空,就更改值为100
while (property!=null){
map.setProperty("lisi","100");
break;
}
Set<Object> obj = map.keySet();
for (Object keyobj : obj) {
Object valueobj = map.get(keyobj);
String key= (String) keyobj;
String value= (String) valueobj;
System.out.println(key+"\t"+value);
}
}
private static void SetProperties(Properties map) throws IOException {
map.setProperty("zhangsan","90");
map.setProperty("lisi","80");
map.setProperty("wangwu","85");
//把对象数据通过属性集合,存在指定的文件中;
map.store(new FileWriter("datanew.properties"),null);
}
**顺序流SequenceInputStream **
可以将其他流逻辑串联;
它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。
File file1 = new File("许巍 - 曾经的你.mp3");
File file2 = new File("许巍 - 蓝莲花.mp3");
File file3 = new File("许巍-歌曲大联唱.mp3");
FileInputStream in1 = new FileInputStream(file1);
FileInputStream in2 = new FileInputStream(file2);
FileInputStream in3 = new FileInputStream(file3);
//串联输入流
SequenceInputStream allIn = new SequenceInputStream(in1, in2);
SequenceInputStream allIn2 = new SequenceInputStream(allIn, in3);
File targetFile = new File("C:\\Users\\Administrator\\Desktop\\test1\\歌曲合并all.mp3");
FileOutputStream out = new FileOutputStream(targetFile);
//将所有流所关联的文件数据依次读取,并输出写到到目标文件中去
int len = 0;
byte[] bytes = new byte[1024 * 8];
while ((len = allIn2.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
allIn2.close();
allIn.close();
out.close();
同样可以吧输入流存入集合,将集合迭代器关联顺序流,同样可以完成串联复制文件;
File file1 = new File("许巍 - 曾经的你.mp3");
File file2 = new File("许巍 - 蓝莲花.mp3");
File file3 = new File("许巍-歌曲大联唱.mp3");
FileInputStream in1 = new FileInputStream(file1);
FileInputStream in2 = new FileInputStream(file2);
FileInputStream in3 = new FileInputStream(file3);
//将三个流对象存入集合
Vector<FileInputStream> vector = new Vector<>();
vector.add(in1);
vector.add(in2);
vector.add(in3);
//创建集合的迭代器,迭代遍历集合中的流对象元素;
Enumeration<FileInputStream> elements = vector.elements();
//将迭代器对象关联进顺序流中
SequenceInputStream all = new SequenceInputStream(elements);
File targetFile = new File("歌曲合并all22222.mp3");
FileOutputStream out = new FileOutputStream(targetFile);
//顺序流读取迭代器进而读取集合中流对象所关联的文件,边读取边写出数据到目标文件中;
int len = 0;
byte[] bytes = new byte[1024 * 8];
while ((len = all.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
all.close();
out.close();