Java文件读写
文件系统及Java文件基本操作
文件概述
• 文件系统是由OS(操作系统)管理的
• 文件系统和Java进程是平行的,是两套系统
• 文件系统是由文件夹和文件递归组合而成
• 文件目录分隔符
–Linux/Unix 用/隔开
–Windows用\隔开,涉及到转义,在程序中需用/或\\代替
• 文件包括文件里面的内容和文件基本属性
• 文件基本属性:名称、大小、扩展名、修改时间等
Java 文件类File
• java.io.File是文件和目录的重要类(JDK6及以前是唯一)
–目录也使用File类进行表示
• File类与OS无关,但会受到OS的权限限制
• 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
• File对象可以作为参数传递给流的构造器
File常用构造器
构造器 | 介绍 |
---|---|
public File(String pathname) |
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。(绝对路径:是一个固定的路径,从盘符开始,相对路径:是相对于某个位置开始) |
public File(String parent,String child) |
以parent为父路径,child为子路径创建File对象。 |
public File(File parent,String child) |
根据一个父File对象和子文件路径创建File对象 |
File类常用方法
–createNewFile,delete,exists, getAbsolutePath, getName,
getParent,getPath, isDirectory, isFile, length, listFiles, mkdir, mkdirs
• 注意: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类的判断功能
方法 | 介绍 |
---|---|
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中的删除不走回收站。
要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录
Java IO 包
• 文件系统和Java是两套系统
• Java读写文件,只能以(数据)流的形式进行读写
• java.io包中
–节点类:直接对文件进行读写
–包装类
• 转化类:字节/字符/数据类型的转化类
• 装饰类:装饰节点类
• 字节:byte, 8bit, 最基础的存储单位
• 字符:a, 10000, 我,の
• 数据类型: 3, 5.25,abcdef
• 文件是以字节保存,因此程序将变量保存到文件需要转化
• 节点类: 直接操作文件类
–InputStream, OutputStream(字节)
• FileInputStream,FileOutputStream
–Reader,Writer(字符)
• FileReader, FileWriter
• 转换类:字符到字节之间的转化
–InputStreamReader:文件读取时字节,转化为Java能理解的字符
–OutputStreamWriter:Java将字符转化为字节输入到文件中
• 装饰类:装饰节点类
–DataInputStream,DataOutputStream: 封装数据流
–BufferedInputStream,BufferOutputStream:缓存字节流
–BufferedReader, BufferedWriter:缓存字符流
• 总结
–Java文件处理类都在java.io包中
–处理类分为:节点类、包装类(转化类、装饰类)
Java IO
1.流的概念
-
在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据, 而当程序需要将一些数据保存起来的时候,就要使用输出流完成。
-
往内存里写,是输入流。 输入流是指从外设流入计算机的数据流 内存往文件里写,是输出流。 输出流是指从计算机流向外设的数据流
-
在 java 使用流的机制进行数据的传送,从文件到内存是输入流,从内存到文件是 输出流,输入流可以通过 read 读取,输出流以write 或 print 写入,对于流可以是分 为高层流和低层流,低层以一个字节或字符为单位进行处理,高层流以一批数据为单位 进行处理。
-
java的流类提供了结构化方法,如,底层流和高层过滤流。而高层流不是从输入设备读取,而是从其他流读取。同样高层输出流也不是写入输出设备,而是写入其他流
流的区别
-
字节流
-Java 语言中提供了很多用于操作字节流的类和接口,都集中在 java.io
包中,其中InputStream、OutputStream
两个类是字节流处理的的基类;InputStream 类是用来处理输入流的,而OutputStream 用来处理输出流。 在这两个基类的基础上,java.io包还衍生出来很多子类供用户使用。比如FileInputStream、FileOutputStream 类,等等。 -
字符流
字符流是在 JDK1.1 里面引进的,是为了处理字符而提出来的;字符流常常用于读取文本类型的数据或字符串流的操作。字符流的处理和字节流差不多,API 基本上完全一样,只是计量单位不同;字符流一次可以读取一个字符(1char = 2byte = 16bit);其专门用来操作字符、字符数组或字符串。
java.io 包中也提供了很多用于操作字符流的类和接口,其中Reader、Writer
两个类是字符流处理的的基类。java.io 包还衍生出来很多子类供用户使用,比如 FileReader、 FileWriter 类,等等。在针对字符、字符串、文本文件进行输入与输出的操作时,应该首选字符流处理。
注意:常用的 GBK 字符集中,英文是占用 1 个字节,中文是 2 个字节;UTF-8 字符集,英文是 1 个字节,中文是 3 个字节;Unicode 字符集,英文中文都是 2 个字节; -
字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲( ),就用字节流好点,如果是关系到中文(文本)的( ),用字符流好点
-
所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列
-
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;
2.字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以 -
字节流是最基本的,所有的InputStrem和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的encode来处理,也就是要进行字符集的转化 这两个之间通过InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联在实际开发中出现的汉字问题实际上都是在字符流和字节流之间转化不统一而造成的
字节流:InputStream、OutputStream
处理字节流的抽象类
InputStream 是字节输入流的所有类的超类,一般我们使用它的子类,如FileInputStream等.
OutputStream是字节输出流的所有类的超类,一般我们使用它的子类,如FileOutputStream等.
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 数组。尝试读取 len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。如果因为流位于文件末尾而没有可用的字节,则返回值-1。 -
public void close() throws IOException
关闭此输入流并释放与该流关联的所有系统资源。
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 开始的len 个字节写入此输出流。 -
public void flush()throws IOException
刷新此输出流并强制写出所有缓冲的输出字节,调用此方法指示应将这些字节立即写入它们预期的目标。 -
public void close() throws IOException
关闭此输出流并释放与该流关联的所有系统资源。
字符流:Reader Writer
Reader
-
int read()
读取单个字符。作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff)(2个字节的Unicode码),如果已到达流的末尾,则返回-1 -
int read(char[] cbuf)
将字符读入数组。如果已到达流的末尾,则返回 -1。否则返回本次读取的字符数。 -
int read(char[] cbuf,int off,int len)
将字符读入数组的某一部分。存到数组cbuf中,从off处开始存储,最多读len个字符。如果已到达流的末尾,则返回-1。否则返回本次读取的字符数。 -
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)
写入字符串。 -
void write(String str,int off,int len)
写入字符串的某一部分。 -
void flush()
刷新该流的缓冲,则立即将它们写入预期目标。 -
public void close() throws IOException
关闭此输出流并释放与该流关联的所有系统资源。
一般使用 FileReader,FileWriter
缓冲流
- 为了提高数据读写的速度,Java
API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。
-
缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:
BufferedInputStream 和 BufferedOutputStream
BufferedReader 和 BufferedWriter -
当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区
-
当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从文件中读取8192个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中读取下一个8192个字节数组。
-
向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法flush()可以强制将缓冲区的内容全部写入输出流
-
关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也会相应关闭内层节点流
-
flush()方法的使用:手动将buffer中内容写入文件
-
如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷新缓冲区,关闭后不能再写出
转换流:InputStreamReader OutputStreamWriter
- 字节流中的数据都是字符时,转成字符流操作更高效。
- 很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。
InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁,它将字节流转换为字符流.
(InputStreamReader:将InputStream转换为Reader)
- 需要和InputStream“套接”。
- 构造器
public InputStreamReader(InputStream in)
public InputSreamReader(InputStream in,String charsetName)
如: Reader isr = new InputStreamReader(System.in,”gbk”);
OutputStreamWriter
OutputStreamWriter是字符流通向字节流的桥梁,它将字符流转换为字节流.
( OutputStreamWriter:将Writer转换为OutputStream)
- 需要和OutputStream“套接”。
- 构造器
public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)
BufferedReader BufferedWriter(处理流之字符缓冲流)
• 是对一个已存在的流的连接和封装,处理流又称为过滤流(Filter)
• 不直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。
• 如缓冲处理流 BufferedReader
• 处理流的构造方法总是要带一个其他的流对象作参数
BufferedReader
由Reader类扩展而来,提供通用的缓冲方式文本读取,readLine读取一个文本行,从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。
BufferedWriter
由Writer 类扩展而来,提供通用的缓冲方式文本写入, newLine使用平台自己的行分隔符,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
InputStream能从來源处读取一個一個byte,所以它是最低级的,
•为了使用方便,经常将System.in用各种处理流进行封装处理,如:BufferedReader br = new BufferedReader(new InputStreamReader( System.in ) );
br.readLine();
标准输入、输出流
-
System.in和System.out分别代表了系统标准的输入和输出设备
-
默认输入设备是:键盘,输出设备是:显示器
-
System.in的类型是InputStream
-
System.out的类型是PrintStream,其是OutputStream的子类FilterOutputStream 的子类
-
重定向:通过System类的setIn,setOut方法对默认设备进行改变。
public static void setIn(InputStream in)
public static void setOut(PrintStream out)
数据流
-
为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。
-
数据流有两个类:(用于读取和写出基本数据类型、String类的数据)
DataInputStream 和 DataOutputStream
分别“套接”在 InputStream 和 OutputStream 子类的流上 -
DataInputStream中的方法
boolean readBoolean()
char readChar()
double readDouble()
long readLong()
String readUTF()
byte readByte()
float readFloat()
short readShort()
int readInt() -
DataOutputStream中的方法
将上述的方法的read改为相应的write即可。
总结
-
一个字符等于两个字节
-
实际上字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的, 而字符流在操作时使用了缓冲区,通过缓冲区再操作文件
-
字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串, 而字节流处理单元为1个字节,操作字节和字节数组。
-
在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,
在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。(这四个都是抽象类) -
在所有的硬盘上保存文件或进行传输的时候都是以字节的方法进行的,包括图片也是按字节完成,
而字符是只有在内存中才会形成的,所以使用字节的操作是最多的。 -
如果要java程序实现一个拷贝功能,应该选用字节流进行操作(可能拷贝的是图片),并且采用边读边写的方式(节省内存)。
-
为什么要把FileInputStream流转换成InputStream流,FIleInputStream是InputStream流的子类,在能用到父类的地方都可以被子类替换
-
对于流可以是分为高层流和低层流,低层以一个字节或字符为单位进行处理,高 层流以一批数据为单位进行处理。
2.文本文件的读写
文件类型
• 文件类型
–一般文本文件(若干行字符构成的文件),如txt等
–一般二进制文件,如数据文件dat
–带特殊格式的文本文件,如xml等
–带特殊格式二进制文件,如doc,ppt等
• 文件是数据的一个容器(口袋)
• 文件可以存放大量的数据
• 文件很大,注定Java只能以流形式依次处理
输入流和输出流的区别
• 从Java角度理解
–输出:数据从Java到文件中,写操作
–输入:数据从文件到Java中,读操作
• 文本文件读写
–输出文本字符到文件中
–从文件中读取文本字符串
先记住:
FieoutputStream节点类,负责写字节;
OutputStreamWriter转化类,负责字符到字节转化;
BufferedWriter装饰类,负责写字符到缓存区。
三者构建关系:BufferedWriter (OutputStreamlriter (File0utputStream)))。
文件读写步骤
导入相关的包
1创建文件File类对象
2创建文件读写输入输出流对象
3进行读写操作
4关闭输入输出流
5整个过程需要异常处理
例如:
1·用FileInputStream读文本文件
导入相关的包
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
构造一个文件输入流对象
File f = new File(“text.txt”);
InputStream fis = new FileInputStream(f);
或
InputStream fis = new FileInputStream(“text.txt”);
利用文件输入流类的方法读取文本文件的数据
fis.available(); //可读取的字节数
fis.read(); //读取文件的数据
关闭文件输入流对象
fis.close();
public static void main (String[] args) {
try{
int size;
InputStream fis = new FileInputStream("text.txt");
System.out.println("可读取的字节数: " +
(size = fis.available()));
char[] text = new char[200] ;
for (int count = 0; count < size; count++) {
text[count] = ((char) fis.read());
System.out.print(text[count]);
}
fis.close();
}catch(IOException ex){
System.out.println (ex.getMessage());
}
}
@Test
public void testFileInputStream() {
FileInputStream fis = null;
try {
//1. 造文件
File file = new File<