标签:String len IO new close null out
1、IO流原理及流的分类
1.1、Java IO 原理
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通信等。
- Java程序中,对于数据的输入/输出操作以“流(stream)”的方式进行。
- java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
1.2、IO流的分类
- 按操作数据单位不同分类:字节流(8 bit),字符流(16 bit)
- 按数据流的流向不同分为:输入流、输出流
- 按流的角色不同分类:节点流,处理流
抽象基类 |
字节流 |
字符列 |
输入流 |
字节流 |
字符流 |
输入流 |
InputStrean |
Reader |
输出流 |
OutputStream |
Writer |
- Java的IO流供涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的。
- 由这4个类派生出来的子类名称都是以其父类名作为子类名后缀
1.3、IO流体系
分类 |
字节输入流 |
字节输出流 |
字符输入流 |
字符输出流 |
抽象基类 |
InputStream |
OutputStream |
Reader |
Writer |
访问文件 |
FileInputStream |
FileOutStream |
FileReader |
FileWriter |
访问数组 |
ByteArrayInputStream |
ByteArrayOutputStream |
CharArrayReader |
CharArrayWriter |
访问管道 |
PipedInputStream |
PipedOutputStream |
PipedReader |
PipedWriter |
访问字符串 |
|
|
StringReader |
StringWriter |
缓冲流 |
BufferedInputStream |
BufferedOutputStream |
BufferedReader |
BufferedWriter |
转换流 |
|
|
InputStreamReader |
OutputStreamWriter |
对象流 |
ObjectInputStream |
ObjectOutputSteam |
|
|
|
FilterInputStream |
FilterOutputStream |
FilterReader |
FilterWriter |
打印流 |
|
PrintStream |
|
PrintWriter |
推回输入流 |
PushbackInputStream |
|
PushbackReader |
|
特殊流 |
DataInputStream |
DataOutputStream |
|
|
2、流的操作
2.1、节点流
2.1.1、FileReader
public static void main(String[] args) throws IOException {
//将hello.txt文件内容读到程序中
FileReader reader = null;
try {
//1.实例化File对象,指明要操作的文件
File file = new File("src/hello.txt");
//2.提供具体的流
reader = new FileReader(file);
//3.数据的读入 read()返回读入的一个字符。如果达到文件末尾,返回-1
int data = reader.read();
while(data != -1){
System.out.println((char)data);
//如果不是-1,继续读下一个字符
data = reader.read();
}
}catch (IOException e){
e.printStackTrace();
}finally {
//4.流的关闭
reader.close();
}
}
public static void main(String[] args) throws IOException {
//将hello.txt文件内容读到程序中
FileReader reader = null;
try {
//1.实例化File对象,指明要操作的文件
File file = new File("src/hello.txt");
//2.提供具体的流
reader = new FileReader(file);
//3.数据的读入 read()返回读入的一个字符。如果达到文件末尾,返回-1
int len;
//一次读写多个字符保存到chars中,len(返回读取的字符个数)
char[] chars = new char[10];
len = reader.read(chars);
while(len != -1){
for(int i=0;i<len;i++){
System.out.print(chars[i]);
}
len = reader.read(chars);
}
}catch (IOException e){
e.printStackTrace();
}finally {
//4.流的关闭
reader.close();
}
}
2.1.2、FileWriter
- 输出操作,对应的File可以不存在
- 如果不存在,在输出的过程中,会自动创建文件
- 如果存在
- 如果使用的构造器是:FileWriter(file,fase)/FileWriter(file):对原有文件进行覆盖操作
- 如果使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件追加数据
public static void main(String[] args) throws IOException {
FileWriter fw = null;
try {
//1.实例化File对象,指明写出到的文件
File file = new File("src/hello.txt");
//2.提供具体的流
fw = new FileWriter(file,true);
//3.写出操作
fw.write("this is content");
}catch (IOException e){
e.printStackTrace();
}finally {
//4.流的关闭
fw.close();
}
}
- 使用FileInputStream和FileOutputStream复制图片
public static void main(String[] args) throws IOException {
FileInputStream input = null;
FileOutputStream out = null;
try {
//1.实例化File对象
File fileIn = new File("src/hello.jpg");
File fileOut = new File("src/hello1.jpg");
//2.提供具体的流
input = new FileInputStream(fileIn);
out = new FileOutputStream(fileOut);
//3.读取图片数据
byte[] buffer = new byte[1024];
int len;
len = input.read(buffer);
while(len != -1){
//写图片数据
out.write(buffer,0,len);
len = input.read(buffer);
}
}catch (IOException e){
e.printStackTrace();
}finally {
//4.流的关闭
if(input != null){
input.close();
}
if(out != null){
out.close();
}
}
}
2.2、缓冲流
- 作用:提高流的读取、写入速度
- 原因:内部提供了一个缓冲区
- BufferedInputStream、BufferedOutputStreamdu读取和写入实现图片的复制
public static void main(String[] args){
FileInputStream input = null;
FileOutputStream out = null;
BufferedInputStream bin = null;
BufferedOutputStream bout= null;
try {
//文件
File fileIn = new File("src/hello.jpg");
File fileOut = new File("src/hello1.jpg");
//字节流
input = new FileInputStream(fileIn);
out = new FileOutputStream(fileOut);
//缓冲流
bin = new BufferedInputStream(input);
bout= new BufferedOutputStream(out);
//读取、写入
byte[] buffer = new byte[1024];
int len;
len = bin.read(buffer);
while (len != -1){
bout.write(buffer,0,len);
len = bin.read(buffer);
}
}catch (IOException e){
e.printStackTrace();
}finally {
//资源关闭,先关外层流,再关内层流
if (bin!=null) {
try {
bin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bout!=null) {
try {
bout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//在关闭外层流的同时,内层流也会自动进行关闭。内层流关闭可以省略
//input.close();
//out.close();
}
}
2.2.2、BufferedReader、BufferedWriter
- BufferedReader、BufferedWriter实现复制文本文件
public static void main(String[] args){
FileReader input = null;
FileWriter out = null;
BufferedReader bin = null;
BufferedWriter bout= null;
try {
//文件
File fileIn = new File("src/hello.txt");
File fileOut = new File("src/hello1.txt");
//字节流
input = new FileReader(fileIn);
out = new FileWriter(fileOut);
//缓冲流
bin = new BufferedReader(input);
bout= new BufferedWriter(out);
//读取、写入
char[] buffer = new char[10];
int len;
len = bin.read(buffer);
while (len != -1){
bout.write(buffer,0,len);
len = bin.read(buffer);
}
}catch (IOException e){
e.printStackTrace();
}finally {
//资源关闭,先关外层流,再关内层流
if (bin!=null) {
try {
bin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bout!=null) {
try {
bout.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//在关闭外层流的同时,内层流也会自动进行关闭。内层流关闭可以省略
//input.close();
//out.close();
}
}
2.3、转换流
- 转换流输入字符流
- InputStreamReader:将一个字节的输入流转换为字符的输入流
- OutputStreamWriter:将一个字符的输出流转换为字节的输出流
- 作用:提供字节流和字符流之间的转换
public static void main(String[] args){
FileInputStream input = null;
InputStreamReader inputReader = null;
try {
input = new FileInputStream("src/hello.txt");
//inputReader = new InputStreamReader(input);
//参数2指明了字符集,具体使用哪个字符集,取决于文件保存时采用的字符集
inputReader = new InputStreamReader(input,"UTF-8");
char[] buffer = new char[10];
int len;
len = inputReader.read(buffer);
while (len != -1){
String str = new String(buffer,0,len);
System.out.print(str);
len = inputReader.read(buffer);
}
}catch (IOException e){
e.printStackTrace();
}finally {
//资源关闭,先关外层流,再关内层流
if (inputReader!=null) {
try {
inputReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//可省略
//input.close();
}
}
2.3.2、OutputStreamWriter
public static void main(String[] args){
FileInputStream input = null;
FileOutputStream out = null;
InputStreamReader inputReader = null;
OutputStreamWriter outReader = null;
try {
input = new FileInputStream("src/hello.txt");
out = new FileOutputStream("src/hello1.txt");
inputReader = new InputStreamReader(input,"UTF-8");
//按gbk字符集存储
outReader = new OutputStreamWriter(out, "gbk");
char[] buffer = new char[10];
int len;
len = inputReader.read(buffer);
while (len != -1){
outReader.write(buffer,0,len);
len = inputReader.read(buffer);
}
}catch (IOException e){
e.printStackTrace();
}finally {
//资源关闭,先关外层流,再关内层流
if (inputReader!=null) {
try {
inputReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outReader != null){
try {
outReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//可省略
//input.close();
//out.close();
}
}
2.4、标准输入输出流
- System.in和System.out分别代表了系统标准的输入和输出设备
- 默认输入设备:键盘,输出设备:控制台
- System.out的类型是InputStream
- System.out的类型是PrintStream
- 重定向:通过System类的setIn,setOut方法对默认设备进行改变
- public static void setIn(InputStream in)
- public static void setOut(PrintStream out)
- 从键盘输入字符串,要求将读取到的整行字符串转换成大写输出,直到输入e或者exit退出程序
public static void main(String[] args) throws IOException {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String data = null;
while (true){
System.out.println("请输入字符串:");
data = br.readLine();
if (data.equals("e") || data.equals("exit")){
break;
}
String upperCase = data.toUpperCase();
System.out.println(upperCase);
}
br.close();
}
2.5、打印流
- 打印流:PrintStream和PrintWriter
- 提供了一系列重载的print()和println()方法,用于多种数据类型的输出
- PrintStream和PrintWriter的输出不会抛出IOException异常
- PrintStream和PrintWriter有自动flush功能
- PrintStream打印的所有字符都使用平台默认字符编码转换为字节,在需要写入字符而不是写入字节的情况下,应该使用PrintWriter类
- System.out返回的是PrintStream的实例
public static void main(String[] args) throws IOException {
//创建输出流
FileOutputStream output = new FileOutputStream(new File("src/hello.txt"));
//创建打印流
PrintStream printStream = new PrintStream(output);
//修改默认的输出设备
System.setOut(printStream);
System.out.println("hello world");
printStream.close();
output.close();
}
2.6、数据流
- 为了方便地操作java语言的基本数据类型和String的数据,可以使用数据流
- 数据流有两个类:
- DataInputStream和DataOutputStream
- 分别套接在InputStream和outPutStream子类的流上
public static void main(String[] args) throws IOException {
//将内存中的字符串、基本数据类型的变量写出到文件中
DataOutputStream dos = new DataOutputStream(new FileOutputStream("SRC/hello.txt"));
dos.writeUTF("陈明林");
dos.flush();
dos.writeInt(22);
dos.flush();
dos.writeBoolean(true);
dos.flush();
dos.close();
/*
*将文件中存储的基本类型变量和字符串读取到内存中,保存在变量中
* 读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致
*/
DataInputStream dis = new DataInputStream(new FileInputStream("src/hello.txt"));
String str = dis.readUTF();
int i = dis.readInt();
boolean b = dis.readBoolean();
System.out.println(str+","+i+","+b);
}
2.7、对象流
- ObjectInputStream和ObjectOutputStream
- 用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把java中的对象写入到数据源中,也能把对象从数据源中还原回来
- 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
- 反序列化:用ObjectInputStream类读取基本数据类型或对象的机制
- ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
- 对象的序列化
- 对象序列化机制允许把内存中的java对象转换成平台无关的二进制流,从而允许把这种二进制流持久第保存在磁盘上,或通过网络将这种二进制流传输到另一个网络结点。当其他程序获取了这种二进制流,就可以恢复成原来的java对象
- 序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
- 序列化是RMI(Remote Method Invoke-远程方法调用)过程的参数和返回值都必须实现的机制,而RMI是javaee的基础。因此序列化机制是javaee平台的基础
- 如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一
- Serializable
- Externalizable
- 凡是实现了Serializable接口的类都有一个表示序列化版本标识符的静态变量
- private static final long serialVersionUID
- serialVersionUID用来表明类的不同版本间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容
- 如果没有显式定义这个变量,它的值是java运行时环境根据类的内部细节自动生成。若类的实例变量做了修改,serialVersionUID可能发生变化。故建议,显式声明
- 简单来说,java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化不一致的异常(InvalidCastException)
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/hello.txt"));
oos.writeObject(new String("hello world"));
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/hello.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
- 自定义类
- 除了当前User类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的(默认情况下,基本数据类型可序列化)
public class User implements Serializable {
private static final long serialVersionUID = 507545713L;
private String id;
private String name;
public User(String id,String name){
this.id= id;
this.name=name;
}
@Override
public String toString() {
return "id:"+this.id+",name:"+this.name;
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/hello.txt"));
oos.writeObject(new User("10001","陈明林"));
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/hello.txt"));
User user = (User)ois.readObject();
System.out.println(user.toString());
ois.close();
}
2.8、随机存取文件流
- RandomAccessFile声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了DataInput、DataOutput这两个接口,也就意味着这个类既可以读也可以写
- RandomAccessFile类支持“随机访问”的方式,程序可以直接跳到文件的任意地方读写文件
- 支持只访问文件的部分内容
- 可以向已存在的文件后追加内容
- RandomAccessFile对象包含一个记录指针,用以标记当前读写处的位置。RandomAccessFile类对象可以自由移动记录指针:
- long getFilePointer():获取文件记录指针的当前位置
- void seek(long pos):将文件记录指针定位到pos位置
- 构造器
- public RandomAccessFile(File file,String mode)
- public RandomAccessFile(String name,Stirng mode)
- 创建RandomAccessFile类的实例需要指定一个mode参数,该参数指定RandomAccessFile的访问模式
- r:以只读方式打开
- rw:打开以便读取和写入
- rwd:打开以便读取和写入;同步文件内容的更新
- rws:打开以便读取和写入;同步文件内容和元数据的更新
- 如果模式为只读r。则不会创建文件,而是去读取一个已经存在的文件,如果读取的文件不存在则会出现异常。如果模式为rw读写。如果文件不存在则会去创建文件,如果文件存在则不会创建文件
public static void main(String[] args) throws IOException {
RandomAccessFile raf1 = new RandomAccessFile("src/bg.jpg","r");
RandomAccessFile raf2 = new RandomAccessFile("src/bg1.jpg","rw");
byte[] buffer = new byte[1024];
int len;
len = raf1.read(buffer);
while (len != -1){
raf2.write(buffer,0,len);
len = raf1.read(buffer);
}
raf1.close();
raf2.close();
}
public static void main(String[] args) throws IOException {
RandomAccessFile raf2 = new RandomAccessFile("src/txt01","rw");
raf2.seek(3);//将指针调到角标为3的位置覆盖
raf2.write("xyz".getBytes());
raf2.close();
}
- 使用RandomAccessFile实现数据的插入效果
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile("src/hello.txt", "rw");
raf.seek(3); //将指针调到角标为3的位置
//保存指针角标3后面的所有数据到StringBuilder中
StringBuilder builder = new StringBuilder((int) new File("src/hello.txt").length());
byte[] buffer = new byte[20];
int len;
len = raf.read(buffer);
while (len != -1){
builder.append(new String(buffer,0,len));
len = raf.read(buffer);
}
//调回指针,"写入xyz"
raf.seek(3);
raf.write("xyz".getBytes());
//将StringBuilder中的数据写入文件
raf.write(builder.toString().getBytes());
raf.close();
}
标签:String,
len,
IO,
new,
close,
null,
out
From: https://www.cnblogs.com/blackyoumo/p/16864446.html