1.File类:对硬盘上的文件和目录进行操作的类。
File类是文件和目录路径名抽象表现形式
构造函数:
1) File(String pathname)
Creates a new File instance by converting the given pathname string into an abstract pathname.
2)File(File parent, String child)
Creates a new File instance from a parent abstract pathname and a child pathname string.
3)File(String parent, String child)
Creates a new File instance from a parent pathname string and a child pathname string.
4)File(URI uri)
Creates a new File instance by converting the given file: URI into an abstract pathname.
import java.io.File;
/*
* 我们要想实现IO的操作,就必须知道硬盘上文件的表现形式。
* 而Java就提供了一个类File供我们使用。
*
* File:文件和目录(文件夹)路径名的抽象表示形式
* 构造方法:
* File(String pathname):根据一个路径得到File对象
* File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
* File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
*/ public class FileDemo01 {
public static void main(String[] args) {
//File(String pathname):根据一个路径得到File对象
//file:文件和目录(文件夹)路径名的抽象表示形式,表示file指向这个f:\\text.txt下的文件,至于是否存在是今后的操作
File file = new File("f:\\files\\text.txt"); //File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
File file2 = new File("f:\\files","text.txt"); //File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
File file3 = new File("f:\\files");
File file4 = new File(file3,"text.txt");
} }
前面只是创建了一个File类的实例,文件还是没有创建出来下面,我们要创建文件:
(1)
import java.io.File;
import java.io.IOException; public class FileDemo { public static void main(String[] args) throws IOException {
//需求在f盘下temp文件夹下 创建files文件夹,指引出创建的目的路径
File file = new File("f:\\temp\\files");
System.out.println("创建文件夹:"+file.mkdir());
//在刚刚创建的files文件夹下创建文件text.txt,指引出创建的目的路径
File file2 = new File("f:\\temp\\files\\text.txt");
System.out.println("创建文件:"+file2.createNewFile());
} }
(2)
import java.io.File;
import java.io.IOException; /*
*创建功能:
*public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
*public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
*public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
*
*/
public class FileDemo {
public static void main(String[] args) throws IOException {
// 需求:我要在e盘目录下创建一个文件夹demo
File file = new File("e:\\demo");
System.out.println("mkdir:" + file.mkdir()); // 需求:我要在e盘目录demo下创建一个文件a.txt
File file2 = new File("e:\\demo\\a.txt");
System.out.println("createNewFile:" + file2.createNewFile()); // 需求:我要在e盘目录test下创建一个文件b.txt
// Exception in thread "main" java.io.IOException: 系统找不到指定的路径。
// 注意:要想在某个目录下创建内容,该目录首先必须存在。
// File file3 = new File("e:\\test\\b.txt");
// System.out.println("createNewFile:" + file3.createNewFile()); // 需求:我要在e盘目录test下创建aaa目录,这是错误的
// File file4 = new File("e:\\test\\aaa");
// System.out.println("mkdir:" + file4.mkdir());
//这里是可以实现的,但是往往多层目录这样创建是很繁琐的,往往使用下一种方法mkdirs()
// File file5 = new File("e:\\test");
// File file6 = new File("e:\\test\\aaa");
// System.out.println("mkdir:" + file5.mkdir());
// System.out.println("mkdir:" + file6.mkdir()); // 其实我们有更简单的方法
File file7 = new File("e:\\aaa\\bbb\\ccc\\ddd");
System.out.println("mkdirs:" + file7.mkdirs()); // 看下面的这个东西:
File file8 = new File("e:\\liuyi\\a.txt");
System.out.println("mkdirs:" + file8.mkdirs());
}
}
其他关于File操作详见Android(java)学习笔记87
2.IO流
2.1 字节输入输出流 InputStream 和 OutputStream(基类 抽象类)
一个流是字节的源或目的地,其次序是有意义的。例如,一个需要键盘输入的程序可以用流来做到这一点。流可以分成两种:输入流和输出流。可以从输入流读,但不能对它写。要进行写操作就必须使用输出流
InputStream 和 OutputStream是Java流类中的两个最基本的类,Java中所有其他的流类都是继承自这两个类。
InputStream类的主要方法:
int available() 返回当前流中可用的字节数
void close() 关闭当前流对象
void mark (int readlimit) 在流中作标记
boolean markSupported () 判断流是否支持标记和复位操作
abstract int read () 从流中读出一个字节的数据
int read (byte[] b) 从流中读取数据并存放到数组b中
int read(byte[] b, int off,int len) 从流的指定地方开始读取指定长度的数据到数组b中
void reset() 返回流中标记过的位置
long skip(long n) 跳过流中的指定字数
OutputStream类的主要方法
void close () 关闭当前流对象
void flush () 强制缓冲区中的所有数据写入到流中
void write (byte[] b) 向流中写入一个字节数组
void write (byte[] b,int off,int len) 向流中写入数组b中从off位置开始长度为len数据
abstract void write (int b) 向流中写入一个字节
通常由于InputStream 和 OutputStream的方法都比较低级,所以很少直接使用,而是往往通过他们的子类去实现更高级的操作,使得输入输出更加便捷。
2.1.1 字节文件的输入输出流 FileInputStream 和 FileOutputStream(InputStream 和 OutputStream的子类,具体实现类)
FileInputStream 和 FileOutputStream分别是InputStream 和 OutputStream的子类,我们往往使用FileInputStream 和 FileOutputStream这两个子类去就可以从一个指定文件中读取或者向某一个文件中写入数据。
如果创建FileInputStream 和 FileOutputStream对象,那我们必须指定 文件的路径和文件名,对象被创建之后,流就打开了,程序结尾处必须结束流的操作。关闭流,释放资源。
(1)首先使用FileInputStream
package com.himi.itcast_02; import java.io.FileInputStream; public class FileDemo1 { public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("f:\\temp\\files\\text.txt");//打开指定的字节文件输出流
byte[] b = new byte[fis.available()];//新建一个字节数组,大小为fis输出流的字节数
fis.read(b);//读取fis字节流中文件到字节数组b之中
fis.close();//及时fis关闭字节流,释放资源
String str = new String(b);
System.out.println(str);//读取文件内容 } }
输出结果为:123456789---Juckly (当然之前在f:\\temp\\files\\处必然有文件text.txt)
(2)使用FileOutputStream
package com.himi.itcast_02; import java.io.FileNotFoundException;
import java.io.FileOutputStream; public class FileDemo2 {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("f:\\temp\\files\\feeling.txt");
byte[] data = "我爱朱茵".getBytes("GB2312");
fos.write(data);
fos.close(); } }
找到相应的目的目录下,如下所示:
打开文件feeling.txt如下结果:
2.1.2 字节缓冲输入输出流 BufferedInputStream 和 BufferedOutputStream(InputStream 和 OutputStream的子类,具体实现类)
前面所使用的字节输入流和字节输出流是以字节为单位进行读写操作的,这样一来就使得文件流效率很低,这时候就要使用缓冲输入流(BufferedInputStream) 和 缓冲输出流 (BufferedOutputStream)。
输入数据的时候,将数据存放到一个缓冲区之中,当需要对数据操作的读写操作的时候,直接访问缓冲区。
当输出数据的时候,数据不会直接向输出流输出,而是先将数据写入缓冲区,当缓冲区中的数据满时候,才会将缓冲区中的数据写入输出流中,这样一来就大大提高了输入输出的效率。
(1)BufferedInputStream 使用
BufferedInputStream(InputStream in) Constructs a new BufferedInputStream on the InputStream in . |
BufferedInputStream(InputStream in, Constructs a new BufferedInputStream on the InputStream in . |
BufferedInputStream 使用的代码示例:
package com.himi.itcast_02; import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException; public class FileDemo3 {
public static void main(String[] args) throws IOException {
// BufferedInputStream(InputStream in)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
"f:\\temp\\files\\text.txt")); // 读取数据
// int by = 0;
// while ((by = bis.read()) != -1) {
// System.out.print((char) by);
// }
// System.out.println("---------");
byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
} // 释放资源
bis.close();
} }
输出结果为:123456789---Juckly
(2)BufferedOutputStream使用
package com.himi.itcast_02; import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException; /*
* 通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,看来有一个缓冲区还是非常好的。
* 既然是这样的话,那么,java开始在设计的时候,它也考虑到了这个问题,就专门提供了带缓冲区的字节类。
* 这种类被称为:缓冲区类(高效类)
* 写数据:BufferedOutputStream
* 读数据:BufferedInputStream
*
* 构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了。
*
* 为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?
* 原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是呢,真正的读写操作还得靠基本的流对象实现。
*/ public class FileDemo5 {
public static void main(String[] args) throws IOException {
// BufferedOutputStream(OutputStream out)
// FileOutputStream fos = new FileOutputStream("bos.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
// 简单写法
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("f:\\temp\\files\\helloworld.txt")); // 写数据
bos.write("朱茵5201314".getBytes()); // 释放资源
bos.close();
} }
输出结果如下:
2.1.3 字节数据输入输出流 DataInputStream 和 DataOutputStream(InputStream 和 OutputStream的子类,具体实现类)
package com.vincent.example; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; public class TestDataStream {
public static void main(String[] args) {
// 使用DataInputStream,DataOutputStream写入文件且从文件中读取数据。
try {
// Data Stream写到输入流中
DataOutputStream dos = new DataOutputStream(new FileOutputStream(
"datasteam.txt"));
dos.writeBytes("世界"); //按2字节写入,都是写入的低位
dos.writeChars("世界"); // 按照Unicode写入
// 按照UTF-8写入(UTF8变长,开头2字节是由writeUTF函数写入的长度信息,方便readUTF函数读取)
dos.writeUTF("世界");
dos.flush();
dos.close(); // Data Stream 读取
DataInputStream dis = new DataInputStream(new FileInputStream(
"datasteam.txt"));
// 读取字节
byte[] b = new byte[2];
dis.read(b);
System.out.println(new String(b, 0, 2)); // 读取字符
char[] c = new char[2];
for (int i = 0; i < 2; i++) {
c[i] = dis.readChar();
}
System.out.println(new String(c, 0, 2)); // 读取UTF
System.out.println(dis.readUTF()); dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出结果:
用16进制方式打开文件如下:
可以看出,第一个“世界”已经被截断,两个汉字都只被写入了低位,因此肯定乱码。
2.1.4字节对象输入输出流 ObjectInputStream 和 ObjectOutputStream(不常用)
2.2 字符流 Reader 和Writer
Reader类是字符输入流的基类,Writer是字符输出流的基类
Reader和Writer对流数据操作都是以一个字符为单位进行处理的,也可以进行字符编码的处理
2.2.1 字符输入输出流 InputStreamReader 和 OutputStreamWriter(字符流 Reader 和Writer的子类,具体实现类)
字符输入输出流 InputStreamReader 和 OutputStreamWriter进行字符处理,也就是以字符为基本单位进行读写操作,并且实现字符流和字节流的转化,字符流操作比字节流操作效率要高。字符输入输出流 InputStreamReader 和 OutputStreamWriter是可以将字节流转化为字符流,它们是转化流。
备注:
InputStream:得到的是字节输入流,InputStream.read("filename")之后,得到字节流
Reader:读取的是字符流
InputStreamReader:从字节到字符的桥梁。
InputStreamReader(InputStream.read("filename"));
reader.read(InputStreamReader(InputStream in));便可从字节变为字符,打印显示了
(1)OutputStreamWriter使用
OutputStreamWriter:字符流,把字节流转换为字符流。字符流 = 字节流 + 编码表(默认)
构造方法:
OutputStreamWriter(OutputStream out ):根据默认编码把字节流转化为字符流
OutputStreamWriter(OutputStream out , String charsetName):根据指定编码把字节流转化为字符流
代码案例如下:
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
// 创建对象
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
// "osw.txt")); // 默认GBK 此时在工程目录下,也可以自己指定目录
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
// "osw.txt"), "GBK"); // 指定GBK
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"osw.txt"), "UTF-8"); // 指定UTF-8
// 写数据
osw.write("中国"); // 释放资源
osw.close();
}
}
结果我们刷新,打开工程目录下osw.txt文件,如下:
双击打开文件osw.txt,显示如下,显示乱码:
这是因为osw.txt文件Eclipse打开它的时候使用的是默认GBK方式,而我们写入数据的时候编码方式是UTF-8,所以我们打开osw.txt文件解读解码也需要使用UTF-8,这样才能正确解读。右击osw.txt修改属性解码方式即可 ,修改完毕之后结果正确显示,如下:
(2)InputStreamReader使用
InputStreamReader(InputStream is ):使用默认的编码方式读取数据
InputStreamReader(InputStream is, String charsetName ):使用指定编码读取数据
这里我们使用InputStreamReader承接上面的OutputStreamWriter案例,上面我写数据(创建osw.txt)到一个工程目录下,写入osw.txt文件中的数据格式是"UTF-8",这里Eclipse保存osw.txt格式是GBK(自然使用Eclipse打开osw.txt文件会出现乱码),这里我们使用InputStreamReader实现安装特定编码读取数据。案例代码如下:
public class FileDemo7 { public static void main(String[] args) throws Exception {
// 创建对象
// InputStreamReader isr = new InputStreamReader(new FileInputStream(
// "osw.txt")); // InputStreamReader isr = new InputStreamReader(new FileInputStream(
// "osw.txt"), "GBK"); InputStreamReader isr = new InputStreamReader(new FileInputStream(
"osw.txt"), "GBK"); // 读取数据
// 一次读取一个字符
int ch = 0;
while ((ch = isr.read()) != -1) {
System.out.print((char) ch);
} // 释放资源
isr.close(); } }
控制台输出结果为:
同样道理,我们更改读取数据的格式为"UTF-8",控制台结果如下:
2.2.2 文件读写字符流 FileReader 和FileWriter(字符流 Reader 和Writer的子类,直接继承自InputStreamReader 和 OutputStreamWriter)
FileReader 和FileWriter是直接继承自InputStreamReader 和 OutputStreamWriter,而且使用指定文件输入输出流可以直接指定文件名或者使用File来打开指定的文件。如果需要指定编码的话,就需要使用InputStreamReader 和 OutputStreamWriter。
(1)FileWriter类的使用
构造方法:
FileWriter fw = new FileWriter(String fileName);//创建字符输出流类对象和已存在的文件相关联。文件不存在的话,并创建。
如:FileWriter fw = new FileWriter("C:\\demo.txt");
FileWriter fw = new FileWriter(String fileName,boolean append);//创建字符输出流类对象和已存在的文件相关联,并设置该该流对文件的操作是否为续写。
如:FileWriter fw = new FileWriter("C:\\demo.txt",ture); //表示在fw对文件再次写入时,会在该文件的结尾续写,并不会覆盖掉。
FileWriter fw = new FileWriter (File file);//创建一个给定文件路径的FileWirter
FileWriter fw = new FileWriter(File file, boolean append);//创建一个指定文件名的FileWriter,并且根据append值来区分文件的打开方式。
主要方法:
void write(String str) //写入字符串。当执行完此方法后,字符数据还并没有写入到目的文件中去。此时字符数据会保存在缓冲区中。
此时在使用刷新方法就可以使数据保存到目的文件中去。
viod flush() //刷新该流中的缓冲。将缓冲区中的字符数据保存到目的文件中去。
viod close() //关闭此流。在关闭前会先刷新此流的缓冲区。在关闭后,再写入或者刷新的话,会抛IOException异常。
代码示例:
package filewriter; import java.io.FileWriter;
import java.io.IOException; public class Filewriter { private static final String LINE_SEPARATOR = System.getProperty("line.separator");//行与行之间的分隔符 /**
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
/**
* 创建一个可以往文件中写入字符数据的字符流输出流对象
* 创建时必须明确文件的目的地
* 如果文件不存在,这回自动创建。如果文件存在,则会覆盖。
* 当路径错误时会抛异常
*
* 当在创建时加入true参数,回实现对文件的续写。
*/
FileWriter fw = new FileWriter("demo1.txt",false);
/**
* 调用该对象的write方法,向文件写入字符。
*
* 其实写入到了临时存储缓冲区中
*/
// fw.write("hello \r\nworld!");//windows中的换行为\r\n unix下为\r。
fw.write("aello"+LINE_SEPARATOR+"world!");
fw.write("hahaha");
/**
* 进行刷新,将字符写到目的地中。
*/
// fw.flush();
/**
* 关闭流,关闭资源。在关闭前会调用flush方法 刷新缓冲区。关闭后在写的话,会抛IOException
*/
fw.close(); } }
结果如下:
双击demo1.txt文件,知道如下:
(2)FileReader 的使用
构造函数:
FileReader fr = new FileReader(String fileName);//创建一个给定文件name的FilerReader
FileReader fr = new FileReader(File file);//创建一个给定File文件的FilerReader
主要方法
int read(); // 读取单个字符。返回作为整数读取的字符,如果已达到流末尾,则返回 -1。
int read(char[] cbuf);//将字符读入数组。返回读取的字符数。如果已经到达尾部,则返回-1。
void close();//关闭此流对象。释放与之关联的所有资源。
代码示例:
package com.himi.itcast_02; import java.io.FileReader;
import java.io.IOException; public class FileReaderDemo {
public static void main(String[] args) throws IOException {
/**
* 创建读取字符数据的流对象。 读取路径不正确时会抛 IOException 用以个读取流对象关联一个已存在文件。
*/
FileReader fr = new FileReader("demo1.txt");
/**
* 用Reader中的read方法读取字符。
*/
/*
* int ch = fr.read(); System.out.print((char)ch); int ch1 = fr.read();
* System.out.print((char)ch1); int ch2 = fr.read();
* System.out.print((char)ch2);
*/
int ch = 0;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
fr.close();
} }
结果为:
总结案例:用FileReader 和 FileWriter 写的复制文本文件的小程序
->1.首先在F:根目录下新建一个my.txt文件,内容如下:
->2.代码内容:代码实现把 F:\\my.txt 复制到 E:\\you.txt
package com.himi.itcast_02; import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; public class FileReaderWriterDemo {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("F:\\my.txt");//倘若F盘根目录下没有my.txt,会抛出java.io.FileNotFoundException
fw = new FileWriter("E:\\you.txt");//倘若E盘根目录下没有you.txt,就会自动创建you.txt. char []buf = new char[1024];
int len = 0;
//读一个数组大小,写一个数组大小方法。
while((len = fr.read(buf)) != -1){
fw.write(buf, 0, len);
} } catch (Exception e) {
System.out.println(e.toString());
} finally {
if (fr != null)
try {
fr.close();
} catch (Exception e2) {
throw new RuntimeException("关闭失败!");
}
if (fw != null)
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException("关闭失败!");
}
}
}
}
->3.结果如下:
2.2.3 字符缓冲读、写流 BufferedReader 和 BufferedWriter((字符流 Reader 和Writer的子类,具体实现类)
当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取;使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
(1)BufferedReader 使用
构造方法:
BufferedReader (Reader in);//以Reader对象in为参数 创建BufferedReader
BufferedReader (Reader in, int sz);//以Reader对象in为参数创建BufferedReader ,并且通过参数sz来指定缓冲区的大小
代码示例:
package com.himi.itcast_02; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.InputStreamReader; public class BufferedReaderDemo { public static void main(String[] args) throws java.io.IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入一段文字,可包含空白:");
String text = br.readLine();
System.out.println("您输入的文字:" + text);
} }
结果如下:
(2)BufferedWriter使用
构造方法摘要
|
|
---|---|
BufferedWriter(Writer out)
创建一个使用默认大小输出缓冲区的缓冲字符输出流。
|
|
BufferedWriter(Writer out, int sz)
创建一个使用给定大小输出缓冲区的新缓冲字符输出流。
|
|
方法摘要
|
|
---|---|
void
|
close()
关闭此流,但要先刷新它。
|
void
|
flush()
刷新该流的缓冲。
|
void
|
newLine()
写入一个行分隔符。
|
void
|
write(char[] cbuf, int off, int len)
写入字符数组的某一部分。
|
void
|
write(int c)
写入单个字符。
|
void
|
write(String s, int off, int len)
写入字符串的某一部分。
|
代码实现如下:
package com.himi.itcast_02; import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException; public class BufferedWriterDemo {
public static void main(String[] args) {
try { String content = "This is the content to write into file"; File file = new File("F:\\temp\\files\\bufferedwriter.txt"); // if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
} FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(content);
bw.close(); System.out.println("Done"); } catch (IOException e) {
e.printStackTrace();
}
}
}
结果如下:
控制台结果显示是:
找到F:\\temp\\files\\路径下,发现出现了bufferedwriter.txt
双击打开文件如下: