慕课JAVA之文件传输基础----JAVA IO流

来源:互联网 发布:软件开发企业收入确认 编辑:程序博客网 时间:2024/06/01 09:58

一、文件的编码

     一个默认的工程有默认的编码方式,在输入文本文件后,要进行读取只能采取默认的编码方式,否则就会出现乱码。

     example:

String s = "中国";

byte[] bytes = s.getBytes();//括号内没有声明采用的编码方式,则采用默认的编码方式

byte[] bytes1 = s.getBytes("gbk");//采用GBK编码方式

byte[] bytes2 = s.getBytes("utf-8");//采用UTF-8编码方式

String s1 = new String(bytes1)//这里采用默认的编码方式进行转换,如果默认编码方式不是GBK,则打印转换的s1会是乱码,因为bytes1是通过GBK方式转换的


二、File类的使用

1.File类常用的API

    File类只是用来表示文件(目录)的信息(名称、大小),不能用于文件内容的访问。

常见的API:

File file = new File("D:\\java\\javaio);//此处路径是随便写的,只为了创建对象来调用API

file.exists();//判断文件(目录)是否存在file.getAbsolutePath();//获得绝对路径,直接打印file也有相同的功能

file.mkdir();//创建单级目录file.getName();//返回文件(目录)名称

file.mkdirs();//创建多级目录file.getParent();//返回上级目录的绝对路径

file.delete();//删除文件(目录)file.getParentFile().getAbsolutePath();//返回上级目录的绝对路径

file.isDirectory();//判断是否为目录

file.isFile();//判断是否为文件

2.遍历目录

对目录及其子目录中的文件名打印出来,要用到递归的方法

example:

/*设计一个静态方法来打印目录下的文件的绝对路径

*如果有子目录则采用递归的方式来打印出子目录下的文件的绝对路径

*String[] filenames=dir.list();//返回的是目录下文件和目录的名称

*File[] files= dir.listFiles();//返回的是目录下的文件(目录)的抽象

*/

    public static void listDirectory(File dir) throws IOException{ 

/判断文件是否存在

if(!dir.exists()){

throw new  IllegalArgumentException("目录:“+dir+"不存在”);

}

//判断文件是否为目录

if(!dir.isDirectory()){

throw new IllegalArgumentException(dir+"不是目录“);

}

File[] files = dir.listFile();

for(File fIle : files){

if(file.isDirectory()){

listDirctory(file);//递归

}else{//如果是文件而不是目录则直接打印出文件的绝对路径

System.out.println(file);

}

}

三、RandomAccessFile类的使用

 RandomAccessFile类提供对文件内容的访问,既可以读文件也可以写文件 

 RandomAccessFile支持随机访问文件,可以访问文件的任意位置

java文件的都时byte byte byte类型存值的,是数据的集合

打开文件有两种方式“rw"/"r":读写/只读

开始时文件指针Pointer = 0;

使用read()和write()方法每次都只读一个字节和写入一个字节,之后文件指针就指向下一个位置 ,最后要记得关闭文件

规范:RandomAccessFile raf = new RandomAccessFile(file,"rw");//第一个参数时操作文件第二个是读写方式

四、字节流

1.字节流之文件输入流FileInputStream和文件输出流FileOutputStream

InputStream 和 OutputStream是两个抽象类

InputStream抽象了应用程序读取数据的方法

OutputStream抽象了应用程序写出数据的方法

1)输入流的基本方法(抽象方法不能创建对像,这里这是讲个规范和抽象方法的使用吧)

InputStream in = new InputStream(*******);

int b = in.read();//读取一个无符号字节填充到int的低八位,-1是EOF

in.read(byte[] bytes);//将文件数据直接存放到byte数据中,如果数组足够大,则儿科一存放全部数据

in.read(byte[] bytes,int start,int size);//从bytes的start的位置开始存放size长度的数据

2)输出流的基本方法

OutputStream out = new OuutputStream(******);

out.write(int b);//写出一个byte到流,写出的是b的低八位

out.write(byte[] buf);//将字节数组都写到流

out.write(byte[] buf,int start,int size);//将字节数组从start位置开始写size长度的字节到流

3)FileInputStream和FileOutputStream分别是两个抽象类的具体实现

2.字节流之数据输入输出流

DataInputStream/DataOutputStream

    对”流“功能的扩展,可以更加全面的读取int,long,字符等类型的数据

example:writeInt()/writeDouble()/writeUTF()读取UTF编码的字节流 

3.字节缓冲流

BufferedInputStream/BufferedOutputStream

两个类为 IO提供了带缓冲的操作,一般打开文件进行写入或者读取操作时,都会加入缓冲,这种流模式提供了IO的性能

从应用程序把输入放入文件,相当于将一缸水倒入另一个缸中

FileOutputStream---->write()方法相当于一滴一滴将水转移过去

DataOutputStream--->writeXxxf()方便一些,相当于将一瓢一瓢转移过去

BufferedOutputStream--->write方法更方便,相当于先一瓢一瓢放入桶中,在将桶中的水倒入另一个缸中

4)字节字符转换流

1) 认识文本和文本文件

java的文本(char)是16位无符号整数,是字符的unicode编码(双字节编码)。

  文本是byte byte byte .....的数据序列

文本文件是文本(char)序列按照某种编码方式(utf-8/gbk/utf-16)序列化成byte的储存结果

2)字符流的基本实现(Reader输入流和Write输出流)-------->操作的是文本文件

字符的处理,一次处理一个字符

字符的底层仍然是基本的字节序列

字符流的基本实现

InputStreamReader------->完成byte流解析为char流的解析过程,按照编码解析

OutputStreamWriter------->提供char流到byte流,按照编码处理

3)字符流的文件输入输出流FileReader/FileWriter,只能按照默认的编码方式进行读取和写入,不能自定义设置编码方式

(如果要自定义编码方式,还是要使用InputStreamReader/FileOutputStreamWriter)

FileReader fr = new FileReader(*******);

FileWriter fw = new FileWriter(*******);

5)字符流过滤器

BufferedReader/BufferWriter/PrintWriter

BufferedReader------->readLine();//一次读一行,但是不能识别换行符号

BufferWriter-------->write();//一次写一行,要调用newLine()方法进行手动换行

PrintWriter-------->println()/print();//一次写一行,前者能自动换行,后者没有换行功能

五、对象的序列化和反序列化

1.序列化基本操作

对象序列化就是将Object转换成byte序列,反之就是反序列化

序列化流ObjectOutputStream是过滤流------->writeObject();

反序列化流ObjectInputStream------>readObject

注意:要实现序列化的类必须要有实现序列化接口Serializable,否则会出现异常

  这个接口没有任何方法,只是一个标准

2.transient及ArrayList源代码分析

transient关键字修饰的类属性在类序列化时不会进行jvm默认的序列化,但可以手动序列化,需要在类中重写两个方法

example:private transient int stuage;

public void writeObject(java.io.ObjectOutStream s) throws java.io.IOException{

s.defaultWriteObject();//进行jvm默认的序列化

s.writeObject();/s.writeInt(this,stuage);//对transient关键字修饰的类属性进行手动序列化

public void readObject(java.io.ObjectInputStream s) throws java.io.IOException,ClassNotFoundException{

s.defaultReadObject();//

this,stuage = s.readInt();//手动反序列化

在ArrayList的源代码中也重写了这两个方法,并且也有transient关键字修饰的element[] elsments:

主要是为了在序列化时可以手动将有效元素进行序列化,而不是盲目地将整个数组进行序列化

3.序列化中子父类构造函数的调用

对子类对象进行反序列化时

如果其父类没有实现Serializable接口

那么其父类的构造函数将被调用



 



原创粉丝点击