程序员学习 IO流

来源:互联网 发布:软件测试个人简历范文 编辑:程序博客网 时间:2024/06/14 21:26

O流分类

按照数据流向

输入流 读入数据

输出流 写出数据

按照数据类型

字节流

字符流

什么情况下使用哪种流呢?

如果数据所在的文件通过windows自带的记事本打开并能读懂里面的内容,就用字符流。其他用字节流。

如果你什么都不知道,就用字节流

字节流的抽象基类:

InputStream 输入流

OutputStream。输出流

字符流的抽象基类:

Reader , Writer。

注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。

如:InputStream的子类FileInputStream。

如:Reader的子类FileReader。

字节流写数据

OutputStream

FileOutputStream

往一个文本文件中写一句话:”helloworld”

分析发现其实更适合用字符流,但是由于字节流先出现,所以,我们考虑先使用字节流后面再讲会什么出现字符流。

FileOutputStream的构造方法

FileOutputStream(File file)

FileOutputStream(String name)

字节流写数据的方式

public void write(int b)

public void write(byte[] b)

public void write(byte[] b,int off,int len)

File类

为了很方便的代表文件的概念,以及存储一些对于文件的基本操作,在java.io包中设计了一个专门的类——File类。

在File类中包含了大部分文件操作的功能方法,该类的对象可以代表一个具体的文件或文件夹,所以以前曾有人建议将该类的类名修改成FilePath,因为该类也可以代表一个文件夹,更准确的说是可以代表一个文件路径。

下面介绍一下File类的基本使用。

1、File对象代表文件路径

File类的对象可以代表一个具体的文件路径,在实际代表时,可以使用绝对路径也可以使用相对路径。

下面是创建的文件对象示例。

public File(String pathname)

该示例中使用一个文件路径表示一个File类的对象,例如:

File f1 = new File(“d:\\test\\1.txt”);

File f2 = new File(“1.txt”);

File f3 = new File(“e:\\abc”);

这里的f1和f2对象分别代表一个文件,f1是绝对路径,而f2是相对路径,f3则代表一个文件夹,文件夹也是文件路径的一种。

public File(String parent, String child)

也可以使用父路径和子路径结合,实现代表文件路径,例如:

File f4 = new File(“d:\\test\\”,”1.txt”);

这样代表的文件路径是:d:\test\1.txt。

2、File类常用方法

File类中包含了很多获得文件或文件夹属性的方法,使用起来比较方便,下面将常见的方法介绍如下:

a、createNewFile方法

public boolean createNewFile() throws IOException

该方法的作用是创建指定的文件。该方法只能用于创建文件,不能用于创建文件夹,且文件路径中包含的文件夹必须存在。

b、delect方法

public boolean delete()

该方法的作用是删除当前文件或文件夹。如果删除的是文件夹,则该文件夹必须为空。如果需要删除一个非空的文件夹,则需要首先删除该文件夹内部的每个文件和文件夹,然后在可以删除,这个需要书写一定的逻辑代码实现。

c、exists方法

public boolean exists()

该方法的作用是判断当前文件或文件夹是否存在。

d、getAbsolutePath方法

public String getAbsolutePath()

该方法的作用是获得当前文件或文件夹的绝对路径。例如c:\test\1.t则返回c:\test\1.t。

e、getName方法

public String getName()

该方法的作用是获得当前文件或文件夹的名称。例如c:\test\1.t,则返回1.t。

f、getParent方法

public String getParent()

该方法的作用是获得当前路径中的父路径。例如c:\test\1.t则返回c:\test。

g、isDirectory方法

public boolean isDirectory()

该方法的作用是判断当前File对象是否是目录。

h、isFile方法

public boolean isFile()

该方法的作用是判断当前File对象是否是文件。

i、length方法

public long length()

该方法的作用是返回文件存储时占用的字节数。该数值获得的是文件的实际大小,而不是文件在存储时占用的空间数。

j、list方法

public String[] list()

该方法的作用是返回当前文件夹下所有的文件名和文件夹名称。说明,该名称不是绝对路径。

k、listFiles方法

public File[] listFiles()

该方法的作用是返回当前文件夹下所有的文件对象。

l、mkdir方法

public boolean mkdir()

该方法的作用是创建当前文件文件夹,而不创建该路径中的其它文件夹。假设d盘下只有一个test文件夹,则创建d:\test\abc文件夹则成功,如果创建d:\a\b文件夹则创建失败,因为该路径中d:\a文件夹不存在。如果创建成功则返回true,否则返回false。

m、mkdirs方法

public boolean mkdirs()

该方法的作用是创建文件夹,如果当前路径中包含的父目录不存在时,也会自动根据需要创建。

n、renameTo方法

public boolean renameTo(File dest)

该方法的作用是修改文件名。在修改文件名时不能改变文件路径,如果该路径下已有该文件,则会修改失败。

o、setReadOnly方法

public boolean setReadOnly()

该方法的作用是设置当前文件或文件夹为只读。

3、File类基本示例

以上各方法实现的测试代码如下:

import java.io.File;

public class FileDemo {

public static void main(String[] args) {

//创建File对象

File f1 = new File("d:\\test");

File f2 = new File("1.txt");

File f3 = new File("e:\\file.txt");

File f4 = new File("d:\\","1.txt");

//创建文件

try{

boolean b = f3.createNewFile();

}catch(Exception e){

e.printStackTrace();

}

//判断文件是否存在

System.out.println(f4.exists());

//获得文件的绝对路径

System.out.println(f3.getAbsolutePath());

//获得文件名

System.out.println(f3.getName());

//获得父路径

System.out.println(f3.getParent());

//判断是否是目录

System.out.println(f1.isDirectory());

//判断是否是文件

System.out.println(f3.isFile());

//获得文件长度

System.out.println(f3.length());

//获得当前文件夹下所有文件和文件夹名称

String[] s = f1.list();

for(int i = 0;i < s.length;i++){

System.out.println(s[i]);

}

//获得文件对象

File[] f5 = f1.listFiles();

for(int i = 0;i < f5.length;i++){

System.out.println(f5[i]);

}

//创建文件夹

File f6 = new File("e:\\test\\abc");

boolean b1 = f6.mkdir();

System.out.println(b1);

b1 = f6.mkdirs();

System.out.println(b1);

//修改文件名

File f7 = new File("e:\\a.txt");

boolean b2 = f3.renameTo(f7);

System.out.println(b2);

//设置文件为只读

f7.setReadOnly();

}

}

4、File类综合示例

下面以两个示例演示File类的综合使用。第一个示例是显示某个文件夹下的所有文件和文件夹,原理是输出当前名称,然后判断当前File对象是文件还是文件夹,如果则获得该文件夹下的所有子文件和子文件夹,并递归调用该方法实现。第二个示例是删除某个文件夹下的所有文件和文件夹,原理是判断是否是文件,如果是文件则直接删除,如果是文件夹,则获得该文件夹下所有的子文件和子文件夹,然后递归调用该方法处理所有子文件和子文件夹,然后将空文件夹删除。则测试时谨慎使用第二个方法,以免删除自己有用的数据文件。

示例代码一:

import java.io.File;

public class AdvanceFileDemo {

public static void main(String[] args) {

File f = new File("e:\\Book");

printAllFile(f);

File f1 = new File("e:\\test");

deleteAll(f1);

}

public static void printAllFile(File f){

//打印当前文件名

System.out.println(f.getName());

//是否是文件夹

if(f.isDirectory()){

//获得该文件夹下所有子文件和子文件夹

File[] f1 = f.listFiles();

//循环处理每个对象

int len = f1.length;

for(int i = 0;i < len;i++){

//递归调用,处理每个文件对象

printAllFile(f1[i]);

}

}

}

public static void deleteAll(File f){

//文件

if(f.isFile()){

f.delete();

}else{ //文件夹

//获得当前文件夹下的所有子文件和子文件夹

File f1[] = f.listFiles();

//循环处理每个对象

int len = f1.length;

for(int i = 0;i < len;i++){

//递归调用,处理每个文件对象

deleteAll(f1[i]);

}

//删除当前文件夹

f.delete();

}

}

}

事例代码二:

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.FilenameFilter;

import java.io.IOException;

 

/*

 * 编写一个程序,将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.jad

 * 

 * 分析:

 *  A:封装数据源目录

 *  B:使用文件名称过滤器获取封装目录下所有的java文件的File数组。

 *  C:遍历数组,获取到每一个文件对象。

 *  D:复制该文件并改名。

 *  a:复制完毕后,在改名

 *  b:复制前改名 自己做。

 */

public class CopyFolder {

public static void main(String[] args) throws IOException {

// 封装数据源目录

File src = new File("d:\\java");

if (!src.exists()) {

throw new RuntimeException("数据源目录不存在");

}

// 封装目的地目录

File dest = new File("d:\\jad");

if (!dest.exists()) {

dest.mkdir();

}

 

// 使用文件名称过滤器获取封装目录下所有的java文件的File数组。

File[] fileArray = src.listFiles(new FilenameFilter() {

@Override

public boolean accept(File dir, String name) {

return new File(dir, name).isFile() && name.endsWith(".java");

}

});

 

// 遍历数组,获取到每一个文件对象。

for (File file : fileArray) {

// d:\java\ArgsDemo.java 数据源存在

// d:\jad\ArgsDemo.jad 不存在

String name = file.getName(); // ArgsDemo.java

File destFile = new File(dest, name);// d:\\jad + ArgsDemo.java

 

// 封装数据源

// File file = new File("c:\\a.txt");

// FileReader fr = new FileReader(file);

// FileReader fr = new FileReader("c:\\a.txt");

BufferedReader br = new BufferedReader(new FileReader(file)); // d:\java\ArgsDemo.java

BufferedWriter bw = new BufferedWriter(new FileWriter(destFile));// d:\\jad\\ArgsDemo.java

 

String line = null;

while ((line = br.readLine()) != null) {

bw.write(line);

bw.newLine();

bw.flush();

}

 

bw.close();

br.close();

}

 

// 整体改名

File[] destFiles = dest.listFiles();

for (File file : destFiles) {

String oldName = file.getName();// ArgsDemo.java

String newName = oldName.replace(".java", ".jad"); // ArgsDemo.jad

File destFile = new File(dest,newName); //d:\\jad\\ArgsDemo.jad

file.renameTo(destFile);

}

}

}

字节流读取数据

InputStream

FileInputStream

把刚才写的数据读取出来显示在控制台

FileInputStream的构造方法

FileInputStream(File file)

FileInputStream(String name)

FileInputStream的成员方法

import java.io.FileInputStream;

import java.io.IOException;

 

/*

 * 字节输入流读取数据:

 * 方式1:一次读取一个字节 int read()

 * 方式2:一次读取一个字节数组 int read(byte[] bys)

 * 

 * 字节输入流使用步骤:

 * A:创建字节输入流对象

 * B:调用对象的读取功能

 * C:释放资源

 */

public class FileInputStreamDemo {

public static void main(String[] args) throws IOException {

// 创建字节输入流对象

FileInputStream fis = new FileInputStream("fos.txt");

 

// 调用对象的读取功能

// 方式1

// int by = 0;

// while ((by = fis.read()) != -1) {

// System.out.print((char) by);

// }

 

// 方式2

byte[] bys = new byte[1024];

int len = 0;

while ((len = fis.read(bys)) != -1) {

System.out.print(new String(bys, 0, len));

}

 

// 释放资源

fis.close();

}

}

 字节流写数据

抽象类OutputStream

子类ileOutputStream

FileOutputStream的构造方法

FileOutputStream(File file)

FileOutputStream(String name)

字节流写数据的方式

public void write(int b)  //每次写入一个字节

public void write(byte[] b)//将一组字节写入输出流中

public void write(byte[] b,int off,int len)//将指定范围的字节数组进行输出

import java.io.FileOutputStream;

import java.io.IOException;

 

/*

 * 需求:把一句话写入到文本文件。

 

 

 * 我们要选择字节输出流。

 * OutputStream

 *  |--FileOutputStream

 * 

 * 字节输出流的使用步骤:

 * A:创建字节输出流对象

 * B:调用对象的写入功能

 * C:释放资源

 * 

 * 需求:"hello,io"

 */

public class FileOutputStreamDemo {

public static void main(String[] args) throws IOException {

// 创建字节输出流对象

// FileOutputStream(String name)

FileOutputStream fos = new FileOutputStream("fos.txt",true);

 

// 写入数据

// String str = "hello,io";

// 把字符串转成字节数组

byte[] bys = str.getBytes();

fos.write(bys);

fos.write("hello,io\r\n".getBytes());

 fos.flush();

//释放资源

fos.close();

}

}

 

字节流写数据常见问题

如何实现数据的换行?

如何实现数据的追加写入?

import java.io.FileWriter;

import java.io.IOException;

 

/*

 * 1:如何把写入文件中的数据换行?

 *  问题:\n表示换行。

 *  但是,不同的系统,识别不太一样。

 *  windows:\r\n

 *  linux:\n

 *  mac:\r

 * 

 *  记事本是windows自带的工具,所以只识别\r\n。

 *  而eclipse自带的记事本工具及Editplus工具他们是既可以识别\n还可以识别\r\n。

 * 

 * 2:如何实现追加数据?

 *  看构造方法:

 *  FileWriter(File file, boolean append) 

 *  FileWriter(String fileName, boolean append) 

 * 

 * 注意:什么时候刷?一定次数后刷。怎么控制呢?统计变量。

 */

public class FileWriterDemo3 {

public static void main(String[] args) throws IOException {

// 创建字符输出流对象

FileWriter fw = new FileWriter("fw.txt",true);

 

// 写入数据

int count = 1;

//一般来说,数据在1-10M之间刷一次。

//10M = 10*1024KB = 10*1024*1024Byte = 5*1024*1024字符

for (int x = 0; x < 10; x++) {

fw.write("hello" + x + "\r\n");

if(count++%10000==0){

fw.flush();

}

// fw.append("hello"+x+"\r\n");

// fw.flush();

//fw.close();

}

 

// 释放资源

fw.close();

}

}

字节流复制数据练习

package cn.itcast.test;

 

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

 

/*

 * 需求:字节流复制文本文件,把fos.txt的内容复制到copy.txt中 

 * 字节流复制数据练习

 * 分析:

 * 

 * 数据源:

 *  fos.txt -- 读取数据 -- InputStream -- FileInputStream

 * 目的地:

 *  copy.txt -- 写入数据 -- OutputStream -- FileOutputStream

 */

public class CopyFile {

public static void main(String[] args) throws IOException {

// 封装数据源

FileInputStream fis = new FileInputStream("fos.txt");

// 封装目的地

FileOutputStream fos = new FileOutputStream("copy.txt");

 

// 基本读写操作

 

// 释放资源

fos.close();

fis.close();

}

}

 

事例二:

package cn.itcast.test;

 

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

 

/*

 * 需求:复制图片

 * 

 * 注意:图片,视频,音频都属于二进制数据。只能使用字节流。

 * 

 * 2个字节 -- 字符

 * 字符 -- 2个字节

 * 字符编码表中:说明了有些数据找不到对应的值。

 * 

 * 数据源:

 *  d:\\mn.jpg

 * 目的地:

 *  mn.jpg

 * 

 * 方式1:字符流

 *  5种

 * 方式2:字节流

 *  4种

 */

public class CopyImage {

public static void main(String[] args) throws IOException {

// // 字符流复制图片

// FileReader fr = new FileReader("d:\\mn.jpg");

// FileWriter fw = new FileWriter("mn.jpg");

//

// //基本读写

// int ch = 0;

// while((ch=fr.read())!=-1){

// fw.write(ch);

// }

//

// fw.close();

// fr.close();

 

// 字节流复制图片

FileInputStream fis = new FileInputStream("d:\\mn.jpg");

FileOutputStream fos = new FileOutputStream("mn.jpg");

int by = 0;

while((by=fis.read())!=-1){

fos.write(by);

}

fos.close();

fis.close();

}

}

事例三

package cn.itcast.test;

 

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

 

/*

 * 需求:复制MP3.

 * 分析:MP3是二进制数据,所以只能只用字节流。而字节流有四种方案。

 * 

 * 方案1:基本流一次读取一个字节 42812毫秒

 * 方案2:基本流一次读取一个字节数组  47毫秒

 * 方案3:缓冲流一次读取一个字节          500毫秒

 * 方案4:缓冲流一次读取一个字节数组  15毫秒

 * 

 * 测试每一种功能的时间。

 */

public class CopyMP3 {

public static void main(String[] args) throws IOException {

long start = System.currentTimeMillis();

//method1();

//method2();

//method3();

method4();

long end = System.currentTimeMillis();

System.out.println((end - start) + "毫秒");

}

 

// 方式1

public static void method1() throws IOException {

FileInputStream fis = new FileInputStream("d:\\zxmzf.mp3");

FileOutputStream fos = new FileOutputStream("copy1.mp3");

 

int by = 0;

while ((by = fis.read()) != -1) {

fos.write(by);

}

 

fos.close();

fis.close();

}

 

// 方式2

public static void method2() throws IOException {

FileInputStream fis = new FileInputStream("d:\\zxmzf.mp3");

FileOutputStream fos = new FileOutputStream("copy2.mp3");

 

byte[] bys = new byte[1024];

int len = 0;

while ((len = fis.read(bys)) != -1) {

fos.write(bys, 0, len);

}

 

fos.close();

fis.close();

}

 

// 方式3

public static void method3() throws IOException {

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(

"d:\\zxmzf.mp3"));

BufferedOutputStream bos = new BufferedOutputStream(

new FileOutputStream("copy3.mp3"));

 

int by = 0;

while ((by = bis.read()) != -1) {

bos.write(by);

}

 

bos.close();

bis.close();

}

 

// 方式4

public static void method4() throws IOException {

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(

"d:\\zxmzf.mp3"));

BufferedOutputStream bos = new BufferedOutputStream(

new FileOutputStream("copy4.mp3"));

 

byte[] bys = new byte[1024];

int len = 0;

while ((len = bis.read(bys)) != -1) {

bos.write(bys, 0, len);

}

 

bos.close();

bis.close();

}

}

字节流和字符流的区别(重点)

      字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,字节流不调用colse()方法时,信息已经输出了,而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法。

 

 

 

字节缓冲流

字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流

字节缓冲输出流

BufferedOutputStream

字节缓冲输入流

 

BufferedInputStream

 

6)转换流:在io中还存在一类是转换流,将字节流转换为字符流,同时可以将字符流转化为字节流。

OutputStreamWriter(OutStream out):j将字节流以字符流输出。

InputStreamReader(InputStream in):将字节流以字符流输入

OutputStreamWriter写数据

OutputStreamWriter写数据方法

public void write(int c)

public void write(char[] cbuf)

public void write(char[] cbuf,int off,int len)

public void write(String str)

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

 

InputStreamReader读数据

OutputStreamWriter读数据方法

public int read()

public int read(char[] cbuf)

事例:

package cn.itcast_05;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileWriter;

import java.io.IOException;

import java.io.InputStreamReader;

 

/*

 * 需求:用标准的键盘录入流读取键盘数据。

 * 

 * 转换流:

 * 把字节流数据转换成字符流数据。

 * InputStreamReader 是字节流通向字符流的桥梁

 */

public class SystemInDemo2 {

public static void main(String[] args) throws IOException {

// 标准键盘录入

// InputStream is = System.in;// 多态

// //字节流 -- 字符流的转换

// InputStreamReader isr = new InputStreamReader(is);

// //创建字符缓冲流对象

// BufferedReader br = new BufferedReader(isr);

 

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

// 写入文本文件

BufferedWriter bw = new BufferedWriter(new FileWriter("bw3.txt"));

 

/*

 * 如果我们能够使用一次读取一行的数据来读取键盘录入,该有多好呢所以,我们也就这样做了。

 * 由于一次读取一行的方法是BufferedReader的特殊功能。 所以,我们就必须创建BufferedReader的对象。

 * 但是,这样又出问题了,因为没有这样的构造。为什么呢因为这个BufferedReader是字符流。它只能对字符流进行包装。

 * 又该怎么办呢? 我们能不能大胆的猜想: 字节流 -- 字符流 -- 字符缓冲流 恭喜你,猜对了。这就是转换流。

 */

String line = null;

while((line=br.readLine())!=null){

if("over".equals(line)){

break;

}

bw.write(line);

bw.newLine();

bw.flush();

}

bw.close();

br.close();

}

}

 

转换流出现的原因及思想

由于字节流操作中文不是特别方便,所以,java就提供了转换流。

字符流=字节流+编码表。

package cn.itcast_05;

 

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.FileReader;

import java.io.IOException;

import java.io.OutputStreamWriter;

 

/*

 * 需求:读取fos.txt中的数据用标准输出流到控制台。

 * 

 * 标准输出流:OutputStream -- System.out

 * 

 * OutputStreamWriter 是字符流通向字节流的桥梁

 */

public class SystemOutDemo {

public static void main(String[] args) throws IOException {

BufferedReader br = new BufferedReader(new FileReader("fos.txt"));

 

// 相当远你最终要把一个字符串通过字节流写入到控制台

// 标准输出流

// OutputStream os = System.out;

// OutputStreamWriter osw = new OutputStreamWriter(os);

// BufferedWriter bw = new BufferedWriter(osw);

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(

System.out));

String line = null;

while((line=br.readLine())!=null){

bw.write(line);

bw.newLine();

bw.flush();

}

bw.close();

br.close();

}

}

转换流出现的原因及思想

由于字节流操作中文不是特别方便,所以,java就提供了转换流。

字符流=字节流+编码表。

转换流的简化写法

转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。

FileWriter

FileReader

字符缓冲流

BufferedWriter

BufferedReader

字符缓冲流复制文本文件

特殊功能

BufferedWriter

void newLine() 换行

BufferedReader

String readLine() 读取一行数据

                                                   ------- android培训java培训、期待与您交流! ----------

0 0