1.基本概念
(1)16种流介绍
(2)Input_OutputStream继承结构图
(3)Reader_Writer继承结构图
2.基本操作
2.1.基本读操作- read()方法
(1)
1 /* 2 java.io.InputStream 3 java.io.FileInputStream 4 按照字节方式读取 5 */ 6 import java.io.*; 7 class FileInputStreamtest 8 { 9 public static void main(String[] args) 10 { 11 FileInputStream fis = null; 12 try{ 13 //文件路径 14 //String filePath="text1.txt";//相对路径,在当前路径下 15 // String filePath="D:\Sourcecode\Editplus\java\file\text1.txt"; 16 String filePath="D:/Sourcecode/Editplus/java/file/text1.txt"; 17 fis = new FileInputStream(filePath); 18 //读 19 int i1 = fis.read();//以字节方式读,只能读取一个字母 20 System.out.println(i1);//输出字母对应的ASSICK值 21 22 }catch(FileNotFoundException e){ 23 e.printStackTrace(); 24 }catch(IOException e){ 25 e.printStackTrace(); 26 }finally{ 27 //保证流一定释放,使用try..catch语句 28 if(fis!=null){ 29 try{ 30 fis.close(); 31 }catch(IOException e){ 32 e.printStackTrace(); 33 } 34 } 35 36 } 37 } 38 }
(2)
1 import java.io.*; 2 class FileInputStreamtest02 3 { 4 public static void main(String[] args) throws Exception 5 { 6 FileInputStream fis = new FileInputStream("text1.txt"); 7 int temp =0; 8 while((temp=fis.read())!=-1){ 9 System.out.println(temp); 10 } 11 fis.close(); 12 } 13 }
(3)
1 /* 2 int read(byte[] bytes) 3 读取之前在内存中准备一个byte数组,每次读取多个字节存储到byte数组中,一次读取多个字节。 4 效率高 5 text1.txt文件中的内容为abcdefg 6 */ 7 import java.io.*; 8 class FileInputStreamtest03 9 { 10 public static void main(String[] args) throws Exception 11 { 12 FileInputStream fis = new FileInputStream("text1.txt"); 13 byte[] bytes = new byte[3];//每次读3个字节 14 15 int i1 = fis.read(bytes); 16 System.out.println(new String(bytes));//abc 17 int i2 = fis.read(bytes); 18 System.out.println(new String(bytes));//def 19 int i3 = fis.read(bytes); 20 System.out.println(new String(bytes));//gef 21 System.out.println(new String(bytes,0,i3));//g 22 int i4 = fis.read(bytes); 23 24 //int类型的i表示每次读取的字节数 25 System.out.println(i1);//3 26 System.out.println(i2);//3 27 System.out.println(i3);//1 28 System.out.println(i4);//-1 29 30 } 31 }
(4)
1 /* 2 循环读取 3 text1.txt文件中的内容为abcdefg 4 */ 5 import java.io.*; 6 class FileInputStreamtest04 7 { 8 public static void main(String[] args) throws Exception 9 { 10 FileInputStream fis = new FileInputStream("text1.txt"); 11 byte[] bytes = new byte[1024];//每次读3个字节 12 int temp =0; 13 while((temp=fis.read(bytes))!=-1){ 14 System.out.print(new String(bytes,0,temp)); 15 } 16 fis.close(); 17 } 18 }
2.2.available()方法和skip()方法
1 import java.io.*; 2 /* 3 available()方法:返回流中剩余的字节数 4 skip(n)方法:跳过n个字节不读取 5 text1.txt文件中的内容为abcdefg 6 */ 7 class FileInputStreamtest05 8 { 9 public static void main(String[] args) throws Exception 10 { 11 FileInputStream fis = new FileInputStream("text1.txt"); 12 System.out.println(fis.available());//7 13 System.out.println(fis.read());//97 14 System.out.println(fis.available());//6 15 fis.skip(2);//跳过两个字节不读取 16 System.out.println(fis.read());//100 17 fis.close(); 18 19 } 20 }
2.3.写入数据的方法
1 /* 2 java.io.OutputStream 3 java.io.FileOutputStream;文件字节输出流 4 将计算机内存中的数据写入硬盘文件中 5 */ 6 import java.io.*; 7 class FileOutputStreamtest01 8 { 9 public static void main(String[] args) 10 { 11 FileOutputStream fos=null; 12 try{ 13 //fos= new FileOutputStream("text2.txt");//多次运行,会覆盖源文件内容 14 fos= new FileOutputStream("text2.txt",true);//追加写入 15 //写入 16 String msg = "Hello World"; 17 //将String转换成byte数组 18 byte[] bytes = msg.getBytes(); 19 fos.flush();//强制写入,保证数据完全写入硬盘,与、需要刷新 20 //fos.write(bytes);//强制写入,写入全部 21 fos.write(bytes,0,3);//写入3个,将byte数组部分写入 22 23 }catch(Exception e){ 24 e.printStackTrace(); 25 }finally{ 26 if(fos!=null){ 27 try{ 28 fos.close(); 29 }catch(Exception e){ 30 e.printStackTrace(); 31 } 32 } 33 34 } 35 } 36 }
2.4.文件的复制粘贴
FileInputStream FileOutputStream
1 /* 2 文件的复制粘贴 3 */ 4 import java.io.*; 5 class Copy01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 FileInputStream fis = new FileInputStream("text1.txt"); 10 FileOutputStream fos = new FileOutputStream("text2.txt"); 11 //读,写 12 byte[] bytes = new byte[1024]; 13 int temp = 0; 14 while((temp=fis.read(bytes))!=-1){ 15 fos.write(bytes,0,temp); 16 } 17 fis.close(); 18 fos.close(); 19 20 } 21 }
fileReader,FileWriter
1 /* 2 文件复制,只能复制纯文本文件 3 */ 4 import java.io.*; 5 class Copy02 6 { 7 public static void main(String[] args) throws Exception 8 { 9 FileReader fr = new FileReader("text1.txt");//一个已经存在的文件 10 FileWriter fw = new FileWriter("text4.txt");//运行后复制出一个文件 11 char [] chars = new char[1024]; 12 int temp =0; 13 while((temp=fr.read(chars)) != -1){ 14 fw.write(chars,0,temp); 15 } 16 fw.flush(); 17 fr.close(); 18 fw.close(); 19 } 20 }
2.5.FileWriter()方法写入文件
1 /* 2 java.io.Writer; 3 java.io.OutputStream;转换流 4 java.io.FileWriter文件字符输出流 5 */ 6 import java.io.*; 7 class FileWritertest01 8 { 9 public static void main(String[] args) throws Exception 10 { 11 FileWriter fw = new FileWriter("text3.txt",true); 12 fw.write("写入文件");//直接写入字符串 13 char [] chars = {'写','入','文','件','{','。','、',}; 14 fw.write(chars,0,6); 15 fw.flush(); 16 fw.close(); 17 } 18 } 19 /* 20 运行结果: 21 写入文件写入文件{。 22 */
2.6.BufferedReader带有缓冲区的字符输入流
1 /* 2 readLine() 方法一次读取一行文本 3 */ 4 import java.io.*; 5 class BufferedReadertest01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 BufferedReader br = new BufferedReader(new FileReader("BufferedReadertest01.java")); 10 String temp = null; 11 while((temp=br.readLine())!=null){ 12 System.out.println(temp); 13 } 14 br.close(); 15 } 16 }
1 /* 2 readLine() 方法一次读取一行文本 3 */ 4 import java.io.*; 5 class BufferedReadertest02 6 { 7 public static void main(String[] args) throws Exception 8 { 9 FileInputStream fis = new FileInputStream("BufferedReadertest01.java");//文件字节输入流 10 InputStreamReader brs = new InputStreamReader(fis); //将字节流转换成字符流 11 BufferedReader br = new BufferedReader(brs);//brs是字符流 12 //将上面的语句合并 13 // BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("BufferedReadertest01.java"))); 14 String temp = null; 15 while((temp=br.readLine())!=null){ 16 System.out.println(temp); 17 } 18 br.close(); 19 } 20 }
3.文件输入/输出流
1.FileinputStream 与FileOutputStream类将文件读出与写入。
2.FileReader和FileWriter将文件读出与写入。
二者的区别:
使用FileOutputStream类向文件中写入数据与使用FileinputStream类从文件中将内容读出来都存在一点不足,即这两个类都只有提供了对字节或字节数组的读取方法,由于汉子在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码的情况,此时采用字符流Reader或Writer类即可避免这种现象。
FileReader和FileWriter字符流对应了FileinputStream 与FileOutputStream类,FileReader流顺序地读取文件,只要不关闭流,每次调用read()方法就顺序地读取源文件中其余内容,直到源的末尾或流被关闭。
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.FileOutputStream; 4 5 public class FileTest3 { 6 7 public static void main(String[] args) { 8 File file = new File("D:/Sourcecode/Java/file/word1.txt"); 9 try{ 10 FileOutputStream out = new FileOutputStream(file); 11 byte buy[] ="风住尘香花已尽,日晚倦梳头。物是人非事事休,欲语泪先流。".getBytes(); 12 out.write(buy); 13 out.close(); 14 }catch(Exception e){ 15 e.printStackTrace(); 16 } 17 try{ 18 FileInputStream inputStream = new FileInputStream(file); 19 byte byt[] = new byte[1024]; 20 int len =inputStream.read(byt); 21 System.out.print("文件中的信息是: "+ new String(byt,0,len)); 22 inputStream.close(); 23 }catch(Exception e){ 24 e.printStackTrace(); 25 } 26 } 27 28 }
1 import java.awt.*; 2 import java.awt.event.*; 3 import java.io.*; 4 5 import javax.swing.*; 6 7 public class Ftest extends JFrame { // 创建类,继承Jframe类 8 private JScrollPane scrollPane; 9 private static final long serialVersionUID = 1L; 10 private JPanel jContentPane = null; // 创建面板对象 11 private JTextArea jTextArea = null; // 创建文本域对象 12 private JPanel controlPanel = null; // 创建面板对象 13 private JButton openButton = null; // 创建按钮对象 14 private JButton closeButton = null; // 创建按钮对象 15 16 private JTextArea getJTextArea() { 17 if (jTextArea == null) { 18 jTextArea = new JTextArea(); 19 } 20 return jTextArea; 21 } 22 23 private JPanel getControlPanel() { 24 if (controlPanel == null) { 25 FlowLayout flowLayout = new FlowLayout(); 26 flowLayout.setVgap(1); 27 controlPanel = new JPanel(); 28 controlPanel.setLayout(flowLayout); 29 controlPanel.add(getOpenButton(), null); 30 controlPanel.add(getCloseButton(), null); 31 } 32 return controlPanel; 33 } 34 35 private JButton getOpenButton() { 36 if (openButton == null) { 37 openButton = new JButton(); 38 openButton.setText("写入文件"); // 修改按钮的提示信息 39 openButton 40 .addActionListener(new java.awt.event.ActionListener() { 41 // 按钮的单击事件 42 public void actionPerformed(ActionEvent e) { 43 // 创建文件对象 44 File file = new File("word.txt"); 45 try { 46 // 创建FileWriter对象 47 FileWriter out = new FileWriter(file); 48 // 获取文本域中文本 49 String s = jTextArea.getText(); 50 out.write(s); // 将信息写入磁盘文件 51 out.close(); // 将流关闭 52 } catch (Exception e1) { 53 e1.printStackTrace(); 54 } 55 } 56 }); 57 } 58 return openButton; 59 } 60 61 private JButton getCloseButton() { 62 if (closeButton == null) { 63 closeButton = new JButton(); 64 closeButton.setText("读取文件"); // 修改按钮的提示信息 65 closeButton 66 .addActionListener(new java.awt.event.ActionListener() { 67 // 按钮的单击事件 68 public void actionPerformed(ActionEvent e) { 69 File file = new File("word.txt"); // 创建文件对象 70 try { 71 // 创建FileReader对象 72 FileReader in = new FileReader(file); 73 char byt[] = new char[1024]; // 创建char型数组 74 int len = in.read(byt); // 将字节读入数组 75 // 设置文本域的显示信息 76 jTextArea.setText(new String(byt, 0, len)); 77 in.close(); // 关闭流 78 } catch (Exception e1) { 79 e1.printStackTrace(); 80 } 81 } 82 }); 83 } 84 return closeButton; 85 } 86 87 public Ftest() { 88 super(); 89 initialize(); 90 } 91 92 private void initialize() { 93 this.setSize(300, 200); 94 this.setContentPane(getJContentPane()); 95 this.setTitle("JFrame"); 96 } 97 98 private JPanel getJContentPane() { 99 if (jContentPane == null) { 100 jContentPane = new JPanel(); 101 jContentPane.setLayout(new BorderLayout()); 102 jContentPane.add(getScrollPane(), BorderLayout.CENTER); 103 jContentPane.add(getControlPanel(), BorderLayout.SOUTH); 104 } 105 return jContentPane; 106 } 107 108 public static void main(String[] args) { // 主方法 109 Ftest thisClass = new Ftest(); // 创建本类对象 110 thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 111 thisClass.setVisible(true); // 设置该窗体为显示状态 112 } 113 /** 114 * @return 115 */ 116 protected JScrollPane getScrollPane() { 117 if (scrollPane == null) { 118 scrollPane = new JScrollPane(); 119 scrollPane.setViewportView(getJTextArea()); 120 } 121 return scrollPane; 122 } 123 }
4.带缓存的输入输出流
由于Java中的字符是Unicode编码,是双字节的,writeBytes只是将字符串中的每一个字符的低字节内容写入目标设备中,而writeChars将字符串的每一个字符的两个字节的内容都写到目标设备中,WriterUTF将字符串按照UTF编码后的字节长度写入目标设备,然后才是每一字节的UTF编码。
DataInputStream类只提供了一个readUTF()方法返回字符串,这是因为要在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法知道读取到什么位置才是这个字符串的结束,DataOutputStream类中只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确的读回写入的字符串。
例:
1 public class Dataintandout { 2 3 public static void main(String[] args) { 4 try{ 5 //创建FileOutputStream对象 6 FileOutputStream fStream = new FileOutputStream("D:/Sourcecode/Java/file/word4.txt"); 7 //创建DataOutputStream对象 8 DataOutputStream dStream = new DataOutputStream(fStream); 9 dStream.writeUTF("使用writeUTF()方法写入数据:不是无心惜落花,落花无意恋春花"); 10 dStream.writeChars("使用writeChars()方法写入数据:今朝春去谁家落,把酒临风千种恨"); 11 dStream.writeBytes("使用writeBytes()方法写入数据:昨日寒鸦一片愁,柳塘新绿却温柔"); 12 dStream.close(); 13 //创建FileInputStream对象 14 FileInputStream fileInputStream = new FileInputStream("D:/Sourcecode/Java/file/word4.txt"); 15 //创建DataInputStream对象 16 DataInputStream dataInputStream = new DataInputStream(fileInputStream); 17 System.out.println(dataInputStream.readUTF());//将文件输出 18 }catch(Exception e){ 19 e.printStackTrace(); 20 } 21 } 22 23 }
运行结果:使用writeUTF()方法写入数据:不是无心惜落花,落花无意恋春花
打开文本内容如下:
尽管在记事本中出现乱码的情况,但在控制台屏幕上仍然能正确显示内容。但如果使用writeChars()方法和writeBytes()方法写入字符串,就不能正确读出。
带缓存的输入输出流
缓存是I/o的一种性能优化,带缓存为I/o流增加了内存缓存区,有了缓存区,使得在流上执行skip(),mark(),reset()方法成为可能。
4.1.BufferedinputStream与BufferedOutputStream类
1. BufferedinputStream有两种构造方法:
(1)BufferedinputStream(inputStream in)
(2)BufferedinputStream(inputStream in,int size)
第一种形式的构造方法创建了一个带有32个字节的缓存流,第二种形式的构造方法按指定的大小来创建缓存区。一个最优的缓存区的大小,取决于它所在的操作系统,可用的内存空间以及机器配置。从构造方法可以看出,BufferedinputStream对象位于InputStream类对象之前
2.BufferedOutputStream类有两种构造方法
(1)BufferedOutputStream(OutputStream in)
(2)BufferedOutputStream(OutputStream in,int size)
第一种构造方法创建了一个有32个字节的缓存区域,第二种构造方法以指定的大小来创建缓存区
注意:flush()方法是用于即使在缓存区域没有存满的情况下,也将缓存区的内容强制写入到外设,习惯上称这个过程为刷新,flush()方法只对使用缓存区的OutputStream类的子类有效,当调用close()方法时,系统在关闭之前,也将缓存区中的信息刷新到磁盘文件中。
4.2.BufferedReader与BufferedWriter类
BufferedReader类常用的方法如下。
(1)read()方法:读取单个字符。
(2)readLine()方法:读取一个文本行,并将其返回为字符串。若无数据可读,则返回null。BufferedWriter类中的方法都返回void,常用的方法如下:
a、 write(String s,int off, int len)方法:写入字符串的某一部分。
b、flush()方法:刷新该流得缓存。
c、newline()方法:写入一个行分隔符。
例:
1 package file; 2 3 import java.io.BufferedReader; 4 import java.io.BufferedWriter; 5 import java.io.File; 6 import java.io.FileReader; 7 import java.io.FileWriter; 8 9 public class Student { 10 public static void main(String []args){ 11 String contet[] = {"夜夜思君情断肠,缘何人不双,夜夜痴迷空自伤,月随人彷徨"}; 12 //创建文件对象 13 File file = new File("D:/Sourcecode/Java/file/word2.txt"); 14 try{ 15 //创建FileWriter类对象 16 FileWriter fw = new FileWriter(file); 17 //创建bufferWriter类对象 18 BufferedWriter buffw = new BufferedWriter(fw); 19 for(int k = 0;k < contet.length;k++){ 20 buffw.write(contet[k]);//将字符串数组中的元素写入到磁盘文件中 21 buffw.newLine();//将数组中的单个元素以单行的形式写入文件 22 } 23 buffw.close(); //将BufferReader流关闭 24 fw.close(); //将FileWriter流关闭 25 }catch(Exception e){ 26 e.printStackTrace(); 27 } 28 try{ 29 //创建FileReader类对象 30 FileReader fr = new FileReader(file); 31 //创建BufferReader类对象 32 BufferedReader bufr = new BufferedReader(fr); 33 String s = null;//创建字符串对象 34 int i = 0; 35 //如果文件文本行数不为空,则进入循环 36 while((s = bufr.readLine()) != null){ 37 i++; 38 System.out.println("第"+i+"行"+s); 39 } 40 bufr.close(); 41 fr.close(); 42 43 }catch(Exception e){ 44 e.printStackTrace(); 45 } 46 } 47 }
运行结果:
第1行夜夜思君情断肠,缘何人不双,
第2行夜夜痴迷空自伤,月随人彷徨
5.序列化和反序列化-对象流
5.1.序列化-ObjectOutputStream
序列化就是将堆中的Java对象存入到硬盘中。
1 import java.io.Serializable;//可序列化的,没有任何方法的标识接口 2 class User implements Serializable 3 { 4 String name; 5 User(String name){ 6 this.name = name; 7 } 8 public String toString(){ 9 return "User[name="+name+"]"; 10 } 11 }
注: User 实现了 Serializable 接口, JVM会给该类添加自动一个属性:序列化版本号。(可以自定义一个序列化版本号,则系统不会再成序列化版本号,
也不会出现版本号不相同的情况)
例:自定义序列化版本号
static final long seriaVersionUID="xxxxxxxxx";
如果不让某个属性参与序列化,可以使用transient关键字修饰;
transient String name;
1 /* 2 java.io.ObjectOutputStream;序列化Java对象到硬盘 3 java.io.ObjectInputStream;将硬盘中的数据反序列化到jvm内存 4 */ 5 import java.io.*; 6 class ObjectOutputStreamtest01 7 { 8 public static void main(String[] args) throws Exception 9 { 10 //创建Java对象 11 User u1 = new User("Java对象"); 12 //创建输出流(序列化流)jvm中的java对象状态保存到硬盘中 13 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("text6.txt")); 14 //写 15 oos.writeObject(u1); 16 oos.flush(); 17 oos.close(); 18 } 19 }
5.2.反序列化-ObjectInputStream
反序列化就是将硬盘中的对象恢复到内存中。
1 /* 2 反序列化 3 */ 4 import java.io.*; 5 class ObjectInputStreamtest01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 //创建反序列化流 10 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("text6.txt")); 11 //反序列化 12 Object o = ois.readObject(); 13 System.out.println(o); 14 ois.close(); 15 } 16 } 17 /* 18 User[name=Java对象] 19 请按任意键继续. . . 20 */
6.File
6.1.特点
Java.io.File;File类和流无关,不能通过该类完成文件的读和写,File是文件和目录路径名的抽象表示形式,File代表的是硬盘上的文件夹和文件名。
6.2.常用方法
1 import java.io.*; 2 /* 3 判断指定路径或文件是否存在,不存在则创建 4 */ 5 class Filetest01 6 { 7 public static void main(String[] args) throws Exception 8 { 9 //相对路径 10 File f1 = new File("text1.txt"); 11 //绝对路径 12 File f2 = new File("D:\Sourcecode\Editplus\java"); 13 14 System.out.println(f1.exists());//true 15 System.out.println(f2.exists());//true 16 17 File f3 = new File("D:\Sourcecode\Editplus\java\AA"); 18 System.out.println(f3.exists());//false 19 //如果不存在则创建 20 if(!f3.exists()){ 21 //创建目录 22 //f3.mkdir(); 23 //创建文件 24 f3.createNewFile(); 25 } 26 File f4 = new File("D:/a/b/c"); 27 if(!f4.exists()){ 28 //创建多重目录 29 f4.mkdirs(); 30 } 31 } 32 }