Java高级-IO流

File类的使用

1.File类的对象,代表一个文件或者一层文件目录(文件夹)

2.File类声明在java.io包下

3.File类中涉及到关于文件或文件目录的创建、删除、重命名、修改等方法。该类未涉及到写入或读取文件内容的操作。如果想要读取或者写入内容,则必须使用IO流来完成。

4..File类的对象常会作为参数传递到IO流的构造器中,指明读取或写入的文件。

File类的构造器

1.File(String filepath)

2.File(String parentPath,String childPath)

3.File(File parentPath,String childPath)

路径的写法,有相对路径和绝对路径

绝对路径:包含盘符在内的路径

路径分隔符: \\  如果是单\且后面跟了特殊字符,比如\t\n,则会被解析成特殊格式。所以要先对\解析。Java也动态的提供分隔符,通过File类的常量separator实现。

相对路径:相较于某个路径下,IDEA中,在JUnit中的单元测试方法中则相对于module下,在main方法中相对于project下,而eclipse相对路径只是project下。

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数组

重命名方法

public boolean renameTo(File dest):把文件重命名为指定的文件路径
    *   比如:file1.renameTo(file2)为例:
    *   要想保证返回true,需要file1在硬盘中是存在的,且file2不能在硬盘中存在。

判断方法

public boolean isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists() :判断是否存在
public boolean canRead() :判断是否可读
public boolean canWrite() :判断是否可写
public boolean isHidden() :判断是否隐藏

创建、删除方法

创建硬盘中对应的文件或文件目录
        public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false
        public boolean mkdir() :创建一级文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
        public boolean mkdirs() :创建多级文件目录。如果此文件目录存在,就不创建了。如果上层文件目录不存在,一并创建
删除磁盘中的文件或文件目录
        public boolean delete():删除文件或者文件夹
            删除注意事项:Java中的删除不走回收站,删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录

IO原理

I/O ===> Input /Output的缩写,I/O是非常实用的技术,用于处理设备之间的数据传输,Java程序中,对于数据的输入和输出操作以流的方式进行。

IO分类

根据操作数据单位不同分为:字节流和字符流(字符流用于处理文本字符文件.txt\.java\.c),字节流用于处理图片、视频、音频、文档等字节文件。

根据数据流的流向不同分为:输入流和输出流 (输入、输出,主要看针对于谁说的,如果是内存读磁盘,把磁盘的文件读入到内层中,叫输入,把内存的东西写到磁盘中,叫输出)

根据流的角色不同分为:节点流、处理流。节点流直接从数据源或目的地读写数据,处理流则不直接连接到数据源或目的地,而是连接在已存在的流上。 

IO流设计了四十多个类,主要从4个抽象基类派生的

抽象基类字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

输入流的基类

InputStream常见的方法

int read()    从输入流中读取数据的下一个字节,返回0到255范围内的int紫戒指,如果到达末尾返回-1

int read(byte[] b)从输入流中将最多b.length个字节的数据读入到一个byte数组中,如果到达末尾返回-1
int read(byte[] b,int off,int len)将输入流最多len个数据字节读入到byte数组中,如果到达末尾返回-1
void close() throws IOException关闭此输入流并释放资源

Reader常见的方法

int read():读取单个字符,字符在0到65535之间,如果到达流的末尾,则返回-1
int read(char[] chars):将字符读入数组,如果到达流的末尾,则返回-1,否则返回本次读取的字符数
int read(char[] chars int off,int lne):将字符读入数组的某一部分,存到数组chars中,从off开始存储,最多读len个字符,如果到达末尾则返回-1,,否则返回本次读取的字符数
void close() throws IOException:关闭输入流并释放系统资源

读入的文件一定要存在,否则会报FileNotFoundException异常。

输出流的基类

OutputStream常见方法

void write(int b):将指定的字节写入此输入流
void write(byte[] b):将b.length个字节从指定的byte数组写入此数据流
void wirte(byte[] b,int off,int len):将指定的byte数组中从off索引开始的len个字节写入此数据流
void flush() throws IOExcetion:刷新此输出流并强制写出所有缓冲的输出字节,调用此方法指示应将这些字节立即写入预期的目标
void close() throws IOException:关闭输出流并释放系统资源

Writer常见方法

void write(int c)写入单个字符 ,写入0 到 65535 之间的Unicode码。
void write(char[] cbuf) 写入字符数组。
void write(char[] cbuf,int off,int len)写入字符数组的某一部分。从off开始,写入len个字符
void write(String str)写入字符串。
void write(String str,int off,int len)写入字符串的某一部分。
void flush()刷新该流的缓冲,则立即将它们写入预期目标。
void close() throws IOException关闭此输出流并释放与该流关联的所有系统资源。

基本步骤

1.创建流

2.对数据进行操作\读或写

3.关闭流

开始使用

1.读入字符流

FileReader fr = new FileReader("hello.txt");

//方式1:
int data;
while((data =fr.read())!= 1){
    System.out.print((char)data);
}

//方式2:
char[] ch = new char[1024];
int data;
while((data = fr.read(ch))!=-1){
    for(int i = 0;i<data;i++){
        System.out.print(ch[i]);
    }
    //或者
    String str = new String(ch,0,data);
    System.out.println(str)
}
//方式3:(不常用)
char[] ch = new char[1024];
int data;
while((data = fr.read(ch,0,data))!=-1){
    System.out.println((char)data);
}

2.输出字符流

FileWriter fw = new FileWriter("hello.txt");
//如果文件不存在,会自动创建文件,
//如果文件存在,且构造器使用的是FileWriter(file,false)或FileWriter(file) : 会覆盖原文件,
//如果构造器用的是(file,true)会在原文件的基础上进行写入操作

//方法1:
fw.write("hello");

//方法2:
char[] chars = new char[]{'h','e','l','l','o'};
fw.write(chars);

//方法3:
fw.write(Unicode编码):只能写入单个字符

//方法4:
char[] chars = new char[]{'h','e','l','l','o'};
fw.write(chars,0,3)//从0下标开始,写入3个字符

//方法5:
fw.write(new String("helloword",0,3))//从下标0开始,写入3个字符
    
fw.close();

3.输入字节流

InputStream
方法和Reader差不多。只不过用的byte[]数组
主要使用FileInputStream

4.输出字节流

OutputStream
方法和Writer也差不多,不过用的是byte[]数组
主要使用OutputStream

处理流之一:缓冲流

使用缓冲流读取字节时,会一次性的读取8192B也就是8Kb,存在缓冲区中,如果缓冲区满了,才会重新从文件中读取下一个8192B个字节
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,才会把缓冲区的数据一次性的写到文件中,也可以使用flush()方法强制将缓冲区的内容全部写入输出流。


关闭流的顺序和打开流的顺序相反,也就是先开后关
作用:提高流的读取,写入效率
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
缓冲流的几个方法
readLine():读取一行,不包括换行符,如果到达文件末尾返回null
newLine():换行

处理流之二:转换流

Java API提供了两个转换流
    InputStreamReader:将InputStream转换成Reader
    OutputStreamWriter:将Writer转换成OutputStream
字节流中的数据都是字符时,转换字符流操作更高效,用转换流来处理文件乱码问题,实现编码和解码的功能

将字节的输入流按照指定字符集转换成字符的输入流
InputStreamReader(InputStream,in)//使用系统默认的字符集
InputStreamReader(Inputstream in,String charset)//指明字符集

将字符的输出流按照指定字符集转换为字节的输出流
public OutputStreamWriter(OutputStream out)//使用系统默认的字符集
public OutputSreamWriter(OutputStream out,String charsetName)//指明输出的文件使用什么编码

常见的编码表

ASCII码 65~90是大写字母A-Z,97~122是小写字母a-z 48~57是数字0-9
GBK(gb2312)中文
UTF-8是使用过最广的一种Unicode的实现方式
UTF-16

标准的输入、输出流

System.in和System.out分别代表系统标准的输入和输出设备
系统默认的输入设备是键盘, 输出设备是控制台
System.in的类型是InputStream
System.out的类型,是PrintStream

方法
    setIn(InputStream in)
    setOut(PrintStream ps)
通过这两个方法对默认设备进行改变    

打印流

PrintStream 和PrintWriter
提供了一系列的重载的print()和println()方法
这两个类有自动flush功能,
PrintStream打印的所有字符都使用系统的默认字符编码转换为字节
打印字符使用PrintWriter类
System.out是PrintStream的实例
作用:将基本数据类型的数据格式化作为字符串输出

数据流

方便操作基本数据类型和String类型,
DataInputStream(InputStream)和DataOutputStream(OutputStream)
DataInputStream方法
    boolean readBoolean()
    char readChar()
    byte readByte()
    xxx readXxx()
    String readUTF()
    void readFully(byte[] b)
DataOutputStream方法和DataInputStream一致,只不过是writeXxx

这两个类用于读取和写出基本数据类型、String类型的数据
读取时,应于写出的顺序一致,否则会报异常

对象流

ObjectOutputStream 和ObjectInputStream
作用:用于读取和存储基本数据类型或对象的数据,可以把java中的对象写入到磁盘中,也可以把对象读取到内存中

重点:
    序列化:用ObjectOutputStream类保存基本数据类型或对象的机制
    反序列化:用ObjectInputStream类读取基本数据类型或对象的机制
对象序列化机制:
    把内存中的java对象转换成二进制流,然后,把这种二进制流保存在磁盘中,或通过网络将二进制流传输到另一个网络节点
反序列化:
    当其他程序获取了这种二进制流,就可以将其恢复成原来的java对象
如果要对象支持序列化,就必须实现Serializable接口或Externalizable接口其中之一
如果实现了Serializable接口,需要提供全局常量serialVersionUID,如果没有显式声明,java运行环境根据类的内部细节自动生成,如果类的实例变量做了修改,提供的serialVersionUID可能会发生变化,再去读取,就会报异常

序列化:通过readObject() 写入对象
写入一次,就应该flush()一次
反序列化:通过readObject()

对Serializable接口的理解

可用于序列化,内部是空方法接口,作为标识作用

RandomAccessFile

RandomAccessFile继承于java.lang.Object类,实现了DataInput,DataOutput两个接口,也就意味着这个类可以实现读取和写出操作
RandomAccessFile对象包含一个记录指针,用以表示当前读写处的位置。RandomAccessFile类对象可以自由移动记录的指针
构造器
    RandomAccessFile(File file,String mode)
    RandomAccessFile(String name,String mode)
    创建RandomAccessFile实例需要指定一个mode参数,改参数指定RandomAccessFile的访问模式
        r:代表只读,如果文件不存在,就不会创建文件,然后报异常
        rw:读取和写入,如果,文件不存在,就会创建文件
        rwd:读取和写入,同步文件内容的更新
        rws:读取和写入,同步文件内容和元数据的更新
long getFilePoniter() 获取文件记录指针的当前位置
void seek(long pos) 将文件记录指针定位到pos位置
     如果文件存在,且有内容,再去做写的操作,则会从文件内容的0下标开始覆盖,知道写入的内容结束,比如,文件原有内容123456,写入,789,运行后,文件内容则会变成789456,如果要做,追加,或插入操作,可以使用 seek()来移动指针,如果是追加,则可以使用file.length(),如果是插入则可以指定位置

NIO

Java NIO(New IO||Non-Blocking IO)是java 1.4版本引入的新的IO API,可以替代标准的Java IO API,NIO与IO有着相同的作用和目的,但是使用的方式完全不同,IO是面向流的,而NIO是支持面向缓冲区的,基于通道的IO操作,NIO会以更高效的方式进行文件的读写操作
Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO
    java.nio.channels.Channel
            FileChannel -->处理本地文件
            SocketChannel-->TCP网络编程的客户端的Channel
            ServerSocketChannel-->TCP网络编程的服务器端的Channel
            DatagramChannel-->UDP网络编程中发送端和接收端的Channel
JDK7,又对NIO,进行升级,称为NIO.2

NIO.2中的类

Path接口

File类来访问文件系统,但File类 功能有限,而且大多数方法在出错时,仅仅返回false,不会提供异常信息
NIO.2就提供了Path接口,就是File类的升级版本,因为是接口无法实例化,然后有提供了工具类Paths 通过Paths工具类提供的get(String url)方法来创建对象
get(String path1,String pathN) :用于将字符串拼接成路径
get(URL url):返回指定的url对应的Path路径

Path接口的方法

String toString() : 返回调用 Path 对象的字符串表示形式
boolean startsWith(String path) : 判断是否以 path 路径开始
boolean endsWith(String path) : 判断是否以 path 路径结束
boolean isAbsolute() : 判断是否是绝对路径
Path getParent() :返回Path对象包含整个路径,不包含Path对象指定的文件路径
Path getRoot() :返回调用 Path 对象的根路径
Path getFileName() : 返回与调用 Path 对象关联的文件名
int getNameCount() : 返回Path 根目录后面元素的数量
Path getName(int idx) : 返回指定索引位置 idx 的路径名称
Path toAbsolutePath() : 作为绝对路径返回调用 Path 对象
Path resolve(Path p) :合并两个路径,返回合并后的路径对应的Path对象
File toFile(): 将Path转化为File类的对象

Files类

用于操作文件或目录的工具类
Files常用方法:
Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
Path createDirectory(Path path, FileAttribute<?> … attr) : 创建一个目录
Path createFile(Path path, FileAttribute<?> … arr) : 创建一个文件
void delete(Path path) : 删除一个文件/目录,如果不存在,执行报错
void deleteIfExists(Path path) : Path对应的文件/目录如果存在,执行删除
Path move(Path src, Path dest, CopyOption…how) : 将 src 移动到 dest 位置
long size(Path path) : 返回 path 指定文件的大小
    
boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
boolean isRegularFile(Path path, LinkOption … opts) : 判断是否是文件
boolean isHidden(Path path) : 判断是否是隐藏文件
boolean isReadable(Path path) : 判断文件是否可读
boolean isWritable(Path path) : 判断文件是否可写
boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
DirectoryStream<Path> newDirectoryStream(Path path) : 打开 path 指定的目录
InputStream newInputStream(Path path, OpenOption…how):获取InputStream 对象
OutputStream newOutputStream(Path path, OpenOption…how) : 获取 OutputStream 对象 


本人是Java初学者,水平有限,本文章中如果有不对的地方,麻烦您能指出来。向您表示感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值