Java基础之IO流

时间:2023-02-16 13:35:03

流的概念

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。

IO流的分类

按流向分为输入流(InputStream和Reader)和输出流(OutputStream和Writer)。

按传输单位分为字节流(InputStream和OutputStream)和字符流(Reader和Writer)。


File类

(在java.io包中)可表示一个文件或者目录。

构造方法摘要

File(String pathname) 通过将给定路径名字符串转换为抽象路径名来创建一个新 File 实例。

pathname:"C:/Users/user/Desktop/天黑请闭眼.txt"

File(File parent, String child) 根据 parent 抽象路径名和 child 路径名字符串创建一个新File 实例。

File(String parent, String child) 根据 parent 路径名字符串和 child路径名字符串创建一个新 File 实例。

"C:/Users/user/Desktop","天黑请闭眼.txt"

File(URI uri) 通过将给定的 file:URI 转换为一个抽象路径名来创建一个新的 File 实例。

"file:///C:/Users/user/Desktop/天黑请闭眼.txt"

例:

//创建File对象

   Filefile = newFile("D:"+File.separator+"天黑请闭眼.txt");

File的重要方法:

         createNewFile(),如果我们这个文件不存在,那么创建一个到本地系统。

         exists(),获取此文件是否存在。存在返回true,否则为false。

         delete(),删除此File对象所映射的真实文件。

         getAbsolutePath(),获取此对象的绝对路径。

         isDirectory(),判断该File对象,是不是目录(文件夹)。

         isFile(),判断该File对象,是不是文件(不是文件夹)。

File(目录)的方法

         mkdir();创建目录,但是如果父目录不存在,就无法创建

         mkdirs();创建目录,如果没有父目录,就连父目录一起创建

         list(),listFile(); 获取出子文件。

例:

package com.java.group.copy;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 复制文件(文件夹)
*
*/
public classCopyTest {

public static void main(String[] args) {
//创建被复制的文件对象
FileoldFile = newFile("D:\\java2");
//创建新的文件对象
FilenewFile = newFile("D:\\java");
//复制
copy(oldFile,newFile,true);
}

//复制
public static void copy(File oldFile,FilenewFile, booleanisCut){
//判断文件是否为目录,如果为目录则调用copyDir,反之,则调用copyFile
if(oldFile.isDirectory()){
copyDir(oldFile,newFile,isCut);
}else{
copyFile(oldFile,newFile,isCut);
}
}

//复制目录
public static void copyDir(FileoldFile,File newFile, boolean isCut){
//创建一个文件对象,名字为被复制的目录的名字
Filefile = newFile(newFile, oldFile.getName());
//真实创建目录
file.mkdirs();
//创建子文件对象
File[]fl = oldFile.listFiles();
//遍历目录
for(File f : fl){
copy(f,file,isCut);
}
//判断是否剪切
if(isCut)
oldFile.delete();
}

//复制文件
public static void copyFile(FileoldFile,File newFile, boolean isCut){
//创建一个文件对象,名字为被复制的文件名
Filefile = newFile(newFile, oldFile.getName());
//判断文件是否存在,不存在返回空
if(!oldFile.canExecute()){
System.out.println("文件不存在!");
return ;
}

//创建引用
FileInputStreamfis = null;
FileOutputStreamfos = null;
try {
//创建对象
fis= newFileInputStream(oldFile);
fos= newFileOutputStream(file);
//创建文件,也可不写,因为在文件操作时,会自动调用
file.createNewFile();
//用于保存读取的字符长度
int lengthRead = 0;
//用于保存读取的字符
byte[] bytes = new byte[1024];
//判断文件内是否有内容
if(fis.available() >0){
//判断是否读完了,读完为-1
while((lengthRead =fis.read(bytes)) != -1){
//没有读完,则写入文件到新目录文件中
fos.write(bytes);
}
}
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally{
try {
//关闭流
if(fis != null)
fis.close();
//关闭流
if(fos != null){
fos.flush();
fos.close();
}
}catch(IOException e) {
e.printStackTrace();
}
}
//是否要剪切
if(isCut)
oldFile.delete();
}
}


字节流:

InputStream/OutputStream所有输入/输出流的父类,是抽象类。

FileInputStream:

构造方法

FileInputStream(File file)
          通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象file 指定。

FileInputStream(String name)
          通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

重要方法:

available()
          返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。

close()
          关闭此文件输入流并释放与此流有关的所有系统资源。

read()
          从此输入流中读取一个数据字节。

read(byte[] b)
          从此输入流中将最多 b.length 个字节的数据读入一个byte 数组中。

read(byte[] b, int off, int len)
          从此输入流中将最多 len 个字节的数据读入一个byte 数组中。

skip(long n)
          从输入流中跳过并丢弃 n 个字节的数据。

FileOutputStream:

构造方法:

FileOutputStream(File file)
          创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

FileOutputStream(File file,boolean append)
          创建一个向指定 File 对象表示的文件中写入数据的文件输出流。当要拼接数据时,append应为true。

FileOutputStream(String name)
          创建一个向具有指定名称的文件中写入数据的输出文件流。

FileOutputStream(String name,boolean append)
          创建一个向具有指定 name 的文件中写入数据的输出文件流。当要拼接数据时,append应为true。

重要方法:

close()
          关闭此文件输出流并释放与此流有关的所有系统资源。

write(byte[] b)
          将 b.length 个字节从指定 byte 数组写入此文件输出流中。

write(byte[] b, int off, int len)
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。

write(int b)
          将指定字节写入此文件输出流。

例:包含FielInputStream和FileOutputStream的操作。

package com.java.group.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

public class InputStreamTest {

public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//创建FileInputStream的对象
fis = new FileInputStream("F:/java/Count500.java");
//创建一个数组用于保存数据
byte[] bytes = new byte[fis.available()];
//读取文件中的数据
fis.read(bytes);
//创建一个文件的对象
File file = new File("F:/111/123.java");
//创建新文件
file.createNewFile();
//创建FileOutputStream的对象
fos = new FileOutputStream(file);
//写入数据
fos.write(bytes);
System.out.println("复制成功!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
//关闭流
if(fis != null)
fis.close();
//关闭流
if(fos != null){
fos.flush();
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}

}
}

}

DataInputStream:

构造方法:

DataInputStream(InputStream in)
          使用指定的底层InputStream 创建一个 DataInputStream。

重要方法:

read(byte[] b)
          从包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组b 中。

read(byte[] b, int off, int len)
          从包含的输入流中将最多 len 个字节读入一个 byte 数组中。

readBoolean()
          读取一个输入字节,如果该字节不是零,则返回 true,如果是零,则返回 false

readByte()
          读取并返回一个输入字节。

readChar()
          读取两个输入字节并返回一个 char 值。

readDouble()
          读取八个输入字节并返回一个 double 值。

readFloat()
          读取四个输入字节并返回一个 float 值。

readInt()
          读取四个输入字节并返回一个 int 值。

readLine()
          从输入流中读取下一文本行。

readLong()
          读取八个输入字节并返回一个 long 值。

DataOutputStream:

构造方法:

DataOutputStream(OutputStream out)
          创建一个新的数据输出流,将数据写入指定基础输出流。

重要方法:

flush()
          清空此数据输出流。

write(byte[] b, int off, int len)
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入基础输出流。

writeBoolean(boolean v)
          将一个 boolean 值以 1-byte 值形式写入基础输出流。

writeByte(int v)
          将一个 byte 值以 1-byte 值形式写出到基础输出流中

writeChar(int v)
          将一个 char 值以 2-byte 值形式写入基础输出流中,先写入高字节。

writeChars(String s)
          将字符串按字符顺序写入基础输出流。

writeDouble(double v)
          使用 Double 类中的 doubleToLongBits 方法将 double 参数转换为一个long 值,然后将该long 值以 8-byte 值形式写入基础输出流中,先写入高字节。

writeFloat(float v)
          使用 Float 类中的 floatToIntBits 方法将 float 参数转换为一个int 值,然后将该int 值以 4-byte 值形式写入基础输出流中,先写入高字节。

writeInt(int v)
          将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。

writeLong(long v)
          将一个 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。

 例:包含DataInputStream和DataOutputStream操作

package com.feicui.group1.buffered;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataInputStreamTest {
public static void main(String[] args){
DataOutputStream dos = null ;
DataInputStream dis = null ;
try {
//1.创建输出流对象
dos = new DataOutputStream(new FileOutputStream(
"../MyJavaTest4/src/com/feicui/group1/buffered/dataread.txt")) ;
//2.写入数据
dos.writeChar('c') ;
dos.writeChars("Hello") ;
dos.writeFloat(1000f) ;
dos.writeDouble(100.00) ;
dos.writeBoolean(false) ;
//创建输入流对象
dis = new DataInputStream(
new FileInputStream(
"../MyJavaTest4/src/com/feicui/group1/buffered/dataread.txt"));
//读数据
System.out.println(dis.readChar()) ;
System.out.println(dis.readChar());
System.out.println(dis.readChar());
System.out.println(dis.readChar());
System.out.println(dis.readChar());
System.out.println(dis.readChar());
System.out.println(dis.readFloat()) ;
System.out.println(dis.readDouble()) ;
System.out.println(dis.readBoolean());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
//关闭流
if(dis!=null)
dis.close() ;
//关闭流
if(dos!=null){
dos.flush() ;
dos.close() ;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

}


BufferedInputStream:

构造方法:

BufferedInputStream(InputStream in)
          创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

BufferedInputStream(InputStream in,int size)
          创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流in,以便将来使用。

重要方法:

available()
          返回可以从此输入流读取(或跳过)、且不受此输入流接下来的方法调用阻塞的估计字节数。

close()
          关闭此输入流并释放与该流关联的所有系统资源。

markSupported()
          测试此输入流是否支持 markreset 方法。

mark(int readlimit)
          在此输入流中标记当前的位置。

reset()
          将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。

skip(long n) 
          
跳过和丢弃此输入流中数据的 n 个字节。

 

BufferedOutputStream:

 构造方法:

BufferedOutputStream(OutputStream out) 
          
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

 BufferedOutputStream(OutputStream out,
int size)
 
          
创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。

重要方法:

flush()
          刷新此缓冲的输出流。

write(byte[] b, int off, int len)
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流。

write(int b)
          将指定的字节写入此缓冲的输出流。

例:包含BufferedInputStream和BufferedOutputStream操作。

package com.java.group.Buffered;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterTest {
public static void main(String[] args) {
//定义输入流
BufferedReader bReader = null;
//定义输出流
BufferedWriter bWriter = null;
try {
bReader =
new BufferedReader(new FileReader("C:\\Users\\Administrator\\Desktop\\新建文本文档222.txt"));
bWriter =
new BufferedWriter(new FileWriter("C:/Users/Administrator/Desktop/新建文本文档 (2).txt"));

//字符串中的截取的起始坐标
int offset = 0;
//读取数据
String str = bReader.readLine();
//写数据
for(int i=0;i<99;i++){
//随机出每行要显示的字符串长度
int random = (int)(Math.random()*(str.length()/100+1));
//获取截取的随机长度的字符串
String str1 = str.substring(offset, offset+random);
//写入文件中
bWriter.append(str1);
//换行
bWriter.newLine();
//下一次截取字符串的起始坐标
offset += random;
}
//最后剩下的字符串写入最后一行
bWriter.append(str.substring(offset));

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
try {
//关闭输入流
if(bReader != null)
bReader.close();
//关闭输出流
if(bWriter != null)
bWriter.flush();
bWriter.close();
} catch (IOException e) {
e.printStackTrace();
}

}

}

}

字符流:

在程序读取和写入时是以一个字符来读写的。

Reader/Writer是所有字符流的父类。

•Reader

  read():这个read方法将给予我们以char为单位的数据读取能力。

  skip():跳过。

  close():关闭流。

•Writer

  append():添加字符

  write():以字符为单位写入数据。

  flush(),close():输出流在关闭前,记得flush。

子类有
  InputStreamReader/OutputStreamWriter 称为从字节流到字符流的桥转换类。这个类可以设定字符转换方式 

  FileReader/FileWriter (FileInputStream/FileOutputStream和InputStreamReader/OutputStreamWriter)的组合,只能是本地默认编码

  Bufferedreader/BufferedWriter  字符缓冲流,其特有方法readLine()读取一个文本行,newLine()表示Writer到下一个文本行。

ObjectOutputStream和ObjectInputStream:

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码,编码内容包括类名和类签名、对象的字段值和数组值,以及从初始对象中引用的其他所有对象的闭包。

writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。

还可以使用 DataOutput 中的适当方法将基本数据类型写入流中。还可以使用 writeUTF 方法写入字符串。

对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字段的值。其他对象的引用(瞬态和静态字段除外)也会导致写入那些对象。可使用引用共享机制对单个对象的多个引用进行编码,这样即可将对象的图形恢复为最初写入它们时的形状。  


ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

ObjectInputStream 确保从流创建的图形中所有对象的类型与 Java 虚拟机中显示的类相匹配。使用标准机制按需加载类。

只有支持 java.io.Serializable 或 java.io.Externalizable 接口的对象才能从流读取。

readObject 方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。在 Java 中,字符串和数组都是对象,所以在序列化期间将其视为对象。读取时,需要将其强制转换为期望的类型。

例:

1、ObjectOutputStream

package com.feicui.group1.buffered;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectOutputStreamTest {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = null;
try {
// 1.创建ObjectOutputStream
oos = new ObjectOutputStream(new FileOutputStream(
"../MyJavaTest4/src/com/feicui/group1/buffered/Cat.obj"));

// 2.使用ObjectOutputStream将一个对象写入文件
Cat cat = new Cat("xiaoT");
cat.size = 100;
cat.age = 5;
oos.writeObject(cat);

} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (oos != null) {
oos.flush();
oos.close();
}
}
}

}

class Cat implements Serializable {
static final long serialVersionUID = 1L ;
String name;
String color = "hon";
static int size = 10;
/**
* 临时变量(transient),他在序列化时,将不会被序列化
* */
transient int age = 1;
//新加变量
int weight = 50;
/***/
public Cat(String name) {
this.name = name;
}

/**
* DIY写对象
* */
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
System.out.println("writeObject") ;
//调用默认写法,写入对象
out.defaultWriteObject() ;

//我们自行添加一个对临时变量的输出
out.writeInt(size);
out.writeInt(age) ;
}

/**
* DIY读对象
* */
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
System.out.println("readObject") ;
//读取数据,调用默认读法,读出对象
in.defaultReadObject();

//读取DIY写入的临时变量 读取的顺序必须和写入的顺序一致
this.size = in.readInt();
this.age = in.readInt() ;
}

}
2、ObjectInputStream
package com.feicui.group1.buffered;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class ObjectInputStreamTest {
public static void main(String[] args) {
//
ObjectInputStream ois ;
try{
//创建ObjectInputStream对象
ois = new ObjectInputStream(new FileInputStream("../MyJavaTest4/src/com/feicui/group1/buffered/Cat.obj")) ;
//从文件读取对象
Cat cat = (Cat)ois.readObject() ;
//我们可以序列化类的对象,以及他的成员属性,但是如果是被静态修饰的,将无法被序列化。
//所以反序列化时,也无法拿到。
System.out.println("name:"+cat.name+",size:"+cat.size+",age:"+cat.age+",color:"+cat.color+",weight:"+cat.weight) ;
}catch(Exception e){
e.printStackTrace() ;
}
}

}