Day18
一、文件的字节输入流与输出流
1.使用字节流读数据
public FileInputStream(Stringname)
开发步骤:
1):创建字节文件输入流对象
2)读数据
3)释放资源
读数据的两种方式:
1)public int read():一次读取一个字节
2)public int read(byte[] b):一次读取一个字节数组
一次读取一个字节数组的速率比一次读取一个字节快。
运用while循环读取,当该文件读取完后 ,返回-1就是结束条件
例:
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("a.txt");
//方法一:一次读取一个字节
// int by=0;
// while((by=fis.read())!=-1){
// System.out.println((char)by);
// }
//方法二:一次读取一个字节数组
byte [] bys=new byte[1024];
int len=0;
while((len=fis.read(bys))!=-1){
System.out.println(newString(bys,0,len));
}
fis.close();
}
}
2.使用字节输入流和字节输出流复制文件
1)E盘下有个geek.exe文件,将其内容复制到当前项目下“清理工具.exe”中
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Copy {
publicstatic void main(String[] args) throws IOException {
//封装数据源
FileInputStream fis = new FileInputStream("E:\\geek.exe");
//封装目的地
FileOutputStream fos = new FileOutputStream("清理工具.exe");
//读写操作
//一次读取一个字节
int bys = 0;
while((bys = fis.read()) != -1) {
//写数据
fos.write(bys);
}
//释放资源
fis.close();
fos.close();
}
}
3.由于字节数组比一次读取一个字节更快,从而引出类更高效的一种流:字节缓冲流
字节缓冲输入流:BufferedInputStream
字节缓冲输出流:BufferedOutputStream
字节缓冲输出流构造方式:
public BufferedOutputStream(OutputStream out):默认缓冲区大小(默认缓冲大小已经足够大了)
为什么字节缓冲流不能直接针对文件进行操作呢?
缓冲流只是提供一个缓冲区,针对IO进行实现数据的传输实际是通过底层基本流进行实现的,所以缓冲流不能直接对文件操作。
flush()和close()方法的区别?
flush():刷新缓冲区的流,强迫将缓冲字节都写到该流中,刷新之后是可以写数据的。
close():关闭流对象所指向指向的这个资源文件,一旦关闭,写数据,写不进去的。
字节缓冲输入流构造方法:
public BufferedInputStream(InputStreamin) :指定默认缓冲区大小创建字节缓冲输入流对象
缓冲输入流:一次读取一个字节:
一次读取一个字节数组
两种方式的读取任选一种
4. 对于图片文件,音频文件,视频文件,优先采用字节缓冲输入流(高效流)一次读取一个字节数组。复制时间比较。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileDemo {
publicstatic void main(String[] args) throws IOException {
long startTime = System.currentTimeMillis();
// method1("D:\\01_回顾内容.exe","a1.exe");//共耗时:223618毫秒
method2("D:\\01_回顾内容.exe","a2.exe");//共耗时:440毫秒
// method3("D:\\01_回顾内容.exe","a3.exe");//共耗时:149302毫秒
// method4("D:\\01_回顾内容.exe","a4.exe"); //共耗时:422毫秒
long endTime = System.currentTimeMillis();
System.out.println("共耗时:" +(endTime - startTime) + "毫秒");
}
// 高效字节流(字节缓冲输入流)一次读取一个字节数组
// private static void method4(String srcString, String destString) throws IOException{
// BufferedInputStream bis = new BufferedInputStream(new
// FileInputStream(srcString)) ;
// BufferedOutputStream bos = new BufferedOutputStream(new
// FileOutputStream(destString)) ;
// byte[] bys = new byte[1024] ;
// int len = 0 ;
// while((len=bis.read(bys))!=-1){
// bos.write(bys, 0, len) ;
// bos.flush() ;
// }
// bis.close() ;
// bos.close() ;
// }
// 高效字节流(字节缓冲输入流)一次读取一个字节
// privatestatic void method3(String srcString, String destString)
// throwsIOException {
// BufferedInputStreambis = new BufferedInputStream(new FileInputStream(
// srcString));
// BufferedOutputStreambos = new BufferedOutputStream(
// newFileOutputStream(destString));
// intby = 0;
// while((by = bis.read()) != -1) {
// bos.write(by);
// bos.flush();
// }
// bis.close();
// bos.close();
// }
// 基本字节流(FileInputStream)一次读取一个字节数组
privatestatic void method2(String srcString, String destString)
throwsIOException {
FileInputStreamfis = new FileInputStream(srcString);
FileOutputStreamfos = new FileOutputStream(destString);
byte[]bys = new byte[1024];
intlen = 0;
while((len = fis.read(bys)) != -1) {
fos.write(bys,0, len);
}
fis.close();
fos.close();
}
// 基本字节流(FileInputStream)一次读取一个字节
// private static void method1(String srcString, String destString) throws
// IOException {
// // TODO Auto-generated method stub
// FileInputStream fis = new FileInputStream(srcString);
// FileOutputStream fos = new FileOutputStream(destString) ;
// int by = 0 ;
// while((by=fis.read())!=-1){
// fos.write(by) ;
// }
// fis.close() ;
// fos.close() ;
// }
}
5. 字节流一次读取一个字节,出现了中文乱码:
原因是:给字节进行强制类型转换,代码的注释中有中文,并且平台默认编码:GBK格式:一个中文对应的两个字节
使用字符流来进行操作:字符流就必须指定编码格式
计算机是如何识别中文的?
1)每个中文左边对应的字节一定是负数
2)GBK格式:右边的字节可以中正数,可以是0,可以是负数
import java.util.Arrays;
public class Demo {
publicstatic void main(String[] args) {
//定义一个字符串
//String s = "abcdefg" ;
//[97, 98, 99, 100, 101, 102, 103]
Strings = "我爱学Java";
//当前平台默认的编码集:GBK:一个中文对应两个字节
//[-50, -46, -80, -82, -47, -89, 74, 97, 118, 97]
//将当前字符串转换成字节数组
byte[]bys = s.getBytes();
System.out.println(Arrays.toString(bys));
}
}
编码:就是能看懂的字符串转换成看不懂的字节数组
public byte[] getBytes(Charset charset):将字符串转换成字节数组,指定编码格式(字符集)
解码:就是将看不懂的字节数组----->能看懂的:将字节数组--->字符串
public String(byte[] bytes, Charset charset)通过使用指定的 编码格式 解码指定的 byte 数组,构造一个新的String。
import java.io.IOException;
import java.util.Arrays;
public class StringDemo2 {
publicstatic void main(String[] args) throws IOException {
Strings = "我爱看书";
//编码
//byte[] bys = s.getBytes("utf-8") ;
//utf-8:[-26, -120, -111, -25, -120, -79, -25, -100, -117, -28, -71, -90]
//如果不写编码格式:默认GBK
byte[] bys = s.getBytes();// GBK[-80, -82, -60, -29]
//System.out.println(bys);
System.out.println(Arrays.toString(bys));
//解码
//public String(byte[] bytes, Charset charset)
//String str = new String(bys, "GBK") ;
String str = new String(bys);// 默认GBK
System.out.println(str);//我爱看书
}
}
二、字符输入流和输出流
1. 字符输入流:字节输入流+编码格式(默认GBK)
例:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderDemo {
publicstatic void main(String[] args) throws IOException {
InputStreamReaderisr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");// 默认为GBK格式,可以不写
char []chs = new char[1024];
int len = 0;
while((len = isr.read(chs)) != -1) {
System.out.println(newString(chs, 0, len));
}
isr.close();
}
}
2.字符输出流:Writer:是一个抽象类
使用的是该抽象类的子类:OutputStreamWriter------>字符转换流:可以将字节输出流转换字符流
public OutputStreamWriter(OutputStreamout,Charset cs):创建一字符输出转换流对象,指定编码格式
字节输出流+编码格式---->字符输出流
编码格式:使用平台的默认编辑集进行编码:GBK
例:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class OutStreamWriterDemo {
publicstatic void main(String[] args) throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),"GBK");// 默认为GBK格式,可以不写
osw.write("中国我爱你");
osw.close();
}
}
3. 使用字符转换流进行操作数据的时候:字节流+编码格式
在书写代码名称非常长,Java提供了以中更简单的类:便捷类:
字符转换输入流:InputStreamReader----->FileReader
FileReder(String fileName)
字符转换输出流:OutputStreamWriter---->FileWriter
FileWriter(String fileName)
例:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 使用字符流进行读写操作
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class CopyDemo {
publicstatic void main(String[] args) throws IOException {
// //创建字符转换输入流对象
// InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"));
// //封装目的地
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"));
// //一次读取一个字符数组
// char []chs = new char[1024];
// int len = 0;
// while((len = isr.read(chs)) != -1) {
// //写数据:
// osw.write(chs,0, len);
// //刷新流
// osw.flush();
// }
// //释放资源
// isr.close();
// osw.close();
//上面代码书写太长,使用便捷类
//数据源:a.txt---->字符流读数据:InputStreamReader------>便捷类:FileReader
//目的地:b.txt---->字符流写数据:OutputStreamWriter----->便捷类:FileWriter
//1)封装数据源和目的地
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
//一次读取一个字符数组
char []chs = new char[1024];
int len = 0;
while((len = fr.read(chs)) != -1) {
fw.write(chs,0, len);
fw.flush();
}
//释放资源
fw.close();
fr.close();
}
}
4. 关于字符输出流写数据的方法:
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):写字符串的一部分
5. 字符流为了提高读写速度,Java就提供了一个字符缓冲流的类:
BufferedReader:字符缓冲输入流
BufferedWriter:字符缓冲输出流
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
可以指定缓冲区的大小,或者接受默认的大小
构造方式:
publicBufferedWriter(Writer out):创建默认缓冲区大小的一个字符缓冲输出流
例:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedReaderDemo {
publicstatic void main(String[] args) throws IOException {
// BufferedWriter bw = new BufferedWriter(new FileWriter("abc.txt"));
// //写数据
// bw.write("hello");
// bw.write("world");
// bw.write("Javaweb");
// //刷新流
// bw.flush();
// //关闭资源
// bw.close();
//读数据
BufferedReader br = new BufferedReader(new FileReader("abc.txt"));
//方式1:一次读取一个字符
//int ch = 0;
//while ((ch = br.read()) != -1) {
//System.out.print((char) ch);
//}
//方式2:一次读取一个字符数组
char []chs = new char[1024];
int len = 0;
while((len = br.read(chs)) != -1) {
System.out.println(newString(chs, 0, len));
}
//关闭资源
br.close();
}
}
6. 字符缓冲输入流的特有功能:
BufferedWriter:
public void newLine():写入一个换行符号
BufferReader:
public String readLine():一次读取一行
例:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedDemo {
publicstatic void main(String[] args) throws IOException {
Write();
Read();
}
privatestatic void Read() throws IOException {
BufferedReaderbr = new BufferedReader(new FileReader("abc.txt"));
//使用循环,当数据读取完毕,如果返回值是null,说明已经读完了
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
//释放资源
br.close();
}
privatestatic void Write() throws IOException {
BufferedWriterbw = new BufferedWriter(new FileWriter("abc.txt"));
//写数据
for(int x = 0; x < 5; x++) {
bw.write(x+" "+"hello javaweb!" );
//没有使用这个方法之前:需要写入换行符号
//bw.write("\r\n") ;
//使用特有功能
bw.newLine();
//刷新该流
bw.flush();
}
//释放资源
bw.close();
}
}
7. 使用IO流的形式读数据
BufferedReadr进行包装
InputStream is = System.in;//标准输入流
使用is对象能不能一次读取一个数据呢?
不能使用它进行读取数据,BufferedReader可以
BufferedReader br = newBufferedReader(is);
字符缓冲输入流只能针对字符输入流进行操作,不能针对字节流进行操作
需要将标准输入流转换成字符输入流:InputStreamReader(InputStream in)
创建字符转换输入流对象
InputStreamReader isr = new InputStreamReader(is) ;
创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(isr) ;
一步走
BufferedReader br = new BufferedReader(newInputStreamReader(System.in));
例:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public classBufferedReaderDemo2 {
public static void main(String[] args) throws IOException {
//运用Scanner
// Scannersc = new Scanner(System.in);
// System.out.println("请输入一个整数:");
// int i = sc.nextInt();
// System.out.println("你输入的整数是:" + i);
// 使用IO流的形式读数据
BufferedReaderbr = new BufferedReader(newInputStreamReader(System.in));
System.out.println("请输入一个整数:");
Stringstr= br.readLine();// 返回值是一个字符串
int i = Integer.parseInt(str);
System.out.println("你输入的整数是:" + i);
}
}
Day19
1. 数据流
DataOutputStream和DataInputStream
都属于数据流:可以针对Java基本数据类型的数据进行读写操作
DataOutputStream构造方法
public DataOutputStream(OutputStream out)
例:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataStreamDemo {
publicstatic void main(String[] args) throws IOException {
// write();
read();
}
//读数据
privatestatic void read() throws IOException {
//创建数据输入流对象
DataInputStream dis = new DataInputStream(new FileInputStream("ab.txt"));
//读数据
byte b = dis.readByte();
int i = dis.readInt();
short s = dis.readShort();
long l = dis.readLong();
char c = dis.readChar();
boolean flag = dis.readBoolean();
float f = dis.readFloat();
double d = dis.readDouble();
//释放资源
dis.close();
System.out.println(b);
System.out.println(i);
System.out.println(s);
System.out.println(l);
System.out.println(c);
System.out.println(flag);
System.out.println(f);
System.out.println(d);
}
//写数据
privatestatic void write() throws IOException {
//创建数据输出流对象
DataOutputStream dos = new DataOutputStream(new FileOutputStream("ab.txt"));
//写数据
dos.writeByte(24);
dos.writeInt(50);
dos.writeShort(120);
dos.writeLong(1000000L);
dos.writeChar('A');
dos.writeBoolean(true);
dos.writeFloat(15.36F);
dos.writeDouble(34.23);
//释放资源
dos.close();
}
}
2. ByteArrayInputStream和ByteArrayOutStream
内存操作流:针对内存的数据进行操作的,程序一结束,这些内存中的数据就消失掉了!
特点:针对小文件进行操作(聊天室项目中使用它进行发送文件)
ByteArrayOutputStream:
public ByteArrayOutputStream():创建默认的缓冲区大小的内存操作输出流(单位是字节)
成员方法:
public byte[] toByteArray()创建一个新分配的 byte数组(将内存操作输出流对象转换成字节数组)
void reset():重置内存操作输出流
ByteArrayInputStream:内存操作输入流:
public ByteArrayInputStream(byte[] buf):参数数一个字节数组(缓冲数组)
内存操作流:查看其释放流对象的源码:
public void close() throws IOException {}
并没有具体的关闭流对象,所以此流对象可以不关闭
例:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class ByteArrayStreamDemo {
publicstatic void main(String[] args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for(int i = 0; i < 5; i++) {
System.out.println(("Hello"+ i).getBytes());
//关闭资源
// baos.close();//并没有具体的关闭流对象,所以此流对象可以不关闭
//将内存操作输出流对象转换成字节数组
//public byte[] toByteArray()创建一个新分配的 byte数组(将内存操作输出流对象转换成字节数组)
byte []buffer = baos.toByteArray();
//创建内存操作输入流对象
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
//一次读取一个字节
int bys= 0;
while((bys= bais.read()) != -1) {
System.out.print((char)bys);
}
//关闭资源
//bais.close();
}
}
}
3. 打印流:
字节打印流:PrintStream
字符打印流:PrintWriter
打印流特点:
1)在复制文件的,打印流不能操作数据源,只能操作目的地的数据(只能输出数据)
2)打印流可以有自动刷新的功能
3)打印流可以直接针对文本文件进行操作:
什么情况下是直接可以针对文本文件进行操作?
查API的时候,看流中构造方法,只要构造方法的参数有File类或者是String类型,都可以针对文本文件进行操作
比如:FileInputStream FileOutputStream FileReader FileWriter
PrintWriter:
构造方法:
public PrintWriter(String fileName)
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterDemo {
publicstatic void main(String[] args) throws IOException {
//创建字符打印流对象
PrintWriter pw = new PrintWriter("pw.txt");
//写数据
pw.write("Hello");
pw.write("world");
pw.write("Javaweb!");
//刷新
pw.flush();
//释放资源
pw.close();
}
}
4. PrintWriter:有自动刷新功能:
public PrintWriter(Writer out,booleanautoFlush)
第二个参数指定为true,则启动自动刷新
PrintWriter pw = new PrintWriter(newFileWriter("pw.txt"),true) ;
加入自动刷新功能并且在写数据的时候,使用println():换行
println("hello")
相当于: pw.write("");
pw.newLine();
pw.flush();
例:
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterDemo2 {
publicstatic void main(String[] args) throws IOException {
//创建字符打印流对象
PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true);// 启动自动刷新功能
//写数据
pw.write("hello");
pw.write("world");
pw.write("javaweb");//写入在一行
//使用println
pw.println("hello");
pw.println("world");
pw.println("javaweb");//写入在三行
//关闭流资源
pw.close();
}
}
5. 复制文件
需求:将当前项目下的PrintWriterDemo.java中的内容复制到当前项目下Copy.java文件中
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class CopyFileDemo {
publicstatic void main(String[] args) throws IOException {
// //封装数据源
// BufferedReader br = new BufferedReader(new FileReader("PrintWriterDemo.java"));
// //封装目的地
// BufferedWriter bw = new BufferedWriter(new FileWriter("Copy.java"));
// //使用BufferedReader中的特有功能读写操作
// String line = null;
// while((line = br.readLine()) != null) {
// //写数据
// bw.write(line);
// //换行
// bw.newLine();
// //刷新流
// bw.flush();
// }
// //释放资源
// bw.close();
// br.close();
//改进
//封装数据源
BufferedReader br = new BufferedReader(new FileReader("PrintWriterDemo.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();
}
}
6. 标准输入和输出流
System类中有两个字段:
In:----->InputStream is = System.in ;
Out:----->PrintStream ps = System.out ;
System.out.println();
import java.io.PrintStream;
public class SystemOutDemo {
publicstatic void main(String[] args) {
//经常使用输出语句
System.out.println("hello");
System.out.println("world");
//字节打印流
PrintStream ps = System.out ;
//字节打印流调用PrintStream类中的方法
ps.println("javaweb");//打印一个字符串数据并且终止当前行
ps.println("javaweb");
}
}
7. 使用BufferedReader完成录入数据:
使该流封装字符转换输入流,然后使用字符转换输入流封装字节流
按照上述方式,将BufferedWriter层层封装标准输出流,将数据打印控制台
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
public class SystemOutDemo2 {
publicstatic void main(String[] args) {
//写入一个分隔符:newLine()是BufferedWriter类中的方法
// BufferedWriter bw = new BufferedWriter(ps);
//将字节打印流转换成字符流OutputStreamWriter osw = new OutputStreamWriter(ps) ;
//创建字符缓冲输出流对象BufferedWriter bw = new BufferedWriter(osw) ;
BufferedWriter bw = null;
try{
bw= new BufferedWriter(new OutputStreamWriter(System.out));
//写数据
bw.write("hello");
bw.newLine();
bw.write("world");
bw.newLine();
bw.write("Javaweb");
bw.newLine();
//刷新
bw.flush();
}catch (IOException e) {
e.printStackTrace();
}finally {
//对流对象进行判断
if(bw != null) {
try{
bw.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
8.RandomAccessFile
RandomAccessFile:随机访问流:此类的实例支持对随机访问文件的读取和写入
不是实际意义上的流,因为它继承自Object类
常用的构造方法:
public RandomAccessFile(String name, Stringmode)
参数一:指定该文件的路径
参数二:指定的一种模式:常用的模式:"rw",这种模式是可以读也可以写
例:
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileDemo {
public static void main(String[] args) throws IOException {
// write();
read();
}
privatestatic void read() throws IOException {
RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");
//读数据
byte b = raf.readByte();
System.out.println(b);
//public long getFilePointer():返回此文件中的当前偏移量文件开头的偏移量(以字节为单位)
System.out.println("getFilePointer:"+raf.getFilePointer());
char ch = raf.readChar();
System.out.println(ch);
String str = raf.readUTF();
System.out.println(str);
}
//写数据
privatestatic void write() throws IOException {
//创建访问流对象
RandomAccessFile raf = newRandomAccessFile("raf.txt","rw");
raf.writeByte(50);
raf.writeChar('z');
raf.writeUTF("我爱中国");
//关闭资源
raf.close();
}
}
9. SequenceInputStream
1)SequenceInputStream:合并流(读数据):表示其他输入流的逻辑串联
合并流在复制文件的时候,只能操作数据源,不能操作目的地
例:
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
public class SequenceInputStreamDemo {
public static void main(String[] args) throws IOException {
//封装两个java文件
InputStream is1 = new FileInputStream("RandomAccessFileDemo.java");
InputStream is2 = new FileInputStream("FileInputStreamDemo.java");
//创建合并流对象
SequenceInputStream sis = new SequenceInputStream(is1,is2);
//封装目的地
BufferedOutputStream os=new BufferedOutputStream(new FileOutputStream("twoCopy.java"));
//一次一个字节数组
byte [] bys=new byte[1024];
int len=0;
while((len=sis.read(bys))!=-1){
os.write(bys,0,len);
os.flush();
}
sis.close();
os.close();
}
}
2) SequenceInputStream的另一种构造方法:复制多个文件
public SequenceInputStream(Enumeration<? extends InputStream> e)
Vector集合中的特有功能:
public Enumeration<E> elements()
例如:
之前的操作:
a.txt--->b.txt
c.txt--->d.txt
e.txt--->f.txt
现在:a.txt+b.txt+e.txt---->f.txt
例:
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
public class SequenceInputStreamDemo2 {
publicstatic void main(String[] args) throws IOException {
//创建一个Vector集合,泛型数据类型为<InputStream>
Vector<InputStream> v = new Vector<InputStream>();
//封装三个java文件
InputStream is1 = new FileInputStream("RandomAccessFileDemo.java");
InputStream is2 = new FileInputStream("FileInputStreamDemo.java");
InputStream is3 = new FileInputStream("twoCopy.java");
//添加到集合中
v.add(is1);
v.add(is2);
v.add(is3);
//调用特有功能public Enumeration<E> elements()
Enumeration<InputStream>e = v.elements();
//创建合并流对象
SequenceInputStreamsis = new SequenceInputStream(e);
//封装目的地
BufferedOutputStream bos = new BufferedOutputStream(
newFileOutputStream("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();
}
}
10. 序列化流:将对象像流的方式或者网络传输中的数据写数据.对象---->流数据:ObjectOutputStream
反序列化:将流数据或者网络传输中的流数据读取出来.流数据---->还原成对象:ObjectInputStream
ObjectOutputStream中的成员方法:
public final void writeObject(Object obj):将obj对象写入到当前的序列化流中
ObjectInputStream中的成员方法:
public final Object readObject():从当前反序列化流中读取一个对象
Serializeable:序列化接口
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化,如果自定义一个类没有实现这个接口,就不能使用
序列化或者是反序列化!如果一个接口中没有字段,没有构造方法,没有成员方法,叫做标记接口
如果一个类实现了标记接口:Serializable,那么对应的该类加载的时候,会产生一个ID
如果启用序列化功能,那么必须实现一个接口:Serializable
序列化和反序列化版本号不一致,会出现InvalidClassException
解决这个异常两种方案:
1)要么改动当前某个类中的数据之后,然后重新序列化和反序列化
这种做法不符合实际要求,在实际开发中,可能直接读数据:将流数据--->还原成对象
2)发现黄色警告线,点击它:生成一个固定ID
注意事项:
比如一个类中有很多成员变量,并不想让一些成员变量被序列化,Java提供了一个关键字:
transient:不用被序列化的时候用它修饰
序列化和反序列化考点:
1)将对象--->流数据或者流数据--->对象,该对象所在的类要实现一个标记接口:serializable
2)序列化和反序列化生产的版本Id不一致的时候,会出现异常,所以使用生产随机ID或者固定ID解决
3)transient:修饰的变量不会被序列化
例:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class ObjectStreamDemo {
publicstatic void main(String[] args) throws Exception {
// write();
read();
}
//读数据
privatestatic void read() throws IOException, ClassNotFoundException {
//创建一个反序列化流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
//使用反序列化
Object obj = ois.readObject();
//关闭资源
ois.close();
System.out.println(obj);
}
//序列化
privatestatic void write() throws IOException {
//创建一个对象
Person p = new Person("张三", 22);
//创建一个序列化流对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
"oos.txt"));
//写数据
oos.writeObject(p);
//释放资源
oos.close();
}
}
import java.io.Serializable;
public class Person implements Serializable{
privatestatic final long serialVersionUID = 1L;
//生成一个ID
private String name;
private int age;
publicPerson() {
super();
}
publicPerson(String name, int age) {
super();
this.name= name;
this.age= age;
}
publicString getName() {
returnname;
}
publicvoid setName(String name) {
this.name= name;
}
publicint getAge() {
returnage;
}
publicvoid setAge(int age) {
this.age= age;
}
@Override
publicString toString() {
return"Person [name=" + name + ", age=" + age + "]";
}
}
11. Properties
1)Properties:属性集合类,该类继承自Hashtable<K,V>,该类属于Map集合
Properties 类表示了一个持久的属性集。
Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串(一般情况:它用作配置文件去使用,MySQL或者Oracle中用它做配置文件)
构造方法:
public Properties():创建一个空属性列表
例:
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
publicstatic void main(String[] args) {
//创建属性集合类对象
Properties prop = new Properties();
//添加元素
prop.put("张三","45");
prop.put("李四","25");
prop.put("王五","40");
prop.put("赵六","30");
//遍历集合
//获取所有的键的集合
Set<Object> keySet = prop.keySet();
//增强for遍历
for(Object key : keySet) {
System.out.println(key+ "=====" + prop.get(key));
}
}
}
2) 属性集合类:Properties有自己的遍历和添加元素的功能
给属性列表中添加元素:
public Object setProperty(String key,Stringvalue)
public Set<String>stringPropertyNames():获取当前属性列表中所有的键的集合,键值都是String类型
public String getProperty(String key)用指定的键在此属性列表中搜索属性值
例:
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo2 {
publicstatic void main(String[] args) {
//创建属性集合类对象
Properties prop = new Properties();
//添加元素
//public Object setProperty(String key,String value)
prop.setProperty("张三","25");
prop.setProperty("李四","35");
prop.setProperty("王五","45");
prop.setProperty("赵六","40");
//遍历属性列表public Set<String> stringPropertyNames()
Set<String> keySet = prop.stringPropertyNames();
for(String key : keySet) {
System.out.println(key+ "====" + prop.getProperty(key));
}
}
}
12. Properties 可保存在流中或从流中加载。
将文件中的数据加载到属性集合中:public void load(Reader reader)
将属性集合中的数据保存到文件中:public void store(Writer writer,String comments)
第二个参数:comments:对当前属性列表的描述
例:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
public class PropertiesDemo3 {
publicstatic void main(String[] args) throws IOException {
// mySave();
myLoad();
}
privatestatic void myLoad() throws IOException {
//创建属性集合对象
Properties pro = new Properties();
//创建字符输入流对象
FileReader fr = new FileReader("Person.txt");
//调用方法
pro.load(fr);
fr.close();
//显示输出
System.out.println(pro);
}
privatestatic void mySave() throws IOException {
//创建属性集和对象
Properties pro = new Properties();
//添加元素
pro.setProperty("张三","30");
pro.setProperty("李四","40");
pro.setProperty("王五","50");
//把属性集合中数据保存到文件中
FileWriter fw = newFileWriter("Person.txt");
//调用方法
pro.store(fw,"names content");
fw.close();
}
}