java中如何清空缓冲区

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中如何清空缓冲区相关的知识,希望对你有一定的参考价值。

import java.util.*;

public class Main

public static void main(String[] args)

Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
for(int i=0;i<n;i++)

String str=cin.nextLine();
System.out.println(str+"\n");



ACM中的相关问题。我想应该是输入n后的缓冲区仍保留换行符的问题,导致cin.nextline();的第一次读取的是换行符。要怎么改?
已学完C++,搞ACM也有段时间了,初学java,C++的思路走惯了。C++中可以用getchar();吃掉换行符或者用cin.ignore();。至于java怎么弄啊

很简单,你再每次输入后都调用一次nextLine();就可以清空了追问

是在int n=cin.nextInt();后面吗?
好像可以,谢谢

参考技术A 你把for循环里的nextLine,该为next,就能解决问题了

 import java.util.*;
public class Demo02 
 public static void main(String[] args) 
  Scanner cin = new Scanner(System.in);
  int n = cin.nextInt();
  for (int i = 0; i < n; i++) 
   String str = cin.next();
   System.out.println(str);
  
 

追问

原题中的str中间是可以有空格的,我没说清楚,上面的方法已经解决问题了,不过还是谢谢

追答你把str中间的回车加上,也能达到你的要求的,你可以试下,多一种方法:
import java.util.*;public class Demo02 public static void main(String[] args)  Scanner cin = new Scanner(System.in);  int n = cin.nextInt();  for (int i = 0; i < n; i++)   String str = cin.next();   System.out.println(str+"\\n");  

你把str中间的回车加上,也能达到你的要求的,你可以试下,多一种方法:
import java.util.*;public class Demo02 public static void main(String[] args)  Scanner cin = new Scanner(System.in);  int n = cin.nextInt();  for (int i = 0; i < n; i++)   String str = cin.next();   System.out.println(str+"\\n");  

追问

JAVA NIO系列 Buffer 解读

缓冲区分类 

NIO中的buffer用于和通道交互,数据是从通道读入缓冲区,从缓冲区中写入通道的。Buffer就像一个数组,可以保存多个类型相同的数据。每种基本数据类型都有对应的Buffer类:

缓冲区的属性

1、capacity(容量):buffer本质是一个数组,在初始化时有固定的大小,这个值就是容量。容量不可改变,一旦缓冲区满了,需要将其清空才能将继续进行读写操作。

2、position(位置):表示当前的位置,初始化时为0,当一个基本数据类型的数据写入buffer时,position会向前移动到下一个可插入数据的Buffer单元。position最大值可以是                              capacity-1。

3、limit(限制):在缓冲区写模式下,limit表示你最多能往Buffer里写多少数据,大小等于capacity;在缓冲区读模式下,limit表示能从缓冲区内读取到多少数据,因此,当切          换Buffer到读模式时,limit会被设置成写模式下的position值。

                          

一、使用NIO进行文件内容的复制:

public class BufferTest
{
    public static void main(String[] args) throws Exception
    {
        FileInputStream fis = new FileInputStream("d:/in.txt");
        FileChannel channel = fis.getChannel();
        
        FileOutputStream fos = new FileOutputStream("d:/out.txt");
        FileChannel channel1 = fos.getChannel();
        //初始化缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(20);
        System.out.println("通道文件的大小:" + channel.size());
        System.out.println("缓冲区初始化时当前位置:" + buffer.position());
        System.out.println("缓冲区初始化时可写的限制:" + buffer.limit());
        System.out.println("---------循环开始-----");
        //判断通道内数据是否读取完成
        while(-1 != channel.read(buffer))
        {
            System.out.println("缓冲区写模式下当前位置:" + buffer.position());
            System.out.println("缓冲区写模式下的限制:" + buffer.limit());
            //将缓冲区从写模式切换到读模式
            buffer.flip();
            System.out.println("缓冲区读模式下当前位置:" + buffer.position());
            System.out.println("缓冲区读模式下的限制:" + buffer.limit());
            //判断缓冲区内是否还有数据可读取
            while(buffer.hasRemaining())
            {
                channel1.write(buffer);
            }
            buffer.clear();
        }
        channel.close();
        channel1.close();
        fis.close();
    }
}

执行结果:

通道文件的大小:36
缓冲区初始化时当前位置:0
缓冲区初始化时可写的限制:20
---------循环开始-----
缓冲区写模式下当前位置:20
缓冲区写模式下的限制:20
缓冲区读模式下当前位置:0
缓冲区读模式下的限制:20
缓冲区写模式下当前位置:16
缓冲区写模式下的限制:20
缓冲区读模式下当前位置:0
缓冲区读模式下的限制:16

1、文件的大小为36个字节,缓冲区初始化的大小为20个字节,程序中进行了两次读取操作,才完成了文件内容的复制。

2、可以看到,在缓冲区写模式下,limit的大小始终等于capacity;而在读模式下,limit等于模式切换前position的大小。

二、Buffer的分配

Buffer对象的获取需要进行分配,每种类型的Buffer对象都有一个allocate方法。我们以程序中的ByteBuffer对象为例:

ByteBuffer buffer = ByteBuffer.allocate(20);

我们去跟踪下源码:

1  public static ByteBuffer allocate(int capacity) {
2     if (capacity < 0)
3         throw new IllegalArgumentException();
4     return new HeapByteBuffer(capacity, capacity);
5     }
HeapByteBuffer(int cap, int lim) {        // package-private

    super(-1, 0, lim, cap, new byte[cap], 0);

//在这里已经创建一个以cap为大小的字节数组(new byte[cap])

ByteBuffer(int mark, int pos, int lim, int cap,    // package-private
         byte[] hb, int offset)
    {
    super(mark, pos, lim, cap);
    this.hb = hb;
    this.offset = offset;
    }
Buffer(int mark, int pos, int lim, int cap) {    // package-private
    if (cap < 0)
        throw new IllegalArgumentException();
    this.capacity = cap;
    limit(lim);
    position(pos);
    if (mark >= 0) {
        if (mark > pos)
        throw new IllegalArgumentException();
        this.mark = mark;
    }
    }

//数组的创建在ByteBuffer类里面已经创建,在父类Buffer里,初始化容量、限制、位置等一些公共属性。

三、Buffer模式的切换

buffer.flip()该方法是用于将缓冲区从写模式切换到读模式,这是一种固定写法,该方法的源码如下:

public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
    }

 调用flip()方法会将position设回0,并将limit设置成之前position的值。

四、remaind方法

public final Buffer rewind() {
    position = 0;
    mark = -1;
    return this;
    }

将position的位置设置为0,表示可以重新读取Buffer中的所有数据,limit保持不变。

五、clear方法

1  public final Buffer clear() {
2     position = 0;
3     limit = capacity;
4     mark = -1;
5     return this;

1、一旦完成对buffer中数据的读取,需要让buffer做好再次被写入的准备,这时候可以调用clear方法来完成。

2、clear方法将position设置为0,limit设置为容量的值,也就意味着buffer被清空了,但是这个清空的概念是写入数据可以从缓冲区的指定位置开始,但buffer里面的数据并没有        删除。

3、如果buffer里面还有数据没有被读取,这个时候调用clear方法会导致那些数据被“遗忘”,因为没有标记告诉你哪些是读取过哪些没有被读取。

六、向buffer中写入数据

1、通过channel写入;

2、通过buffer的put方法写入:

buffer.put("channel".getBytes());

七、从buffer中读取数据

1、通过channel读取;

2、通过buffer的get方法读取:

byte b = buffer.get();

 

以上是关于java中如何清空缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

如何清空(清除)Android中的logcat缓冲区[重复]

linux如何清空串口接收缓冲区和发送缓冲区数据

c#从串口读取数据怎样读一个就清空缓存

io操作中,通常使用啥方法来强制清空缓存区

vs2019清空输入缓冲区

JAVA NIO系列 Buffer 解读