java的io安卓能用吗_Java中的IO

输入和输出是所有应用中所必需的组成部分,通过IO可以读取输入数据以及存储数据到外部设备上。Java中的输入和输出是通过java.io来支持的。下面是本人在学习中的归纳和体会。

1. File类和文件过滤器

顾名思义,File类中是有关文件的操作。这里必须明确,文件还包括目录。通过文件或目录路径的字符串作为参数,根据传入的是目录路径还是文件名路径可以分别初始化不同的File对象。在File对象中封装了对文件的操作,例如新建文件,删除文件和重命名等方法。但是它并不能访问文件本身的内容,这需要输入输出流来完成。下面是有关File类的代码。

publicclassFileTest

{

publicstaticvoidmain(String[] args)throwsIOException

{

//以当前路径来创建一个File对象

File file =newFile(".");

//直接获取文件名,输出一点

System.out.println(file.getName());

//获取相对路径的父路径可能出错,下面代码输出null

System.out.println(file.getParent());

//获取绝对路径

System.out.println(file.getAbsoluteFile());

//获取上一级路径

System.out.println(file.getAbsoluteFile().getParent());

//在当前路径下创建一个临时文件

File tmpFile = File.createTempFile("aaa",".txt", file);

//指定当JVM退出时删除该文件

tmpFile.deleteOnExit();

//以系统当前时间作为新文件名来创建新文件

File newFile =newFile(System.currentTimeMillis() +"");

System.out.println("newFile对象是否存在:"+ newFile.exists());

//以指定newFile对象来创建一个文件

newFile.createNewFile();

//以newFile对象来创建一个目录,因为newFile已经存在,

//所以下面方法返回false,即无法创建该目录

newFile.mkdir();

//使用list方法来列出当前路径下的所有文件和路径

String[] fileList = file.list();

System.out.println("======当前路径下所有文件和路径如下=====");

for(String fileName : fileList)

{

System.out.println(fileName);

}

//listRoots静态方法列出所有的磁盘根路径。

File[] roots = File.listRoots();

System.out.println("======系统所有根路径如下=====");

for(File root : roots)

{

System.out.println(root);

}

}

}

在上面的代码中,使用list()方法可以返回目录下所有文件的路径和名称。使用文件过滤器,可以根据自己的需要选择返回的文件类型。通过一个实现了FilenameFilter接口的类对象作为list()方法的参数,就可以实现文件过滤的作用。过滤的规则在重写FilenameFilter中的accept()方法中定义。代码如下:

publicclassFilenameFilterTest

{

publicstaticvoidmain(String[] args)

{

File file =newFile(".");

String[] nameList = file.list(newMyFilenameFilter());

for(String name : nameList)

{

System.out.println(name);

}

}

}

//实现自己的FilenameFilter实现类

classMyFilenameFilterimplementsFilenameFilter

{

publicbooleanaccept(File dir, String name)

{

//如果文件名以.java结尾,或者文件对应一个路径,返回true

returnname.endsWith(".java")

||newFile(name).isDirectory();

}

}

2. 输入输出流

在Java中,从不同角度定义了输入输出流的分类。以内存作为流的方向基点,可将其分为输入流和输出流,流向内存的成为输入流,流出内存的成为输出流。从数据操作的最小单元来分类,可将其分为字节流和字符流。根据抽象程度分类,可将其分为节点流和处理流,处理流是连接到实际物理节点的节点流的封装,这样既可以不必去关注节点的来源(文件或者数组),用统一的方法去操作,又可以使用更加方面的方法来实现操作。

在学习中,本人对于输入输出流的总结归纳:

A. 字节流和字符流其实并没有本质的区别,无非是它们二者的操作单元不同。字节流的基类为InputStream和OutputStream,字符流的基类为Reader和Writer。它们所提供的读写方法一样,区别在于参数,需要对应流类型。

B. 输入流中的read系列方法是从输入流中读取数据的操作。空参数将返回所读取的字节(字符)。read方法中可以传入数组参数,数组的类型必须和流的数据类型相匹配,相当于一个竹筒,一次可读取最多等于数组容量的数据,并将所读数据装进数组中。

C. 输出流中的write系列方法是向输出流中写入数据的操作。方法中的参数可以是整型或字符型变量,也可以传入数组参数,数组的类型必须和流的数据类型相匹配,相当于一个竹筒,一次可写入最多等于数组容量的数据。特别地,字符型输出流的write方法可以传入字符串。

D. InputStream和OutputStream,Reader和Writer这四个类作为Java中输入输出流的抽象基类,并不能直接被初始化使用。Java中提供了一些继承了它们的类,用于实现具体的某种流操作。如:

a.File前缀系列的类(如FileInputStream),用于对文件类进行流操作,使用文件名作为构造函数的参数;示例代码如下:

输出类:

publicclassFileOutputStreamTest

{

publicstaticvoidmain(String[] args)throwsIOException

{

FileInputStream fis =null;

FileOutputStream fos =null;

try

{

//创建字节输入流

fis =newFileInputStream("FileOutputStreamTest.java");

//创建字节输入流

fos =newFileOutputStream("newFile.txt");

byte[] bbuf =newbyte[32];

inthasRead =0;

//循环从输入流中取出数据

while((hasRead = fis.read(bbuf)) >0)

{

//每读取一次,即写入文件输出流,读了多少,就写多少。

fos.write(bbuf ,0, hasRead);

}

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

finally

{

//使用finally块来关闭文件输入流

if(fis !=null)

{

fis.close();

}

//使用finally块来关闭文件输出流

if(fos !=null)

{

fos.close();

}

}

}

}

输入类:

publicclassFileInputStreamTest

{

publicstaticvoidmain(String[] args)throwsIOException

{

//创建字节输入流

FileInputStream fis =newFileInputStream("FileInputStreamTest.java");

//创建一个长度为1024的“竹筒”

byte[] bbuf =newbyte[1024];

//用于保存实际读取的字节数

inthasRead =0;

//使用循环来重复“取水”过程

while((hasRead = fis.read(bbuf)) >0)

{

//取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!

System.out.print(newString(bbuf ,0, hasRead ));

}

fis.close();

}

}

b. 数组前缀系列类(如ByteArrayInputSteam),用于对数组进行流操作,使用数组对象作为构造函数的参数;

c. 转换流InputStreamReader将字节输入流转换为字符输入流;InputStreamReader将字节输出流转换为字符输出流,代码如下:

publicclassKeyinTest

{

publicstaticvoidmain(String[] args)

{

BufferedReader br =null;

try

{

//将Sytem.in对象转换成Reader对象

InputStreamReader reader =newInputStreamReader(System.in);

//将普通Reader包装成BufferedReader

br =newBufferedReader(reader);

String buffer =null;

//采用循环方式来一行一行的读取

while((buffer = br.readLine()) !=null)

{

//如果读取的字符串为"exit",程序退出

if(buffer.equals("exit"))

{

System.exit(1);

}

//打印读取的内容

System.out.println("输入内容为:"+ buffer);

}

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

//关闭输入流

finally

{

try

{

br.close();

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

}

}

}

d. 字符流的子类有String前缀(StringReader和StringWriter)系列类可以对字符串进行操作,代码如下:

publicclassStringNodeTest

{

publicstaticvoidmain(String[] args)

{

String src ="从明天起,做一个幸福的人\n"

+"喂马,劈柴,周游世界\n"

+"从明天起,关心粮食和蔬菜\n"

+"我有一所房子,面朝大海,春暖花开\n"

+"从明天起,和每一个亲人通信\n"

+"告诉他们我的幸福\n";

StringReader sr =newStringReader(src);

char[] buffer =newchar[32];

inthasRead =0;

try

{

//采用循环读取的访问读取字符串

while((hasRead = sr.read(buffer)) >0)

{

System.out.print(newString(buffer ,0, hasRead));

}

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

finally

{

sr.close();

}

//创建StringWriter时,实际上以一个StringBuffer作为输出节点

//下面指定的20就是StringBuffer的初始长度

StringWriter sw =newStringWriter(20);

//调用StringWriter的方法执行输出

sw.write("我远离了大海,\n");

sw.write("看不到春暖花开,\n");

sw.write("我只有一只小龟,\n");

sw.write("一样可以闻到馥郁花香\n");

System.out.println("------下面是sw的字符串节点里的内容------:");

//使用toString方法返回StringWriter的字符串节点的内容

System.out.println(sw.toString());

}

}

d.推回输入流PushbackInputStream和PushbackReader带有一个推回缓冲区,使用unread(数组)方法可以将一个字节/字符数组推回到推回缓冲区中。推回输入流也有read方法,使用read方法读取输入流时,首先从输入缓冲区中读取,读完之后才从输入流中读。代码如下:

publicclassPushbackTest

{

publicstaticvoidmain(String[] args)

{

PushbackReader pr =null;

try

{

//创建一个PushbackReader对象,指定推回缓冲区的长度为64

pr =newPushbackReader(newFileReader("PushbackTest.java") ,64);

char[] buf =newchar[32];

//用以保存上次读取的字符串内容

String lastContent ="";

inthasRead =0;

//循环读取文件内容

while((hasRead = pr.read(buf)) >0)

{

//将读取的内容转换成字符串

String content =newString(buf ,0, hasRead);

inttargetIndex =0;

//将上次读取的字符串和本次读取的字符串拼起来,查看是否包含目标字符串

//如果包含目标字符串

if((targetIndex = (lastContent + content).indexOf("new PushbackReader")) >0)

{

//将本次内容和上次内容一起推回缓冲区

pr.unread((lastContent + content).toCharArray());

//再次读取指定长度的内容(就是目标字符串之前的内容)

pr.read(buf ,0, targetIndex);

//打印读取的内容

System.out.print(newString(buf ,0,targetIndex));

System.exit(0);

}

else

{

//打印上次读取的内容

System.out.print(lastContent);

//将本次内容设为上次读取的内容

lastContent = content;

}

}

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

finally

{

try

{

if(pr !=null)

pr.close();

}

catch(IOException ioe)

{

ioe.printStackTrace();

}

}

}

}

E. 在Java虚拟机中可以通过exec方法执行其他的应用程序,并返回Proess对象。利用该对象的getErrorStream、getInputStream和getOutputStream方法可以分别获得子进程的错误流,输出流和输入流(方向是以程序角度为基点)。

F. RandomAccessFile类提供对文件的随机访问,程序可以直接跳转到文件的任何地方来读取数据。它内部提供了与字节流同法相同的读写方法,另外又加入了自由定位文件记录指针的方法seek。在读写操作时以字节为单位。在构造函数中还需加入一个mode参数由于制定读写权限。

G. 需要注意Scanner对象的使用。Scanner对象用于捕获输入,并将输入内容转换为字符串。

//使用System.in创建Scanner对象,用于获取标准输入

Scanner sc =newScanner(System.in);

PrintStream ps =newPrintStream(

newFileOutputStream("out.txt"));

//增加下面一行将只把回车作为分隔符

sc.useDelimiter("\n");

//判断是否还有下一个输入项

while(sc.hasNext())

{

//输出输入项

ps.println("键盘输入的内容是:"+ sc.next());

}

ps.close();

对于初学者来说一个容易忽略的地方是,需要区别节点流和处理流构造方法中参数的意义。节点流中,构造方法参数是要读取或者输出地物理节点,是“目的地”或者“始发地”,而处理流的构造函数参数是所要包装的处理流对象,包装之后的操作实际上是间接操作节点流,并未对被包装的节点流本身属性做修改。采用处理流包装后,可以不用管节点流的数据类型,而根据处理流的性质传递在节点流中不能传递的内容,例如Obj;同时还可以增加一些便于操作的方法,比如缓冲区。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值