输入输出流
File
java.io.File类:文件和文件目录路径的抽象表示形式,和平台无关
File可以对文件或者目录实现增删重命名。但是File不可以访问文件或者目录内容,如果要访问内容,则需要使用输入输出流
构造器:

路径编写分隔符的问题:

File常用方法
获取功能:

getPath是获取你在构造器中填写的那个路径,getAbsolutePath是获取绝对路径。
重命名功能:

file1.renameTo(file2)
要想保证成功,就要使file1在硬盘中存在,file2在硬盘中是不存在的。
相当于实现了一个另存为的功能。
判断功能:

创建功能:

删除功能:

当一个File创建的时候,如果这个路径下真的存在文件或者目录,那么这个File对象的属性是被显示赋值的。如果没有就会使用默认值。
IO流(input和output)
用于处理设备之间的数据传输(输入输出是相当于程序,不是文件)
java中对于数据的输入和输出都是使用的”流(stream)“的形式进行
流的分类:
按照操作数据单位的不同:字节流(8bit) 字符流(16bit)
按照数据流的方向不同:输入流 输出流
按照数据流的角色不同分为:节点流 处理流

节点流和处理流:节点流就是说直接进行数据操作的流,他操作的对象是数据,处理流操作的对象是节点流。
IO流体系

节点流为FileInputStream FileOutputStream FileReader FileWriter
其他的为处理流。
字符输入流:
虽然不知道具体的原因,但是字符流,每次都是操作一个字符,无论是中文还是英文。
@Test
public void test03() {
File file=new File("C:\\Users\\26779\\Desktop\\temp.txt");
FileReader fileReader=null;
try{
fileReader=new FileReader(file);
int data=-1;
while((data=fileReader.read())!=-1){
if(data=='\r'||data=='\n')
continue;
System.out.print((char)data);
}
}
catch (Exception e){
e.printStackTrace();
}
finally {
try {
if(fileReader!=null){
fileReader.close();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
换行是'\r''\n'或者只是一个'\n'
public void test04(){
File file=new File("C:\\Users\\26779\\Desktop\\temp.txt");
FileReader fileReader=null;
int len=-1;
try {
fileReader=new FileReader(file);
char[] buf=new char[5];
while((len=fileReader.read(buf))!=-1){
/* for(int i=0;i<len;i++){
System.out.print(buf[i]);
}*/
String str=new String(buf,0,len);
System.out.print(str);
}
}
catch (Exception e){
e.printStackTrace();
}
finally {
try {
if(fileReader!=null){
fileReader.close();
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
字符输出流
@Test
public void test05(){
File file=new File("C:\\Users\\26779\\Desktop\\temp.txt");
FileWriter fileWriter=null;
try {
fileWriter=new FileWriter(file,true);
fileWriter.write("我是一个人",0,2);
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(fileWriter!=null){
fileWriter.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
我们是不可以通过字符流实现图片等字节文件的处理。
字节输入流:
字节输出流:
public void test06(){
File file1=new File("C:\\Users\\26779\\Desktop\\1111.png");
File file2=new File("C:\\Users\\26779\\Desktop\\2222.png");
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
try{
fileInputStream=new FileInputStream(file1);
fileOutputStream=new FileOutputStream(file2,false);
byte[] bytes=new byte[10];
int len=-1;
while((len=fileInputStream.read(bytes))!=-1){
fileOutputStream.write(bytes,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(fileInputStream!=null){
fileInputStream.close();
}
if(fileOutputStream!=null){
fileOutputStream.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
缓冲流(提高文件的读写效率)
先关闭外层流再关闭内层流。(其实关闭外层流的时候内层流也会关闭)
缓冲流有一个readline()函数,每次读取一行
package com.geng;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class FileTest {
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("C:\\Users\\26779\\Desktop\\autoQQ.txt");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str = null;
while((str = bufferedReader.readLine()) != null) {
if(str.equals("")){
continue;
}
System.out.println(str);
}
inputStream.close();
bufferedReader.close();
}
}
public void test07(){
File file1=new File("C:\\Users\\26779\\Desktop\\1111.png");
File file2=new File("C:\\Users\\26779\\Desktop\\2222.png");
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
BufferedInputStream bufferedInputStream=null;
BufferedOutputStream bufferedOutputStream=null;
try{
fileInputStream=new FileInputStream(file1);
fileOutputStream=new FileOutputStream(file2,false);
bufferedInputStream=new BufferedInputStream(fileInputStream);
bufferedOutputStream=new BufferedOutputStream(fileOutputStream);
byte[] bytes=new byte[10];
int len=-1;
while((len=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
//bufferedOutputStream.flush();
//刷新缓冲区
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(bufferedInputStream!=null){
bufferedInputStream.close();
}
if(bufferedOutputStream!=null){
bufferedOutputStream.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
传统的io操作是存在堵塞的,当你进行读的时候,你的写是停止的,缓冲流是在内存中开辟一个空间,存放读写的数据,这样减少了堵塞的时间,所以看起来更加高效(是一种空间换时间的操作)
转换流(实现字符流和字节流之间的转换)

public void test09(){
File file1=new File("C:\\Users\\26779\\Desktop\\autoQQ.txt");
File file2=new File("C:\\Users\\26779\\Desktop\\temp.txt");
FileInputStream fileInputStream=null;
FileOutputStream fileOutputStream=null;
InputStreamReader inputStreamReader=null;
OutputStreamWriter outputStreamWriter=null;
try{
fileInputStream=new FileInputStream(file1);
fileOutputStream=new FileOutputStream(file2,false);
inputStreamReader=new InputStreamReader(fileInputStream,"utf-8");
outputStreamWriter=new OutputStreamWriter(fileOutputStream,"gbk");
char[] buff=new char[5];
int len=-1;
while((len=inputStreamReader.read(buff))!=-1){
outputStreamWriter.write(buff,0,len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try{
if(outputStreamWriter!=null){
outputStreamWriter.close();
}
if(inputStreamReader!=null){
inputStreamReader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
编码字符集:
在Java(其中主要包括在JVM中、内存中、在代码里声明的每一个char、String类型的变量中。)中字符只以一种形式存在,那就是Unicode,不选择任何特定的编码,直接使用它们在字符集中的编号,这是统一的唯一的方法。
在JVM内部,统一使用Unicode表示,当着字符从JVM内部移动到外部时(即保存为文件系统中的一个文件内容时),就进行了编码转换,使用了具体的编码方案。因此也可以说,所有的编码转换只发生在边界的地方,也就是各种输入/输出流的起作用的地方。
(6条消息) Java中弄懂Unicode和UTF-8编码方式_诚-CSDN博客_java unicode
标准输入输出流
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出

public static void main(String[] args){
InputStreamReader inputStreamReader=null;
BufferedReader bufferedReader=null;
try {
inputStreamReader=new InputStreamReader(System.in);
bufferedReader=new BufferedReader(inputStreamReader);
while(true){
System.out.println("请输入:");
String str=bufferedReader.readLine();
if("exit".equalsIgnoreCase(str)){
break;
}
System.out.println(str);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(bufferedReader!=null){
bufferedReader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
打印流

public static void main(String[] args){
InputStreamReader inputStreamReader=null;
BufferedReader bufferedReader=null;
FileOutputStream fileOutputStream=null;
PrintStream printStream=null;
try {
inputStreamReader=new InputStreamReader(System.in);
bufferedReader=new BufferedReader(inputStreamReader);
fileOutputStream=new FileOutputStream("C:\\Users\\26779\\Desktop\\temp.txt",false);
printStream=new PrintStream(fileOutputStream,true);//开启自动刷新
System.setOut(printStream);
while(true){
String str=bufferedReader.readLine();
if("exit".equalsIgnoreCase(str)){
break;
}
System.out.println(str);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(bufferedReader!=null){
bufferedReader.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
数据流

对象流
用于存储和读取java的基本数据类型数据和对象的处理流
序列化:ObjectOutputStream类保存基本数据类型或者对象的机制
反序列化:ObjectInputStream类读取基本数据类型或者对象的机制
注意对象流是不可以序列化static和transient修饰的成员变量的。
对象的序列化机制:
允许把内存中的java对象转换成平台无关的二进制流,从而允许这种二进制流持久的存储在磁盘上,或通过网络将这种二进制传输到另一个网络节点。
序列化时RMI(远程方法调用)过程的参数和返回值都必须实现的机制
如果需要将某个对象支持序列化机制,我们让对象所属的类是可以被序列化的,就必须实现两个接口之一,否则会抛出NotSerializableException异常
Serializable
Externalizable
凡是实现了Serializable接口的类都有一个表示序列化版本标识符的静态常量
private static final long serialVersionUID;
这个常量会实现类的版本控制(确定是否兼容)
如果类没有显示定义这个静态常量,他的值就是java运行时根据类的内部细节生成的,也就是说如果你修改了类,可能会导致这个常量发生变化,此时如果你进行反序列化,就会报错InvalidCastException
(简单来说java的序列化机制时通过在运行时判断类的serialVersionUID来验证版本是否一致,在进行反序列化的时候,jvm会将传来的字节流的serialVersionUID和本地实体类的进行比较,如果一致才可以进行反序列化)
import org.junit.Test;
import org.junit.experimental.theories.suppliers.TestedOn;
import java.io.*;
import java.util.Scanner;
public class FileTest {
@Test
public void test1(){
Store store=new Store(12,"lala","0100101");
ObjectOutputStream objectOutputStream=null;
try {
objectOutputStream=new ObjectOutputStream
(new FileOutputStream
("C:\\Users\\26779\\Desktop\\temp.txt",false)
);
objectOutputStream.writeObject(store);
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(objectOutputStream!=null){
objectOutputStream.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
@Test
public void test2(){
ObjectInputStream objectInputStream=null;
try {
objectInputStream=new ObjectInputStream
(new FileInputStream
("C:\\Users\\26779\\Desktop\\temp.txt")
);
Object store=objectInputStream.readObject();
if(store instanceof Store)
store=(Store)store;
System.out.println(store.toString());
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(objectInputStream!=null){
objectInputStream.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
class Store implements Serializable{
private int count;
private String name;
private String id;
public Store(int count, String name, String id) {
this.count = count;
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "Store{" +
"count=" + count +
", name='" + name + '\'' +
", id='" + id + '\'' +
'}';
}
}
其实我们除了保证类是可以进行序列化的,我们也要保证类中的所有属性都是可以进行序列化的
任意存取文件流RandomAccessFile(不是继承于四个基本抽象类而是直接继承自Object)


rw模式下数据不会立即写入到磁盘中,而rwd数据会立即写入到磁盘中。也就是说如果写的过程中,如果出现异常,rwd会保存当前进度,rw会丢失。
任意存取文件流在写入的时候,如果不指定指针位置,是在开始位置,然后进行覆盖(这个覆盖其实是一个个字符进行覆盖)
这个类是可以实现一个多线程断点下载的功能,其实我们在下载文件的时候,都会建立两个临时文件,一个是和被下载文件大小相同的空文件,另一个是记录指针的位置文件,每次下载暂停的时候我们都会从上一次的地方接着下载。
Java NIO
从jdk1.4版本开始引入的一套新的IO API,NIO是支持面向缓冲区的(IO是面向流的)基于通道的IO操作。NIO将以更加高效的方式进行文件读写操作
JAVA API提供了两套NIO,一套是针对标准的输入出输出NIO,一套是网络编程NIO
NIO2


Path 、Paths和Files




关于IO apache提供了很多官方api,在org.apache.commons.io这个包内
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class FileUtilsTest {
public static void main(String[] args) throws IOException {
File file1=new File("C:\\Users\\26779\\Desktop\\老婆.jpg");
File file2=new File("C:\\Users\\26779\\Desktop\\2121.jpg");
FileUtils.copyFile(file1,file2);
}
}
浙公网安备 33010602011771号