IO流相关笔记

File

1、File类的一个对象代表一个文件或一个文件目录(即文件夹)。

2File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流来完成。

3、想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。

4、File对象常作为参数传递给流的构造器

 

File类构造器

新建文件要加文件相应的后缀!

public File(String pathname)

以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。

绝对路径: 是一个固定的路径,从盘符开始

相对路径: 是相对于当前位置开始,如果在main方法下新建,则是在当前工程下;如果在其他方法下新建,则是在当前module下。

public File(String parent,String child)

以parent为父路径, child为子路径创建File对象。

public File(File parent,String child)

根据一个父File对象和子文件路径创建File对象

路径分隔符

路径中的每级目录之间用一个路径分隔符隔开。

路径分隔符和系统有关:windows和DOS系统默认使用“\”来表示;UNIX和URL使用“/”来表示

为了解决这个隐患, File类提供了一个常量:

public static final String separator。根据操作系统,动态的提供分隔符。

 

File类常用方法:

File类的获取功能

Ø public String getAbsolutePath(): 获取绝对路径

Ø public String getPath() : 获取路径

Ø public String getName() : 获取名称

Ø public String getParent(): 获取上层文件目录路径。 若无, 返回null

Ø public long length() : 获取文件长度(即:字节数) 。 不能获取目录的长度。

Ø public long lastModified() : 获取最后一次的修改时间, 毫秒值

Ø public String[] list() : 获取指定文件目录下的所有文件或者文件目录的名称数组

Ø public File[] listFiles() : 获取指定文件目录下的所有文件或者文件目录的File数组

File类的重命名功能

Ø public boolean renameTo(File dest):把文件重命名指定的文件路径

要想保证重命名为指定路径成功,那么要保证调用的file对象真实存在,方法形参dest不能真实存在。

File类的判断功能

Ø public boolean isDirectory(): 判断是否是文件目录

Ø public boolean isFile() : 判断是否是文件

Ø public boolean exists() : 判断是否存在

Ø public boolean canRead() : 判断是否可读

Ø public boolean canWrite() : 判断是否可写

Ø public boolean isHidden() : 判断是否隐藏

File类的创建功能

Ø public boolean createNewFile() : 创建文件。 若文件存在, 则不创建, 返回false

Ø public boolean mkdir() : 创建文件目录。 如果此文件目录存在, 就不创建了。如果此文件目录的上层目录不存在, 也不创建

Ø public boolean mkdirs() : 创建文件目录。 如果上层文件目录不存在, 一并创建

注意事项:如果你创建文件或者文件目录没有写盘符路径, 那么, 默认在项目路径下。

File类的删除功能

Ø public boolean delete(): 删除文件或者文件夹

删除注意事项:

Java中的删除不走回收站

要删除一个文件目录, 请注意该文件目录内不能包含文件或者文件目录 。

 

File类的内存结构

 

 

IO

I/O是Input/Output的缩写, 用于处理设备之间的数据传输。 如读/写文件,网络通讯等。Java程序中,对于数据的输入/输出操作以“流(stream)的方式进行。java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过相似的标准的方法输入或输出数据。

 

输入input: 读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。

输出output: 将程序(内存)数据输出到磁盘、光盘等存储设备中。

 

流的分类:

按数据流的流向不同分为: 输入流,输出流

按操作数据单位不同分为: 字节流(8 bit,主要操作图片数据),字符流(16 bit,主要操作文本数据)

按流的连接对象的不同分为: 节点流(直接连接在源文件上),处理流(作用在流上)

 

抽象基类和IO流体系:

Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。

 

抽象基类的方法

InputStream:

int read()

从输入流中读取数据的下一个字节。 返回 0 到 255 范围内的 int 字节值。 如果因为已经到达流末尾而没有可用的字节, 则返回值 -1。

int read(byte[] b)(用的多)

从此输入流中将输入流中的数据全部读入输入参数 byte[]数组中。每次读取整个字节流,这时byte[]数组就起到一个缓冲的作用,因为通常byte[]数组大小小于字节流,所以每次往里面填满byte[]后,立刻控制台输出或者用输出流write出来,新的read方法可以覆盖掉byte[]数组中之前read的内容,如此while循环,如果读取到字节流末尾后, 则返回值 -1, 否则以整数形式返回实际读取的字节数。

int read(byte[] b, int off,int len)(用得少)

将输入流中最多 len 个数据字节读入 byte 数组。 尝试读取 len 个字节, 但读取的字节也可能小于该值。 以整数形式返回实际读取的字节数。 如果因为流位于文件末尾而没有可用的字节, 则返回值 -1。

public void close() throws IOException

关闭此输入流并释放与该流关联的所有系统资源。

Reader:

int read()

读取单个字符。 作为整数读取的字符, 范围在 0 到 65535 之间 (0x00-0xffff)(2个

字节的Unicode码) , 如果已到达流的末尾, 则返回 -1

int read(char[] cbuf)(用得多)

将字符读入数组,每次read都会将数组填充满。 如果已到达流的末尾, 则返回 -1。 否则返回本次读取的字符数。

int read(char[] cbuf,int off,int len)(用的少)

将字符读入数组的某一部分,不填充满,添充长度为len。 存到数组cbuf中, 从off处开始存储, 最多读len个字符。 如果已到达流的末尾, 则返回 -1。 否则返回本次读取的字符数。

String readLine()

将文件中的字符数据按行存储在一个String中,每调用一次存一行数据。如果已经到达流的末尾,则返回null。

public void close() throws IOException

关闭此输入流并释放与该流关联的所有系统资源。

OutputStream & Writer:

OutputStream 和 Writer 也非常相似:

void write(int b/int c);

void write(byte[] b/char[] cbuf);

void write(byte[] b/char[] buff, int off, int len);

void flush();

void close(); 需要先刷新,再关闭此流;因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,即以 String 对象作为参数

void write(String str);

void write(String str, int off, int len);

FileOutputStream 从文件系统中的某个文件中获得输出字节。 FileOutputStream用于写出非文本数据之类的原始字节流。 要写出字符流, 需要使用 FileWriter

OutputStream

void write(int b)

将指定的字节写入此输出流。 write 的常规协定是:向输出流写入一个字节。 要写入的字节是参数 b 的八个低位。 b 的 24 个高位将被忽略。 即写入0~255范围的。

void write(byte[] b)

将 b.length 个字节从指定的 byte 数组写入此输出流。 write(b) 的常规协定是:应该与调用 write(b, 0, b.length) 的效果完全相同。

void write(byte[] b,int off,int len)(用的多)

将指定 byte 数组中从off处开始写入,写入byte数组的 len 个字节。

public void flush()throws IOException

刷新此输出流并强制写出所有缓冲的输出字节, 调用此方法指示应将这些字节立即写入它们预期的目标。

public void close() throws IOException

关闭此输出流并释放与该流关联的所有系统资源

Writer

void write(int c)

写入单个字符。 要写入的字符包含在给定整数值的 16 个低位中, 16 高位被忽略。 即写入0 到 65535 之间的Unicode码。

void write(char[] cbuf)

写入字符数组。

void write(char[] cbuf,int off,int len)(用的多)

写入字符数组的某一部分。 从off处开始写入, 写入len个字符

void write(String str)

写入字符串,和readLine()对应。

void write(String str,int off,int len)

写入字符串的某一部分。

void flush()

刷新该流的缓冲, 则立即将它们写入预期目标。

public void close() throws IOException

关闭此输出流并释放与该流关联的所有系统资源。

 

节点流(文件流)

读取数据从文件中

(以字符流为例):

或(使用read()的重载方法)

错误原因:

 

(以字节流为例):

 

▲要注意一定要保证流的关闭,所以出现异常的情况下要使用try-catch-finally。

▲在读取文件时,一定要保证文件真实存在在硬盘中。

节点流在读数据时有一个构造器FileInputStream(String)/FileReader(String)可以直接将路径当做参数,不用新建File类。

写出数据到文件中

(以字符流为例):

 

▲在写入一个文件时,如果目标文件不是真实存在的,则会自动创建一个真实文件。

如果使用构造器FileOutputStream(file),则目录下有同名文件将被覆盖而不是对文件内容覆盖。

如果使用构造器FileOutputStream(file,true),则目录下的同名文件不会被覆盖,在文件内容末尾追加内容。

 

▲字节流操作字节,可以操作图片,比如: .mp3, .avi, .rmvb, mp4, .jpg, .doc, .ppt;也可以操作文本文件,只是如果文本文件包含中文的话,在内存中查看时会出现乱码。

字符流操作字符,只能操作普通文本文件。最常见的文本文件: .txt, .java, .c, .cpp 等语言的源代码。

 

缓冲流(处理流的一种)

BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter

作用是提高流的读取和写入的速度:

在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。 当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区,当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从文件中读取8192个(8Kb), 存在缓冲区中, 直到缓冲区装满了, 才重新从文件中读取下一个8192个字节数组。向流中写入字节时, 不会直接写到文件, 先写到缓冲区中直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法flush()可以强制将缓冲区的内容全部写入输出流。

 

字节流的读取和写入

字符流的读取和写入

 

▲关于流的关闭只用关外层的缓冲流,内层不用手动关闭会自动关闭。

 

缓冲流的练习题视频没看!

 

转换流(处理流的一种)

转换流提供了在字节流和字符流之间的转换,Java API提供了两个转换流:

InputStreamReader:将InputStream字节流转换为Reader字符流,其本身是字符流

OutputStreamWriter:将Writer字符流转换为OutputStream字节流,其本身是字符流

字节流中的数据都是字符时,转成字符流操作更高效。很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。

 

 

InputStreamReader/OutputStreamWriter构造方法:

InputStreamReader(InputStream)//使用系统默认的字符集

InputStreamReader(InputStream,String charSet)//使用指定的字符集

 

使用InputStreamReader:

使用InputStreamReader和OutputStreamWriter:

 

输入输出流

System.in:标准输入流,它的类型为InputStream字节流,默认输入设备为键盘

System.out:标准输出流,它的类型为PrintStream打印流,是OutputStream字节流的子类,默认输出设备为显示器

 

重定向:通过System类的setIn, setOut方法对默认设备进行改变。

public static void setIn(InputStream in):System.setIn(输入字节流实例)

public static void setOut(PrintStream out) :System.setOut(打印流实例)

 

打印流

打印流:PrintStreamPrintWriter

Ø 提供了一系列重载的print()和println()方法,用于多种数据类型的输出

Ø PrintStream和PrintWriter的输出不会抛出IOException异常

Ø PrintStream和PrintWriter有自动flush功能

Ø PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。

Ø System.out返回的是PrintStream的实例

 

数据流

为了方便地操作Java语言的基本数据类型String的数据,可以使用数据流。数据流有两个类: (用于读取和写出基本数据类型、 String类的数据):

DataInputStream 和 DataOutputStream

分别“套接”在 InputStream 和 OutputStream 子类的流上

 

方法:

DataInputStream/DataOutputStream中的方法,用于将基本数据类型和字符串写入到文件中或从文件中读取相应的基本数据类型和字符串

boolean read/writeBoolean()

char read/writeChar()

double read/writeDouble()

long read/writeLong()

String read/writeUTF()

byte read/writeByte()

float read/writeFloat()

short read/writeShort()

int read/writeInt()

void read/writeFully(byte[] b)

 

注意:使用数据流时可以用同一个数据流对象执行多个不同类型数据的读取和写入操作,但是写入和读取的类型顺序必须相同!

对象流和序列化机制

用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

 

序列化:用ObjectOutputStream类把基本类型数据或对象作为可存储的字节数组

反序列化:用ObjectInputStream类读取基本类型数据或对象的机制

 

对象序列化机制允许把内存中的Java对象转换成平台无关的二进制字节流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象

序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原

 

如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类需要:

1、实现Serializable、Externalizable两个接口之一。

2、声明static final long serialVersionUID = xxxxxxxxxxxL;

serialVersionUID用来表明类的不同版本间的兼容性。 简言之,其目的是保证序列化对象所在类在对象反序列化时是否兼容。如果类没有显示定义这个静态常量,它的值是Java运行时环境根据类的内部细节自动生成的。 若类的实例变量做了修改, serialVersionUID 可能发生变化。 故建议,显式声明。)

3、除了保证该类可序列化,还要保证类中的属性也都是可序列化的。(默认基本数据类型属性可序列化)

否则,会抛出NotSerializableException异常

 

一个对象的序列化:

一个对象的反序列化:

 

注意:使用对象流时可以用同一个对象流对象执行多个不同类型的读取和写入操作,但是写入和读取的类型顺序必须相同!

ObjectOutputStreamObjectInputStream对象流不能序列化和反序列化一个对象中的statictransient修饰的属性。

 

随机存取文件流

RandomAccessFile 声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了DataInput、 DataOutput这两个接口,也就意味着这个类属于字节流且既可以作为输入流又可以作为输出流

 

RandomAccessFile 类支持 “随机访问” 的方式,程序可以直接跳到文件的任意地方来读、写文件。

支持只访问文件的部分内容

可以向已存在的文件后追加内容

RandomAccessFile 对象包含一个记录指针,用以标示当前读写处的位置,可以自由移动记录指针:

long getFilePointer()获取文件记录指针的当前位置

void seek(long pos)将文件记录指针定位到 pos 位置

 

 

构造器:

public RandomAccessFile(File file, String mode)

public RandomAccessFile(String name, String mode)

其中的mode指定 RandomAccessFile 的访问模式:

r: 以只读方式打开(常用,此时只作为输入流

rw:打开以便读取和写入(常用,此时同时作为输入流和输出流

rwd:打开以便读取和写入;同步文件内容的更新

rws:打开以便读取和写入; 同步文件内容和元数据的更新

 

方法:

同样有一系列的read()和write()方法。使用时类似于缓冲流的使用。

long getFilePointer()获取文件记录指针的当前位置

void seek(long pos)将文件记录指针定位到pos 位置

 

 

注意,RandomAccessFile流作为输出流时,如果写出的文件不存在,则会自动创建;如果写出的文件存在,则会对文件内容进行覆盖而不是对文件覆盖

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值