java中使用Files.readLines()处理文本中行数据方式

目录
  • 使用Files.readLines()处理文本中行数据
  • 被readLine()折腾了一把
    • 发数据
    • 读数据
    • readLine()的实质(下面是从JDK源码摘出来的)
    • 小结,使用readLine()一定要注意

使用Files.readLines()处理文本中行数据

开发中遇到对数据库导出到文件里的数据进行处理,然后对处理后的数据再重新写回文件中,在这个过程中使用到了Files.readLines()方法

/**
 *
 * @param file : existed file
 * @throws IOException
 */
public void lineProcess(File file) throws IOException {
    Files.readLines(file, Charset.defaultCharset(), new LineProcessor() {
        File outFile = new File("outfile");//处理后的数据输出文件
        List<String> lines = new ArrayList<String>();
        @Override
        public boolean processLine(String line) throws IOException {
            String newLine = "";
            //file中的 line数据格式:name,age,address -> NAME,AGE,ADDRESS,
            String[] contents = line.split(",");
            for (int i=0;i<contents.length;i++){
                newLine.concat(contents[i].toLowerCase());
            }
            lines.add(newLine);
            //将处理后的数写入新的文件 outFile
            FileUtils.writeLines(outFile,lines,true);
            lines.clear();
            return true;
        }
        @Override
        public Object getResult() {
            try{
                FileUtils.writeLines(outFile,lines,true);
            }catch (Exception e){
                e.getCause();
            }
            lines.clear();
            return null;
        }
    });
}

方法中的LineProcessor()实现对每一行数据处理逻辑。

依赖guava

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

被readLine()折腾了一把

虽然写IO方面的程序不多,但BufferedReader/BufferedInputStream倒是用过好几次的,原因是:

它有一个很特别的方法:readLine(),使用起来特别方便,每次读回来的都是一行,省了很多手动拼接buffer的琐碎;

它比较高效,相对于一个字符/字节地读取、转换、返回来说,它有一个缓冲区,读满缓冲区才返回;一般情况下,都建议使用它们把其它Reader/InputStream包起来,使得读取数据更高效。

对于文件来说,经常遇到一行一行的,特别相符情景。

这次是在蓝牙开发时,使用两个蓝牙互相传数据(即一个发一个收),bluecove这个开源组件已经把数据读取都封装成InputStream了,也就相当于平时的IO读取了,很自然就使用起readLine()来了。

发数据

BufferedWriter output = new BufferedWriter(new OutputStreamWriter(conn.openOutputStream()));
int i = 1;
String message = "message " + i;
while(isRunning) {
    output.write(message+"/n");
    i++;
}

读数据

BufferedReader input = new BufferedReader(new  InputStreamReader(m_conn.openInputStream()));
String message = "";
String line = null;
while((line = m_input.readLine()) != null) {
    message += line;
}
System.out.println(message);

上面是代码的节选,使用这段代码会发现写数据时每次都成功,而读数据侧却一直没有数据输出(除非把流关掉)。经过折腾,原来这里面有几个大问题需要理解:

误以为readLine()是读取到没有数据时就返回null(因为其它read方法当读到没有数据时返回-1),而实际上readLine()是一个阻塞函数,当没有数据读取时,就一直会阻塞在那,而不是返回null;因为readLine()阻塞后,System.out.println(message)这句根本就不会执行到,所以在接收端就不会有东西输出。要想执行到System.out.println(message),一个办法是发送完数据后就关掉流,这样readLine()结束阻塞状态,而能够得到正确的结果,但显然不能传一行就关一次数据流;另外一个办法是把System.out.println(message)放到while循环体内就可以。

readLine()只有在数据流发生异常或者另一端被close()掉时,才会返回null值。

如果不指定buffer大小,则readLine()使用的buffer有8192个字符。在达到buffer大小之前,只有遇到"/r"、"/n"、"/r/n"才会返回。

readLine()的实质(下面是从JDK源码摘出来的)

String readLine(boolean ignoreLF) throws IOException {
 StringBuffer s = null;
 int startChar;
        synchronized (lock) {
            ensureOpen();
     boolean omitLF = ignoreLF || skipLF;
     bufferLoop:
     for (;;) {
  if (nextChar >= nChars)
      fill(); //在此读数据
  if (nextChar >= nChars) { /* EOF */
      if (s != null && s.length() > 0)
   return s.toString();
      else
   return null;
  }
      ......//其它
}
private void fill() throws IOException {
 ..../其它
 int n;
 do {
     n = in.read(cb, dst, cb.length - dst); //实质
 } while (n == 0);
 if (n > 0) {
     nChars = dst + n;
     nextChar = dst;
 }
    }

从上面看出,readLine()是调用了read(char[] cbuf, int off, int len) 来读取数据,后面再根据"/r"或"/n"来进行数据处理。

在Java I/O书上也说了:

public String readLine() throws IOException
This method returns a string that contains a line of text from a text file. /r, /n, and /r/n are assumed to be line breaks and are not included in the returned string. This method is often used when reading user input from System.in, since most platforms only send the user's input to the running program after the user has typed a full line (that is, hit the Return key).
readLine() has the same problem with line ends that DataInputStream's readLine() method has; that is, the potential to hang on a lone carriage return that ends the stream . This problem is especially acute on networked connections, where readLine() should never be used.

小结,使用readLine()一定要注意

读入的数据要注意有/r或/n或/r/n

没有数据时会阻塞,在数据流异常或断开时才会返回null

使用socket之类的数据流时,要避免使用readLine(),以免为了等待一个换行/回车符而一直阻塞

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • java 实现读取txt文本数据并以数组形式一行一行取值

    首先来读取txt文本中的内容,输出在控制台,直接上代码: import java.io.BufferedReader; import java.io.File; import java.io.FileReader; public class ReadFiledata { public static String txt2String(File file){ StringBuilder result = new StringBuilder(); try{ BufferedReader br = n

  • java8 Stream流逐行处理文本文件

    本文中为大家介绍使用java8 Stream API逐行读取文件,以及根据某些条件过滤文件内容 1. Java 8逐行读取文件 在此示例中,我将按行读取文件内容并在控制台打印输出. Path filePath = Paths.get("c:/temp", "data.txt"); //try-with-resources语法,不用手动的编码关闭流 try (Stream<String> lines = Files.lines( filePath )) {

  • 解决BufferedReader.readLine()遇见的坑

    目录 BufferedReader.readLine()遇见的坑 今天踩了这个坑,所以做个笔记 所以使用readLine()一定要注意 BufferedReader.readLine解析 BufferedReader.readLine()遇见的坑 在写ftp上传文件至服务器的过程中,有这样一个判断:判断某个文件夹下有多少个文件,内容为null的文件不上传,所以利用BufferedReader读取文件的内容,判断是否为null,所以用到了BufferedReader.readLine(),结果竟然

  • 关于BufferedReader的read()和readLine()的区别

    目录 BufferedReader的read()和readLine()区别 小结一下 项目经验 BufferedReader.readLine()总结 正确的代码如下 BufferedReader的read()和readLine()区别 从一个有若干行deep文件中依次读取各行,处理后输出,如果用以下方法,则会出现除第一行外首字符丢失的现象 String str = null; br=new BufferedReader(new FileReader(fileName)); do{ str =

  • java中使用Files.readLines()处理文本中行数据方式

    目录 使用Files.readLines()处理文本中行数据 被readLine()折腾了一把 发数据 读数据 readLine()的实质(下面是从JDK源码摘出来的) 小结,使用readLine()一定要注意 使用Files.readLines()处理文本中行数据 开发中遇到对数据库导出到文件里的数据进行处理,然后对处理后的数据再重新写回文件中,在这个过程中使用到了Files.readLines()方法 /** * * @param file : existed file * @throws

  • 在Java中轻松将HTML格式文本转换为纯文本的方法示例(保留换行)

    第一步:引入Jsoup和lang和lang3的依赖: Jsoup是HTML解析器 lang和lang3这两个包里有转换所需的工具类 <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency> <dependency> <group

  • java中创建、写入文件的5种方式

    在java中有很多的方法可以创建文件写文件,你是否真的认真的总结过?下面笔者就帮大家总结一下java中创建文件的五种方法. Files.newBufferedWriter(Java 8) Files.write(Java 7 推荐) PrintWriter File.createNewFile FileOutputStream.write(byte[] b) 管道流 实际上不只这5种,通过管道流的排列组合,其实有更多种,但是笔者总结的这五种可以说是最常用及最佳实践, 前提小知识 以前我在写技术文

  • java中进程与线程_三种实现方式总结(必看篇)

    一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程是指处于运行过程中的程序,并且具有一定的独立功能.进程是系统进行资源分配和调度的一个单位.当程序进入内存运行时,即为进程. 进程的三个特点: 1:独立性:进程是系统中独立存在的实体,它可以独立拥有资源,每一个进程都有自己独立的地址空间,没有进程本身的运行,用户进程不可以直接访问其他进程的地址空间. 2:

  • Java 中责任链模式实现的三种方式

    责任链模式 责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系, 将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止.这里就不再过多的介绍什么是责任链模式,主要来说说java中如何编写.主要从下面3个框架中的代码中介绍. servlet中的filter dubbo中的filter mybatis中的plugin 这3个框架在实现责任链方式不尽相同. servlet中的Filter servlet中分别定义了一个 Filter和Filter

  • Java中关于线程安全的三种解决方式

    三个窗口卖票的例子解决线程安全问题 问题:买票过程中,出现了重票.错票-->出现了线程的安全问题 问题出现的原因:当某个线程操作车票的过程中,尚未操作完成时,其他线程参与进来,也操作车票 如何解决:当一个线程a在操作ticket的时候,其他线程不能参与进来,知道线程a操作完ticket时,其他线程才可以开始操作ticket,这种情况即使线程a出现了阻塞,也不能被改变 在Java中,我们通过同步机制,来解决线程的安全问题.(线程安全问题的前提:有共享数据) 方式一:同步代码块 synchroniz

  • Java中Map实现线程安全的3种方式

    目录 方式1. 使用Hashtable 方式2. 使用Collections.synchronizedMap(newHashtable()) 方式3. 使用ConcurrentHashMap 方式1.  使用Hashtable Map<String,Object> hashtable=new Hashtable<String,Object>(); 这是所有人最先想到的,那为什么它是线程安全的?那就看看它的源码,我们可以看出我们常用的put,get,containsKey等方法都是同

  • Java中JDBC连接池的基本原理及实现方式

    目录 一. 应用程序直接建立数据库连接模型 二.使用数据库连接池优化模型 1.关于连接池中的连接数量的一些规定: 2.编写数据库连接池 创建数据库连接池: 进一步封装一些相关数据库的类的方法 三.两个开源的数据库连接池 1.dbcp连接 (1)导入相关jar包 (2)在项目根目录增加配置文件dbcp.properties (3)程序实现dbcp连接 2.c3p0连接池 (1)导入相关的jar包 (2)在项目根目录下增加配置文件 (3)编写类文件,创建连接池 3.dbcp和c3p0不同之处 一.

  • java中String字符串删除空格的七种方式

    目录 trim() strip() stripLeading() 和 stripTrailing() replace replaceAll replaceFirst 总结 在Java中从字符串中删除空格有很多不同的方法,如trim,replaceAll等.但是,在JDK 11添加了一些新的功能,如strip.stripLeading.stripTrailing等. 想要从String中移除空格部分,有多少种方法,下面介绍JDK原生自带的方法,不包含第三方工具类库中的类似方法 trim() : 删

  • 浅析Java中对象的创建与对象的数据类型转换

    Java:对象创建和初始化过程 1.Java中的数据类型     Java中有3个数据类型:基本数据类型(在Java中,boolean.byte.short.int.long.char.float.double这八种是基本数据类型).引用类型和null类型.其中,引用类型包括类类型(含数组).接口类型.     下列语句声明了一些变量: int k ; A a; //a是A数据类型的对象变量名. B b1,b2,-,b10000;// 假定B是抽象类或接口. String s; 注意:从数据类型

随机推荐