文章目录
Java I/O
核心掌握五个类(File、OutputStream、InputStream、Reader、Writer)一个接口(Serializable)
1.File文件操作类
File类既可以描述具体文件也可以描述文件夹,是唯一一个与文件本身操作(创建、删除、取得信息)有关的程序类。
产生File对象的构造方法:
public File(String pathName){}//根据文件绝对路径产生File对象
public File(URI uri){}//根据网络产生File对象
1.1常用操作方法
public boolean createNewFile(){}//创建新文件
public boolean exists(){}//判断文件是否存在
public boolean delete(){}//删除文件
//文件分隔符:File.separator
//使用范例
public class test {
public static void main(String[] args) throws IOException {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop"+File.separator+"TestIO.java");
if(file.exists()){
file.delete();
}else
file.createNewFile();
}
}
1.2目录操作
public String getParent()//取得父路径
public File getParentFile()//取得父路径的File对象
public boolean mkdirs()//创建多级父目录(一次性创建多级不存在的父目录)
//使用范例
public class test {
public static void main(String[] args) throws IOException {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop"+File.separator+"www"+File.separator+"bit"+File.separator+"TestIO.java");
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(file.exists()){
file.delete();
}else
file.createNewFile();
}
}
1.3取得文件信息
public boolean isFile()//判断File对象是否为文件
public boolean isDirectory()//判断File对象是否为文件夹
public long length()//取得文件大小-字节为单位
public long lastModified()//取得上次修改时间
//使用范例
public class test {
public static void main(String[] args) throws IOException {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop"+File.separator+"www"+File.separator+"bit"+File.separator+"TestIO.java");
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(file.exists()&&file.isFile()){
System.out.println("文件大小为:"+file.length()/1024+"kb");
System.out.println("上次修改时间:"+file.lastModified());
}
}
}
1.4列出目录中全部组成
pubic File[] listFiles()
//这个方法只能列出本目录中的第一级信息,
//如果要求列出目录中所有级信息,必须自己处理
public class IO {
public static void main(String[] args) {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop");
listAllFiles(file);
}
// 一个目录下的全部文件
public static void listAllFiles(File file){
if (file.isFile()){
System.out.println(file);
}else{
if (file.exists()&&file.isDirectory()){
File [] files = file.listFiles();
for (File file1:files) {
listAllFiles(file1);
}
}
}
}
}
2.字节流与字符流
java.io包中流分为两类:输入流和输出流
字节流:InputStream、OutputStream(byte)
——原生操作,无需转换,可以处理文本、文件、图像、音乐、视频等资源
字符流:Reader、Writer(char)
——经过处理后的操作,只能处理中文文本。
流模型的操作流程:
1.取得终端对象
2.根据终端对象取得输入输出流
3.根据输入输出流进行数据读取与写入
4.关闭流(IO操作属于资源操作,所有资源操作(IO操作、数据库操作、网络)最后必须要进行关闭)
2.1字节输出流(OutPutStream)
public abstract class OutputStream implements Closeable,Flushable
OutputStream类实现了两个接口,这两个接口中的方法:
public void close() throws IOException
public void flush() throws IOException
核心方法:
- 将给定的字节数组内容全部输出: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;
使用OutputStream输出数据时,若指定文件不存在,FileOutputStream会自动创建文件(不包括创建目录),使用FileOutputStream输出内容时,默认为文件内容的覆盖,若要进行文件内容追加,使用如下构造:public FileOutputStream(File file,boolean append)
JDK1.7提供了AutoCloseable自动关闭接口,要使用此接口必须使用try-catch块(不推荐使用)
public class test {
public static void main(String[] args) throws IOException {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
OutputStream outputStream = new FileOutputStream(file,true);
String msg = "ghw";
outputStream.write(msg.getBytes());
outputStream.close();
}
}
2.2字节输入流(InputStream)
public abstract class InputStream implements Closeable
核心方法
1.public int read(byte b[]) throws IOException
2.pubic int read(byte b[],int off,int len) throws IOException
3.public abstract int read() throws IOException
方法1返回值的三种情况:读取数据到字节数组中,返回数据的读取个数。如果此时开辟的字节数组大小大于读取的数据大小,则返 回的就是读取个数;如果要读取的数据大于数组的内容,那么这个时候返回的就是数组长度;如果没有数据了还在读,则返回-1
public class test {
public static void main(String[] args) throws IOException {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
if (file.exists()){
InputStream in = new FileInputStream(file);
byte [] bytes = new byte[1024];
int len = in.read(bytes);
//将字节数组转为String
String str = new String (bytes,0,len);
System.out.println("读取内容为:"+str);
in.close();
}
}
}
2.3 字符输出流Writer
public abstract class Writer implements Appendable,Closeable,Flushable
在Writer类中也提供了write()方法,而且该方法接收的类型都是char型,要注意的是,Writer类提供了一个直接输出字符串的方法:
public void write(String str)throws IOException
如果要操作文件使用FileWriter子类。
public class test {
public static void main(String[] args) throws IOException {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
if (!file.getParentFile().exists()){
file.mkdirs();
}
String msg = "hello bit";
Writer writer = new FileWriter(file);
writer.write(msg);
writer.close();
}
}
Writer类的结构与方法的使用与OutputStream非常相似,只是Writer类对于中文的支持很好并且提供了直接写入 String的方法而已。
未关闭流时,数据在缓存区存放,不会输出到目标终端,要想输出,要么关闭流,要么使用flush()强制刷新。
2.4 字符输入流(Reader)
!!!Reader类中没有方法可以直接读取字符串类型,这个时候只能通过字符数组进行读取操作。
public class test {
public static void main(String[] args) throws IOException {
File file = new File("C:"+File.separator+"Users"+File.separator+
"vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt");
if(file.exists()){
Reader in = new FileReader(file);
char [] data = new char[1024];
//将数据读取到字符数组中
int len = in.read(data);
String str = new String (data,0,len);
System.out.println("读取内容为:"+str);
in.close();
}
}
}
3.转换流(字节流——>字符流)
3.1基本使用
OutputStreamWriter:将字节输出流变为字符输出流
InputStreamReader:将字节输入流变为字符输入流
这两类流的继承关系以及构造方法:
public class OutputStreamWriter extends Writer
public OutputStreamWriter(OutputStream out)
public class InputStreamReader extends Reader
public InputStreamReader(InputStream in)
字符流的具体子类大都是通过转换流将字节流转为字符流的。
3.2文件拷贝
public class FileCopy {
public static void main(String[] args) throws Exception {
//源路径&目标路径
String sourcePath = "C:"+File.separator+"Users"+File.separator +
"vsus"+File.separator+"Desktop"+File.separator+"TestIO.txt";
String destPath = "C:"+File.separator+"Users"+File.separator +
"vsus"+File.separator+"Desktop"+File.separator+"Testcopy.txt";
copyFile(sourcePath,destPath);
}
public static void copyFile(String sourcePath,String destPath) throws Exception {
//1.获取file对象
File sourcefile = new File(sourcePath);
File destfile = new File(destPath);
//2.取得输入输出流
InputStream in = new FileInputStream(sourcefile);
OutputStream out = new FileOutputStream(destfile);
//根据输入输出流操作数据
int len = 0;
byte [] data = new byte[1024];
len = in.read(data);
out.write(data);
//4.关闭流
in.close();
out.close();
}
}
4.字符编码
4.1常用字符编码
1.GBK,GB2312:GBK包含简体与繁体中文,而GB2312只包含简体中文(这两种编码都是描述中文的编码)
2.UNICODE:java提供的16进制编码,可以描述世界上任意的文字信息,但编码进制数太高,编码体积较大,故会造成网络传输的负担。
3.ISO-8859-1:国际通用编码,不支持中文,浏览器默认编码
4.UTF编码:结合UNICODE与ISO-8859-1,最常用的就是UTF-8编码。
4.2乱码产生原因
大部分都是由于编解码不一致造成的,极少个别是由于数据丢失造成。
5.内存操作流程
需要进行IO处理,但是又不希望产生文件,这种情况下就可以使用内存作为操作终端。内存流分为两类:
字节内存流:ByteArrayInputStream/ByteArrayOutputStream
字符内存流:CharArrayReader/CharArrayWruter
构造方法:
//将指定的字节数组内容存放到内存中
public ByteArrayInputStream(byte buf[])
public ByteArrayOutputStream()
//内存流实现小写转大写
import java.io.*;
public class IOTouppercase {
//利用内存流实现转大写操作
public static void main(String[] args) throws Exception {
String msg = "hellobit";
ByteArrayInputStream in = new ByteArrayInputStream(msg.getBytes());
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len = 0;
while ((len=in.read())!=-1){
out.write(Character.toUpperCase(len));
}
System.out.println(out);
in.close();
out.close();
}
}
6.打印流(输出流的强化版本)
字节打印流:PrintStream
字符打印流:PrintWriter
//范例:自己设计一个简单打印流
public class PrintUtil {
private OutputStream outputStream;
public PrintUtil(OutputStream outputStream) {
this.outputStream = outputStream;
}
public void print(String str) {
try {
this.outputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
public void println(String str){
this.print(str+"\n");
}
public void print(int data){
this.print(String.valueOf(data));
}
public void println(int data){
this.print(data+"\n");
}
public void close(){
try {
this.outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
打印流的设计属于装饰设计模型——基于抽象类
特点: 核心依然是某个类(OutputStream提供的write方法)的功能。但是为了得到更好的操作效果,让其支持的功能更多一些,使用装饰类(PrintStream)。
优点: 很容易更换装饰类来达到不同的操作效果。
缺点: 造成类结构复杂
7.System类对IO的支持
标准输出(显示器):System.out
标准输入(键盘):System in
错误输出:System.err
7.1系统输出
系统输出一共有两个常量:out、err,且这两个常量表示的都是PrintStream类的对象。
由于System.out是PrintStream的实例化对象,而PrintStream又是OutputStream的子类,所以可以直接使用 System.out直接为OutputStream实例化,这个时候的OutputStream输出的位置将变为屏幕。
public class test {
public static void main(String[] args) throws IOException {
OutputStream out = System.out;
out.write("hello".getBytes());
}
}
7.2系统输入
System.in是InputStream的直接对象
//范例:使用System.in实现数据读入
public class test {
public static void main(String[] args) throws IOException {
InputStream in = System.in;
byte []data = new byte[1024];
System.out.println("请输入内容....");
int len = in.read(data);
System.out.println("输出内容为"+new String(data,0,len));
in.close();
}
}
8.两种输入流
8.1BufferedReader类
核心方法:String readLine () throws IOException
这个方法可以直接读取一行数据(以回车为换行)
//使用BufferedReader实现键盘输入
public class TestPrint {
public static void main(String[] args) throws Exception {
BufferedReader buf = new BufferedReader(
new InputStreamReader(System.in)) ;
System.out.println("请输入信息 :") ;
// 默认的换行模式是BufferedReader的大缺点
String str = buf.readLine() ;
// 默认使用回车换行
System.out.println("输入信息为:" + str );
}
}
8.2java.util.Scanner类
在这个类中主要关注以下方法:
- 判断是否有指定类型数据:
public boolean hasNextXxx()
- 取得指定类型的数据:
public 数据类型 nextXxx()
- 定义分隔符:
public Scanner useDelimiter(Pattern pattern)
- 构造方法:
public Scanner(InputStream source)
//使用Scanner实现数据输入
public class test {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容....");
if (scanner.hasNext()){
System.out.println("输入内容为"+scanner.next());
}
scanner.close();
}
}
//接收各种数据类型
public class test {
public static void main(String[] args) throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入内容....");
if (scanner.hasNextInt()){
System.out.println("输入内容为"+scanner.nextInt());
}else
System.out.println("输入的不是数字");
scanner.close();
}
}
9.序列化
9.1概念
定义: 将内存中保存的对象变为二进制流进行输出或保存在文本中。
要想让类支持序列化,必须实现Serializable接口,Serializable接口为标识接口。只有实现了Serializable接口的类才具备对象序列化的功能。
9.2序列化与反序列化
要想实现序列化与反序列化的对象操作,在java.io包中提供有两个处理类:ObjectOutputStream、ObjectInputStream
序列化:ObjectOutputStream
核心方法:writeObject(Object obj)
,将obj变为二进制流输出到目标终端
反序列化:ObjectInputStream
核心方法:readObject():Object
,将二进制流反序列化为对象
class Person implements Serializable{
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class test {
public static File file = new File("C:"+File.separator+"Users"
+File.separator+"vsus"+File.separator+"Desktop"+File.separator+"test.txt");
public static void main(String[] args) throws Exception {
Person person = new Person("zhangsan",27);
Ser(person);
}
public static void Ser(Object obj) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(obj);
oos.close();
}
public static void dSer(Object obj)throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
System.out.println(ois.readObject());
ois.close();
}
}
9.3transient关键字
若希望类中若干属性不被序列化,可以在属性前添加transient关键字。