JAVA学习笔记之(文件——IO流)

Java.IO.File类表示文件或目录,只用于表示文件或目录得信息,不能用于文件的访问。
常用的API:
1.创建File对象:File file=new File(String path);注意:File.seperater();获取系统分隔符,如:”\“.
2.boolean file.exists();是否存在.
3.file.mkdir();或者file.mkdirs();创建目录或多级目录。
4.file.isDirectory()或者file.isFile()判断是否是目录或者是否是文件。
5.file.delete();删除文件或目录。
6.file.createNewFile();创建新文件。
7.file.getName()获取文件名称或目录绝对路径。
8.file.getAbsolutePath()获取绝对路径。
9.file.getParent();获取父级绝对路径。
10.file.getSize();获取文件大小。
11.file.getFormat();获取文件格式名。

IO流
1.字节流
1)InputStream、OutputStream
抽象应用程序读写数据的方式
2)EOF = End 读到-1就读到结尾
3)输入流
int b in.read();读取一个字节
in.read(byte[] buf) 读取数据填充到字节数组
in.read(byte[] buf,int start,int size)
4)输出流
out.write(int b)
out.write(byte[] buf)
out.write(byte[] buf,int start,int size)
5)FileInputStream 具体实现了在文件上的读取操作


/**
* 批量读取,对大文件而言效率高,也是我们最常用的读文件的方式【重点】
* @param fileName
* @throws IOException
*/
public static void printHexByByteArray(String fileName)throws IOException{
FileInputStream in = new FileInputStream(fileName);
byte[] buf = new byte[8 * 1024];
/*从in中批量读取字节,放入到buf这个字节数组中,
* 从第0个位置开始放,最多放buf.length个
* 返回的是读到的字节的个数
*/
/*int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
int j = 1;
for(int i = 0; i < bytes;i++){//注意这不用buf.length是因为可能数组内存不够大,所以定为有效长度。
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}*/

Ps:当字节数组不够大,一次性读不完文件时怎么办?

int bytes = 0;
int j = 1;
while((bytes = in.read(buf,0,buf.length))!=-1){
for(int i = 0 ; i < bytes;i++){
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}
}
in.close();
}


字节流之文件输入流FileOutputStream操作 II

/**
* 文件拷贝,字节批量读取
* @param srcFile//源文件
* @param destFile//因为目标文件不存在则会自动创建,所以无需if判断
* @throws IOException
*/
public static void copyFile(File srcFile,File destFile)throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:"+srcFile+"不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[8*1024];
int b ;
while((b = in.read(buf,0,buf.length))!=-1){
out.write(buf,0,b);
out.flush();//最好加上(也可以不写);刷新此输出流并强制写出所有缓冲的输出字节。
}
in.close();
out.close();

}


DataOutputStream/DataInputStream
对流功能的扩展,可以更加方便的读取,int long 字符等类型数据
writeInt/Double/UTF()

代码:DataOutputStream
String file="demo/dos.dat";
DataOutputStream dos=new DataOutputStream(
new FileOutputStream(file));
dos.writeInt(10);
//采用utf-8写出
dos.writeUTF("中国");
//采用utf-16be编码写出
dos.writeChars("中国");


代码:DataIntputStream
DataInputStream dis=new DataInputStream(
new FileInputStream(file));
int/long/Double/String i=dis.readInt/Long/Double/UTF();


BufferedInputStream&BufferedOutputStream
提供了带缓存区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能
从应用程序中把输入放入文件,相当于将一罐水倒入到另外一个罐中:
FileOutputStream-->write()方法相当于一滴一滴地把水“转移”过去
DataOutputStream-->writeXxx()方法会方便一些,相当于一瓢一瓢把水“转移”
BuffereOutputStream-->write()方法更方便,相当于一瓢一瓢先放入 桶中,在从桶中倒入到另外一个罐中


字符流 (操作的是文本 文本文件) 注意默认的编码方式
1)编码问题
2)认识文本和文本文件
java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)
文件是byte byte byte 的数据序列
文本文件是文本(char)序列按照某种编码方案(utf-8,utf-16be,gbk)序列化byte的存储
3)字符流(Reader Writer)
字符的处理,一次处理一个字符
字符的底层依然是基本的字节序列
4)InputStreamreader 完成byte流解析成char流 按照编码解析
OutputStreamWrite 提供char流到byte流 按照编码处理


字符流:
fileRead/filewriter类
代码:实现字符读写
FileRead fr=new FileRead(文件路径);
//加true则直接在文件中追加内容
FileWriter fw=new FileWriter(文件路径,true);
char[] buffer=new char[2056];
int c;
while(c=fr.read(buffer,0,buffer.length)!=-1){
fw.write(buffer,0,c);//复制文件
fw.flush();
}
注:读取utf-8文件时会乱码,则要在输出流或者输入流中控制编码方式


BufferedReader br = new BufferReader(new InputStreamReader
(new FileInputStream("E:\\java\\a.txt")));//文件读取缓冲区
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter
(new FileOutputStream("E:\\java\\c.txt")));//文件输入缓冲区
bw.newLine();//读取一行
PrintWriter pw = new PrintWriter("E:\\java\\c.txt");//替代BufferedWriter
pw.println();//读取一行
PrintWriter pw1 = new PrintWriter(OutputStreamWriter,boolean autoFlush);//可以进行自动刷新操作


对象序列化流和反序列化流2
- 序列化流:ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(string型文件路径或File型))
反序列化流:ObjectInputStream ois = new ObjectInputStream(new FileInputStream(string型文件路径或File型))

- 读写方法:
将对象写入文件:oos.writeObject(对象); (写完记得oos.flush()和oos.close())
从文件读出对象(读出的是默认object类型的对象,要强转):yy zz = (yy)ois.readObject();
- 要注意这种情况:比如定义类A(没有实现Serializable接口),然后子类B继承于类A并实现了Serializable接口(可序列化),子类C继承于类B(自动继承实现了可序列化),此时:
序列化:创建C的对象并进行序列化写入文件,其父类B和A的构造方法都会被递归调用;
反序列化:从文件读出对象并强转后赋给C的对象,其父类A(没有实现Serializable接口的)的构造方法会被调用,B的(实现Serializable接口的)不会。


序列化:
transient 关键字:被transient修饰的元素,该元素不会进行jvm默认的序列化,但可以自己完成这个元素的序列化
注意:
(1)在以后的网络编程中,如果有某些元素不需要传输,那就可以用transient修饰,来节省流量;对有效元素序列化,提高性能。
(2)可以使用writeObject自己完成这个元素的序列化。ArrayList就是用了此方法进行了优化操作。ArrayList最核心的容器Object[] elementData使用了transient修饰,但是在writeObject自己实现对elementData数组的序列化。只对数组中有效元素进行序列化。readObject与之类似。
(3)java.io.ObjectOutputStream.defaultWriteObject();
// 把jvm能默认序列化的元素进行序列化操作
java.io.ObjectOutputStream.writeInt(age);// 自己完成序列化
(4)
java.io.ObjectOutputStream.defaultReadObject();// 把jvm能默认反序列化的元素进行反序列化
this.age = java.io.ObjectOutputStream.readInt(); // 自己完成age的反序列化操作


序列化时父类构造函数:
1.子类在反序列化时,父类实现了序列化接口,不会递归调用其构造函数
而父类实现了serializable接口,子类继承就可序列化
2.子类在反序列化时,父类没有实现序列化接口,则会递归调用其构造函数
父类未实现serializable接口,子类自行实现可序列化
结论:当父类实现了serializable接口,子类可以被序列化,当对子类对象进行反序列化操作时,如果其父类没有实现序列化接口,则其父类的构造函数会被调用,反之父类的构造函数不会被调用。归结为有序列化接口的构造函数不会被调用



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值