java中的文件流按输出方向分为输入流和输出流,输入就是读取数据(即我们读取了一个文件),输出就是写入数据(即我们去创建了一个文件并写入了内容)。java的I/O原码是通过装饰者模式设计的。
按读取单位分,主要分为两种,字节流和字符流。
字节是计算机存储容量的一种单位。字节流就是以字节为单位处理文件流。实现字节流的类都分别继承了InputStream(输入流),OutputStream(输出流),一个英文一个字节,一个中文两个字节。
字符就是我们java用的char,一个字母或者一个中文都是一个字符,实现字符流的类都分别继承了Reader(输入流)和Writer(输出流)
讲其他流的时候,先说说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。
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是字符流。分别实现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字符流就可以避免这种情况。
在不知道输入流的长度和大小,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();
}
}
从构造函数上可以看出来缓存流肯定是在其他普通输出输入流之后创建,因为创建缓存流需要其他的输入输出流。
@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();
}
在使用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();
}
压缩文件:
@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();
}
}