【问题标题】:python-like Java IO library?类似python的Java IO库?
【发布时间】:2011-02-17 15:57:14
【问题描述】:

Java 不是我的主要编程语言,所以我可能会问一些显而易见的问题。

但是在 Java 中是否有一个简单的文件处理库,例如 python

比如我只想说:

File f = Open('file.txt', 'w')
for(String line:f){
      //do something with the line from file
}

谢谢!

更新:好吧,stackoverflow 自动接受了一个奇怪的答案。这与我放置的赏金有关 - 因此,如果您想查看其他答案,只需向下滚动!

【问题讨论】:

  • 我记得你详细的回答为什么要删除它?
  • 我没有,我只是将我的代码移到了 pastebin,因为它变得很长。
  • 如果您有冒险精神,请查看 scala。它允许您完成这些类型的任务。该语言是在 java jvm 之上编写的,这意味着您可以合并您的 java,反之亦然。

标签: java python file-io


【解决方案1】:

我在想更多的东西:

File f = File.open("C:/Users/File.txt");

for(String s : f){
   System.out.println(s);
}

这是我的源代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;

public abstract class File implements Iterable<String>{
    public final static String READ = "r";
    public final static String WRITE = "w";

    public static File open(String filepath) throws IOException{
        return open(filepath, READ);
    }   

    public static File open(String filepath, String mode) throws IOException{
    if(mode == READ){
        return new ReadableFile(filepath);
    }else if(mode == WRITE){
        return new WritableFile(filepath);
    }
    throw new IllegalArgumentException("Invalid File Write mode '" + mode + "'");
    }

    //common methods
    public abstract void close() throws IOException;

    // writer specific
    public abstract void write(String s) throws IOException;

}

class WritableFile extends File{
    String filepath;
    Writer writer;

    public WritableFile(String filepath){
        this.filepath = filepath;
    }

    private Writer writer() throws IOException{
        if(this.writer == null){
            writer = new BufferedWriter(new FileWriter(this.filepath));
        }
        return writer;
    }

    public void write(String chars) throws IOException{
        writer().write(chars);
    }

    public void close() throws IOException{
        writer().close();
    }

    @Override
    public Iterator<String> iterator() {        
        return null;
    }
}

class ReadableFile extends File implements Iterator<String>{
    private BufferedReader reader;
    private String line;    
    private String read_ahead;

    public ReadableFile(String filepath) throws IOException{        
        this.reader = new BufferedReader(new FileReader(filepath)); 
        this.read_ahead = this.reader.readLine();
    }

    private Reader reader() throws IOException{
         if(reader == null){
               reader = new BufferedReader(new FileReader(filepath));   
         }
         return reader;
    }

    @Override
    public Iterator<String> iterator() {
        return this;
    }

    @Override
    public void close() throws IOException {
        reader().close();
    }

    @Override
    public void write(String s) throws IOException {
        throw new IOException("Cannot write to a read-only file.");
    }

    @Override
    public boolean hasNext() {      
        return this.read_ahead != null;
    }

    @Override
    public String next() {
        if(read_ahead == null)
            line = null;
        else
            line = new String(this.read_ahead);

        try {
            read_ahead = this.reader.readLine();
        } catch (IOException e) {
            read_ahead = null;
            reader.close()
        }
        return line;
    }

    @Override
    public void remove() {
        // do nothing       
    }
}

这里是它的单元测试:

import java.io.IOException;
import org.junit.Test;

public class FileTest {
    @Test
    public void testFile(){
        File f;
        try {
            f = File.open("File.java");
            for(String s : f){
                System.out.println(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testReadAndWriteFile(){
        File from;
        File to;
        try {
            from = File.open("File.java");
            to = File.open("Out.txt", "w");
            for(String s : from){           
                to.write(s + System.getProperty("line.separator"));
            }
            to.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }   
    }
}

【讨论】:

  • 这很有趣,你可以让它看起来几乎像在 Python 中一样。我会将File 类称为其他名称,以避免与Java 自己的java.io.File 混淆。在您的 FileIterator 中创建 remove() 方法 throw UnsupportedOperationException 而不是将其留空。
  • 谢谢!我不确定如何删除那里 ;-) 我想我会保留文件名,但是与命名空间一样,我没有看到任何问题出现。我对此进行了更多更改-我真的希望有Java背景的人来看看它。明天我会在 pastebin 上发布我的版本。
  • Drozzy,我认为无论长度如何,都最好将代码留在这里。在回答时,我总是假设地球上的所有其他网站都会消失(是的,甚至 MSDN、维基百科等)。 SO上的答案应该能够站在他们自己的优点上。我没有任何问题可以链接到其他网站以获取更多详细信息,但“肉”应该在这里。让我们想想如果 pastebin 破产(或者更糟糕的是,开始将他们的投资货币化),这个答案会发生什么。然后这个答案就变得毫无用处了,因为它基本上是问题的引用。
  • 我什至会 +2 你(Q & A)试图说服你把代码留在这里:-)
  • +1 表示聪明,但你的迭代器需要确保在 next() 中发生 IOException 时关闭文件
【解决方案2】:

在Java中逐行读取文件:

BufferedReader in = new BufferedReader(new FileReader("myfile.txt"));

String line;
while ((line = in.readLine()) != null) {
    // Do something with this line
    System.out.println(line);
}

in.close();

大多数 I/O 类都在包 java.io 中。请参阅该软件包的 API 文档。请查看Sun's Java I/O tutorial 了解更多详细信息。

addition:上面的例子将使用您系统的默认字符编码来读取文本文件。如果要显式指定字符编码,例如 UTF-8,请将第一行更改为:

BufferedReader in = new BufferedReader(
    new InputStreamReader(new FileInputStream("myfile.txt"), "UTF-8"));

【讨论】:

  • 嗯.. 看起来还是很笨重:-(
  • 是的,但这就是它与 Java 的标准 API 一起工作的方式,Java 并不是最简洁的语言...
  • 那么,除了逐行读取文件的玩具示例之外,您还想做什么?恕我直言,这不是那么笨重。
  • 嗯,基本上和 python 的 File 对象一样。它还具有二进制模式。我从来没有遇到过问题。 docs.python.org/py3k/library/functions.html#open
  • 在 Eclipse 中有一个代码模板会很酷,stackoverflow.com/questions/1028858/…
【解决方案3】:

如果您已经依赖于 Apache commons langcommons io,这可能是一个替代方案:

String[] lines = StringUtils.split(FileUtils.readFileToString(new File("myfile.txt")), '\n');
for(String line: lines){
      //do something with the line from file
}

(我更喜欢 Jesper 的回答)

【讨论】:

  • 将整个文件读入String,然后将整个文件拆分到内存中……如果文件很大,可能会占用大量内存。
  • 我支持@Jesper 的考虑。内存中的字符串太多了,并且可以从字面上杀死您的应用程序(OutOfMemoryError)
  • 在添加赏金之前添加了一个替代方案,我还推荐了 Jespers 回答。对于较小的文件,它可以正常工作。
  • FileUtils 有一个方法 readLines,它返回一个字符串列表。
  • 我尽量远离 Apache commons 中的任何内容,因为这通常意味着在 apache commons 中包含所有 100 Zillion 其他依赖项。
【解决方案4】:

如果您想按字符串遍历文件,您可能会发现一个有用的类是 Scanner 类。

import java.io.*;
import java.util.Scanner;

    public class ScanXan {
        public static void main(String[] args) throws IOException {
            Scanner s = null;
            try {
                s = new Scanner(new BufferedReader(new FileReader("myFile.txt")));

                while (s.hasNextLine()) {
                    System.out.println(s.nextLine());
                }
            } finally {
                if (s != null) {
                    s.close();
                }
            }
        }
    }

API 非常有用:http://java.sun.com/javase/7/docs/api/java/util/Scanner.html 您还可以使用正则表达式解析文件。

【讨论】:

  • 谢谢,但我真的不想与 BufferedReaders 或类似的东西有任何关系。只需给它一个文件路径,就完成了!嗯...但如果我想得更多 - 我可能会将这个扫描仪包装在我自己的包装器中,这样会带来一些便利。
【解决方案5】:

我从不厌倦在 Google 的 guava-libraries 上拉皮条,这让我从……嗯,Java 中的大多数事情中消除了很多痛苦。

怎么样:

for (String line : Files.readLines(new File("file.txt"), Charsets.UTF_8)) {
   // Do something
}

如果您有一个大文件,并且想要逐行回调(而不是将整个内容读入内存),您可以使用 LineProcessor,它添加了一些样板文件(由于没有闭包...叹息)但仍然可以保护您免于处理阅读本身以及所有相关的Exceptions

int matching = Files.readLines(new File("file.txt"), Charsets.UTF_8, new LineProcessor<Integer>(){
  int count;

  Integer getResult() {return count;}

  boolean processLine(String line) {
     if (line.equals("foo")
         count++;
     return true;
  }
});

如果您实际上并不希望从处理器中返回结果,并且您永远不会提前中止(从processLine 返回布尔值的原因),您可以然后执行以下操作:

class SimpleLineCallback extends LineProcessor<Void> {
    Void getResult{ return null; }

    boolean processLine(String line) {
       doProcess(line);
       return true;
    }

    abstract void doProcess(String line);
}

然后你的代码可能是:

Files.readLines(new File("file.txt"), Charsets.UTF_8, new SimpleLineProcessor(){
  void doProcess(String line) {
     if (line.equals("foo");
         throw new FooException("File shouldn't contain 'foo'!");
  }
});

相应地更干净。

【讨论】:

  • 如果您发布代码以以一种很好的方式使用回调,我会接受:-)
  • @drozzy:完成了,还有一点我会用来再次减少样板的小技巧。
  • 很抱歉,我看到了它 - 这有点麻烦。它不像(对于文件中的行)那么简单:做事。我希望你知道我的意思。但我确实赞成你的回答。也许我可以使用你的代码作为我实现的核心——它应该处理很多异常处理和正确的文件/缓冲区关闭。
  • 这很难。 Google 可以有一个简单的 readLines 版本,它返回一个 Iterable,而不是 List,并且不保存在内存中,但这很尴尬——事实上,Java 中的所有 IO 操作都可以抛出 IOException,并且拥有一个完全隐藏它的干净 API 并不容易。迭代器遇到这样的异常应该怎么办?假装没有下一个项目?重新抛出未经检查的异常?等等。不幸的是,检查异常很难以“最少惊喜”的方式进行。
  • 我想说抛出一个未经检查的异常。默默地失败并不是一个真正的选择。另一种选择是在此时记录失败(但您的 Iterator 可能只是一个私有 API)。
【解决方案6】:
  public static void main(String[] args) throws FileNotFoundException {
    Scanner scanner = new Scanner(new File("scan.txt"));
    try {
      while (scanner.hasNextLine()) {
        System.out.println(scanner.nextLine());
      }
    } finally {
      scanner.close();
    }
  }

一些注意事项:

【讨论】:

    【解决方案7】:

    使用来自 guava-io 的 Files.readLines()LineProcessor 回调的简单示例:

    import java.io.File;
    import java.io.IOException;
    
    import com.google.common.base.Charsets;
    import com.google.common.io.Files;
    import com.google.common.io.LineProcessor;
    
    public class GuavaIoDemo {
    
        public static void main(String[] args) throws Exception {
            int result = Files.readLines(new File("/home/pascal/.vimrc"), //
                Charsets.UTF_8, // 
                new LineProcessor<Integer>() {
                    int counter;
    
                    public Integer getResult() {
                        return counter;
                    }
    
                    public boolean processLine(String line) throws IOException {
                        counter++;
                        System.out.println(line);
                        return true;
                    }
                });
        }
    }
    

    【讨论】:

    • 谢谢你,但现在我看到了 - 它看起来确实有点像很多工作:-)
    【解决方案8】:

    您可以使用jython,它可以让您在 Java 中运行 Python 语法。

    【讨论】:

      【解决方案9】:

      这里是一个很好的例子:Line by line iteration

      【讨论】:

      • 这确实是我的想法。除非代码未经任何人审查和测试。如果有一个公用事业项目社区,那就太好了。另外 - 问题是代码吃掉了换行符。 (我必须承认我的回答也是如此——但它应该把角色留在里面)。
      【解决方案10】:

      试试看 groovy!

      它是在 JVM 中运行的 Java 的超集。大多数有效的 Java 代码也是有效的 Groovy,因此您可以直接访问数百万个 Java API 中的任何一个。

      此外,它还有许多 Python 爱好者熟悉的高级结构,此外 一些扩展来消除 Maps、Lists、sql、xml 的痛苦,你猜对了——文件 IO。

      【讨论】:

      • 是的,但我真的不喜欢 Groovy 可以包含 java 源代码的事实。我的意思是,这就像采用非常混乱的语言语法并在其上添加一些“不错”的语法。
      猜你喜欢
      • 2016-03-21
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-01
      • 2018-04-25
      • 2010-10-28
      • 1970-01-01
      相关资源
      最近更新 更多