0
点赞
收藏
分享

微信扫一扫

5、java的IO操作


1、byte与String相互转化:
1.1 String转byte:
String str = “哈哈666”;
byte[] bytes = str.getBytes(“gbk”); //str转为bytes,告诉系统我要将gbk转为bytes,如果这里不声明gbk,就是用项目默认编码
1.2 byte转String:
1.2.1 不声明转码会默认用项目编码将byte转为字符串:
String str1 = new String(bytes)
System.out.println(str1)
1.2 声明编码:
String str3 = new String(bytes,’gbk’)//哈哈666
String str4 = new String(bytes,’utf8’) //乱码
String str5 = new String(bytes,’utf16be’)//乱码
【注】:如果str是GBK,就是转成字节是GBK转过去的字节bytes,如果在把bytes转出来显示也必须是转成gbk,转成其他的都会乱码

2、File类(java.io.File) :File表示文件、目录信息(名称、大小等),不能访问文件内容
2.1 常用api:
file.exists(); //文件是否存在
file.getName();//获取文件名称
file.delete(); //删除文件
file.createNewFile();//创建新文件
file.mkdir();//创建以及目录
file.mkdirs();//创建多级目录
file.getAbsolutePath();//返回文件绝对路径
file.getAbsoluteFile();//返回文件绝对路径
file.getPath();//返回文件相对路径
file.getParent();//返回父目录
file.getParentFile();//返回父文件
file.list();//返回目录所有列表

2.2 列出目录下所有文件:
public void listDir(String fileDir) throws Exception{

System.out.println(fileDir);
File dir = new File(fileDir);
if(!dir.exists()){
throw new Exception("文件不存在");
}
if(!dir.isDirectory()){
throw new Exception("必须要传入一个文件夹");
}

// String filenames[] = file.list(); //返回当前目录下所有名称,字符串数组
File[] files = dir.listFiles(); //返回当前目录下所有文件,文件数组
if(files != null && files.length > 0){
for(File file : files){
if(file.isDirectory()){
this.listDir(file.getAbsolutePath());
}else{
System.out.println(fileDir + ‘/’ + file.getName());
}
}
}
}

3、RandomAccessFile:既可以读取文件内容,又可以写文件,并且可以随机访问文件,访问文件任何位置
3.1 硬盘上的文件是byte、byte、byte存储的,是数据的集合
3.2 打开文件有两种方式:
rw(读写)、r(读)
RandomAccessFile raf = new RandomAccessFile(file,’rw’);
打开文件时,指针在开头poiner = 0
3.3 写方法
raf.write(int) —–>只写一个字节(后8bit),同时指针指向下个位置,准备写入
3.4 读方法
int b = raf.read()—>都一个字节
3.5 文件读写完成后一定要关闭

4、IO流(输入、输出流)
4.1 字节流:
4.1.1 InputStream、OutputStream(都是抽象类)
InputStream:抽象了应用程序读取数据的方式
OutputStream抽象了应用程序写出数据的方式
4.1.2 结束:EOF=End 读到-1就读到结尾
4.1.3 输入流基本方法
int b = in.read();读取一个字节无符号填充到int第8位,-1是EOF
in.read(byte[] buf);读取数据直接填充到字节数组
in.read(byte[] buf,int start,int size);读取数据直接填充到字节数组,从start开始放,放多少size长度的数据
4.1.4 输出流基本方法
out.write(int b) 写出一个byte到流,b的第8位
out.write(byte[] buf);
out.write(byte[] buf,int start,int size);
4.1.5 FileInputStream:具体实现了在文件上读取数据到内存
FileOutputStream:从内存读取到文件
创建:FileOutputStream out = new FileOutputStream(“E:/aa.dat”);
追加:FileOutputStream out = new FileOutputStream(“E:/aa.dat”,true); //如果第二个参数不传true,则被清空

【FileInputStream事例】从文件中读取
方法一:一个一个字节读取
/**
* 一个一个字节读取,读取指定文件内容,按照16进制输出到控制台,并且每输出10bit换行
* @param dir
* @throws Exception
*/
public void test(String filename) throws Exception{
//把文件作为字节流进行操作
FileInputStream in = new FileInputStream(filename);
int b;
int i = 1;
while((b = in.read()) != -1){ //一次一个字节
System.out.println(Integer.toHexString(b)+" ");
if(i++ % 10 == 0){
System.out.println("\n");
}
}
}
方法二:一块一块读取
/**
* 批量读取,开辟内存读取一块一块读取,非一个一个字节读取,读取指定文件内容,按照16进制输出到控制台,并且每输出10bit换行
* @param dir
* @throws Exception
*/
public void test(String filename) throws Exception{
FileInputStream in = new FileInputStream(filename);
byte[] buf = new byte[20*1024]; //暂时缓冲
//从in中批量读取字节吗放入到buf这个字节数组中,从第0个位置开始放,最多放buf.length个,返回的是读到的字节个数
int bytes = 0;
int j = 1;
while((bytes = in.read(buf,0,buf.length)) != -1){
for(int i=0;i<bytes;i++){
System.out.println(Integer.toHexString(buf[i])+" ");
if(j++ % 10 == 0){
System.out.println("\n");
}
}
}
}


【FileOutputStream事例】向文件中写入

创建:FileOutputStream out = new FileOutputStream("E:/aa.dat");
追加:FileOutputStream out = new FileOutputStream("E:/aa.dat",true); //如果第二个参数不传true,则被清空

方法一:一个字节一个字节写入:
/**
* 拷贝文件
* @param src
* @param des
* @throws Exception
*/
public void copyFile(File src,File des) throws Exception{

if(!src.isFile()){
throw new Exception("src不是一个文件");
}

FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(des);

int b ;
while( (b= in.read()) != -1){ //读取文件到buf(缓冲区)
out.write(b);//从buf(缓冲区)读取出来写到文件
out.flush();//手动清空缓冲数据
}
in.close();
out.close();
}

方法二:批量写入
/**
* 批量写入文件
* 拷贝文件
* @param src
* @param des
* @throws Exception
*/
public void copyFile(File src,File des) throws Exception{

if(!src.isFile()){
throw new Exception("src不是一个文件");
}

FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(des);
byte[] buf = new byte[8*1024];
int b ;
while( (b= in.read(buf,0,buf.length)) != -1){ //读取文件到buf(缓冲区)
out.write(buf,0,b);//从buf(缓冲区)读取出来写到文件
out.flush();//手动清空缓冲数据
}
in.close();
out.close();
}


4.1.6 DataOutputStream、DataInputStream (就是对FileOutputStream\FileInputStream包装了一层):对"流"功能的扩展,可以更方便读取int、long、字符等类型数据
4.1.6.1 DataOutputStream:
writeInt()\writeDouble()\writeUTF()//UTF:中文汉字以utf8编码输出

事例:
String file = "E:/www/test66";
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
dos.writeInt(10);
dos.writeInt(-10);
dos.writeLong(10l);
dos.writeDouble(10.8);
dos.writeUTF("牛逼");//以UTF-8形式写出
dos.close();

4.1.6.2 DataInputStream:
readInt()\readDouble()\readUTF()//UTF:中文汉字以utf8编码输出

事例:
String file = "E:/www/test66";
DataInputStream dis = new DataInputStream(new FileInputStream(file));
int i1 = dis.readInt();
System.out.println(i1);
int i2 = dis.readInt();
System.out.println(i2);
long i3 = dis.readLong();
System.out.println(i3);
Double i4 = dis.readDouble();
System.out.println(i4);
String i5 = dis.readUTF();
System.out.println(i5);


4.1.7 BufferedInputStream、BufferedOutputStream:为IO读写提供了缓冲区,性能更高

性能高体现:
从应用程序中把输入放入文件,相当于把一缸水到入另一缸中:
FileOutputStream->wirte :相当于一滴一滴转移
DataOutputStream->writeXxx:相当于一瓢一瓢转移
BufferedOutputStream->write:相当于一瓢一瓢先放入桶(缓冲)中,然后一起把桶中的倒入缸中

利用缓冲区写入
/**
* 拷贝文件
* @param src
* @param des
* @throws Exception
*/
public void test(File src,File des) throws Exception{

if(!src.isFile()){
throw new Exception("src不是一个文件");
}

BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(des));
int b ;
while( (b= in.read()) != -1){ //读取文件到buf(缓冲区)
out.write(b);//从buf(缓冲区)读取出来写到文件
out.flush();//刷新缓冲区
}
in.close();
out.close();
}



4.2 字符流
4.2.1 编码问题
4.2.2 认识文本和文本文件:
4.2.2.1 java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)文件是byte byte byte...的数据序列
4.2.2.2 文本文件是文本(char)按照某种编码方案(utf-8、utf-16be、gbk..)序列化为byte存储的
4.2.3 字符流(Reader\Writer):操作的是文本文件
字符处理:一次处理一个字节,字符底层依然是基本的字节序列
字符流基本实现:
InputStreamReader 完成byte流解析为char流,按照编码解析
OutputStreamWrite 提供char流到byte流,按照编码处理

事例:
【读取文件操作】:
FileInputStream in = new FileInputStream("E:/www/MyEclipse10/note.java");
InputStreamReader isr = new InputStreamReader(in,"utf-8"); //如果note.java是utf-8,那这里就要设置utf-8,否则读出来就是乱码,不写的话默认是项目编码
int b;

// //一次读一个字符
// while((b = isr.read()) != -1){
// System.out.println((char)b);
// }

//批量读取
char[] buffer = new char[8*1024];//一次读8M
while((b = isr.read(buffer,0,buffer.length)) != -1){
String s = new String(buffer,0,b);
System.out.println(s);
}



【读取、写入】
//获取InputStreamReader对象
FileInputStream in = new FileInputStream("E:/www/MyEclipse10/note.java");
InputStreamReader isr = new InputStreamReader(in,"gb2312");
//获取OutputStreamWriter对象
FileOutputStream out = new FileOutputStream("E:/www/MyEclipse10/note2.java");
OutputStreamWriter osw = new OutputStreamWriter(out,"gb2312");

//批量读取、写入
int b;
char[] buffer = new char[8*1024];//一次读8M
while((b = isr.read(buffer,0,buffer.length)) != -1){
osw.write(buffer, 0, b);
osw.flush();
}
isr.close();
osw.close();



4.2.4 FileReader\FileWrite:专门处理文件的
【注】:无法设置读、取编码,只能根据项目便来来读取
FileReader fr = new FileReader("E:\\www\\MyEclipse10\\note2.java");
FileWriter fw = new FileWriter("E:\\www\\MyEclipse10\\note4.java",true); //第二个参数true是追加
char[] buffer = new char[2048];
int b ;
while((b = fr.read(buffer,0,buffer.length))!=-1){
fw.write(buffer,0,b);
fw.flush();
}

fr.close();
fw.close();
}

4.2.5 字符流过滤器(BufferedReader、BufferedWriter):

【读取、写入】
方法一:
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:/www/MyEclipse10/note2.java")));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:/www/MyEclipse10/note3.java")));

String line;
while((line = br.readLine()) != null){ //一次读取一行,不会自动加换行
System.out.println(line);
bw.write(line);
bw.newLine(); //换行操作
bw.flush();
}

br.close();
bw.close();


方法二:使用PrintWriter替代BufferedWriter
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("E:/www/MyEclipse10/note2.java")));
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("E:/www/MyEclipse10/note3.java")));
PrintWriter pw = new PrintWriter("E:/www/MyEclipse10/note4.java");
String line;
while((line = br.readLine()) != null){ //一次读取一行,不会自动加换行
System.out.println(line);
pw.println(line); //换行直接println,不换行print
pw.flush();
}

br.close();
pw.close();

5、序列化:
5.1 对象序列化、反序列化
5.2 对象序列化,就是将Object转换成bytexulie,反之叫对象的反序列化
5.3 序列化流(ObjectOutputStream),是过滤流—writeObject
反序列化流(ObjectInputStream),是过滤流—readObject
5.4 序列化接口(Serializable)
对象序列化必须实现接口Serializable,才能进行序列化,否则将出现异常,这个接口没有任何方法,只是一个标准

【事例】

public class Student implements Serializable{

private String stuno;
private String stuname;
private int stuage;

public Student(){

}

public Student(String stuno,String stuname,int stuage){
this.stuno = stuno;
this.stuname = stuname;
this.stuage = stuage;
}

public String getStuno() {
return stuno;
}
public void setStuno(String stuno) {
this.stuno = stuno;
}
public String getStuname() {
return stuname;
}
@Override
public String toString() {
return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
+ stuage + "]";
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getStuage() {
return stuage;
}
public void setStuage(int stuage) {
this.stuage = stuage;
}
}

//序列化保存
String file = "E:/www/MyEclipse10/stu.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
Student stu = new Student("1001","张三",20);
oos.writeObject(stu);
oos.flush();
oos.close();

//反序列化读取
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Student oldstu = (Student)ois.readObject();
ois.close();
System.out.println(oldstu.getStuage());
System.out.println(oldstu.getStuname());
System.out.println(oldstu.getStuno());


5.5 transient : transient修饰的属性,不会被jvm默认序列化,可以自己完成序列化

例子:private transient int stuage;


public class Student implements Serializable{

private String stuno;
private String stuname;
private transient int stuage; //本来不会在jvm默认序列化,但是writeObject、readObject会使其序列化

public Student(){

}

public Student(String stuno,String stuname,int stuage){
this.stuno = stuno;
this.stuname = stuname;
this.stuage = stuage;
}

public String getStuno() {
return stuno;
}
public void setStuno(String stuno) {
this.stuno = stuno;
}
public String getStuname() {
return stuname;
}
@Override
public String toString() {
return "Student [stuno=" + stuno + ", stuname=" + stuname + ", stuage="
+ stuage + "]";
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getStuage() {
return stuage;
}
public void setStuage(int stuage) {
this.stuage = stuage;
}

private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{
s.defaultWriteObject();//将jvm能序列化的都给序列化
s.writeInt(this.stuage); //自定义序列化
}

private void readObject(java.io.ObjectInputStream s) throws java.io.IOException,ClassNotFoundException{
s.defaultReadObject(); //将jvm能反序列化的都给反序列化
this.stuage = s.readInt(); //自定义反序列化
}
}




5.6 序列化中父类与子类构造方法的问题:序列化中如果父类序列化了,子类就不需要序列化

5.6.1 :子类序列化时,父类、子类都会调用构造方法
5.6.2 : 反序列化时,如果父类没有实现序列化接口,会调用父类构造方法,如果父类实现了序列化接口,则父类不会被调用构造方法


举报

相关推荐

0 条评论