前言: Java IO编程是Java API的重要内容。
本文分十二个部分记录一下我的学习的过程。
IO的操作部分重点掌握两个代码模型:
在
java.io
包之中file类是唯一一个与文件本身操作(文件的创建、删除、取得文件信息等等)
Java.io.File
是一个普通的类,所以直接实例化对象操作就好。实例对象需要两个构造方法:
· 构造方法一:File(String pathname)
· 构造方法二:File(File parent, String child) 设置父路径和子路径
如果要进行文件的基本操作可以使用如下方法:
· 创建一个新文件:public boolean createNewFile()
· 删除一个文件:public boolean delete()
· 判断文件是否存在:public boolean exists()
· 取得父路径:public File getParentFile()
· 创建目录:public boolean mkdirs()
· 路径分隔符常量:public static final String separator (file.separator)
public class TestDemo {
public static void main(String[] args) throws Exception {
File file = new File("C:" + File.separator + "Users" + File.separator +"lenovo" + File.separator +"Desktop" + File.separator +"hello" + File.separator +"hello_world.txt");
if (!file.getParentFile().exists()) {//父目录不存在
file.getParentFile().;//创建父目录
}
if (file.exists()) {
file.delete();
}else {
file.createNewFile();
}
}
}
注意: 创建目录会用到路径分隔符常量:
public static final String separator (file.separator)
为了区分不同系统的不同分隔符,在Windows系统中为C:\XXX,而在linux系统中为C:/XXX
3.1 针对文件:
· 判断路径是否是文件:public boolean isFile()
· 判断路径是否是目录:public boolean isDirectory()
· 取得文件大小(字节):public long length()
· 最后修改日期:public long lastModified()
class Mymath {
public static double round(double num, int scale) {
return Math.round(num * Math.pow(10, scale)) / Math.pow(10, scale);
}
}
public class TestDemo {
public static void main(String[] args) throws Exception {
File file = new File("C:" + File.separator + "Users" + File.separator +"lenovo" + File.separator +"Desktop" + File.separator +"time.png");
if (file.exists() && file.isFile()) {
System.out.println("文件大小:" + Mymath.round(file.length()/(double) 1024 / 1024, 2));
System.out.println("最后一次修改日期:" + new Date(file.lastModified()));
}
}
}
3.2 针对目录:
· 列出目录中的全部组成:public File[] listFiles()
listFiles()只能列出本目录第一级的信息,如果要求列出目录中所有级的信息,则就必须自己来实现处理。必须通过递归的操作来实现
public class TestDemo {
public static void main(String[] args) throws Exception {
File file = new File("C:" + File.separator + "Users" + File.separator +"lenovo" + File.separator +"Desktop" );
listdir(file);
}
public static void listdir(File file){
if (file.isDirectory()) {
File result [] = file.listFiles();
for (int i = 0; i < result.length; i++) {
listdir(result[i]);
}
}
System.out.println(file);
}
}
File类不支持文件内容处理,如果要处理文件必须要通过流模式来完成。流分为输入流和输出流
字节流和字符流的区别:
只有处理中文才会用字符流,字符流通过缓存来处理,需要close()或者flush(),来强制输出
· 字节流:InputStream、OutputStream;
· 字符流:Reader、Writer
不管使用的字节流还是字符流,一定要记住,其使用流程基本是固定的:
要根据文件的路径创建File类对象
根据字节流或字符流的子类实例化父类对象
进行数据的读取、写入操作
关闭流(close())
对于IO操作属于资源处理,所有的资源操作处理必须要进行关闭
实现了Closeable、Flushable两个接口
· Closeable : public void close() throws IOException
· Flushable : public void flush() throws IOException
OutputStream里面的方法:
· 将给定的字节数组内容全部输出:public void write(byte[] b) throws IOException
· 将部分的字节数组内容输出:public void write(byte[] b,int off,int len) throws IOException
· 输出单个字节:public abstract void write(int b) throws IOException
· 接收File类:public FileOutputStream(File file)throws FileNotFoundException
· 追加内容:public FileOutputStream(File file,boolean append) throws FileNotFoundException
public class TestDemo {
public static void main(String[] args) throws Exception {
//1.新建File类对象
File file = new File("C:" + File.separator + "Users" + File.separator +"lenovo" + File.separator +"Desktop" + File.separator + "hello.txt" );
if (!file.getParentFile().exists()) {//确保目录存在
file.getParentFile().mkdirs();
}
//2.OutputStream是一个抽象类。所以需要通过子类进行实例化,意味着只能进行文件操作
OutputStream output = new FileOutputStream(file,true);
//3.进行文件的输出处理操作。
String msg = "abcdefghijk\r\n";//要求输出的内容
output.write(msg.getBytes(),0,3);//将内容变为字节数组
//4.关闭输出
output.close();
}
}
字节输出流实现了内容到文件的处理,现在要进行文件到内容的处理,通过程序读取内容
public abstract class InputStream extends Object implements Closeable
有如下方法:
· 读取数据到字节数组之中: public int read(byte[] b) throws IOException 返回数据的读取个数如果此时开辟的字节数组大小大于了读取的数据大小,则返回的就是读取个数 如果此时要读取的数据大于开辟的数组内容,返回的就是数组的长度。
· 读取部分数据到字节数组之中: public int read(byte[] b,int off,int len) throws IOException 每次只读取传递数组的部分内容,如果读取满了则返回的就是长度(len)。如果没有读取满,那么就是返回的读取的数据个数,如果最后没有数据了返回-1
· 读取单个字节:public abstract int read() throws IOException 每次只读取传递数组的一个字节的内容。如果最后没有数据了返回-1
同理: InputStream是一个抽象类,所以按照抽象类的一个原则来讲,要想为我们的父类实例化,那么就需要使用子类。因为方法名称都被父类定义好了。所以我们所关注的只是子类的构造方法。如果要进行文件的操作,可以使用FileIntputStream类来处理
public class TestDemo {
public static void main(String[] args) throws Exception {
//1.新建File类对象
File file = new File("C:" + File.separator + "Users" + File.separator +"lenovo" + File.separator +"Desktop" + File.separator + "hello.txt" );
if (file.exists()) {//确保目录存在
InputStream input = new FileInputStream(file);
byte data[] = new byte[1024]; //每次可以读取的最大数量
int len = input.read(data);//
System.out.println("读取内容为: " + new String(data,0,len));
input.close();
}
}
}
字符适合处理中文数据,Writer类是字符输出流的处理类,定义如下:
· 输出内容:public void write(String str) throws IOException
如果要操作文件肯定使用FileWriter子类,通过Writer实现输出
public class TestDemo {
public static void main(String[] args) throws Exception {
//1.新建File类对象
File file = new File("C:" + File.separator + "Users" + File.separator +"lenovo" + File.separator +"Desktop" + File.separator + "hello.txt" );
if (!file.getParentFile().exists()) {//确保目录存在
file.getParentFile().mkdirs();
}
String msg = "世界和平!";
Writer wt = new FileWriter(file);
wt.write(msg);
wt.close();
}
}
直接上例子:
public class TestDemo {
public static void main(String[] args) throws Exception {
//1.新建File类对象
File file = new File("C:" + File.separator + "Users" + File.separator +"lenovo" + File.separator +"Desktop" + File.separator + "hello.txt" );
if (file.exists()) {//确保目录存在
Reader input = new FileReader(file);
char data[] = new char[1024]; //每次可以读取的最大数量
int len = input.read(data);//
System.out.println("读取内容为: " + new String(data,0,len));
input.close();
}
}
}
字节流和字符流互相转换:
· OutputStreamWriter:将字节输出流转换为字符输出流
· InputStreamReader:将字节输入流转换为字符输入流
IO操作除了可以在文件中,也可以在内存中,进行内存操作流。文件流的操作一定会产生一个文件数据(不管这个文件数据最后保存与否)。如果希望进行IO处理,又不希望产生文件。这种情况下就可以使用内存作为操作的终端。
· 字节内存流:ByteArrayInputStream ByteArrayOutputStream
· 字符内存流:CharArrayReader CharArrayWriter
通过内存流实现大小写转换的操作:
public class Copy {
//没有文件产生,理解为临时文件
public static void main(String[] args) throws IOException {
String msg = "hello world!!!";
byte[] buf = new byte[1024];
buf = msg.getBytes();
InputStream input = new ByteArrayInputStream(buf);
OutputStream output = new ByteArrayOutputStream();
int temp = 0;
while ((temp = input.read()) != -1) {
output.write(Character.toUpperCase(temp));
}
System.out.println(output);
input.close();
output.close();
}
}
BufferedReader类的重要方法:
· 读取一行:public String readLine() throws IOException
输入信息读取:
public class TestDemo {
public static void main(String[] args) throws Exception {
InputStreamReader input = new InputStreamReader(System.in);
BufferedReader buf = new BufferedReader(input);
System.out.print("请输入信息: ");
String str = buf.readLine();
System.out.println("输入信息: " + str);
}
}
Scanner类替换了BufferedReader类,它是一个专门进行输入流处理的程序类、同时也可以直接结合正则表达式进行各项处理
注意以下方法:
· 判断是否有指定类型的数据:public boolean hasNextXXX()
· 取得指定类型的数据:public 数据 nextXXX()
· 定义分隔符:public Scanner useDelimiter(String pattern)
· 构造方法:public Scanner(InputStream source)
使用Scanner实现数据的输入:
public class TestDemo {
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(System.in);
System.out.print("请输入内容: ");
if (scan.hasNext()) {//现在有输入内容,补判断空字符串
System.out.println("输入内容为: " + scan.next());
}
scan.close();
}
}
除了二进制类型的文件拷贝。以后文件输出用打印流(PrintWriter):
PrintWriter = new PrintWriter(new FileOutputStream(new File(pathname)));
文件输入用Scanner扫描流
个人博客链接:xvanning.cn