如何优雅地读取文件中的每一行?

发布于 2022-08-28 00:27:46 字数 847 浏览 28 评论 0

最近文件操作较多,但大多数都是一行一行地读取,每一行是一条新闻。经常用的代码是这样的:

InputStream is = null;
try {
    is = new FileInputStream(textPath);
    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"), 512);
    // 读取一行,存储于字符串列表中
    for (String line = reader.readLine(); line != null; line = reader.readLine()) {
        line = line.trim();
        // do something here
    }

}catch (FileNotFoundException fnfe){
    fnfe.printStackTrace();
}catch (IOException ioe){
    ioe.printStackTrace();
} finally {
    try {
        if (is != null) {
            is.close();
            is = null;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

当do something变得很庞大时,这try语句块就变得有点臃肿。是否能存在这样的一个文件读取类,就像Iterator迭代器一样,使用hasNext()和next()遍历文件中的所有行,而将异常处理等全部隐藏起来?还是有什么其它更加优雅的方法?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

如此安好 2022-09-04 00:27:46

java当然可以很优雅, 宇宙第一的编程语言也不是光靠sun和oracle忽悠出来的.

这里 我们需要把 文件处理 的逻辑 和 业务逻辑分开, 引入 strategy 模式是比较合适的. 文件处理的部分是不变的可以重用的, 业务逻辑是变化的.

还有就是java7 引入 try-with-resource, 已经不需要自己去关闭流了.

代码:

public interface FileProcessor {
    void processByLine(String FilePath, LineProcessor processor);
}

public interface LineProcessor {
    void doSomeThing(String oneLine);
}

public class FileProcessorImpl implements FileProcessor {

    @Override
    public void processByLine(String filePath, LineProcessor processor) {
        try (BufferedReader br =
                new BufferedReader(new FileReader(filePath))) {
                String line = br.readLine();
                processor.doSomeThing(line.trim());
        }catch (FileNotFoundException fnfe){
            fnfe.printStackTrace();
        }catch (IOException ioe){
            ioe.printStackTrace();
        }
    }
}

public class FileProcessImplTest {

    @Test
    public void testProcessByLine() {
        final StringBuilder sb=new StringBuilder();
        final StringBuilder sb1=new StringBuilder();
        FileProcessor fp=new FileProcessorImpl();

        fp.processByLine("a.txt", new LineProcessor(){
            @Override
            public void doSomeThing(String oneLine) {
                sb.append(oneLine);
            }
        });

        fp.processByLine("a_reverse_by_line.txt", new LineProcessor(){
            @Override
            public void doSomeThing(String oneLine) {
                sb1.append(new StringBuilder(oneLine).reverse());
            }
        });

        assertEquals(sb.toString(), sb1.toString());
    }

}
复古式 2022-09-04 00:27:46

可以使用 commons-ioFileUtils:

LineIterator:

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

final LineIterator it = FileUtils.lineIterator(new File(""), "UTF-8");
try {
    while (it.hasNext()) {
        final String line = it.nextLine();
    }
} finally {
    it.close();
}

如果内存足够:

import org.apache.commons.io.Charsets;
import org.apache.commons.io.FileUtils;

final List<String> lines = FileUtils.readLines(new File(""), Charsets.UTF_8);

另外推荐 LZ 使用 org.apache.commons.io.Charsets.UTF_8 代替字符串的 "UTF-8",如:

// 不会抛出 UnsupportedEncodingException
new InputStreamReader(is, Charsets.UTF_8)
str.getBytes(Charsets.UTF_8);

因为 Java 规定了所有平台都必须实现 UTF-8 ,这里本来就不可能抛出 UnsupportedEncodingException 。Java 7 中我们就可以用 java.nio.charset.StandardCharsets 了,Java 6 暂时拿这个顶一下。

另外 LZ 可以用 org.apache.commons.io.IOUtils.closeQuietly 来关闭一个流。你的 finally 块可以简化为:

finnaly {
    IOUtils.closeQuiety(is);
}
苦妄 2022-09-04 00:27:46

" 每一个优雅的接口背后,都有一个龌龊的实现 “

伴梦长久 2022-09-04 00:27:46

用python可好?

for line in open(textPath,'r'):
    print line
过期以后 2022-09-04 00:27:46

撸主,「瓜娃」guava 你值得拥有:

import java.io.File;
import java.io.IOException;

import com.google.common.base.Charsets;
import com.google.common.io.Files;

public class App {
    public static void main(String[] args) throws IOException {
        for (String line : Files.readLines(new File("~/test.txt"), Charsets.UTF_8)) {
            System.out.println(line);
        }
    }
}

ps:看了下源码,是把整个文件读入到 List<String>,大文件会把内存撑爆,可以自己山寨一个:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        for (String line : IO.lineSeq("d:/test.txt")) {
            System.out.println(line);
        }
    }
}

final class IO {
    public static Iterable<String> lineSeq(final String path) throws FileNotFoundException {

        return new Iterable<String>() {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(
                                      path)));

            public Iterator<String> iterator() {
                return new Iterator<String>() {
                    private String content;

                    public void remove() {
                        throw new UnsupportedOperationException();
                    }

                    public String next() {
                        return content;
                    }

                    public boolean hasNext() {
                        try {
                            content = reader.readLine();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        if (content != null) {
                            return true;
                        }

                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        return false;
                    }
                };
            }

        };

    }
}
雨落□心尘 2022-09-04 00:27:46
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
public class Test {

    public static void main(String[] args) {
        FileInputStream fis = null;
        InputStreamReader isr = null;
        BufferedReader br = null; //用于包装InputStreamReader,提高处理性能。因为BufferedReader有缓冲的,而InputStreamReader没有。
        try {
            String str = "";
            String str1 = "";
            fis = new FileInputStream("c:\\小志.txt");// FileInputStream
            // 从文件系统中的某个文件中获取字节
            isr = new InputStreamReader(fis);// InputStreamReader 是字节流通向字符流的桥梁,
            br = new BufferedReader(isr);// 从字符输入流中读取文件中的内容,封装了一个new InputStreamReader的对象
            while ((str = br.readLine()) != null) {
                str1 += str + "\n";
            }
            // 当读取的一行不为空时,把读到的str的值赋给str1
            System.out.println(str1);// 打印出str1
        } catch (FileNotFoundException e) {
            System.out.println("找不到指定文件");
        } catch (IOException e) {
            System.out.println("读取文件失败");
        } finally {
            try {
                br.close();
                isr.close();
                fis.close();
                // 关闭的时候最好按照先后顺序关闭最后开的先关闭所以先关s,再关n,最后关m
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
请输入代码
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文