Java中IO总结
File介绍
在整个IO包了,唯一表示与文件本身有关的类就是File类。使用File类可以进行1创建或删除文件等常用操作。要想使用File类。则首先要观察File类的构造方法,此类的常用构造方法如下所示:
No. 方法或常量 类型 描述
- 1 public static final String pathSeparator 常量 表示路径的分隔符(windows是“;”)
- 2 public static final String separator 常量 表示路径的分隔符(windows是“\”)
- 3 public File(String pathname) 构造 创建File类对象,传入完整路径
- 4 public boolean createNewFile()throws IOException 普通 创建新文件
- 5 public boolean delete() 普通 删除文件
- 6 public boolean exists() 普通 判断文件是否存在
- 7 public boolean isDirectory() 普通 判断给定的路径是否在一个目录
- 8 public long length() 普通 返回文件的大小
- 9 public String[] list() 普通 列出指定目录的全部内容,只是名称
- 10 public File[] listFiles() 普通 列出指定目录的全部内容,会有路径
- 11 Public Boolean mkdir() 普通 创建一个目录
- 12 Public Boolean renameTo(File dest) 普通 为已有的文件重命名
代码:
public static void testFile() throws Exception {
//新建
File hello = new File("J:"+File.separator+"hello.txt");
if (!hello.exists()) {
hello.createNewFile();
}
File hello2 = new File("J:"+File.separator+"hello.txt");
System.out.println(hello2.exists());//说明如果文件存在就使用现有的文件
System.out.println(hello.getAbsolutePath());//J:\hello.txt
System.out.println(hello.getPath());//J:\hello.txt
hello.renameTo(new File("J:\\h.txt"));
//删除
if (hello.exists()) {
// hello.delete();
}
//新建文件夹
File zhtFiles = new File("J:"+File.separator+"zhtFiles");
if (!zhtFiles.exists()) {
zhtFiles.mkdirs();
}
System.out.println(zhtFiles.getPath());//J:\zhtFiles
//If this abstract pathname is already absolute,
//then the pathname string is simply returned as if by the getPath method.
System.out.println(zhtFiles.getAbsolutePath());//J:\zhtFiles
//新建了多个文件
for (int i=1; i<11; i++) {
File fi = new File(zhtFiles.getPath() + File.separator +"zht"+i+".txt");
fi.createNewFile();
}
File[] fs = zhtFiles.listFiles();
for (File f : fs) {
System.out.println(f);//带路径打印文件名
}
String[] strs = zhtFiles.list();
for (String s : strs) {
System.out.println(s);//只打印文件名
}
if (zhtFiles.isDirectory()) {
zhtFiles.delete();//只能删除空文件夹
}
deleteFile(zhtFiles.getAbsolutePath());
}
//使用递归进行文件删除操作
static void deleteFile(String pathName) {
File file = new File(pathName);
if (!file.exists()) return;//文件不存在
if (!file.isDirectory()) {//是文件
file.delete();
} else {//是文件夹
//删除文件夹下的文件
File[] fs = file.listFiles();
for (File f : fs) {
deleteFile(f.getAbsolutePath());
}
file.delete();//删除空文件夹
}
}
IO介绍
IO就相当于程序对数据源的读入或者写出的操作方法API的集合。
参考:
http://www.jianshu.com/p/0b86343232d2
http://www.cnblogs.com/liuhongfeng/p/5175109.html
http://www.jianshu.com/p/328f4f67714b
IO是输入和输出的简称,在实际的使用时,输入和输出是有方向的。就像现实中两个人之间借钱一样,例如A借钱给B,相对于A来说是借出,而相对于B来说则是借入。所以在程序中提到输入和输出时,也需要区分清楚是相对的内容。
在程序中,输入和输出都是相对于当前程序而言的,例如从硬盘上读取一个配置文件的内容到程序中,则相当于将文件的内容输入到程序内部,因此输入和“读”对 应,而将程序中的内容保存到硬盘上,则相当于将文件的内容输出到程序外部,因此输出和“写”对应。熟悉输入和输出的对应关系,将有助于后续内容的学习。
在Java语言中,输入和输出的概念要比其它语言的输入和输出的概念涵盖的内容广泛得多,不仅包含文件的读写,也包含网络数据的发送,甚至内存数据的读写以及控制台数据的接收等都由IO来完成。
为了使输入和输出的结构保持统一,从而方便程序员使用IO相关的类,在Java语言的IO类设计中引入了一个新的概念——Stream(流)。
由于在进行IO操作时,需要操作的种类很多,例如文件、内存和网络连接等,这些都被称作数据源(data source),对于不同的数据源处理的方式是不一样的,如果直接交给程序员进行处理,对于程序员来说则显得比较复杂。所以在所有的IO类设计时,在读数据时,JDK API将数据源的数据转换为一种固定的数据序列,在写数据时,将需要写的数据以一定的格式写入到数据序列,由JDK API完成将数据序列中的数据写入到对应的数据源中。这样由系统完成复杂的数据转换以及不同数据源之间的不同的变换,从而简化程序员的编码。
IO的 这种设计就和城市中的供水和排水系统设计是一样的,在供水的时候,水源有江河水、湖水和地下水等不同类型,由自来水公司完成把水源转换为对应的水流(InputStream)。而在 排水系统设计时,只需要将污水排入污水管道即可(OutputStream),至于这些污水是怎么被处理的,则不需要关心,这样也简化了家庭用水的处理。
IO设计中这种数据序列被形象的称作流(Stream)。通过使用流的概念,使程序员面对不同的数据源时只需要建立不同的外壳流即可,不同的外壳流里面都是统一的内部流,程序员面对的就这个外壳流,外壳流封装了很方便统一的操作API,而外壳流和内部流之间的复杂转换则由系统完成,从而使程序员不必深入的了解每种数据源的读写方式,从而降低了IO编程的复杂度。
如图所示:
QQ截图20170729150115.jpg字节流
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:
- 字节流:数据流中最小的数据单元是字节
- 字符流:数据流中最小的数据单元是字符, Java中的字 符是Unicode编码,一个字符占用两个字节。
InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
InputStream 为字节输入流,它本身为一个抽象类,必须依靠其子类实现各种功能,此抽象类是表示字节输入流的所有类的超类。 继承自InputStream 的流都是向程序中输入数据的,且数据单位为字节(8bit);
InputStream是输入字节数据用的类,所以InputStream类提供了3种重载的read方法.Inputstream类中的常用方法:
(1) public abstract int read( ):读取一个byte的数据,返回值是高位补0的int类型值。若返回值=-1说明没有读取到任何字节读取工作结束。
(2) public int read(byte b[ ]):读取b.length个字节的数据放到b数组中。返回值是读取的字节数。该方法实际上是调用下一个方法实现的
(3) public int read(byte b[ ], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的b数组中。
(4) public int available( ):返回输入流中可以读取的字节数。注意:若输入阻塞,当前线程将被挂起,如果InputStream对象调用这个方法的话,它只会返回0,这个方法必须由继承InputStream类的子类对象调用才有用,
(5) public long skip(long n):忽略输入流中的n个字节,返回值是实际忽略的字节数, 跳过一些字节来读取
(6) public int close( ) :我们在使用完后,必须对我们打开的流进行关闭.
主要的子类(截图):
io2.jpg- 1) FileInputStream把一个文件作为InputStream,实现对文件的读取操作
- 2) ByteArrayInputStream:把内存中的一个缓冲区作为InputStream使用
- 3) StringBufferInputStream:把一个String对象作为InputStream
- 4) PipedInputStream:实现了pipe的概念,主要在线程中使用
- 5) SequenceInputStream:把多个InputStream合并为一个InputStream
OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。 Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。
OutputStream提供了3个write方法来做数据的输出,这个是和InputStream是相对应的。
- 1. public void write(byte b[ ]):将参数b中的字节写到输出流。
- 2. public void write(byte b[ ], int off, int len) :将参数b的从偏移量off开始的len个字节写到输出流。
- 3. public abstract void write(int b) :先将int转换为byte类型,把低字节写入到输出流中。
- 4. public void flush( ) : 将数据缓冲区中数据全部输出,并清空缓冲区。
- 5. public void close( ) : 关闭输出流并释放与流相关的系统资源。
主要的子类(截图):
IO3.jpg- ByteArrayOutputStream:把信息存入内存中的一个缓冲区中
- FileOutputStream:把信息存入文件中
- PipedOutputStream:实现了pipe的概念,主要在线程中使用
- SequenceOutputStream:把多个OutStream合并为一个OutStream
流结束的判断:方法read()的返回值为-1时;readLine()的返回值为null时。
- SequenceOutputStream:把多个OutStream合并为一个OutStream
缓冲输入输出流 BufferedInputStream/ BufferedOutputStream
计算机访问外部设备非常耗时。访问外存的频率越高,造成CPU闲置的概率就越大。为了减少访问外存的次数,应该在一次对外设的访问中,读写更多的数据。为此,除了程序和流节点间交换数据必需的读写机制外,还应该增加缓冲机制。缓冲流就是每一个数据流分配一个缓冲区,一个缓冲区就是一个临时存储数据的内存。这样可以减少访问硬盘的次数,提高传输效率。
BufferedInputStream:当向缓冲流写入数据时候,数据先写到缓冲区,待缓冲区写满后,系统一次性将数据发送给输出设备。
BufferedOutputStream :当从向缓冲流读取数据时候,系统先从缓冲区读出数据,待缓冲区为空时,系统再从输入设备读取数据到缓冲区。
字符流
字符流主要用来处理文本文件。
Reader(文件格式操作):抽象类,基于字符的输入操作。
Writer(文件格式操作):抽象类,基于字符的输出操作。
程序:
static void testStream() throws Exception {
//FileInputStream
FileOutputStream fos = new FileOutputStream("J:\\stream1.txt",true);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 'T' HH:mm:ss.SSS");
String dateStr = sdf.format(new Date()) + "你好啊 " +"\n";
fos.write(dateStr.getBytes("utf-8"));
fos.close();
FileInputStream fis = new FileInputStream("J:\\stream1.txt");
int len = fis.available();
byte[] buf = new byte[len];
fis.read(buf);
// System.out.println(new String(buf, "utf-8"));
dump(new FileInputStream("J:\\stream1.txt"), new FileOutputStream("J:\\n.txt"));
dump(new FileInputStream("J:\\stream1.txt"), new FileOutputStream("J:\\n2.txt"));
//byteArray ByteArrayInputStream 将byte数组作为数据源
//ByteArrayOutputStream 新建的bos对象内部包含了一个用来存储数据的byte数组,初始大小32,自动增大
//Creates a ByteArrayInputStream so that it uses buf as its buffer array.
byte[] byteSoure = "hello world 你好啊".getBytes("utf-8");
ByteArrayInputStream bis = new ByteArrayInputStream(byteSoure);
//Creates a new byte array output stream.
//The buffer capacity is initially 32 bytes,
//though its size increases if necessary.
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024*10);
byte[] buf2 = new byte[100];
int len2 = 0;
while ((len2 = bis.read(buf2)) != -1) {
bos.write(buf2, 0, len2);
}
System.out.println(new String(bos.toByteArray(), "utf-8"));
//data Stream 在基本的stream上做了一层封装,可以方便对各种数据类型进行读写
DataOutputStream dos = new DataOutputStream(new FileOutputStream("J:\\data"));
dos.writeInt(120);
dos.writeFloat(88.45f);
dos.writeUTF("hello data");
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("J:\\data"));
System.out.println(dis.readInt());
System.out.println(dis.readFloat());
System.out.println(dis.readUTF());
//Object Stream 对类进行读写,类要实现serializable接口
Person p1 = new Person("zht", 28);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("J:\\object"));
oos.writeObject(p1);
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("J:\\object"));
Person p2 = (Person) ois.readObject();
System.out.println(p2.toString());
//打印类转换成的字符串
ByteArrayOutputStream bos2 = new ByteArrayOutputStream();
ObjectOutputStream oos2 = new ObjectOutputStream(bos2);
oos2.writeObject(p1);
System.out.println(new String(bos2.toByteArray()));
}
//文件复制
static void dump(InputStream scr, OutputStream dest) {
try (InputStream tscr = scr; OutputStream tdest = dest) {//自动关闭
byte[] buf = new byte[1024];
int len = -1;
while ((len = tscr.read(buf)) != -1) {
tdest.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//更高效的复制
static void dumpHighSpeed(InputStream scr, OutputStream dest) {
try (BufferedInputStream tscr = new BufferedInputStream(scr);
BufferedOutputStream tdest = new BufferedOutputStream(dest)) {//自动关闭
byte[] buf = new byte[1024];
int len = -1;
while ((len = tscr.read(buf)) != -1) {
tdest.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//编辑文档
static void testWriterReader() throws Exception {
//Reader通过InputStreamReader转换而来,在转换的时候注意设置编码格式
//Writer通过OutputStreamWriter转换而来
InputStreamReader reader = new InputStreamReader(System.in, "gbk");//使用utf-8会有乱码
OutputStreamWriter writer = new OutputStreamWriter(System.out, "gbk");
// writer.write("hello 你好");
writer.flush();//控制台打印输出
char[] buf = new char[1024];
//
// int len = reader.read(buf);//从控制台读取数据
// writer.write("get:"+new String(buf));
// writer.flush();
//常用 的FileReader FileWriter,因为不能设置编码格式,建议尽量少用
FileWriter fileWriter1 = new FileWriter("J:\\fw1.txt");//使用系统默认编码
fileWriter1.write("你好zht");
fileWriter1.close();
FileReader fReader1 = new FileReader("J:\\fw1.txt");//使用系统默认编码
fReader1.read(buf);
System.out.println(new String(buf));
//正确的读写文件姿势
BufferedWriter bufferedWriter = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("J:\\bw1.txt"), "utf-8"));
bufferedWriter.write("你好 bufferWriter");
bufferedWriter.flush();
bufferedWriter.close();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(new FileInputStream("J:\\bw1.txt"), "utf-8"));
System.out.println(bufferedReader.readLine());
charSetConvert("J:\\w.txt", "utf-8", "gbk");
}
//文件编码格式转换
static void charSetConvert(String srcFileName, String readCharSet,
String writeCharSet) throws Exception {
File wFile = new File("J:\\"+new Date().getTime());//临时生成新的文件存放编码转换后的结果
char[] buf = new char[1024];
int len = 0;
//自动关闭文件
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(srcFileName), readCharSet);
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(wFile), writeCharSet)) {
while ((len = reader.read(buf)) != -1) {//编码转换
writer.write(buf, 0, len);
}
writer.flush();
//将临时生成的文件覆盖原文件
byte[] bs = new byte[1024];
FileInputStream fis = new FileInputStream(wFile);
FileOutputStream fos = new FileOutputStream(srcFileName);
while ((len = fis.read(bs)) != -1) {
fos.write(bs, 0, len);
}
fos.close();
fis.close();
}
wFile.delete();//删除临时文件
}
class Person implements Serializable {
String name;
int age;
public Person(String n, int a) {
name = n;
age = a;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "["+name+","+age+"]";
}
}