Java I/O(一)流和文件类File的概述、FileInputStream和FileInputStream
一、流概述 & InputStream、OutputStream
流包括输入流和输出流,即I/O(Input和Output),具体结构如下:
I/O类都被放在java.io包中,所有的输入流类都是InputStream(针对字节)和Reader(针对字符)两个抽象类的子类,而所有输出流都是OutputStream(针对字节)和Writer(针对字符)的子类。
InputStream是一个抽象类,它的架构如下:
两个InputStream类的框架图。
InputStream类包含的API如下:
int available() void close() void mark(int readlimit) boolean markSupported() int read(byte[] buffer) abstract int read() int read(byte[] buffer, int offset, int length) synchronized void reset() long skip(long byteCount)
两个OutputStream类的框架图。
OutputStream类包含的API如下:
void close() void flush() void write(byte[] buffer, int offset, int count) void write(byte[] buffer) abstract void write(int oneByte)
一段程序,但有一点不太懂:
package stream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class isos { public static void inecho(InputStream is) { try { while(true) { int i=is.read(); if(i==-1) { break; } char c=(char) i; System.out.print(c); } } catch(IOException e) { e.printStackTrace(); } System.out.println(); } public static void outecho(OutputStream os) { try { String s="JAVAIO"; byte []b=s.getBytes(); os.write(b); os.flush(); } catch(IOException e) { e.printStackTrace(); } } public static void main(String []args) { inecho(System.in); //输入一行之后回显 // outecho(System.out); //输出字符串s } }
System.in和System.out究竟是什么类型?InputStream和OutputStream?InputStream和OutputStream不是抽象类吗?关于InputStream、OutputStream、ByteArrayInputStream和ByteArrayOutputStream先留在这里,以后再看一次看有什么新的收获没。主要重点还是放在FileInputStream和FileInputStream及其他一些知识上。
二、File类
File类创建文件对象,但是不能读写文件内容。
1.首先来看目录的创建mkdir()方法:
public class file { public static void main(String []args) { File dir=new File("D:/dir"); dir.mkdir(); } }
我的电脑并没有D盘,但是这个并不会报错,没有任何变化,待挖!
如果将D盘改为E盘,则会在E盘根目录下建立名为dir的目录,再运行一次,不会有什么变化。使用mkdir之后,在使用createNewFile也不报错,但都会无效:
public class file { public static void main(String []args) { File dir=new File("E:/dir"); dir.mkdir(); try { dir.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
mkdir之后的代码无效了,但是不报错。
2.之后是建立多级目录的方法mkdirs(),例如:
public class file { public static void main(String []args) { File dir=new File("/tmp/one/two/three"); dir.mkdirs(); } }
有几个注意的点,第一如果不加盘符,我的默认是G盘,可能是之前设置的部分,加盘符就在前面加,例如E://tmp/one/two/three。第二多级目录使用mkdir()那就无反应,两个一起用是会建立的目录。三是使用错误的盘符,例如D盘,可以运行,但是没有建立任何目录。
3.建立子目录方法
可以直接使用建立多级目录的方法来建立子目录,例如想要建立dir的子目录aaa,可以使用
File sub1=new File("/dir/aaa"); sub1.mkdirs();
建立dir的子目录aaa,无论dir存在与否,没有就建立dir,有直接建立子目录aaa。
还可以使用
File sub1 = new File("dir", "aaa");
sub1.mkdir();
但是实验结果不是那样,失败了,以下是网上说性质,与上一种方法不同,必须要有子目录。(已解决,原因是第一个参数少加’/‘,改为File sub1 = new File("/dir", "aaa");即可)
4.新建文件方法
File f=new File("E:/test.txt");
try { f.createNewFile(); } catch (IOException e) { e.printStackTrace(); }
Windows必须要使用绝对路径?像建立目录那样的使用相对路径,运行完也不报错,但是没有文件(已解决,但原因尚未清楚!)。还有创建文件必须要使用try-catch语句,而且必须是要存在的路径,否则报警告路径不存在。
File f=new File("/dir","test.txt");
也可改为绝对路径,不过要保证该路径存在,否则直接抛出异常。
最后运行结果:
File aa = new File("/dir"); File f=new File(aa,"/test.txt");
这两句和前面效果一样,不过也是要保证路径存在,否则抛出异常。
最后还有一种使用URI的方法,再此只标注一下,无需详细了解:
try { URI uri = new URI("file:/home/dir"); File file4 = new File(uri); file4.mkdirs(); URI uri2 = new URI("file:/home/dir/test.txt"); File f2=new File(uri2); f2.createNewFile(); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
5.File的一些API使用
boolean canExecute() // 测试应用程序是否可以执行此抽象路径名表示的文件。
boolean canRead() // 测试应用程序是否可以读取此抽象路径名表示的文件。
boolean canWrite() // 测试应用程序是否可以修改此抽象路径名表示的文件。
boolean delete() // 删除此抽象路径名表示的文件或目录。
boolean equals(Object obj) // 测试此抽象路径名与给定对象是否相等。
boolean exists() // 测试此抽象路径名表示的文件或目录是否存在。
File getAbsoluteFile() // 返回此抽象路径名的绝对路径名形式。
String getAbsolutePath() // 返回此抽象路径名的绝对路径名字符串。
File getCanonicalFile() // 返回此抽象路径名的规范形式。
String getCanonicalPath() // 返回此抽象路径名的规范路径名字符串。
long getFreeSpace() // 返回此抽象路径名指定的分区中未分配的字节数。
String getName() // 返回由此抽象路径名表示的文件或目录的名称。
String getParent() // 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
File getParentFile() // 返回此抽象路径名父目录的抽象路径名;如果此路径名没有指定父目录,则返回 null。
String getPath() // 将此抽象路径名转换为一个路径名字符串。
long getTotalSpace() // 返回此抽象路径名指定的分区大小。
long getUsableSpace() // 返回此抽象路径名指定的分区上可用于此虚拟机的字节数。
int hashCode() // 计算此抽象路径名的哈希码。
boolean isAbsolute() // 测试此抽象路径名是否为绝对路径名。
boolean isDirectory() // 测试此抽象路径名表示的文件是否是一个目录。
boolean isFile() // 测试此抽象路径名表示的文件是否是一个标准文件。
boolean isHidden() // 测试此抽象路径名指定的文件是否是一个隐藏文件。
long lastModified() // 返回此抽象路径名表示的文件最后一次被修改的时间。
long length() // 返回由此抽象路径名表示的文件的长度。
String[] list() // 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
String[] list(FilenameFilter filter) // 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。
File[] listFiles() // 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
File[] listFiles(FileFilter filter) // 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
File[] listFiles(FilenameFilter filter) // 返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。
static File[] listRoots() // 列出可用的文件系统根。
boolean renameTo(File dest) // 重新命名此抽象路径名表示的文件。
boolean setReadOnly() // 标记此抽象路径名指定的文件或目录,从而只能对其进行读操作。
String toString() // 返回此抽象路径名的路径名字符串。
String name=f2.getName(); long length=f2.length(); String path=f2.getPath(); String parent=f2.getParent(); String p2=f2.getAbsolutePath(); String p3=f2.getCanonicalPath(); long fs=f2.getFreeSpace(); long ts=f2.getTotalSpace(); long us=f2.getUsableSpace(); boolean b1=f2.exists(); boolean b2=f2.canWrite(); boolean b3=f2.canExecute(); boolean b4=f2.canRead(); System.out.print(name+" "+length+" "+b1+" "+b2+" "+b3+" "+b4); System.out.println(); System.out.print(path+" "+parent+" "+p2+" "+p3+" "+fs+" "+ts+" "+us); System.out.println(); long time=f2.lastModified(); boolean b5=f2.isDirectory(); boolean b6=f2.isFile(); boolean b7=f2.isHidden(); boolean b8=f2.isAbsolute(); // for(String s:f2.list()) // System.out.println(s); System.out.print(b5+" "+b6+" "+b7+" "+b8+" "+time);
结果:
test.txt 7 true true true true
\home\dir\test.txt \home\dir G:\home\dir\test.txt G:\home\dir\test.txt 89270075392 107666731008 89270075392
false true false false 1545665029004
注:经过简单测试,汉字length为2,回车length为2。
而之前对f2使用list方法出现错误,一直抛出空指针的异常,后来发现这个方法会返回该目录下的所有目录和文件的名称,但是你的对象是一个文件的话,那就会抛出异常了,也就是说你的对象要首先是一个目录,才能调用该方法:
String []list=file4.list(); for(String s:list) System.out.println(s);
结果:
sub(目录)
test.txt(文件)
三、FileInputStream & FileInputStream
FileInputStream输入,对应文件的读操作(Read)。
FileOutputStream输出,对应文件的写操作(Write)
package stream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class FileStream { public static void main(String []args) { try { FileOutputStream fos=new FileOutputStream("G:\\home\\dir\\test.txt"); byte[] bb="武一鸣".getBytes(); fos.write(bb);
fos.write(33); //FileInputStream写入write参数可以是byte[]或者int,但是int也会变成byte 33变为!,但经过实测char好像也可以 fos.close(); FileInputStream fis=new FileInputStream("G:\\home\\dir\\test.txt"); int i=fis.read(); while(i!=-1) { byte b=(byte) i; System.out.print((char)b); i=fis.read(); //注意不要忘记,刚开始写代码这句忘了,一直无限循环。 } fis.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
结果分析:FileOutputStream写入会使之前的文件信息全部消失。
其实这里应该详细讲解InputStream和OutpStream的方法的,例如write()、flush()、read()、mark()等等,但是由于种种原因已到了BufferedInpuStream后面讲了,移步到Java I/O(二)。