Java中readLine方法如何忽略行中的回车符\r

按行读取只使用\n换行,忽略\r

我们查看调用链,发现使用了Files和BufferedReader两个类,需要修改的代码是BufferedReader的String readLine(boolean ignoreLF)方法,这里写死了以\r和\n换行,我们只需要修改这里代码就行,所以我们重写这两个类,能继承用继承,不能继承copy源码来改就行了。

调用入口

Path path=Paths.get("test.txt");
List<String> lines= FilesExtend.readAllLines(path, Charset.forName("utf8"));

重写Files类

package org.xxx.utils; 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import static java.nio.file.Files.newInputStream;

/**
 * Description Files文件操作类,使用我们的BufferExtend基础类
 * author dragonKJ
 * createTime 2021/11/21  12:59
 */
public class FilesExtend {
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:18
     * @param path
     * @param cs
     * @return java.util.List<java.lang.String>
     */
    public static List<String> readAllLines(Path path, Charset cs) throws IOException {
        //使用我们的继承类BufferedReaderExtend
        try (BufferedReaderExtend reader = newBufferedReader(path, cs)) {
            List<String> result = new ArrayList<>();
            for (;;) {
                String line = reader.readLine();
                if (line == null)
                    break;
                result.add(line);
            }
            return result;
        }
    }


    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:18
     * @param path
     * @param cs
     * @return BufferExtend
     */
    public static BufferedReaderExtend newBufferedReader(Path path, Charset cs)
            throws IOException
    {
        CharsetDecoder decoder = cs.newDecoder();
        Reader reader = new InputStreamReader(newInputStream(path), decoder);
        return new BufferedReaderExtend(reader);
    }


}

重写BufferedReader

package org.xxx.utils; 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;

/**
 * Description BufferedReader继承类,为了实现文件按行读取,只以\n换行,忽略\r
 * author dragonKJ
 * createTime 2021/11/21  12:49
 */
public class BufferedReaderExtend extends BufferedReader {
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private Reader in;
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private char cb[];
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private int nChars, nextChar;
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private static final int INVALIDATED = -2;
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private static final int UNMARKED = -1;
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private int markedChar = UNMARKED;
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private int readAheadLimit = 0; /* Valid only when markedChar > 0 */

    /**
     * If the next character is a line feed, skip it
     */
    private boolean skipLF = false;

    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private static int defaultCharBufferSize = 8192;
    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     */
    private static int defaultExpectedLineLength = 80;

    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:12
     *
     * @param in
     */
    public BufferedReaderExtend(Reader in) {
        this(in, defaultCharBufferSize);
    }

    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:13
     *
     * @param in
     * @param sz
     */
    public BufferedReaderExtend(Reader in, int sz) {
        super(in);
        if (sz <= 0)
            throw new IllegalArgumentException("Buffer size <= 0");
        this.in = in;
        cb = new char[sz];
        nextChar = nChars = 0;
    }

    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:13
     *
     * @return java.lang.String
     */
    @Override
    public String readLine() throws IOException {
        return readLine(false);
    }

    /**
     * Description 文件按行读取,只以\n换行,忽略\r
     * author dragonKJ
     * time 2021/11/21 14:13
     *
     * @param ignoreLF
     * @return java.lang.String
     */
    String readLine(boolean ignoreLF) throws IOException {
        StringBuffer s = null;
        int startChar;

        synchronized (lock) {
            // 确保底层的inputStream未被关闭
            ensureOpen();
            boolean omitLF = ignoreLF || skipLF;

            // 接下来是两个循环,第一层bufferLoop主要是用来往底层的数组里填充字符,这个底层数组就相当于一个缓冲区
            // 而这个缓冲区的大小可以通过BufferedReader(Reader in, int
            // sz)这个构造方法的第二个参数来指定,默认为8192bytes
            // 而charLoop则是用来遍历底层数组,每次读完底层数组里的数据,就把这些数据写到一个StringBuffer里,
            // 直到读到"\n"的时候,写入最后一批数据之后就返回结果并退出整个循环
            bufferLoop:
            for (; ; ) {

                if (nextChar >= nChars)
                    fill();
                if (nextChar >= nChars) { /* EOF */
                    if (s != null && s.length() > 0)
                        return s.toString();
                    else
                        return null;
                }
                boolean eol = false;
                char c = 0;
                int i;

                /* Skip a leftover '\n', if necessary */
                if (omitLF && (cb[nextChar] == '\n'))
                    nextChar++;
                skipLF = false;
                omitLF = false;

                // 注意:这个类的修改点就是这里,修改点删除\r跳出循环判断
                // 修改之前:退出这一层循环有两种情况:1、读到"\r"或者"\n" 2、底层数组cb被读完了
                // 修改之后:退出这一层循环有两种情况:1、读到"\n" 2、底层数组cb被读完了
                charLoop:
                for (i = nextChar; i < nChars; i++) {
                    c = cb[i];

                    if ((c == '\n')) {
                        eol = true;
                        break charLoop;
                    }
                }

                startChar = nextChar;
                nextChar = i;

                if (eol) {
                    String str;
                    if (s == null) {
                        str = new String(cb, startChar, i - startChar);
                    } else {
                        s.append(cb, startChar, i - startChar);
                        str = s.toString();
                    }
                    nextChar++;
                    if (c == '\r') {
                        skipLF = true;
                    }
                    return str;
                }

                if (s == null)
                    s = new StringBuffer(defaultExpectedLineLength);
                s.append(cb, startChar, i - startChar);
            }
        }
    }


    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:14
     */
    private void fill() throws IOException {
        int dst;
        if (markedChar <= UNMARKED) {
            /* No mark */
            dst = 0;
        } else {
            /* Marked */
            int delta = nextChar - markedChar;
            if (delta >= readAheadLimit) {
                /* Gone past read-ahead limit: Invalidate mark */
                markedChar = INVALIDATED;
                readAheadLimit = 0;
                dst = 0;
            } else {
                if (readAheadLimit <= cb.length) {
                    /* Shuffle in the current buffer */
                    System.arraycopy(cb, markedChar, cb, 0, delta);
                    markedChar = 0;
                    dst = delta;
                } else {
                    /* Reallocate buffer to accommodate read-ahead limit */
                    char ncb[] = new char[readAheadLimit];
                    System.arraycopy(cb, markedChar, ncb, 0, delta);
                    cb = ncb;
                    markedChar = 0;
                    dst = delta;
                }
                nextChar = nChars = delta;
            }
        }

        int n;
        do {
            n = in.read(cb, dst, cb.length - dst);
        } while (n == 0);
        if (n > 0) {
            nChars = dst + n;
            nextChar = dst;
        }
    }

    /**
     * Description TODO
     * author dragonKJ
     * time 2021/11/21 14:14
     */
    private void ensureOpen() throws IOException {
        if (in == null)
            throw new IOException("Stream closed");
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Readline 是一个JNI包装器,它封装了GNU readline或editline命令库。 通过使用Java的BufferedReader类,我们可以读取文件的文本。例如,使用BufferedReader的readLine()方法可以读取一文本,一被认为是由一个换('\n')、回车('\r')或回车的任何一个被终止紧跟一个换。 使用BufferedReader需要先创建一个BufferedReader对象,然后通过传入文件路径或输入流来初始化该对象,例如可以通过new BufferedReader(new FileReader("c:/test.txt"))来创建一个从文件读取的BufferedReader对象。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Java Readline-开源](https://download.csdn.net/download/weixin_42176612/20134793)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [java readline函数 返回的是什么](https://blog.csdn.net/weixin_36212732/article/details/114089289)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值