java的读写操作是学java开发的必经之路,下面就来总结下java的读写操作。
从上图可以开出,java的读写操作(输入输出)可以用“流”这个概念来表示,总体而言,java的读写操作又分为两种:字符流和字节流。
什么是流?
流是一个抽象的概念。当Java程序需要从数据源读取数据时,会开启一个到数据源的流。数据源可以是文件,内存或者网络等。同样,当程序需要输出数据到目的地时也一样会开启一个流,数据目的地也可以是文件、内存或者网络等。流的创建是为了更方便地处理数据的输入输出。
那么字节流和字符流又有什么区别呢?
1.字节流也称为原始数据,需要用户读入后进行相应的编码转换。而字符流的实现是基于自动转换的,读取数据时会把数据按照JVM的默认编码自动转换成字符。
2.字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。
所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的。
3.字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串,字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以;
基于以上的区别,那么什么情况下用字符流,什么情况下用字节流呢?
如果是音频文件、图片、歌曲,就用字节流好点;如果是中文(文本)的,用字符流更好;
说了这么多,字节流和字符流处理文件到底怎么用呢?
稍安勿躁,让我们先来看看在java中,输入输出操作的步骤是什么?
1 使用File类打开一个文件
2 通过字节流或字符流的子类,指定输出的位置,注,
3 进行读/写操作
4 关闭输入/输出
IO操作属于资源操作,一定要记得关闭
字节流:
1.按照字节流的方式从文件中读取数据。
1 package ioInJava.characterStream; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 import java.io.InputStream; 8 9 public class CharIo { 10 11 public static void main(String[] args) { 12 13 // 第一种方式读文件,因为方法throws了异常,所以在这要捕获异常 14 try { 15 CharIo.readFromFileByByte(); 16 } catch (FileNotFoundException e) { 17 e.printStackTrace(); 18 System.out.println("找不到文件啊"); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 System.out.println("读不成功啊!"); 22 } 23 24 System.out.println("==========================="); 25 26 // 第二种方式读文件 27 try { 28 CharIo.readFromFileByteTwo(); 29 } catch (IOException e) { 30 e.printStackTrace(); 31 System.out.println("还是读不成功啊!"); 32 } 33 34 } 35 36 /** 37 * 第一种方法读文件 38 * 通过字符流读取文件中的数据 39 * @throws IOException 40 */ 41 public static void readFromFileByByte() throws IOException{ 42 File file = new File("abc.txt"); 43 // 如果文件不存在则创建文件 44 if (!file.exists()) { 45 file.createNewFile(); 46 } 47 InputStream inputStream = new FileInputStream(file); 48 // 这里定义了数组的长度是1024个字节,如果文件超出这字节,就会溢出,结果就是读不到1024字节以后的东西 49 byte[] bs = new byte[1024]; 50 // 这里len获得的是文件中内容的长度 51 int len = inputStream.read(bs); 52 inputStream.close(); 53 System.out.println(new String(bs)); 54 } 55 56 /** 57 * 第二种方法读文件 58 * 通过字符流读取文件中的数据 59 * @throws IOException 60 */ 61 public static void readFromFileByteTwo() throws IOException{ 62 // 注意这里的不同,File.separator是分隔符,这里指明绝对路径,即D盘根目录下的abc.txt文件 63 File file = new File("d:" + File.separator+"abc.txt"); 64 // 如果文件不存在则创建文件 65 if (!file.exists()) { 66 file.createNewFile(); 67 } 68 InputStream inputStream = new FileInputStream(file); 69 // 这里也有不同,可以根据文件的大小来声明byte数组的大小,确保能把文件读完 70 byte[] bs = new byte[(int)file.length()]; 71 // read()方法每次只能读一个byte的内容 72 inputStream.read(bs); 73 inputStream.close(); 74 System.out.println(new String(bs)); 75 } 76 77 }
2.按照字节流的方式向文件中写入数据。
1 package ioInJava.byteStream; 2 3 import java.io.File; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 import java.io.OutputStream; 8 9 /** 10 * 不要被那么多的try和catch吓到奥,那只是因为不想在main上throws 11 * @author wsg 12 */ 13 public class WriteToFile { 14 15 public static void main(String[] args) { 16 File file = new File("D:"+File.separator+"write.doc"); 17 OutputStream outputStream = null; 18 if (!file.exists()) { 19 try { 20 // 如果文件找不到,就new一个 21 file.createNewFile(); 22 } catch (IOException e) { 23 e.printStackTrace(); 24 } 25 } 26 try { 27 // 定义输出流,写入文件的流 28 outputStream = new FileOutputStream(file); 29 } catch (FileNotFoundException e) { 30 e.printStackTrace(); 31 } 32 // 定义将要写入文件的数据 33 String string = "Hell Java, Hello World, 你好,世界!"; 34 // 把string转换成byte型的,并存放在数组中 35 byte[] bs = string.getBytes(); 36 try { 37 // 写入bs中的数据到file中 38 outputStream.write(bs); 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } 42 43 try { 44 outputStream.close(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 49 // =================到此,文件的写入已经完成了! 50 51 // 如果想在文件后面追加内容的话,用下面的方法 52 OutputStream outToFileEnd = null; 53 try { 54 outToFileEnd = new FileOutputStream(file,true); 55 } catch (FileNotFoundException e) { 56 e.printStackTrace(); 57 }finally {// 这里利用了finally总会被执行的特性,索性把后面的代码都写在finally中 58 String string2 = "Here I come!!"; 59 byte[] bs2 = string2.getBytes(); 60 try { 61 outToFileEnd.write(bs2); 62 } catch (IOException e) { 63 e.printStackTrace(); 64 }finally { 65 try { 66 outToFileEnd.close(); 67 } catch (IOException e) { 68 e.printStackTrace(); 69 } 70 } 71 } 72 } 73 }
=====================================================注意!!==================================================
1.初学者一般很容易搞混,或者弄不清inputstream和outpustream到底哪个是读数据,哪个是写数据,这里要说明的是,“读和写”是相对于程序本身而言的,主要记清楚一点即可,那就是凡是需要提供给程序处理的数据就是输入数据,当然就是inputstream,这里的in是要in到程序里面去,那么数据从哪里来呢,自然是从外界(网络,内存或者文件),那么针对文件而言,inputstream就是读文件了。反之,凡是程序已经处理过的数据,当然要流出程序啦,那就是out咯,所以outputstream就是输出的,那么从程序中流出,只能到外界(网络、内存或者文件),针对文件而言,就是写操作啦!(同样的道理可以针对字符流的操作)
【简言之,针对程序而言,in是入,out是出;这对文件而言,in是读,out是写!】
2.inputstream和OutputStream都是抽象类,不能实例化,使用时必须实例化一个子类(其中FileInputStream和FileOutputStream使用最多)对象来进行相关操作。
3.InputStream inputStream = new FileInputStream(fileName);当使用这个命令时,系统会提示有异常抛出,因为我们上面定义的文件程序认为是有可能存在,有可能不存在的,所以在eclipse中,给出了两个解决办法,一个是直接抛出异常声明,由系统自己解决;另一个是用try,catch结构处理异常!
===============================================================================================================
3.按照字符流的方式向文件中写入数据。
1 package ioInJava.characterStream; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileWriter; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.Writer; 10 11 public class CharIo { 12 13 public static void main(String[] args) throws IOException { 14 // 定义一个d盘根目录下的test文档,File.separator是分隔符 15 // 下面这句代码,就算原本没有这个文件,也会在对应的目录创建一个文件 16 File file = new File("D:" + File.separator + "test.docx"); 17 // 下面这也会抛出异常,这次我们为了代码结构清晰起见,直接throw给main吧 18 Writer writer = new FileWriter(file); 19 String string = "今天是教师节!"; 20 writer.write(string); 21 // 在这一定要记得关闭流 22 writer.close(); 23 } 24 }
但是,上面的代码有一个问题,比如,载定义一个string2,再次调用writer.write(string2)方法的时候,会发现test文件中的内容会被string2的内容覆盖,要想实现内容追加到文件尾部,代码如下,其实就是小小的修改,利用它的一个方法!
1 package ioInJava.characterStream; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileWriter; 7 import java.io.IOException; 8 import java.io.InputStream; 9 import java.io.Writer; 10 11 public class CharIo { 12 13 public static void main(String[] args) throws IOException { 14 // 定义一个d盘根目录下的test文档,File.separator是分隔符 15 // 下面这句代码,就算原本没有这个文件,也会在对应的目录创建一个文件 16 File file = new File("D:" + File.separator + "test.docx"); 17 // 下面这也会抛出异常,这次我们为了代码结构清晰起见,直接throw给main吧 18 // 这里改变了writer的类型,变成了追加型 19 Writer writer = new FileWriter(file, true); 20 String string = "今天是教师节!"; 21 writer.write(string); 22 String string2 = "祝愿所有的老师教师节快乐!"; 23 writer.write(string2);; 24 // 在这一定要记得关闭流 25 writer.close(); 26 } 27 }
4.按照字符流的方式从文件中读取数据。
1 package ioInJava.characterStream; 2 3 import java.io.File; 4 import java.io.FileNotFoundException; 5 import java.io.FileReader; 6 import java.io.FileWriter; 7 import java.io.IOException; 8 import java.io.Reader; 9 10 public class ReadFromFile { 11 12 public static void main(String[] args) throws IOException { 13 File file = new File("d:" + File.separator + "test.docx"); 14 Reader reader = new FileReader(file); 15 char[] cs= new char[1024]; 16 // 上面定义了一个大小为1024的char型数组,如果文件内容过大,程序就会报错,而不是只读到1024的大小 17 reader.read(cs, 0, (int)file.length()); 18 System.out.println(cs); 19 reader.close(); 20 } 21 22 }
上面的代码只能读取内容不超过1024字符的内容,这显然不是我们想要的,如何读取一个任意大小的文件呢!那么最简单的方法就是加大数组的空间大小了,可以用file.length获取文件的大小,从而定义数组的大小!char[] cs= new char[(int)file.length()];
当然,这不是最好的办法,请看下面的代码:
1 package ioInJava.characterStream; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.File; 6 import java.io.FileNotFoundException; 7 import java.io.FileReader; 8 import java.io.FileWriter; 9 import java.io.IOException; 10 import java.io.Reader; 11 import java.io.Writer; 12 13 public class ReadFromFile { 14 15 public static void main(String[] args) throws IOException { 16 try { 17 // 声明一个可变长的stringBuffer对象 18 StringBuffer sb = new StringBuffer(""); 19 20 /* 21 * 读取完整文件 22 */ 23 Reader reader = new FileReader("d:" + File.separator + "test.docx"); 24 // 这里我们用到了字符操作的BufferedReader类 25 BufferedReader bufferedReader = new BufferedReader(reader); 26 String string = null; 27 // 按行读取,结束的判断是是否为null,按字节或者字符读取时结束的标志是-1 28 while ((string = bufferedReader.readLine()) != null) { 29 // 这里我们用到了StringBuffer的append方法,这个比string的“+”要高效 30 sb.append(string + "/n"); 31 System.out.println(string); 32 } 33 // 注意这两个关闭的顺序 34 bufferedReader.close(); 35 reader.close(); 36 37 /* 38 * 完整写入文件 39 */ 40 Writer writer = new FileWriter("d:" + File.separator + "test2.docx"); 41 BufferedWriter bw = new BufferedWriter(writer); 42 // 注意这里调用了toString方法 43 bw.write(sb.toString()); 44 // 注意这两个关闭的顺序 45 bw.close(); 46 writer.close(); 47 48 } catch (FileNotFoundException e) { 49 e.printStackTrace(); 50 } catch (IOException e) { 51 e.printStackTrace(); 52 } 53 } 54 }
上面的代码我们顺利实现了从test文件中读取全文,并将其写入test2文件中!!