java中的文件流按输出方向分为输入流和输出流,输入就是读取数据(即我们读取了一个文件),输出就是写入数据(即我们去创建了一个文件并写入了内容)。java的I/O原码是通过装饰者模式设计的。
按读取单位分,主要分为两种,字节流和字符流。
字节是计算机存储容量的一种单位。字节流就是以字节为单位处理文件流。实现字节流的类都分别继承了InputStream(输入流),OutputStream(输出流),一个英文一个字节,一个中文两个字节。
字符就是我们java用的char,一个字母或者一个中文都是一个字符,实现字符流的类都分别继承了Reader(输入流)和Writer(输出流)
File
讲其他流的时候,先说说File类。FIle表示一个文件或者一个文件目录。就是我们常看到的目录和文件。
创建File有三种形式()
1:File file = new File(String pathname);
pathname:是指路径名称(包含文件名)
2:File file = new File(String parentPath,String childPath);
parentPath:父路劲 chldPath:子路径
3:File file = new File(File parentFile,String childPath);
parentFile:父路径文件对象 childPath:子路劲字符串
@Test public void newFileTest1(){ String pathname = "E:\\学习\\项目测试文件\\file.txt"; File file = new File(pathname); System.out.println(file.exists()); } @Test public void newFileTest2(){ String parentPath = "E:\\学习\\项目测试文件"; String childPath = "file.txt"; File file = new File(parentPath,childPath); System.out.println(file.exists()); } @Test public void newFileTest3(){ File parentFile = new File( "E:\\学习\\项目测试文件"); String childPath = "file.txt"; File file = new File(parentFile,childPath); System.out.println(file.exists()); }假如你的路径是一个目录,则你可以通过listFiles方法获取目录下的所有文件。
@Test public void listFileTest(){ String path = null; try { path = "E:\\学习\\项目测试文件"; File file = new File(path); File[] files = file.listFiles(); for (File file1 : files) { System.out.println(file1.getName()); } } catch (Exception e) { e.printStackTrace(); } }
如果路径指定的文件不存在。则可以通过file的createNewFile()创建一个文件名为file.txt的文件,创建成功会返回true,反之,如果文件已经存在,则返回false
如果file.txt存在,则可以通过delete()方法删除,删除成功返回true,文件不存在,删除失败返回false。
File对象的一些方法属性
String fileName = file.getName();//获取文件的名称 boolean isCanRead = file.canRead();//判断文件是否是可读的 boolean isCanWrite = file.canWrite();//判断文件是否存在 boolean isExits = file.exists();//文件是否存在 long length = file.length();//文件的长度(以字节为单位) String filePath = file.getAbsolutePath();//获取文件的绝对路径 String parentPath = file.getParent();//获得文件的父路径 boolean isFile = file.isFile();//文件是否存在 boolean isDirectory = file.isDirectory();//文件是否是一个目录 boolean isHiddenFile = file.isHidden();//文件是否是隐藏文件 long lastModifiedDate = file.lastModified();//返回文件的最后修改时间 boolean isRename = file.renameTo(new File("E:\\学习\\项目测试文件\\file1.txt"));//重命名文件
boolean renameTo(File file);重命名文件,重命名成功返回true,反之false。可以理解为用新file去替换原来的file。
FileInputStream,OutputStream
FileInputStream类与FileOutputStream类都是用来操做磁盘文件的,是字节流。创建FileInputStream常用的两种构造方法:
1: new FileInputStream(String filePath);
filePath:文件路劲
2:new FileInputStream(new File(...));
file:文件对象
@Test public void newFileInputStreamTest1() throws IOException { FileInputStream fileInputStream = new FileInputStream("FileTest.java"); System.out.println(fileInputStream); fileInputStream.close(); } @Test public void newFileInputStreamTest2() throws IOException { FileInputStream fileInputStream = new FileInputStream(new File("E:\\学习\\项目测试文件\\file.java")); System.out.println(fileInputStream); fileInputStream.close(); }
写一个简单的文件读取和写入操作
虽然java在程序结束时自动关闭所有打开的流,但是当使用完流后,显示的关闭任何打开的流是一个好习惯。不然很容易造成系统资源浪费,并影响其他人读取这个流.
@Test public void fileOutputStreanmWriteTest(){ try{ FileOutputStream out = new FileOutputStream("E:\\学习\\项目测试文件\\outputStream.txt"); byte text[] = "nulidexiaoma".getBytes(); out.write(text); out.close(); }catch (Exception e){ e.printStackTrace(); } } @Test public void fileInoutStreamReadTest(){ try{ FileInputStream in = new FileInputStream("E:\\学习\\项目测试文件\\outputStream.txt"); byte b[] = new byte[1024];//读取文件的速度,即每次读取1024个字节。 int len = in.read(b); System.out.println("读取的信息是"+new String(b,0,len)); in.close(); }catch (Exception e){ } }
FileReader.FileWriter
FileReader和FileWriter是字符流。分别实现Reader和Writer。因为FileInputStream和FileOutputStream是字节流,处理中文容易出现乱码的问题,所以采用FileReader和FileWriter字符流就可以避免这种情况。
@Test public void writeText() throws IOException { String path = "E:\\学习\\项目测试文件\\fileWriter.txt"; FileWriter writer = new FileWriter(path); writer.write("努力的小码"); writer.close(); } @Test public void readText() throws IOException { String path = "E:\\学习\\项目测试文件\\fileWriter.txt"; FileReader reader = new FileReader(path); char[] c = new char[1024]; int index = reader.read(c);//index为读取当前字符的最后一个字符的下标 System.out.println(new String(c,0,index)); reader.close(); }
FileReader和FileWriter是字符流。分别实现Reader和Writer。因为FileInputStream和FileOutputStream是字节流,处理中文容易出现乱码的问题,所以采用FileReader和FileWriter字符流就可以避免这种情况。
DataInputStream、DataOutputStream
DataInputStream和DataInputStream,是数据的输入输出流,允许应用程序以机器无关的方式从底层输入流中读取基本java数据类型。也就是说,当去读一个数据时,不必再关心这个数据应当是什么类型的数据。
构造方法:DataInputStream(InputStream in);
DataOutputStream(OutputStream out);
DataOutputStream提供了三种写入字符串的方法:
writeBytes(String s)
writeChars(String s)
writeUTF(String s)
DataOutputStream提供了一个readUTF();读取字符串。
在不知道输入流的长度和大小,writeUTF方法可以向目标设备写入字符串的长度。redUTF()所以也能准确的读回字符串。
@Test public void DataTest() throws IOException { try { String path = "E:\\学习\\项目测试文件\\DataOutPutStream.txt"; FileOutputStream fo = new FileOutputStream(path); DataOutputStream da = new DataOutputStream(fo); /* da.writeBytes("使用writeBytes()");*/ /*da.writeChars("使用writeChars()");*/ /*da.writeUTF("使用writeUTF()");*/ da.close(); FileInputStream fi = new FileInputStream(path); DataInputStream di = new DataInputStream(fi); String readStr = di.readUTF(); /*byte readBt = di.readByte();*/ /*char readCr = di.readChar();*/ System.out.println(readStr); fo.close(); da.close(); fi.close(); di.close(); } catch (Exception e) { e.printStackTrace(); } }
缓存流
缓存是I/O的一种性能优化。缓存刘为I/O流增加了内存缓存区,有了缓存区,使得在流上执行skip,mark。和reset方法都成为可能!BufferedInputStream有两个构造函数
BufferedInputStream(InputStream in):创建带有32个字节的缓存流(也叫缓存区),
BufferedInputStream(InputStream in,int size):创建指定的size缓存流。
一个最优缓存区的小取决于它所在的操作系统,
BufferedOutputStream和OutputStream有一个flush方法来将缓存区的数据强制输出完。
BufferedOutputStream(OutputStream in)
BufferedOutputStream(OutputStream in,int size)
flush()就是用于即使缓存区没有满的情况下,也将缓存区的内容强制写入到外设。习惯上叫做刷新。
从构造函数上可以看出来缓存流肯定是在其他普通输出输入流之后创建,因为创建缓存流需要其他的输入输出流。
字节缓存流BufferedInputStream,BufferedOutputStream
@Test public void bufferInputTest() throws IOException { String path = "E:\\学习\\项目测试文件\\bufferOutputStream.txt"; FileOutputStream out = new FileOutputStream(path); BufferedOutputStream bf = new BufferedOutputStream(out); String text = "nulidexiaoma"; bf.write(text.getBytes());//都是覆盖原来的内容 bf.flush(); out.close(); bf.close(); } @Test public void bufferOutputStream() throws IOException { String path = "E:\\学习\\项目测试文件\\bufferOutputStream.txt"; FileInputStream in = new FileInputStream(path); BufferedInputStream bf = new BufferedInputStream(in); byte[] b = new byte[1024];//是字节流就定义字节,是字符就定义字符 int index = bf.read(b); System.out.println(new String(b,0,index)); in.close(); bf.close(); }
字符缓存流:BufferedReader,BufferedWriter
常用方法:read():单个字符
readLIne():读取一个文本行,并将其返回为字符串,若无数据可读,则返回null
write(String s,int off,int len):写入字符串的某个部分
flush:刷新该流的缓存
newLine:写入一个行分隔符
在使用BufferWriter的write方法时,数据并没有马上写入输出流,而是首先写入缓存区中,如果想立刻将缓存的数据写入输入流中,一定要调用flush方法。
@Test public void bufferWriter() throws IOException { String path = "E:\\学习\\项目测试文件\\bufferWriter.txt"; FileWriter fw = new FileWriter(path); BufferedWriter bw = new BufferedWriter(fw); String txt = "努力的小码"; bw.write(txt.toCharArray());//写入如果是字符流,肯定是写入字符,是字节就写入字节,所以要转换! bw.flush(); fw.close(); bw.close(); } @Test public void bufferRead() throws IOException { String path = "E:\\学习\\项目测试文件\\bufferWriter.txt"; FileReader fr = new FileReader(path); BufferedReader br = new BufferedReader(fr); char[] c = new char[1024]; int index = br.read(c); System.out.println(new String(c,0,index)); fr.close(); br.close(); }
Zip解压、压缩文件流
压缩文件:
@Test public void zipTest(){ String path1 = "E:\\学习\\项目测试文件\\zip1.txt"; try { FileOutputStream fos1 = new FileOutputStream(path1); String str = "测试压缩"; fos1.write(str.getBytes()); /*以上步骤是在‘项目测试文件‘目录下新建一个文件*/ String zoutPath = "E:\\学习\\项目测试文件\\ziptest.zip"; ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zoutPath));//压缩后的文件 FileInputStream fis = new FileInputStream(path1); File file = new File(path1); zout.putNextEntry(new ZipEntry(file.getName())); byte[] bytes = new byte[1024]; int i ; while((i = fis.read(bytes))!=-1){ zout.write(bytes,0,i); } fos1.close(); fis.close(); zout.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
解压文件:
@Test public void zipOutPutTest(){ try { String path = "E:\\学习\\项目测试文件\\ziptest.zip"; ZipFile zip = new ZipFile(new File(path), Charset.forName("GBK")); Enumeration entries = zip.entries(); entries.hasMoreElements(); ZipEntry entry = (ZipEntry) entries.nextElement(); InputStream in = zip.getInputStream(entry); String outPath = "E:\\学习\\项目测试文件\\ziptest\\" + entry.getName(); File file = new File(outPath); file.createNewFile(); OutputStream out = new FileOutputStream(outPath); byte[] bt = new byte[1024]; int index; while((index = in.read(bt))!=-1){ out.write(bt,0,index); } zip.close(); in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } }