初学io

时间:2021-06-17 16:22:35

IO流:

01.File

创建文件

    //创建文件夹
private static void mkdirs() {
System.out.println("请您输入创建的文件夹名称:(默认是E:/)");
String fileName = input.next();
//创建File对象
File file=new File("E:/"+fileName);
if (file.mkdirs()){
System.out.println("创建成功");
}else{
System.out.println("创建失败");
}
}

//创建文件

    private static void createNewFile() {
System.out.println("请您输入文件的名称:(默认是E:/)"); String fileName = input.next(); //创建File对象 File file=new File("E:/"+fileName); if (file.exists()){ //文件已经存在 System.out.println("该文件已经存在!"); }else{ try { boolean flag= file.createNewFile(); if (flag){ System.out.println("文件创建成功!"); }else{ System.out.println("文件创建失败!");    } } catch (IOException e) { e.printStackTrace(); }
}
}

删除文件

//修改文件

    private static void updateFile() {
System.out.println("请您输入需要修改文件的名称:(默认是E:/)");
String oldFileName = input.next();
System.out.println("请您输入文件的新名称:(默认是E:/)");
String newFileName = input.next();
//创建File对象
File oldFile=new File("E:/"+oldFileName);
File newFile=new File("E:/"+newFileName);
if(oldFile.renameTo(newFile)){
System.out.println("修改成功"); }else{
System.out.println("修改失败"); }
}

修改文件

  //修改文件
private static void updateFile() {
System.out.println("请您输入需要修改文件的名称:(默认是E:/)");
String oldFileName = input.next();
System.out.println("请您输入文件的新名称:(默认是E:/)");
String newFileName = input.next();
//创建File对象
File oldFile=new File("E:/"+oldFileName);
File newFile=new File("E:/"+newFileName);
if(oldFile.renameTo(newFile)){
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
}

显示文件信息

   // 查询文件夹下所有的文件列表
private static void findFileList() {
System.out.println("请您输入查询的文件夹名称:(默认是E:/)");
String fileName = input.next();
//创建File对象
File file=new File("E:/"+fileName);
File[] files = file.listFiles();
int dirNums=0;
int fileNums=0;
//遍历集合
for (File f:files){
if (f.isDirectory()){
dirNums++;
}
if (f.isFile()){
fileNums++;
System.out.println(f.getName());
}
}
System.out.println("有多少个文件夹?"+dirNums);
System.out.println("有多少个文件?"+fileNums);
}

02.字节流

     InputStream(输入)        OutputStream(输出)  基类

 都不能实例化

  public static void main(String[] args) {
//创建输入流和输出流对象
InputStream inputStream=null;
OutputStream outputStream=null;
try {
inputStream=new FileInputStream("e:/a.txt");
// true 代表是否向文件中拼接,不删除之前的内容
outputStream=new FileOutputStream("e:/a.txt",true);
//先向文件写入内容
outputStream.write("54321".getBytes()); //outputStream.flush(); 自己没有实现
// read 方法将返回0-255之间的数字 如果流读到了最后,将返回-1
int num=0;
while ((num=inputStream.read())!=-1){
System.out.println((char)num);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}

03.字符流

Reader            Writer

    public static void main(String[] args) {
//创建输入和输出流
Reader reader=null;
Writer writer=null;
try {
reader=new FileReader("e:/a.txt");
writer=new FileWriter("e:/a.txt",true);
writer.write("大家辛苦了1111!");
writer.flush(); // 清空缓冲区
writer.write("大家辛苦了4444!");
writer.close();
//读取
// 创建一次性读取多少个字符
char [] data=new char[1024];
int num=0;
StringBuffer sb=new StringBuffer();
while((num=reader.read(data))!=-1) {
sb.append(data);
}
System.out.println(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}

04.缓冲流

BufferReader       BufferWriter 不单独使用

一般和Reader  Writer 联用   在debug的情况下能看清楚Flush的作用

public static void main(String[] args) {
//创建输入和输出流
Reader reader=null;
Writer writer=null;
BufferedReader br=null;
BufferedWriter bw=null;
try {
writer=new FileWriter("e:/a.txt",true);
bw=new BufferedWriter(writer); //封装
bw.write("大家辛苦了!");
bw.newLine(); //换行
bw.write("大家别眨眼!");
bw.flush();
bw.write("大家别眨眼22!");
bw.write("大家别眨眼33!");
bw.close();
writer.close(); //如果不关闭 后续两句话没法获取
//读取
reader=new FileReader("e:/a.txt");
br=new BufferedReader(reader);//封装
String line=null;
StringBuffer sb=new StringBuffer();
while ((line=br.readLine())!=null){
sb.append(line);
}
System.out.println(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
br.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

05.二进制流

DataInputStream    DataOutputStream

不单独使用  一般需要与 InputStream   OutputStream 联用

public static void main(String[] args) {
//创建输入流和输出流对象
InputStream inputStream=null;
OutputStream outputStream=null;
DataInputStream dis=null;
DataOutputStream dos=null;
try {
//获取了输入流 猫咪进内存了
inputStream=new FileInputStream("e:/dog.jpg");
dis=new DataInputStream(inputStream);
//获取输出流
outputStream=new FileOutputStream("e:/u1/cat.jpg");
dos=new DataOutputStream(outputStream);
//先读取
int num=0;
while ((num=dis.read())!=-1){
dos.write(num); //复制
}
} catch (Exception e) {
e.printStackTrace();
}finally { //释放资源
try {
dos.close();
dis.close();
outputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

06.序列化和反序列化

ObjectInputStream  ObjectOutputStream

序列化:序列化(Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。

持久化:持久化是将程序数据在持久状态和瞬时状态间转换的机制。

注意 实体类需要接口Serializable 要不然无法序列化

 static Scanner  input=new Scanner(System.in);

    //创建需要的输入和输出流对象

    static   InputStream inputStream=null;

    static  OutputStream outputStream=null;

    static ObjectInputStream objectInputStream=null;

    static ObjectOutputStream  objectOutputStream=null;

    public static void main(String[] args) {

         //注册   序列化

        //register();

        //登录  反序列化

        login();

}

//注册

    private static void register()  {

        User user=new User();

        System.out.println("请输入您的用户名:");

        user.setUserName(input.next());

        System.out.println("请输入您的密码:");

        user.setPassword(input.next());
try {
outputStream=new FileOutputStream("e:/user.txt");
objectOutputStream=new ObjectOutputStream(outputStream);
//把对象输出到文件中
objectOutputStream.writeObject(user);
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
objectOutputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} //登录
private static void login() {
try {
inputStream=new FileInputStream("e:/user.txt");
objectInputStream=new ObjectInputStream(inputStream);
//读取对象
User user= (User) objectInputStream.readObject();
System.out.println(user);
} catch (Exception e) {
e.printStackTrace();
}finally { try {
objectInputStream.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

NIO:

非堵塞io  全称new io

Java NIO: Channels and Buffers(通道和缓冲区)

为了理解Buffer的工作原理,需要熟悉它的三个属性:

  • capacity
  • position
  • limit

position和limit的含义取决于Buffer处在读模式还是写模式。不管Buffer处在什么模式,capacity的含义总是一样的。

这里有一个关于capacity,position和limit在读写模式中的说明,详细的解释在插图后面。

capacity

作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。

position

当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.

当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。

limit

在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。

当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)

Buffer的分配

要想获得一个Buffer对象首先要进行分配。 每一个Buffer类都有一个allocate方法。下面是一个分配48字节capacity的ByteBuffer的例子。

1

ByteBuffer buf = ByteBuffer.allocate(48);

这是分配一个可存储1024个字符的CharBuffer:

1

CharBuffer buf = CharBuffer.allocate(1024);

向Buffer中写数据

写数据到Buffer有两种方式:

  • 从Channel写到Buffer。
  • 通过Buffer的put()方法写到Buffer里。

从Channel写到Buffer的例子

1

int bytesRead = inChannel.read(buf); //read into buffer.

通过put方法写Buffer的例子:

1

buf.put(127);

put方法有很多版本,允许你以不同的方式把数据写入到Buffer中。例如, 写到一个指定的位置,或者把一个字节数组写入到Buffer。 更多Buffer实现的细节参考JavaDoc。

flip()方法

flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。

换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。

从Buffer中读取数据

从Buffer中读取数据有两种方式:

  1. 从Buffer读取数据到Channel。
  2. 使用get()方法从Buffer中读取数据。

从Buffer读取数据到Channel的例子:

1

int bytesWritten = inChannel.write(buf);

使用get()方法从Buffer中读取数据的例子

1

byte aByte = buf.get();

01他是基于缓冲区对数据进行读取或者是写入

02通道是双向的,流是单向的

03可以异步的读写

常用的实现

1.Filechannel:从文件中读写数据

2.DatagrarmChannel:通过UDP读写网络中的数据Udp:不安全 非链接 快

3.SocketChannel:通过TCp读写网络中的数据  Tcp: 安全  链接  慢

4.serverSocketChannel:可以监听新来的Tcp链接,每进来一个都会创建一个新的serverSocketChannel

内存映射

就是把文件映射到电脑的内存中,通过操作内存从而到达操作文件的目的

内存中操作速度是最快的!

Java中的读取文件方式

1.RandomAccessFile    随机读取,速度最慢 可以设置读写

2.FileInputStream         流的方式读取

3.BufferReader            缓存的方式读取

4.MappedByteBuffer   内存映射,速度最快

内存映射的三种模式 :MapMode

  1. READ_ONLY  :对缓冲区的内容只读
  2. READ_WRITE   :对缓冲区的内容读写
  3. PRIVATE:      只会对缓冲区的内容修改,不会影响到真实文件

通常适用于文件的读取! 一般不会涉及到文件袋写入

文件锁

  1. FileLock 基于FIleChannel对文件提供锁的功能!
    1. 共享锁 共享读的操作 只能有一个写的操作 适合读取数据

为了防止其他线程使用独占锁

  1. 独占锁 读写不能同时 只能一个读或者写   适合写数据

Lock(); 没有参数的是独占锁 有参数的是共享锁也有可能是独占锁

Nio:将buffer写入 Channel

  public static void main(String[] args) {
System.out.println("d");
//创建数组
String[] bytee = {"dd", "dd", "dd"};
//创建文件对象 自动创建
File file = new File("d:/a.txt");
// 创建输出流对象
FileOutputStream fos = null;
// 创建管道对应的实现类
FileChannel fileChannel = null; try {
fos = new FileOutputStream(file);
// 获取管道
fileChannel = fos.getChannel();
// 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 循环出数组的数据
for (String s : bytee) {
// 将训话你的数据写缓冲区
System.out.println(s.getBytes() );
buffer.put(s.getBytes());
}
// 从写模式切换读模式
buffer.flip();
// 正在的写入
fileChannel.write(buffer);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fileChannel.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
} }

Nio2:将文件内容复制到另一个文件里面

 
  //从文件a到文件b传数据

    public static void main(String[] args) {

//创建需要的两个文件

        File afile = new File("d:/a.txt");

        File bfile = new File("d:/b.txt");

//        创建输出流对象

        FileInputStream fileInputStream = null;

        FileOutputStream fileOutputStream = null;

//        创建管道对应的实现类

        FileChannel inputchannel = null;

        FileChannel outputchannel = null;

        try {

            fileInputStream = new FileInputStream(afile);

            fileOutputStream = new FileOutputStream(bfile);

//          获取管道

            inputchannel = fileInputStream.getChannel();

            outputchannel = fileOutputStream.getChannel();

//            创建缓冲区

            ByteBuffer buffer = ByteBuffer.allocate(1024);

//           从写模式切换读模式

            int num = 0;

            while ((num = inputchannel.read(buffer)) != -1) {

//               切换模式

                buffer.flip();

                //写入到b文件里面

                outputchannel.write(buffer);

                //清空缓存区

                buffer.clear();

                System.out.println(buffer);

                System.out.println(num);

            }

//            正在的写入

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            try {

                inputchannel.close();

                outputchannel.close();

                fileInputStream.close();

                fileOutputStream.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }
}

Nio3:比较内存映射和io的时间

  public static void main(String[] args) {

        FileChannel channel = null;

        try {

//            找打指定的文件并且设置读写模式

            RandomAccessFile file = new RandomAccessFile("d:/a.txt", "rw");

//创建管道

            channel = file.getChannel();

            MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

            ByteBuffer byteBuffer1 = ByteBuffer.allocate(1204);

            byte[] bytes = new byte[1024];

            long length = file.length();

            long beginTime = System.currentTimeMillis();

            for (int i = 0; i < length; i += 1024) {

                if (length - i > 1024) {

                    buffer.get(bytes);

                } else {

                    buffer.get(new byte[(int) (length - i)]);

                }

            }

            long endTime = System.currentTimeMillis();

            System.out.println("使用内存映射时间" + (endTime - beginTime));

            System.out.println("-------------------------------------------------------");

            beginTime = System.currentTimeMillis();

            while (channel.read(byteBuffer1) > 0) {

                byteBuffer1.flip();

                byteBuffer1.clear();

            }

            endTime = System.currentTimeMillis();

            System.out.println("使用普通io时间" + (endTime - beginTime));

        } catch (Exception e) {

            e.printStackTrace();

        }

    }