java之IO流(二)
------- android培训、java培训、期待与您交流! ----------
流操作规律
1.源:键盘录入 目的:控制台 (上面的例子即是)
2.源:键盘录入 目的:文件(需求是将键盘录入的数据录入到一个文件中)
将代码
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
改为
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("存放的指定路径")));
3.源:文件 目的:控制台(需求是将一个文件的数据打印到控制台上)
将代码
BufferedReader bufr=new BufferedReader(new InputStreamReader(new FileInputStream("读取的文件路径")));
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out));
流操作的基本规律:我们经常遇到的问题是流很多,但是不清楚该用到哪一个
1.明确源和目的(源是输入流,InputStream Reader 目的是输出流,OutputStream Writer)
2.操作是数据是否是纯文本(是:字符流 否:字节流)
3.当体系明确后,还需要知道要使用哪个具体对象,通过设备来区分
源设备:内存,硬盘,键盘
目的设备:内存,硬盘,控制台
改变标准输入输出设备
System.setIn(new FileInputStream("读取的文件路径"));
System.setOut(new PrintStream("复制到指定文件路径"));
异常的日志信息(将异常的日志信息打印到指定的文件中)
public static void main(String[] args) {
try {
int []arr=new int[2];
System.out.println(arr[3]);
} catch (Exception e) {
try {
Date d=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM--dd HH:mm:ss");
String s=sdf.format(d);
PrintStream ps=new PrintStream("打印到指定的文件路径");
ps.println(ps);
} catch (Exception e2) {
throw new RuntiemException("日志文件创建失败");
e2.printStackTrace(System.out);
}
}
}
获取系统信息
Properties prop=System.getProperties();
prop.list(new PrintStream("打印到指定的文件路径"));
File类
File对象可以作为参数传递给流的构造函数
作用:用来将文件或者文件夹封装成对象,方便对文件与文件的属性 夹进行操作。
格式:File f1=new Fille("路径");
File f2=new Fille("父路径","子路径");
File.separator相当于//,用于解决跨平台时所产生的问题
File对象功能---创建和删除
1.创建:boolean mkdir():创建文件夹
boolean mkdirs():创建多级文件夹
boolean createNewFile();在指定位置创建文件,如果该文件已经存在,则不创建,返回false
和输出流不一样,输出流对象一建立创建文件,而且文件已经存在,会覆盖。
如: File f1=new File("a.txt");
System.Out.println(f1.createNewFile());
第一次运行时的结果为true,再次运行时结果为false
2.删除:boolean delete(); //删除失败时返回false
void deleteOnExit(); //在程序退出时删除指定的文件
如: File f1=new File("a.txt");
System.Out.println(f1.delete());
第一次运行时的结果为true,再次运行时结果为false
3.判断:boolean exists():文件是否存在
isFile():是否是文件
isDirectory():是否是目录
isAbsolute():是否是绝对路径
(在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在,通过exists判断)
如: File f1=new File("a.txt");
System.Out.println(f1.exists());
如果文件存在返回true,不存在返回false
4.获取信息:
4-1.getName():返回文件的名称
4-2.getPath(): 返回文件的相对路径
4-3 getParent():返回文件的父目录(如果创建的时候没有指定则返回null)
如: File f1=new File("a.txt");
System.Out.println(f1.getParent());
该结果返回null
4-4getAbsolutePath():返回文件的绝对路径
4-5 lastModified():返回文件最后一次被修改的时间
4-6 length():返回文件的长度
4-7renameTo():覆盖原文件名
如:File f1=new File("c:\\a.txt");
File f2=new File("c:\\b.txt"); System.Out.println(f1.renameTo(f2));结果是f1的文件名变成了f2的,也可操作不同硬盘之间,文件的内容不会改变
文件列表
1.获取系统文件的有效盘符:listRoots()
File[] files=File.listRoots();
for(File f:files){
System.Out.println(f);
}
2.获取指定目录下的所有文件名称,包括隐藏文件的名称:list()
File f =new File("c:\\"); //调用list方法的file对象必须是封装了一个目录,该目录还必须存在
String [] names=f.list();
for(String name:names){
System.Out.println(name);
}
list()和listFiles()的区别在于前者只能获取文件名称,后者还可以获取文件的长度,一般使用后者
3.文件名过滤
File dir=new File("指定需要过滤的文件夹");
String []name =dir.list(new FilenameFilter(){
public boolean accept(File dir,String name){
return name.endsWith("需要过滤的文件的后缀名,比如说.txt");
}
});
4.列出目录下的所有内容--递归,即指定目录下的文件或文件夹,包含子目录中的内容
public static void main(String[] args){
File dir=new File("指定的文件夹路径");
showDir(dir);
}
public static void showDir(File dir){
System.out.println(dir);
File[] files=dir.listFiles();
for (int i = 0; i < files.length; i++) {
if(files[i].isDirectory())
showDir(files[i]);
else
System.out.println(files[i]);
}
}
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可
在列出过程中出现的还是目录的话,还可以再次调用本功能,也就是函数自身调用自身
像这种表现形式或者编程手法称之为递归。
递归要注意的事项:限定条件;注意递归的次数,尽量避免内存溢出。
5.删除一个带内容的目录
删除原理:在window中,删除目录是从里往外删的,这就需要递归
public static void main(String[] args){
File dir=new File("删除指定的目录路径");
removeDir(dir);
}
public static void removeDir(File dir){
File[] files=dir.listFiles();
for (int i = 0; i < files.length; i++) {
//判断是否是隐藏文件和是否是目录,系统隐藏文件一般是不能删除的
if(!files[i].isHidden()&&files[i].isDirectory()){
removeDir(files[i]);
}else{
System.out.println(files[i].toString()+"--------"+files[i].delete());
}
System.out.println(dir+"-------"+dir.delete());
}
}
6.创建java的文件列表
需求:将一个指定目录下的java文件的绝对路径,存储到一个文本文件中
建立一个java 文件列表
思路:
6-1.对指定的目录进行递归
6-2.获取递归过程索引的java文件路径
6-3.将这些路径存储到集合中
6-4.将集合中的数据写入到一个文件中
/*
* 测试代码
*/
public static void main(String[] args)throws IOException{
File dir=new File("指定目录下的文件夹的路径");
List<File> list=new ArrayList<File>();
fileToList(dir,list);
//dir是父级目录,javalist.txt为目的文件夹名称
File file=new File(dir,"javalist.txt");
writeToList(list,file.toString());
}
/*
* 提取.java为后缀名的文件的方法
*/
public static void fileToList(File dir,List<File>list){
File[] files=dir.listFiles();
for(File file:files){
if(file.isDirectory()){
fileToList(file,list);
}else{
if(file.getName().endsWith(".java"))
list.add(file);
}
}
}
/*
* 将集合中的文件对象以字符串的形式存储指定的路径中
*/
public static void writeToList(List<File>list,String javaListFile)throws IOException{
BufferedWriter bufw=null;
try {
bufw=new BufferedWriter(new FileWriter(javaListFile));
for (File f:list) {
String path=f.getAbsolutePath();
bufw.write(path);
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
throw e;
}
finally{
try {
if(bufw!=null)
bufw.close();
} catch (IOException e) {
throw e;
}
}
}
Properties简述
Properties是hashtable的子类,也就是说它具有map集合的特点,而且里面存储的键值都是字符串
是集合中和IO技术相结合的集合容器,该对象的特点是可以用于键值对形式的配置文件
那么在加载数据时,需要数据具有固定的格式:键=值
Properties设置和存取元素 public static void setAndGet(){Properties prop=new Properties();
//设置元素
prop.setProperty("zhangsan", "30");
prop.setProperty("lisi", "20");
//获取lisi的值
String value=prop.getProperty("lisi"); System.Out.println(value); //重新设置lisi的值
prop.setProperty("lisi", 89+“”);
//获取所有的键值
Set<String> names=prop.stringPropertyNames();
for (String s:names) {
System.out.println(s+"----"+prop.getProperty(s));
}
}
Properties存储配置文件 需求:如何将流中的数据存储到集合中,例如想要info.txt中键值存到集合中进行操作 思路: 1.用一个流和info.txt文件关联 2.读取一行数据,将该行数据用”=“进行切割 3.等号左边作为键,右边作为值,存入到Properties集合中即可 /*
* 第一种形式,自定义,相当于load()方法
*/
public static void method()throws IOException{
BufferedReader bufr=new BufferedReader(new FileReader("info.txt"));
String line=null;
Properties prop=new Properties();
while((line=bufr.readLine())!=null){
String[]arr=line.split("=");
System.out.println(arr[0]+"----"+arr[1]);
prop.setProperty(arr[0], arr[1]);
}
bufr.close();
System.out.println(prop);
}
/*
* 第二种形式:使用load()方法
*/
public static void loadTest()throws IOException{
Properties prop=new Properties();
FileInputStream fis=new FileInputStream("info.txt");
prop.load(fis);
System.out.println(prop);
//另一种输出的形式:
//System.out.println(System.out); fis.Colse(); }
当我们需要重新设置数据时,需要加上一些代码,相当于刷新一样,否则只在内存中修改。 prop.setProperty("lisi","25"); FileOutputStream fos=new FileOutputStream("info.txt"); prop.store(fos,”注释信息,都是带#号的”); fos.Close(); IO流中的其他类 打印流PrintWriter与PrintStream,可以直接操作输入流和文件 序列流SequenceInputStream,对多个流进行合并 操作对象ObjectInputStream与ObjectOutputStream,被操作的对象需要实现Serializable(标记接口) PintStream(字节打印流) 构造函数可以接收的参数类型 1.file对象,File 2.字符串路径,Stirng 3.字节输出流,OutputStream PintWriter(字符输出流)构造函数可以接收的参数类型1.file对象,File2.字符串路径,Stirng 3.字节输出流,OutputStream4.字符输出流,Writer public static void main(String[] args) throws IOException {
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in));
PrintWriter out=new PrintWriter(new FileWriter("a.txt"),true);
String line=null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
out.write(line.toUpperCase());
}
out.close();
bufr.close(); 管道流(PipedInputStream和PipedOutputStream)
/* java 管道流的读写操作 用于两个线程之间
PipedOutputStream PipedInputStream 连接起来就是一个管道
管道输出流可以向管道写入数据 管道输入流可以从管道读取数据
这种Decorator 装饰 的设计模式 大大增强了java流的功能
可以在构造流的时候连接 管道输入输出流 也可以通过connect函数连接
*/
import java.io.* ;
class PipeTest
{
public static void main(String []args) throws Exception
{
PipedInputStream pis=new PipedInputStream() ; //构造管道输入流
PipedOutputStream pos=new PipedOutputStream(pis); //构造输出流并且连接输入流形成管道
new Procedure(pos).start() ; //线程启动
new Consumer(pis).start(); //线程启动
}
}
class Procedure extends Thread //线程1管道 输出流
{
private PipedOutputStream pos ;
Procedure(PipedOutputStream pos)
{
this.pos=pos ;
}
public void run()
{
try
{
pos.write("hello! welcome you!".getBytes()); //向管道写入 数据
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
class Consumer extends Thread
{
private PipedInputStream pis ;
Consumer(PipedInputStream pis)
{
this.pis=pis ;
}
public void run()
{
try
{
byte []buf=new byte[100] ;
int len=pis.read(buf,0,100); //从管道读取数据
System.out.println(new String(buf,0,len));
}
catch(Exception e)
{
e.printStackTrace() ;
}
}
Java操作基本数据类型的流对象DataStream
子类:DataInputStream和DataOutputStream
public static void main(String[] args) throws IOException {
// writeData();
// readData();
// writeUTFDemo();
readUTFDemo();
}
public static void readUTFDemo() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("utfdate.txt"));
String s = dis.readUTF();
System.out.println(s);
dis.close();
}
public static void writeUTFDemo() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("utfdate.txt"));
dos.writeUTF("你好"); // UTF-8修改版
dos.close();
}
public static void readData() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num=" + num);
System.out.println("b=" + b);
System.out.println("d=" + d);
dis.close();
}
public static void writeData() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(9887.543);
dos.close();
}
}
用于操作字节数组的流对象
ByteArrayInputStream:在构造的时候,需要接收数据源,而且数据源是一个字节数组
ByteArrayOutputStream:在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组
这就是数据目的地。
由于以上两个流对象都是操作的是数组,并没有使用系统资源,所以不用进行Close()关闭。
例如:
ByteArrayInputStream bis=new ByteArrayInputStream("ABCDEFD".getByte());
ByteArrayOutputStream bos=new ByteArrayOutputStream();
int by=0;
while((by=bis.read())!=-1){
bos.write(by);
}
System.Out.println(bos.size());
System.Out.println(bos.toString());
------- android培训、java培训、期待与您交流! ----------