Java基础---IO流(中)

来源:互联网 发布:没有合并计算的数据 编辑:程序博客网 时间:2024/05/04 22:03


IO流常用基类-字节流

示例 (获取用户键盘录入的数据并将数据变成大写显示在控制台,如果用户输入的是over,结束)

import java.io.IOException;import java.io.InputStream;public class ReadKey{public static void main(String[] args) throws IOException{readKey();}public static void readKey() throws IOException{//1、创建容器StringBuilder sb =new StringBuilder();//2、获取键盘读取流InputStream in = System.in;//3、定义变量记录读取到的字节,并循环获取int ch = 0;while((ch = in.read())!=-1){//在存储之前需要判断是否是换行标记,因为换行标记不存储if(ch=='\r')continue;if(ch=='\n'){String temp = sb.toString();if("over".equals(temp))break;System.out.println(temp.toUpperCase());sb.delete(0,sb.length());}else{//将读取到的字节存储到StringBuilder中sb.append((char)ch);}}}}

转换流

特点:

1、是字节流和字符流之间的桥梁。

2、该流对象中可以对读取到的字节数据进行指定的编码转换。

什么时候使用?

1、当字节和字符之间有转换时。

2、流操作的数据需要进行编码表的制定时。

字符流的应用:字节流的数据都是字符时,转成字符流操作更高效。

具体对象体现:

InputStreamReader:字节到字符的桥梁,解码

OutputStreamWriter:字符到字节的桥梁,编码

这两个流对象是字符流体系中的成员。

那么他们转换作用,而本身又不是字符流。所以在构造的时候,需要传入字节流对象进来。

构造函数:

InputStreamReader(InputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK

InputStreamReader(InputSteam,String charSet):通过该构造函数初始化,可以指定编码表。

OutputStreamWriter(OutputStream):通过该构造函数初始化,使用的是本系统默认的编码表GBK

OutputStreamWriter(OutputSteam,String charSet):通过该构造函数初始化,可以指定编码表。

操作文件的字符流对象是转换流的子类

Reader

     |--InputStreamReader

              |--FileReader

Writer

    |--OutputStreamWriter

             |--FileWriter

如果要使用指定的编码表时,必须使用转换流。

FileReader fr = new FileReader("a.txt");//操作a.txt的中的数据使用的本系统的默认的GBK.

InputSteamReader isr = new InputStreamReader(new FileInputStream("a.txt"));

这两句代码的意义相同。但如果a.txt中的文件的字符数据是通过utf-8的形式编码。那么在读取时,就必须指定编码表。那么转换流必须使用。

InputStreamReader isr = new InputreamReader(new FileInputStream("a.txt"),"utf-8");

示例1:(InputStreamReader是字节流通向字符流的桥梁)

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;public class TransStreamDemo{public static void main(String[] args) throws IOException{//子节流InputStream in = System.in;//将字节转成字符的桥梁,转换流InputStreamReader isr = new InputStreamReader(in);//对字符流进行高效装饰,缓冲区BufferedReader bufr = new BufferedReader(isr);/*简写BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));*/String line = null;//读取到了字符串数据while((line=bufr.readLine())!=null){if("over".equals(line))break;System.out.println(line.toUpperCase());}}}


示例2:(OutputStreamReader是字符流通向字节流的桥梁)
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.OutputStream;public class TransStreamDemo{public static void main(String[] args) throws IOException{BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//System.out的类型是PrintStream,属于OtputStreamBufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));String line = null;//读取到了字符串数据while((line=bufr.readLine())!=null){if("over".equals(line))break;//将字符数据用缓冲区对象将数据写入缓冲区,目的地System.outbufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}}}

示例3:(将键盘录入的数据写入到一个文件中)

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.FileOutputStream;public class TransStreamDemo{public static void main(String[] args) throws IOException{BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt")));String line = null;while((line=bufr.readLine())!=null){if("over".equals(line))break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}}}

示例4:(将一个文本内容显示在控制台上)

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.FileOutputStream;import java.io.FileInputStream;public class TransStreamDemo{public static void main(String[] args) throws IOException{BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));String line = null;while((line=bufr.readLine())!=null){if("over".equals(line))break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}<span style="white-space:pre"></span>}}

示例5:(将一个文本内容复制到另一个文件中)

import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.io.OutputStream;import java.io.FileOutputStream;import java.io.FileInputStream;public class TransStreamDemo{public static void main(String[] args) throws IOException{BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));String line = null;while((line=bufr.readLine())!=null){if("over".equals(line))break;bufw.write(line.toUpperCase());bufw.newLine();bufw.flush();}}}
流的操作规律:之所以弄清楚这个规律,是因为流对象太多,开发时不知道用哪个对象合适。

想要知道对象的开发时用到哪些对象,只要通过四个明确即可。

1、明确源和目的

源:InputStream Readr

目的:OutputStream Writer

2、明确数据是否纯文本数据

源:是纯文本:Reader  否:InputStream

目的:是纯文本:Writer 否:OutputStream

到这里,就可以明确需求中具体要使用哪个体系。

3、明确具体的设备

源设备:硬盘 File、键盘 System.in、内存 数组、网络 Socket流 

目的设备:硬盘 File、控制台System.out、内存 数组、网络 Socket流

4、是否需要其它额外功能

是否需要高效(缓冲区):是,就加上buffer

需求1:复制一个文本文件

1、明确源和目的   源:InputStream Readr 目的:OutputStream Writer

2、明确数据是否纯文本数据    源:是纯文本:Reader    目的:是纯文本:Writer 

3、明确具体的设备       源设备: File      目的设备: File

FileReader fr = new FileReader("a.txt");  FileWriter fw = new FileWriter("b.txt");

4、是否需要其它额外功能 

需要,高效  BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));  BufferedWriter bufw = new BufferedWriter(new FileStreamWriter("b.txt"));

============================================================

需求2:读取键盘录入信息,并写入到一个文件中

1、明确源和目的   源:InputStream Readr 目的:OutputStream Writer

2、明确数据是否纯文本数据    源:是纯文本:Reader    目的:是纯文本:Writer 

3、明确具体的设备       源设备: 键盘 System.in      目的设备: File

FileReader fr = System.in;  FileWriter fw = new FileWriter("b.txt");

这样做可以完成,但是麻烦。将读取的字节数据转换成字符串,在由字符流操作

4、是否需要其它额外功能 

需要,转换。将字节流转换字符流,因为明确源是Reader,这样操作文本更快捷。

InputStreamReader isr = new InputStreamReader(System.in); FileWriter fw = new FileWriter("b.txt");

还需要功能么?

需要,高效  BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));  BufferedWriter bufw = new BufferedWriter(new FileStreamWriter("b.txt"));

====================================================================

需求3:将一个文本数据显示在控制台上

1、明确源和目的   源:InputStream Readr 目的:OutputStream Writer

2、明确数据是否纯文本数据    源:是纯文本:Reader    目的:是纯文本:Writer 

3、明确具体的设备       源设备:File      目的设备: 控制台System.out

FileReader fr = new FileReader("a.txt");  FileWriter fw = System.out;

4、是否需要其它额外功能 

需要,转换。FileReader fr = new FileReader("a.txt"); OutputStreamWriter osw= new OutputStreamWriter(System.out);

还需要功能么?

需要,高效  BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));  BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter (System.out));

任何Java识别的字符数据都是Unicode码表,但是FileWriter写入本地文件使用的是本地编码,也就是GBK码表。而OutputStreamWriter可以使用指定的编码将要写入流中的字符编码成字节。

示例1:(UTF-8编码)

import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStreamWriter;public class TransStreamDemo{public static void main(String[] args) throws IOException{writeText();}public static void writeText() throws IOException{//下面这句代码等同于FileWriter fw = new FileWriter("b.txt")//FileWriter其实就是转换流指定了本机默认码表的体现,而且这个转换流的子类对象,可以方便操作文本文件。//简单说:操作文件的字节流+本机默认的编码表。//这是按照默认码表来操作的便捷类//OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"GBK");//如果操作文本文件需要明确的具体码表,FileWriter就不行了,必须用转换流。OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");osw.write("你好");osw.close();}}

P.S.

UTF-8编码,一个中文三个字节
示例2:(UTF-8解码 打印d.txt(内容是采用utf-8编码的)文件中的内容)

import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.BufferedReader;public class TransStreamDemo{public static void main(String[] args) throws IOException{writeText();}public static void writeText() throws IOException{//这里不能使用FileReader 因为d.txt文件中是由UTF-8编码的“你好”,6个字节。//如果使用FileReader类是用GBK编码进行读取,6个字节代表3个字符 会乱码InputStreamReader isr = new InputStreamReader(new FileInputStream("d.txt"),"UTF-8");BufferedReader bufr = new BufferedReader(isr);String line = null;while((line = bufr.readLine())!=null){System.out.println(line);}bufr.close();}}

File类

File类用来将文件或者文件夹封装成对象,方便对文件与文件夹的属性信息进行操作。File对象可以作为参数传递给流的构造函数。

P.S.

流只能操作数据,不能操作文件。

示例1:

import java.io.File;public class FileDemo{public static void main(String[] args){constructorDemo();}public static void constructorDemo(){//可以将一个已经存在的,或者不存在的文件或者目录封装成file对象//方式一File f1 = new File("d:\\demo\\a.txt");//方式二File f2 = new File("d:\\demo","a.txt");//方式三File f = new File("d:\\demo");File f3 = new File(f,"a.txt");//考虑到Windows和Linux系统通用File f4 = new File("d:"+File.separator+"demo"+File.separator+"a.txt");}}
P.S.

File.separator是与系统有关的默认名称分隔符。在UNIX系统上,此字段的值为‘/’;在Microsoft Windows系统上,它为‘\\’。

File对象的常用方法:

1、获取

getName():获取文件或者文件夹的名称。

getPath():File对象中封装的路径是什么,获取的就是什么。

getAbsolutePath():物流File对象中封装的路径是什么,获取的都是绝对路径。

getParent():获取File对象封装的文件或者文件夹的父目录。如果封装的是相对路径,那么返回null

long length():获取文件大小

long lastModified():获取文件或者文件最后一次修改的时间

static File[] listRoots():获取的是被系统中有效盘符

String[] list():获取指定目录下当前文件以及文件夹的名称。

String[] list(FilenameFilter):可以根据指定的过滤器,过滤后的文件及文件夹名称

File[] listFiles():获取指定目录下的文件以及文件夹对象

示例2:

import java.io.File;import java.text.DateFormat;import java.util.Date;public class FileMethodDemo{public static void main(String[] args){getDemo();}public static void getDemo(){File file1 = new File("a.txt");File file2 = new File("d:\\demo\\a.txt");String name = file2.getName();String absPath = file2.getAbsolutePath();//绝对路径String path1 = file1.getPath();String path2 = file2.getPath();long len = file2.length();long time = file2.lastModified();//相对路径不同,父目录不同//如果此路径名没有指定的父目录,则返回nullString parent1 = file1.getParent();String parent2 = file2.getParent();Date date = new Date(time);DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);String str_time = df.format(date);System.out.println("name:" + name);System.out.println("absPath:" + absPath);System.out.println("path1:" + path1);System.out.println("path2:" + path2);System.out.println("len:" + len);System.out.println("str_time:" + str_time);System.out.println("parent1:" + parent1);System.out.println("parent2:" + parent2);}}

2、创建和删除

创建:

boolean createNewFile() throws IOException:创建文件,如果被创建的文件已经存在,则不创建

boolean mkdir():文件夹。

boolean mkdirs():创建多级文件夹。

删除:

boolean delete():可以删除文件或者文件夹。注意:对于文件夹只能删除不带内容的空文件夹,对带有内容的,不可以直接删除,必须要从里往外删除。

void deleteOnExit(): 删除动作交给系统完成,物流是否发生异常,系统在退出时执行删除动作

示例3:

import java.io.File;import java.io.IOException;public class FileMethodDemo{public static void main(String[] args) throws IOException{createAndDeleteDemo();}public static void createAndDeleteDemo() throws IOException{File file = new File("file.txt");//和输出流不一样,如果文件不存在,则创建,如果文件存在,则不创建boolean b1 = file.createNewFile();System.out.println("b1="+b1);//使用delete方法删除文件夹的时候,如果文件夹中有文件,则会删除失败boolean b2 = file.delete();System.out.println("b2="+b2);File dir = new File("abc\\ab");//使用mkdir可以创建多级目录boolean b3 = dir.mkdir();//make directorySystem.out.println("b3="+b3);//最里层目录被干掉,dir代表的是最里的目录boolean b4 = dir.delete();System.out.println("b4="+b4);}}

3、判断

boolean exists():判断文件或者文件夹是否存在

boolean isFile():判断File对象中封装的是否是文件

boolean isDirectory():判断File对象封装的是否是文件夹

boolean isHidden():判断文件或者文件夹是否隐藏。

示例4:

import java.io.File;import java.io.IOException;public class FileMethodDemo{public static void main(String[] args) throws IOException{isDemo();}public static void isDemo() throws IOException{File f = new File("aaa.txt");boolean b = f.exists();System.out.println("b="+b);//falseif(!f.exists()){f.createNewFile();}//最好先判断是否存在if(f.exists()){System.out.println(f.isFile());//trueSystem.out.println(f.isDirectory());//false}f = new File("aa\\bb");f.mkdirs();if(f.exists()){System.out.println(f.isFile());//falseSystem.out.println(f.isDirectory());//true}}}

4、重命名:

renameTo(File):
File f1 = new File("c:\\a.txt");
File f2 = new File("c:\\b.txt");
f1.renameTo(f2);//将c盘的a.txt文件改名为b.txt文件

示例5:

import java.io.File;import java.io.IOException;public class FileMethodDemo{public static void main(String[] args) throws IOException{renameToDemo();}public static void renameToDemo() throws IOException{File f1 = new File("D:\\javaExc\\0.mp3");File f2 = new File("D:\\javaExc\\123.mp3");boolean b = f1.renameTo(f2);System.out.println("b="+b);//true}}
示例6:(系统根目录和容量获取)
import java.io.File;import java.io.IOException;public class FileMethodDemo{public static void main(String[] args) throws IOException{listRootsDemo();}public static void listRootsDemo() throws IOException{File[] files = File.listRoots();for(File file : files){System.out.println(file);}File file = new File("d:\\");System.out.println("getFreeSpace:"+file.getFreeSpace());System.out.println("getTotalSpace:"+file.getTotalSpace());System.out.println("getUsableSpace:"+file.getUsableSpace());}}

示例7:(获取目录下的文件以及文件夹的名称)

import java.io.File;import java.io.IOException;public class FileMethodDemo{public static void main(String[] args) throws IOException{listDemo();}public static void listDemo() throws IOException{File file = new File("c:\\");//获取目录下的文件以及文件夹的名称,包含隐藏文件//调用list方法的File对象中封装的必须是目录,否则会产生NullPointerException//如果访问的是系统级目录也会发生空指针异常//如果目录存在但是没有内容,会返回一个数组,但长度为0String[] names = file.list();for(String name:names){System.out.println(name);}}}

示例8:(获取d盘javaExc目录下后缀名为java的文件)
import java.io.File;import java.io.FilenameFilter;public class FileMethodDemo{public static void main(String[] args){listDemo();}public static void listDemo(){File file = new File("D:\\javaExc");String[] names = file.list(new FilterByJava(".java"));for(String name:names){System.out.println(name);}}}class FilterByJava implements FilenameFilter{private String suffix;public FilterByJava(String suffix){this.suffix = suffix;}public boolean accept(File dir,String name){return name.endsWith(suffix);}}


递归:
其实就是在使用一个功能过程中,又对该有需求。 就出现了函数自身调用。
注意:
1,一定要限条件,否则内存溢出。
2,使用递归时,调次数不要过多否则也会出现内存溢。
需求:
想要列出指定目录下的文件以及文件夹中的文件(子文件)
// 列出指定目录下的当前文件或者夹。// 想要列出当前目录下的文件夹中,其实就是在重新使用该功能。

import java.io.File;class TestDemo{public static void main(String[] args){File f = new File("C:\\myclass");listDir(f,0);}public static void listDir(File dir,int level){System.out.println(getLevel(level)+dir.getName());level++;File[] files = dir.listFiles();for(int x = 0;x<files.length;x++){if(files[x].isDirectory())//如果遍历到的是目录listDir(files[x],level);//那么就行该功能的重复使用 递归。elseSystem.out.println(getLevel(level)+files[x].getName());}}public static String getLevel(int level){StringBuilder sb = new StringBuilder();sb.append("|--");for(int x = 0;x<level;x++){sb.insert(0,"|  ");}return sb.toString();}}






0 0